197 lines
5.3 KiB
Go
197 lines
5.3 KiB
Go
package clients
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"mira/backend/internal/auth"
|
|
"mira/backend/internal/users"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
type Routes struct {
|
|
store Store
|
|
}
|
|
|
|
func NewRoutes(store Store) Routes {
|
|
return Routes{store: store}
|
|
}
|
|
|
|
func (r Routes) Register(router *gin.RouterGroup, requireAuth gin.HandlerFunc) {
|
|
router.Use(requireAuth)
|
|
|
|
router.GET("", r.list)
|
|
router.POST("", r.create)
|
|
router.GET("/:clientId", r.get)
|
|
router.PATCH("/:clientId", r.update)
|
|
router.DELETE("/:clientId", r.delete)
|
|
}
|
|
|
|
func (r Routes) list(c *gin.Context) {
|
|
claims, ok := auth.ClaimsFromContext(c)
|
|
if !ok {
|
|
c.JSON(http.StatusUnauthorized, gin.H{"message": "Autenticacao obrigatoria."})
|
|
return
|
|
}
|
|
|
|
var clients []Client
|
|
var err error
|
|
if claims.Role == users.RoleSuperAdmin || claims.Role == users.RoleAgencyUser {
|
|
clients, err = r.store.List(c.Request.Context())
|
|
} else {
|
|
clients, err = r.store.ListForUser(c.Request.Context(), claims.UserID)
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel listar clientes."})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"clients": clients})
|
|
}
|
|
|
|
type createClientRequest struct {
|
|
Name string `json:"name" binding:"required,min=2"`
|
|
}
|
|
|
|
func (r Routes) create(c *gin.Context) {
|
|
claims, ok := auth.ClaimsFromContext(c)
|
|
if !ok || claims.Role != users.RoleSuperAdmin {
|
|
c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."})
|
|
return
|
|
}
|
|
|
|
var input createClientRequest
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Informe um nome de cliente valido."})
|
|
return
|
|
}
|
|
|
|
client, err := r.store.Create(c.Request.Context(), input.Name)
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel criar o cliente."})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusCreated, gin.H{"client": client})
|
|
}
|
|
|
|
func (r Routes) get(c *gin.Context) {
|
|
if !r.canReadClient(c, c.Param("clientId")) {
|
|
c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."})
|
|
return
|
|
}
|
|
|
|
client, err := r.store.FindByID(c.Request.Context(), c.Param("clientId"))
|
|
if errors.Is(err, ErrNotFound) {
|
|
c.JSON(http.StatusNotFound, gin.H{"message": "Cliente nao encontrado."})
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel carregar o cliente."})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"client": client})
|
|
}
|
|
|
|
type updateClientRequest struct {
|
|
Name string `json:"name"`
|
|
Status string `json:"status"`
|
|
WebsiteURL string `json:"website_url"`
|
|
InstagramURL string `json:"instagram_url"`
|
|
FacebookURL string `json:"facebook_url"`
|
|
LinkedinURL string `json:"linkedin_url"`
|
|
Color string `json:"color"`
|
|
Notes string `json:"notes"`
|
|
}
|
|
|
|
func (r Routes) update(c *gin.Context) {
|
|
claims, ok := auth.ClaimsFromContext(c)
|
|
if !ok || claims.Role != users.RoleSuperAdmin {
|
|
c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."})
|
|
return
|
|
}
|
|
|
|
var input updateClientRequest
|
|
if err := c.ShouldBindJSON(&input); err != nil {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Dados invalidos."})
|
|
return
|
|
}
|
|
|
|
color := strings.TrimSpace(input.Color)
|
|
if color != "" && !hexColorPattern.MatchString(color) {
|
|
c.JSON(http.StatusBadRequest, gin.H{"message": "Cor invalida."})
|
|
return
|
|
}
|
|
|
|
client, err := r.store.Update(c.Request.Context(), c.Param("clientId"), input.Name, input.Status, input.WebsiteURL, input.InstagramURL, input.FacebookURL, input.LinkedinURL, color, input.Notes)
|
|
if errors.Is(err, ErrNotFound) {
|
|
c.JSON(http.StatusNotFound, gin.H{"message": "Cliente nao encontrado."})
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel atualizar o cliente."})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"client": client})
|
|
}
|
|
|
|
var hexColorPattern = regexp.MustCompile(`^#[0-9a-fA-F]{6}$`)
|
|
|
|
func (r Routes) archive(c *gin.Context) {
|
|
claims, ok := auth.ClaimsFromContext(c)
|
|
if !ok || claims.Role != users.RoleSuperAdmin {
|
|
c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."})
|
|
return
|
|
}
|
|
|
|
client, err := r.store.Archive(c.Request.Context(), c.Param("clientId"))
|
|
if errors.Is(err, ErrNotFound) {
|
|
c.JSON(http.StatusNotFound, gin.H{"message": "Cliente nao encontrado."})
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel arquivar o cliente."})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"client": client})
|
|
}
|
|
|
|
func (r Routes) delete(c *gin.Context) {
|
|
claims, ok := auth.ClaimsFromContext(c)
|
|
if !ok || claims.Role != users.RoleSuperAdmin {
|
|
c.JSON(http.StatusForbidden, gin.H{"message": "Permissao insuficiente."})
|
|
return
|
|
}
|
|
|
|
err := r.store.Delete(c.Request.Context(), c.Param("clientId"))
|
|
if errors.Is(err, ErrNotFound) {
|
|
c.JSON(http.StatusNotFound, gin.H{"message": "Cliente nao encontrado."})
|
|
return
|
|
}
|
|
if err != nil {
|
|
c.JSON(http.StatusInternalServerError, gin.H{"message": "Nao foi possivel excluir o cliente."})
|
|
return
|
|
}
|
|
|
|
c.JSON(http.StatusOK, gin.H{"message": "Cliente excluido."})
|
|
}
|
|
|
|
func (r Routes) canReadClient(c *gin.Context, clientID string) bool {
|
|
claims, ok := auth.ClaimsFromContext(c)
|
|
if !ok {
|
|
return false
|
|
}
|
|
if claims.Role == users.RoleSuperAdmin || claims.Role == users.RoleAgencyUser {
|
|
return true
|
|
}
|
|
|
|
allowed, err := r.store.UserCanAccess(c.Request.Context(), claims.UserID, clientID)
|
|
return err == nil && allowed
|
|
}
|