package handler import ( "github.com/gofiber/fiber/v2" "github.com/gosec/gsc-ops-api/internal/middleware" "github.com/gosec/gsc-ops-api/internal/service" "github.com/gosec/gsc-ops-api/pkg/types" ) // LDAPGroupHandler handles LDAP group endpoints type LDAPGroupHandler struct { svc *service.LDAPService } // NewLDAPGroupHandler creates a new LDAP group handler func NewLDAPGroupHandler(svc *service.LDAPService) *LDAPGroupHandler { return &LDAPGroupHandler{svc: svc} } // List handles GET /api/v1/ldap/groups func (h *LDAPGroupHandler) List(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) search := c.Query("search") limit := c.QueryInt("limit", 50) if limit > 500 { limit = 500 } groups, err := h.svc.ListGroups(search, limit) if err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewPagedResponse(groups, int64(len(groups)), limit, 0, reqID)) } // Get handles GET /api/v1/ldap/groups/:cn func (h *LDAPGroupHandler) Get(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) cn := c.Params("cn") group, err := h.svc.GetGroup(cn) if err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } if group == nil { apiErr := types.NewNotFound("Group not found: " + cn) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewDataResponse(group, reqID)) } // Create handles POST /api/v1/ldap/groups func (h *LDAPGroupHandler) Create(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) var req types.LDAPGroupCreate if err := c.BodyParser(&req); err != nil { apiErr := types.NewBadRequest("Invalid request body: " + err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } if req.CN == "" { apiErr := types.NewValidation("cn is required") return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } group, err := h.svc.CreateGroup(&req) if err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.Status(fiber.StatusCreated).JSON(types.NewDataResponse(group, reqID)) } // Update handles PUT /api/v1/ldap/groups/:cn func (h *LDAPGroupHandler) Update(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) cn := c.Params("cn") var req types.LDAPGroupUpdate if err := c.BodyParser(&req); err != nil { apiErr := types.NewBadRequest("Invalid request body: " + err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } group, err := h.svc.UpdateGroup(cn, &req) if err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewDataResponse(group, reqID)) } // Delete handles DELETE /api/v1/ldap/groups/:cn func (h *LDAPGroupHandler) Delete(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) cn := c.Params("cn") if err := h.svc.DeleteGroup(cn); err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewDataResponse(fiber.Map{"cn": cn, "deleted": true}, reqID)) } // ListMembers handles GET /api/v1/ldap/groups/:cn/members func (h *LDAPGroupHandler) ListMembers(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) cn := c.Params("cn") members, err := h.svc.GetGroupMembers(cn) if err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } if members == nil { apiErr := types.NewNotFound("Group not found: " + cn) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewDataResponse(members, reqID)) } // AddMembers handles POST /api/v1/ldap/groups/:cn/members func (h *LDAPGroupHandler) AddMembers(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) cn := c.Params("cn") var req types.LDAPGroupMemberAdd if err := c.BodyParser(&req); err != nil { apiErr := types.NewBadRequest("Invalid request body: " + err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } if len(req.Members) == 0 { apiErr := types.NewValidation("members array is required and must not be empty") return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } if err := h.svc.AddGroupMembers(cn, req.Members); err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewDataResponse(fiber.Map{"cn": cn, "added": req.Members}, reqID)) } // RemoveMember handles DELETE /api/v1/ldap/groups/:cn/members/:uid func (h *LDAPGroupHandler) RemoveMember(c *fiber.Ctx) error { reqID := middleware.GetRequestID(c) cn := c.Params("cn") uid := c.Params("uid") if err := h.svc.RemoveGroupMember(cn, uid); err != nil { apiErr := types.NewInternal(err.Error()) return c.Status(apiErr.Status).JSON(types.NewErrorResponse(apiErr, reqID)) } return c.JSON(types.NewDataResponse(fiber.Map{"cn": cn, "removed": uid}, reqID)) }