Files
gochat/internal/handler/api/v1/profile_handler.go
T

233 lines
7.1 KiB
Go

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
}
accountID := c.GetUint("account_id")
user, err := h.svc.Get(c.Request.Context(), userID, accountID)
if err != nil {
applogger.L().Errorf("Get profile for user %d: %v", userID, err)
handleServiceError(c, err)
return
}
c.JSON(http.StatusOK, 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
}
accountID := c.GetUint("account_id")
user, svcErr := h.svc.Update(c.Request.Context(), userID, accountID, req.Profile)
if svcErr != nil {
applogger.L().Errorf("Update profile for user %d: %v", userID, svcErr)
handleServiceError(c, svcErr)
return
}
c.JSON(http.StatusOK, 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
}
accountID := c.GetUint("account_id")
user, svcErr := h.svc.UpdateAvatar(c.Request.Context(), userID, accountID, req)
if svcErr != nil {
applogger.L().Errorf("Update avatar for user %d: %v", userID, svcErr)
handleServiceError(c, svcErr)
return
}
c.JSON(http.StatusOK, 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
}
user, 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
}
c.JSON(http.StatusOK, user)
}
// 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
}
user, 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
}
c.JSON(http.StatusOK, user)
}
// 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
}
accountID := c.GetUint("account_id")
user, svcErr := h.svc.ResetAccessToken(c.Request.Context(), userID, accountID)
if svcErr != nil {
applogger.L().Errorf("ResetAccessToken for user %d: %v", userID, svcErr)
handleServiceError(c, svcErr)
return
}
c.JSON(http.StatusOK, 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
}
accountID := c.GetUint("account_id")
user, err := h.svc.DeleteAvatar(c.Request.Context(), userID, accountID)
if err != nil {
applogger.L().Errorf("DeleteAvatar for user %d: %v", userID, err)
handleServiceError(c, err)
return
}
c.JSON(http.StatusOK, user)
}