package handlers import ( "encoding/json" "net/http" "strings" "github.com/imc-vibe/backend/internal/db" ) type DomainHandler struct { db *db.DB } func NewDomainHandler(database *db.DB) *DomainHandler { return &DomainHandler{db: database} } type CreateDomainRequest struct { Name string `json:"name"` } type DomainPermissions struct { DomainID uint `json:"domainId"` DomainName string `json:"domainName"` UserID uint `json:"userId"` CanManage bool `json:"canManage"` } func (h *DomainHandler) List(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } authCtx := GetAuthContext(r) if authCtx == nil { Error(w, http.StatusUnauthorized, "authentication required") return } isAdmin := authCtx.IsAdmin() domains, err := h.db.GetUserAccessibleDomains(authCtx.UserID, isAdmin) if err != nil { Error(w, http.StatusInternalServerError, "database error") return } domainStats := make([]db.DomainStats, len(domains)) for i, d := range domains { var userCount, aliasCount int64 h.db.Model(&db.User{}).Where("domain_id = ?", d.ID).Count(&userCount) h.db.Model(&db.Alias{}).Where("domain_id = ?", d.ID).Count(&aliasCount) domainStats[i] = db.DomainStats{ ID: d.ID, Name: d.Name, UserCount: userCount, AliasCount: aliasCount, } } Success(w, domainStats) } func (h *DomainHandler) Get(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } domainName := extractDomainName(r.URL.Path) if domainName == "" { Error(w, http.StatusBadRequest, "domain name required") return } domain, err := h.db.GetDomainByName(domainName) if err != nil { Error(w, http.StatusNotFound, "domain not found") return } authCtx := GetAuthContext(r) if authCtx == nil { Error(w, http.StatusUnauthorized, "authentication required") return } canAccess, _ := h.db.CanAccessDomain(authCtx.UserID, domainName, authCtx.IsAdmin()) if !canAccess { Error(w, http.StatusForbidden, "access denied") return } Success(w, domain) } func (h *DomainHandler) Create(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } authCtx := GetAuthContext(r) if authCtx == nil || !authCtx.IsAdmin() { Error(w, http.StatusForbidden, "admin access required") return } var req CreateDomainRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { Error(w, http.StatusBadRequest, "invalid request body") return } if req.Name == "" { Error(w, http.StatusBadRequest, "domain name required") return } existing, err := h.db.GetDomainByName(req.Name) if err == nil && existing != nil { Error(w, http.StatusConflict, "domain already exists") return } domain, err := h.db.CreateDomain(req.Name) if err != nil { Error(w, http.StatusInternalServerError, "failed to create domain") return } Created(w, domain) } func (h *DomainHandler) Delete(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } authCtx := GetAuthContext(r) if authCtx == nil || !authCtx.IsAdmin() { Error(w, http.StatusForbidden, "admin access required") return } domainName := extractDomainName(r.URL.Path) if domainName == "" { Error(w, http.StatusBadRequest, "domain name required") return } domain, err := h.db.GetDomainByName(domainName) if err != nil { Error(w, http.StatusNotFound, "domain not found") return } if err := h.db.DeleteDomain(domain.ID); err != nil { Error(w, http.StatusInternalServerError, "failed to delete domain") return } NoContent(w) } func (h *DomainHandler) GetPermissions(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } authCtx := GetAuthContext(r) if authCtx == nil { Error(w, http.StatusUnauthorized, "authentication required") return } if !authCtx.IsAdmin() { Error(w, http.StatusForbidden, "admin access required") return } domainName := extractDomainName(r.URL.Path) if domainName == "" { Error(w, http.StatusBadRequest, "domain name required") return } domain, err := h.db.GetDomainByName(domainName) if err != nil { Error(w, http.StatusNotFound, "domain not found") return } users, err := h.db.GetUsersForDomain(domain.ID) if err != nil { Error(w, http.StatusInternalServerError, "database error") return } permissions := make([]DomainPermissions, len(users)) for i, u := range users { permissions[i] = DomainPermissions{ DomainID: domain.ID, DomainName: domain.Name, UserID: u.ID, CanManage: true, } } Success(w, permissions) } func (h *DomainHandler) AddPermission(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } authCtx := GetAuthContext(r) if authCtx == nil || !authCtx.IsAdmin() { Error(w, http.StatusForbidden, "admin access required") return } domainName := extractDomainName(r.URL.Path) if domainName == "" { Error(w, http.StatusBadRequest, "domain name required") return } domain, err := h.db.GetDomainByName(domainName) if err != nil { Error(w, http.StatusNotFound, "domain not found") return } var req struct { UserID uint `json:"userId"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { Error(w, http.StatusBadRequest, "invalid request") return } if err := h.db.AddUserToDomain(req.UserID, domain.ID); err != nil { Error(w, http.StatusInternalServerError, "failed to add user to domain") return } Success(w, map[string]string{"message": "user added to domain"}) } func (h *DomainHandler) RemovePermission(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodDelete { Error(w, http.StatusMethodNotAllowed, "method not allowed") return } authCtx := GetAuthContext(r) if authCtx == nil || !authCtx.IsAdmin() { Error(w, http.StatusForbidden, "admin access required") return } domainName := extractDomainName(r.URL.Path) if domainName == "" { Error(w, http.StatusBadRequest, "domain name required") return } domain, err := h.db.GetDomainByName(domainName) if err != nil { Error(w, http.StatusNotFound, "domain not found") return } userID := extractIDFromPath(r.URL.Path) if err := h.db.RemoveUserFromDomain(userID, domain.ID); err != nil { Error(w, http.StatusInternalServerError, "failed to remove user from domain") return } NoContent(w) } func extractDomainName(path string) string { parts := strings.Split(strings.TrimPrefix(path, "/api/"), "/") if len(parts) >= 2 && parts[1] != "" { return parts[1] } return "" } func extractIDFromPath(path string) uint { parts := strings.Split(path, "/") for i := len(parts) - 1; i >= 0; i-- { if idStr := parts[i]; idStr != "" { var id uint for _, c := range idStr { if c >= '0' && c <= '9' { id = id*10 + uint(c-'0') } else { break } } if id > 0 { return id } } } return 0 }