package users import ( "net/http" "strings" "time" "github.com/gin-gonic/gin" ) type Routes struct { store Store appPublicURL string } func NewRoutes(store Store, appPublicURL string) Routes { return Routes{ store: store, appPublicURL: strings.TrimRight(appPublicURL, "/"), } } func (r Routes) Register(router *gin.RouterGroup, requireAuth gin.HandlerFunc) { router.Use(requireAuth) router.GET("", r.list) router.GET("/invitations", r.listInvitations) router.POST("/invitations", r.createInvitation) } func (r Routes) list(c *gin.Context) { if c.GetString("auth_role") != RoleSuperAdmin { c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."}) return } users, err := r.store.List(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel listar usuarios."}) return } c.JSON(http.StatusOK, gin.H{"users": users}) } func (r Routes) listInvitations(c *gin.Context) { if c.GetString("auth_role") != RoleSuperAdmin { c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."}) return } invitations, err := r.store.ListInvitations(c.Request.Context()) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel listar convites."}) return } c.JSON(http.StatusOK, gin.H{"invitations": invitations}) } type createInvitationRequest struct { Email string `json:"email" binding:"required,email"` Role string `json:"role" binding:"required"` ClientID string `json:"client_id"` } func (r Routes) createInvitation(c *gin.Context) { if c.GetString("auth_role") != RoleSuperAdmin { c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."}) return } var input createInvitationRequest if err := c.ShouldBindJSON(&input); err != nil { c.JSON(http.StatusBadRequest, gin.H{"message": "Informe os dados do convite."}) return } role := strings.TrimSpace(input.Role) if role != RoleAgencyUser && role != RoleClientViewer { c.JSON(http.StatusBadRequest, gin.H{"message": "Perfil invalido para convite."}) return } if role == RoleClientViewer && strings.TrimSpace(input.ClientID) == "" { c.JSON(http.StatusBadRequest, gin.H{"message": "Convites de cliente precisam de um cliente vinculado."}) return } token, tokenHash, err := NewInvitationToken() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel gerar o convite."}) return } invitation, err := r.store.CreateInvitation(c.Request.Context(), CreateInvitationInput{ Email: strings.TrimSpace(input.Email), Role: role, ClientID: strings.TrimSpace(input.ClientID), TokenHash: tokenHash, ExpiresAt: time.Now().Add(7 * 24 * time.Hour), CreatedBy: c.GetString("auth_user_id"), }) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel criar o convite."}) return } invitation.InvitationURL = r.invitationURL(token) c.JSON(http.StatusCreated, gin.H{"invitation": invitation}) } func (r Routes) invitationURL(token string) string { if r.appPublicURL == "" { return "/accept-invitation?token=" + token } return r.appPublicURL + "/accept-invitation?token=" + token }