package v1 import ( "net/http" "github.com/gin-gonic/gin" "github.com/gochat/gochat/internal/service" applogger "github.com/gochat/gochat/pkg/logger" "github.com/gochat/gochat/pkg/response" ) // ProfileHandler handles Profile get/update + avatar + availability + auto_offline + set_active_account + resend_confirmation + reset_access_token. // Reference: Chatwoot app/controllers/api/v1/profile_controller.rb type ProfileHandler struct { svc *service.ProfileService } // NewProfileHandler creates a new Profile handler. func NewProfileHandler(svc *service.ProfileService) *ProfileHandler { return &ProfileHandler{svc: svc} } // Get returns the current user's profile. // GET /api/v1/profile func (h *ProfileHandler) Get(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } user, err := h.svc.Get(c.Request.Context(), userID) if err != nil { applogger.L().Errorf("Get profile for user %d: %v", userID, err) handleServiceError(c, err) return } response.OK(c, user) } // Update updates the current user's profile. // PUT /api/v1/profile func (h *ProfileHandler) Update(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } var req service.ProfileUpdatePayload if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error()) return } user, svcErr := h.svc.Update(c.Request.Context(), userID, req.Profile) if svcErr != nil { applogger.L().Errorf("Update profile for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, user) } // UpdateAvatar updates the current user's avatar. // PUT /api/v1/profile/avatar func (h *ProfileHandler) UpdateAvatar(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } var req service.UpdateAvatarRequest if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error()) return } user, svcErr := h.svc.UpdateAvatar(c.Request.Context(), userID, req) if svcErr != nil { applogger.L().Errorf("Update avatar for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, user) } // SetAvailability updates the user's availability status for a specific account. // POST /api/v1/profile/availability // Reference: Chatwoot profiles_controller#availability func (h *ProfileHandler) SetAvailability(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } var req service.ProfileAvailabilityPayload if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error()) return } au, svcErr := h.svc.SetAvailability(c.Request.Context(), userID, req.Profile) if svcErr != nil { applogger.L().Errorf("SetAvailability for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, au) } // SetAutoOffline updates the user's auto_offline setting for a specific account. // POST /api/v1/profile/auto_offline // Reference: Chatwoot profiles_controller#auto_offline func (h *ProfileHandler) SetAutoOffline(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } var req service.ProfileAutoOfflinePayload if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error()) return } au, svcErr := h.svc.SetAutoOffline(c.Request.Context(), userID, req.Profile) if svcErr != nil { applogger.L().Errorf("SetAutoOffline for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, au) } // SetActiveAccount sets the user's currently active account. // PUT /api/v1/profile/set_active_account // Reference: Chatwoot profiles_controller#set_active_account func (h *ProfileHandler) SetActiveAccount(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } var req service.ProfileSetActiveAccountPayload if err := c.ShouldBindJSON(&req); err != nil { response.AbortWithStatusError(c, http.StatusBadRequest, response.ErrBadRequest, err.Error()) return } svcErr := h.svc.SetActiveAccount(c.Request.Context(), userID, req.Profile) if svcErr != nil { applogger.L().Errorf("SetActiveAccount for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.NoContent(c) } // ResendConfirmation sends a confirmation email to the user if not yet confirmed. // POST /api/v1/profile/resend_confirmation // Reference: Chatwoot auth/resend_confirmations_controller#create func (h *ProfileHandler) ResendConfirmation(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } svcErr := h.svc.ResendConfirmation(c.Request.Context(), userID) if svcErr != nil { applogger.L().Errorf("ResendConfirmation for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.NoContent(c) } // ResetAccessToken regenerates the user's access token, invalidating current JWTs. // POST /api/v1/profile/reset_access_token // Reference: Chatwoot profiles_controller#reset_access_token func (h *ProfileHandler) ResetAccessToken(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } user, svcErr := h.svc.ResetAccessToken(c.Request.Context(), userID) if svcErr != nil { applogger.L().Errorf("ResetAccessToken for user %d: %v", userID, svcErr) handleServiceError(c, svcErr) return } response.OK(c, user) } // DeleteAvatar removes the user's avatar. // DELETE /api/v1/profile/avatar // Reference: Chatwoot ProfilesController#destroy_avatar func (h *ProfileHandler) DeleteAvatar(c *gin.Context) { userID := getUserID(c) if userID == 0 { response.AbortWithStatusError(c, http.StatusUnauthorized, response.ErrUnauthorized, "user not authenticated") return } user, err := h.svc.DeleteAvatar(c.Request.Context(), userID) if err != nil { applogger.L().Errorf("DeleteAvatar for user %d: %v", userID, err) handleServiceError(c, err) return } response.OK(c, user) }