First release of open core
This commit is contained in:
192
pkg/admin/admin_handlers.go
Normal file
192
pkg/admin/admin_handlers.go
Normal file
@@ -0,0 +1,192 @@
|
||||
package admin
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"epigas.gitea.cloud/RiskRancher/core/pkg/auth"
|
||||
)
|
||||
|
||||
// PasswordResetRequest is the expected JSON payload
|
||||
type PasswordResetRequest struct {
|
||||
NewPassword string `json:"new_password"`
|
||||
}
|
||||
|
||||
// HandleAdminResetPassword allows a Sheriff to forcefully overwrite a user's password.
|
||||
func (h *Handler) HandleAdminResetPassword(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := r.PathValue("id")
|
||||
userID, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid user ID in URL", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var req PasswordResetRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid JSON payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if req.NewPassword == "" {
|
||||
http.Error(w, "New password cannot be empty", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hashedPassword, err := auth.HashPassword(req.NewPassword)
|
||||
if err != nil {
|
||||
http.Error(w, "Internal server error during hashing", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.Store.UpdateUserPassword(r.Context(), userID, hashedPassword)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to update user password", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "Password reset successfully",
|
||||
})
|
||||
}
|
||||
|
||||
type RoleUpdateRequest struct {
|
||||
GlobalRole string `json:"global_role"`
|
||||
}
|
||||
|
||||
// HandleUpdateUserRole allows a Sheriff to promote or demote a user.
|
||||
func (h *Handler) HandleUpdateUserRole(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := r.PathValue("id")
|
||||
userID, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid user ID in URL", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
var req RoleUpdateRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid JSON payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validRoles := map[string]bool{
|
||||
"Sheriff": true, "Wrangler": true, "RangeHand": true, "CircuitRider": true, "Magistrate": true,
|
||||
}
|
||||
if !validRoles[req.GlobalRole] {
|
||||
http.Error(w, "Invalid role provided", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.Store.UpdateUserRole(r.Context(), userID, req.GlobalRole)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to update user role", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "User role updated successfully to " + req.GlobalRole,
|
||||
})
|
||||
}
|
||||
|
||||
// HandleDeactivateUser allows a Sheriff to safely offboard a user.
|
||||
func (h *Handler) HandleDeactivateUser(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := r.PathValue("id")
|
||||
userID, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid user ID in URL", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
err = h.Store.DeactivateUserAndReassign(r.Context(), userID)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to deactivate user", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]string{
|
||||
"message": "User successfully deactivated and tickets reassigned.",
|
||||
})
|
||||
}
|
||||
|
||||
// CreateUserRequest is the payload the Sheriff sends to invite a new user
|
||||
type CreateUserRequest struct {
|
||||
Email string `json:"email"`
|
||||
FullName string `json:"full_name"`
|
||||
Password string `json:"password"`
|
||||
GlobalRole string `json:"global_role"`
|
||||
}
|
||||
|
||||
// HandleCreateUser allows a Sheriff to manually provision a new user account.
|
||||
func (h *Handler) HandleCreateUser(w http.ResponseWriter, r *http.Request) {
|
||||
var req CreateUserRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, "Invalid JSON payload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Email == "" || req.FullName == "" || req.Password == "" || req.GlobalRole == "" {
|
||||
http.Error(w, "Missing required fields", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
validRoles := map[string]bool{
|
||||
"Sheriff": true, "Wrangler": true, "RangeHand": true, "CircuitRider": true, "Magistrate": true,
|
||||
}
|
||||
if !validRoles[req.GlobalRole] {
|
||||
http.Error(w, "Invalid role provided", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
hashedPassword, err := auth.HashPassword(req.Password)
|
||||
if err != nil {
|
||||
http.Error(w, "Internal server error during hashing", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := h.Store.CreateUser(r.Context(), req.Email, req.FullName, hashedPassword, req.GlobalRole)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "UNIQUE constraint failed") {
|
||||
http.Error(w, "Email already exists in the system", http.StatusConflict)
|
||||
return
|
||||
}
|
||||
http.Error(w, "Failed to provision user", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"message": "User provisioned successfully. Share the temporary password securely.",
|
||||
"id": user.ID,
|
||||
"email": user.Email,
|
||||
"full_name": user.FullName,
|
||||
"global_role": user.GlobalRole,
|
||||
})
|
||||
}
|
||||
|
||||
// HandleGetUsers returns a list of all users in the system for the Sheriff to manage.
|
||||
func (h *Handler) HandleGetUsers(w http.ResponseWriter, r *http.Request) {
|
||||
users, err := h.Store.GetAllUsers(r.Context())
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to fetch user roster", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(users)
|
||||
}
|
||||
|
||||
// HandleGetWranglers returns a clean list of IT users for assignment dropdowns
|
||||
func (h *Handler) HandleGetWranglers(w http.ResponseWriter, r *http.Request) {
|
||||
wranglers, err := h.Store.GetWranglers(r.Context())
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to fetch wranglers", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(wranglers)
|
||||
}
|
||||
Reference in New Issue
Block a user