This commit is contained in:
162
internal/httpapp/maintenance_handlers.go
Normal file
162
internal/httpapp/maintenance_handlers.go
Normal file
@@ -0,0 +1,162 @@
|
||||
package httpapp
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"gitea.avt.data-center.id/othman.suseno/atlas/internal/backup"
|
||||
"gitea.avt.data-center.id/othman.suseno/atlas/internal/errors"
|
||||
"gitea.avt.data-center.id/othman.suseno/atlas/internal/models"
|
||||
)
|
||||
|
||||
// handleGetMaintenanceStatus returns the current maintenance mode status
|
||||
func (a *App) handleGetMaintenanceStatus(w http.ResponseWriter, r *http.Request) {
|
||||
if a.maintenanceService == nil {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeInternal,
|
||||
"maintenance service not available",
|
||||
http.StatusInternalServerError,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
status := a.maintenanceService.GetStatus()
|
||||
writeJSON(w, http.StatusOK, status)
|
||||
}
|
||||
|
||||
// handleEnableMaintenance enables maintenance mode
|
||||
func (a *App) handleEnableMaintenance(w http.ResponseWriter, r *http.Request) {
|
||||
if a.maintenanceService == nil {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeInternal,
|
||||
"maintenance service not available",
|
||||
http.StatusInternalServerError,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Require administrator role
|
||||
user, ok := getUserFromContext(r)
|
||||
if !ok {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeUnauthorized,
|
||||
"authentication required",
|
||||
http.StatusUnauthorized,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != models.RoleAdministrator {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeForbidden,
|
||||
"administrator role required",
|
||||
http.StatusForbidden,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
var req struct {
|
||||
Reason string `json:"reason"`
|
||||
AllowedUsers []string `json:"allowed_users,omitempty"`
|
||||
CreateBackup bool `json:"create_backup,omitempty"`
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
// Description is optional, so we'll continue even if body is empty
|
||||
_ = err
|
||||
}
|
||||
|
||||
// Create backup before entering maintenance if requested
|
||||
var backupID string
|
||||
if req.CreateBackup && a.backupService != nil {
|
||||
// Collect all configuration data
|
||||
backupData := backup.BackupData{
|
||||
Users: a.userStore.List(),
|
||||
SMBShares: a.smbStore.List(),
|
||||
NFSExports: a.nfsStore.List(),
|
||||
ISCSITargets: a.iscsiStore.List(),
|
||||
Policies: a.snapshotPolicy.List(),
|
||||
Config: map[string]interface{}{
|
||||
"database_path": a.cfg.DatabasePath,
|
||||
},
|
||||
}
|
||||
|
||||
id, err := a.backupService.CreateBackup(backupData, "Automatic backup before maintenance mode")
|
||||
if err != nil {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeInternal,
|
||||
"failed to create backup",
|
||||
http.StatusInternalServerError,
|
||||
).WithDetails(err.Error()))
|
||||
return
|
||||
}
|
||||
backupID = id
|
||||
}
|
||||
|
||||
// Enable maintenance mode
|
||||
if err := a.maintenanceService.Enable(user.ID, req.Reason, req.AllowedUsers); err != nil {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeInternal,
|
||||
"failed to enable maintenance mode",
|
||||
http.StatusInternalServerError,
|
||||
).WithDetails(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// Set backup ID if created
|
||||
if backupID != "" {
|
||||
a.maintenanceService.SetLastBackupID(backupID)
|
||||
}
|
||||
|
||||
status := a.maintenanceService.GetStatus()
|
||||
writeJSON(w, http.StatusOK, map[string]interface{}{
|
||||
"message": "maintenance mode enabled",
|
||||
"status": status,
|
||||
"backup_id": backupID,
|
||||
})
|
||||
}
|
||||
|
||||
// handleDisableMaintenance disables maintenance mode
|
||||
func (a *App) handleDisableMaintenance(w http.ResponseWriter, r *http.Request) {
|
||||
if a.maintenanceService == nil {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeInternal,
|
||||
"maintenance service not available",
|
||||
http.StatusInternalServerError,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
// Require administrator role
|
||||
user, ok := getUserFromContext(r)
|
||||
if !ok {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeUnauthorized,
|
||||
"authentication required",
|
||||
http.StatusUnauthorized,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if user.Role != models.RoleAdministrator {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeForbidden,
|
||||
"administrator role required",
|
||||
http.StatusForbidden,
|
||||
))
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.maintenanceService.Disable(user.ID); err != nil {
|
||||
writeError(w, errors.NewAPIError(
|
||||
errors.ErrCodeInternal,
|
||||
"failed to disable maintenance mode",
|
||||
http.StatusInternalServerError,
|
||||
).WithDetails(err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
writeJSON(w, http.StatusOK, map[string]string{
|
||||
"message": "maintenance mode disabled",
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user