355 lines
10 KiB
Go
355 lines
10 KiB
Go
package handlers
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
|
|
"github.com/gorilla/mux"
|
|
"github.com/noteapp/backend/internal/interfaces/middleware"
|
|
"go.mongodb.org/mongo-driver/v2/bson"
|
|
|
|
"github.com/noteapp/backend/internal/application/dto"
|
|
"github.com/noteapp/backend/internal/application/services"
|
|
)
|
|
|
|
// AdminHandler handles admin-level HTTP requests
|
|
type AdminHandler struct {
|
|
adminService *services.AdminService
|
|
}
|
|
|
|
// NewAdminHandler creates a new AdminHandler
|
|
func NewAdminHandler(adminService *services.AdminService) *AdminHandler {
|
|
return &AdminHandler{adminService: adminService}
|
|
}
|
|
|
|
// ListUsers handles GET /admin/users
|
|
func (h *AdminHandler) ListUsers(w http.ResponseWriter, r *http.Request) {
|
|
users, err := h.adminService.ListUsers(r.Context())
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"users": users})
|
|
}
|
|
|
|
// DeleteUser handles DELETE /admin/users/{userId}
|
|
func (h *AdminHandler) DeleteUser(w http.ResponseWriter, r *http.Request) {
|
|
targetUserID, err := bson.ObjectIDFromHex(mux.Vars(r)["userId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid user id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
currentUserIDHex, err := middleware.GetUserIDFromContext(r.Context())
|
|
if err != nil {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
currentUserID, err := bson.ObjectIDFromHex(currentUserIDHex)
|
|
if err != nil {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
if err := h.adminService.DeleteUser(r.Context(), currentUserID, targetUserID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// UpdateUserGroups handles PUT /admin/users/{userId}/groups
|
|
func (h *AdminHandler) UpdateUserGroups(w http.ResponseWriter, r *http.Request) {
|
|
userID, err := bson.ObjectIDFromHex(mux.Vars(r)["userId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid user id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.UpdateUserGroupsRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
groupIDs := make([]bson.ObjectID, 0, len(req.GroupIDs))
|
|
for _, groupID := range req.GroupIDs {
|
|
parsed, err := bson.ObjectIDFromHex(groupID)
|
|
if err != nil {
|
|
http.Error(w, "invalid group id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
groupIDs = append(groupIDs, parsed)
|
|
}
|
|
|
|
user, err := h.adminService.UpdateUserGroups(r.Context(), userID, groupIDs)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(user)
|
|
}
|
|
|
|
// DeleteGroup handles DELETE /admin/groups/{groupId}
|
|
func (h *AdminHandler) DeleteGroup(w http.ResponseWriter, r *http.Request) {
|
|
groupID, err := bson.ObjectIDFromHex(mux.Vars(r)["groupId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid group id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.adminService.DeleteGroup(r.Context(), groupID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// ListGroups handles GET /admin/groups
|
|
func (h *AdminHandler) ListGroups(w http.ResponseWriter, r *http.Request) {
|
|
groups, err := h.adminService.ListGroups(r.Context())
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"groups": groups})
|
|
}
|
|
|
|
// CreateGroup handles POST /admin/groups
|
|
func (h *AdminHandler) CreateGroup(w http.ResponseWriter, r *http.Request) {
|
|
var req dto.CreatePermissionGroupRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
group, err := h.adminService.CreateGroup(r.Context(), &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(group)
|
|
}
|
|
|
|
// UpdateGroup handles PUT /admin/groups/{groupId}
|
|
func (h *AdminHandler) UpdateGroup(w http.ResponseWriter, r *http.Request) {
|
|
groupID, err := bson.ObjectIDFromHex(mux.Vars(r)["groupId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid group id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.UpdatePermissionGroupRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
group, err := h.adminService.UpdateGroup(r.Context(), groupID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(group)
|
|
}
|
|
|
|
// ListAllSpaces handles GET /admin/spaces
|
|
func (h *AdminHandler) ListAllSpaces(w http.ResponseWriter, r *http.Request) {
|
|
spaces, err := h.adminService.ListAllSpaces(r.Context())
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"spaces": spaces})
|
|
}
|
|
|
|
// UpdateSpace handles PUT /admin/spaces/{spaceId}
|
|
func (h *AdminHandler) UpdateSpace(w http.ResponseWriter, r *http.Request) {
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid space id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.CreateSpaceRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
space, err := h.adminService.UpdateSpace(r.Context(), spaceID, &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(space)
|
|
}
|
|
|
|
// SetSpaceVisibility handles PUT /admin/spaces/{spaceId}/visibility
|
|
func (h *AdminHandler) SetSpaceVisibility(w http.ResponseWriter, r *http.Request) {
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid space id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
var req struct {
|
|
IsPublic bool `json:"is_public"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
if err := h.adminService.SetSpaceVisibility(r.Context(), spaceID, req.IsPublic); err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]string{"message": "visibility updated"})
|
|
}
|
|
|
|
// AddSpaceMember handles POST /admin/spaces/{spaceId}/members
|
|
func (h *AdminHandler) AddSpaceMember(w http.ResponseWriter, r *http.Request) {
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid space id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var req dto.AddSpaceMemberRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
userID, err := bson.ObjectIDFromHex(req.UserID)
|
|
if err != nil {
|
|
http.Error(w, "invalid user id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.adminService.AddSpaceMember(r.Context(), spaceID, userID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(map[string]string{"message": "member added"})
|
|
}
|
|
|
|
// ListSpaceMembers handles GET /admin/spaces/{spaceId}/members
|
|
func (h *AdminHandler) ListSpaceMembers(w http.ResponseWriter, r *http.Request) {
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid space id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
members, err := h.adminService.ListSpaceMembers(r.Context(), spaceID)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"members": members})
|
|
}
|
|
|
|
// RemoveSpaceMember handles DELETE /admin/spaces/{spaceId}/members/{userId}
|
|
func (h *AdminHandler) RemoveSpaceMember(w http.ResponseWriter, r *http.Request) {
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid space id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
userID, err := bson.ObjectIDFromHex(mux.Vars(r)["userId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid user id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.adminService.RemoveSpaceMember(r.Context(), spaceID, userID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// DeleteSpace handles DELETE /admin/spaces/{spaceId}
|
|
func (h *AdminHandler) DeleteSpace(w http.ResponseWriter, r *http.Request) {
|
|
spaceID, err := bson.ObjectIDFromHex(mux.Vars(r)["spaceId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid space id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.adminService.DeleteSpace(r.Context(), spaceID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|
|
|
|
// GetFeatureFlags handles GET /admin/feature-flags
|
|
func (h *AdminHandler) GetFeatureFlags(w http.ResponseWriter, r *http.Request) {
|
|
flags, err := h.adminService.GetFeatureFlags(r.Context())
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(flags)
|
|
}
|
|
|
|
// UpdateFeatureFlags handles PUT /admin/feature-flags
|
|
func (h *AdminHandler) UpdateFeatureFlags(w http.ResponseWriter, r *http.Request) {
|
|
var req dto.UpdateFeatureFlagsRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
|
http.Error(w, "invalid request body", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
flags, err := h.adminService.UpdateFeatureFlags(r.Context(), &req)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
json.NewEncoder(w).Encode(flags)
|
|
}
|
|
|
|
// DeleteProvider handles DELETE /admin/auth/providers/{providerId}
|
|
func (h *AdminHandler) DeleteProvider(w http.ResponseWriter, r *http.Request) {
|
|
providerID, err := bson.ObjectIDFromHex(mux.Vars(r)["providerId"])
|
|
if err != nil {
|
|
http.Error(w, "invalid provider id", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if err := h.adminService.DeleteProvider(r.Context(), providerID); err != nil {
|
|
http.Error(w, err.Error(), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|