initial commit

This commit is contained in:
m.zare
2026-04-10 18:25:21 +03:30
commit 77ca6c34a3
263 changed files with 34470 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
package backoffice
import (
"context"
"github.com/gin-gonic/gin"
"github.com/rs/zerolog"
"go.uber.org/fx"
"base/config"
appProfileRole "base/internal/application/profilerole"
"base/internal/server/middleware"
)
type Controller struct {
logger zerolog.Logger
middleware middleware.Middleware
config *config.AppConfig
e *gin.Engine
profileRoleService appProfileRole.Service
}
type Param struct {
Logger zerolog.Logger
Engine *gin.Engine
Middleware middleware.Middleware
Config *config.AppConfig
ProfileRoleService appProfileRole.Service
fx.In
}
func New(lc fx.Lifecycle, param Param) *Controller {
c := &Controller{
logger: param.Logger,
middleware: param.Middleware,
config: param.Config,
e: param.Engine,
profileRoleService: param.ProfileRoleService,
}
lc.Append(
fx.Hook{
OnStart: func(ctx context.Context) error {
c.SetupRouter()
return nil
},
OnStop: func(ctx context.Context) error {
return nil
},
},
)
return c
}
// getMaxFileSize returns the maximum file size in bytes from configuration
func (ctl *Controller) getMaxFileSize() int64 {
return ctl.config.Server.GetMaxFileSizeBytes()
}
func (ctl *Controller) SetupRouter() {
router := ctl.e.Group("/api/v1")
ctl.registerRoutes(router)
}
func (ctl *Controller) registerRoutes(router *gin.RouterGroup) {
backofficeRouter := router.Group("/backoffice")
profileRoleRouter := backofficeRouter.Group("/profile-roles")
profileRoleRouter.GET("", ctl.ListProfileRoles)
profileRoleRouter.GET("/:id", ctl.GetProfileRole)
protected := profileRoleRouter.Use(ctl.middleware.AuthShield())
protected.POST("", ctl.CreateProfileRole)
protected.PUT("/:id", ctl.UpdateProfileRole)
protected.DELETE("/:id", ctl.DeleteProfileRole)
}

View File

@@ -0,0 +1,7 @@
package backoffice
var HttpRoutePermissionMap = map[string]string{}
var GrpcRoutePermissionMap = map[string]string{}
var ExcludedGrpcRoutePermissionMap = map[string]string{}

View File

@@ -0,0 +1,216 @@
package backoffice
import (
"errors"
"net/http"
"github.com/gin-gonic/gin"
"github.com/google/uuid"
appProfileRole "base/internal/application/profilerole"
"base/internal/dto"
)
// ListProfileRoles returns the list of profile roles.
// @Summary list profile roles
// @Description returns all profile roles (id, title, status)
// @Tags BackOffice
// @Accept json
// @Produce json
// @Success 200 {array} dto.ProfileRole "list of profile roles"
// @Failure 500 {object} dto.ErrorResponse "internal server error"
// @Router /api/v1/backoffice/profile-roles [get]
func (ctl *Controller) ListProfileRoles(c *gin.Context) {
lg := ctl.logger.With().
Str("module", "backoffice").
Str("router", "profile-roles").
Str("handler", "ListProfileRoles").
Logger()
roles, err := ctl.profileRoleService.List(c.Request.Context())
if err != nil {
lg.Error().Err(err).Msg("failed to list profile roles")
r := dto.InternalServerError()
c.JSON(r.Status, r)
return
}
c.JSON(http.StatusOK, roles)
}
// CreateProfileRole creates a new profile role.
// @Summary create profile role
// @Description create a new profile role
// @Tags BackOffice
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param request body dto.CreateProfileRoleRequest true "create request"
// @Success 201 {object} dto.ProfileRole "created profile role"
// @Failure 400 {object} dto.ErrorResponse "invalid request"
// @Failure 401 {object} dto.ErrorResponse "unauthorized"
// @Failure 500 {object} dto.ErrorResponse "internal server error"
// @Router /api/v1/backoffice/profile-roles [post]
func (ctl *Controller) CreateProfileRole(c *gin.Context) {
lg := ctl.logger.With().
Str("module", "backoffice").
Str("router", "profile-roles").
Str("handler", "CreateProfileRole").
Logger()
var req dto.CreateProfileRoleRequest
if !ctl.validateRequest(c, &req) {
return
}
role, err := ctl.profileRoleService.Create(c.Request.Context(), req)
if err != nil {
lg.Error().Err(err).Msg("failed to create profile role")
r := dto.InternalServerError()
c.JSON(r.Status, r)
return
}
r := dto.Created(role)
c.JSON(r.Status, r)
}
// GetProfileRole returns a profile role by ID.
// @Summary get profile role by ID
// @Description get profile role by ID
// @Tags BackOffice
// @Accept json
// @Produce json
// @Param id path string true "profile role ID"
// @Success 200 {object} dto.ProfileRole "profile role"
// @Failure 400 {object} dto.ErrorResponse "invalid request"
// @Failure 404 {object} dto.ErrorResponse "not found"
// @Failure 500 {object} dto.ErrorResponse "internal server error"
// @Router /api/v1/backoffice/profile-roles/{id} [get]
func (ctl *Controller) GetProfileRole(c *gin.Context) {
lg := ctl.logger.With().
Str("module", "backoffice").
Str("router", "profile-roles").
Str("handler", "GetProfileRole").
Logger()
var req dto.GetProfileRoleRequest
if !ctl.validateRequest(c, &req) {
return
}
id, err := uuid.Parse(req.ID)
if err != nil {
r := dto.BadRequest().WithMessage("invalid profile role ID")
c.JSON(r.Status, r)
return
}
role, err := ctl.profileRoleService.GetByID(c.Request.Context(), id)
if err != nil {
if errors.Is(err, appProfileRole.ErrNotFound) {
r := dto.NotFound().WithMessage("profile role not found")
c.JSON(r.Status, r)
return
}
lg.Error().Err(err).Msg("failed to get profile role")
r := dto.InternalServerError()
c.JSON(r.Status, r)
return
}
r := dto.OK().WithData(role)
c.JSON(r.Status, r)
}
// UpdateProfileRole updates a profile role.
// @Summary update profile role
// @Description update an existing profile role
// @Tags BackOffice
// @Accept json
// @Produce json
// @Security BearerAuth
// @Param id path string true "profile role ID"
// @Param request body dto.UpdateProfileRoleRequest true "update request"
// @Success 200 {object} dto.ProfileRole "updated profile role"
// @Failure 400 {object} dto.ErrorResponse "invalid request"
// @Failure 401 {object} dto.ErrorResponse "unauthorized"
// @Failure 404 {object} dto.ErrorResponse "not found"
// @Failure 500 {object} dto.ErrorResponse "internal server error"
// @Router /api/v1/backoffice/profile-roles/{id} [put]
func (ctl *Controller) UpdateProfileRole(c *gin.Context) {
lg := ctl.logger.With().
Str("module", "backoffice").
Str("router", "profile-roles").
Str("handler", "UpdateProfileRole").
Logger()
var req dto.UpdateProfileRoleRequest
if !ctl.validateRequest(c, &req) {
return
}
role, err := ctl.profileRoleService.Update(c.Request.Context(), req)
if err != nil {
if errors.Is(err, appProfileRole.ErrNotFound) {
r := dto.NotFound().WithMessage("profile role not found")
c.JSON(r.Status, r)
return
}
lg.Error().Err(err).Msg("failed to update profile role")
r := dto.InternalServerError()
c.JSON(r.Status, r)
return
}
r := dto.OK().WithData(role)
c.JSON(r.Status, r)
}
// DeleteProfileRole deletes a profile role.
// @Summary delete profile role
// @Description delete a profile role
// @Tags BackOffice
// @Produce json
// @Security BearerAuth
// @Param id path string true "profile role ID"
// @Success 200 {object} dto.Response "success"
// @Failure 400 {object} dto.ErrorResponse "invalid request"
// @Failure 401 {object} dto.ErrorResponse "unauthorized"
// @Failure 404 {object} dto.ErrorResponse "not found"
// @Failure 500 {object} dto.ErrorResponse "internal server error"
// @Router /api/v1/backoffice/profile-roles/{id} [delete]
func (ctl *Controller) DeleteProfileRole(c *gin.Context) {
lg := ctl.logger.With().
Str("module", "backoffice").
Str("router", "profile-roles").
Str("handler", "DeleteProfileRole").
Logger()
var req dto.DeleteProfileRoleRequest
if !ctl.validateRequest(c, &req) {
return
}
id, err := uuid.Parse(req.ID)
if err != nil {
r := dto.BadRequest().WithMessage("invalid profile role ID")
c.JSON(r.Status, r)
return
}
if err := ctl.profileRoleService.Delete(c.Request.Context(), id); err != nil {
if errors.Is(err, appProfileRole.ErrNotFound) {
r := dto.NotFound().WithMessage("profile role not found")
c.JSON(r.Status, r)
return
}
lg.Error().Err(err).Msg("failed to delete profile role")
r := dto.InternalServerError()
c.JSON(r.Status, r)
return
}
r := dto.OK().WithMessage("profile role deleted successfully")
c.JSON(r.Status, r)
}

View File

@@ -0,0 +1,50 @@
package backoffice
import (
"net/http"
"strings"
"github.com/gin-gonic/gin"
"base/internal/dto"
"base/pkg/helper"
"base/pkg/validation"
)
func shouldBindJSON(c *gin.Context) bool {
switch c.Request.Method {
case http.MethodPost, http.MethodPut, http.MethodPatch:
default:
return false
}
contentType := c.ContentType()
return contentType == "application/json" || strings.HasSuffix(contentType, "+json")
}
func (ctl *Controller) validateRequest(c *gin.Context, request dto.DTO) bool {
if err := c.ShouldBindUri(request); err != nil {
ctl.logger.Error().Err(err).Msg("RequestBindErr")
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request path parameters"})
return false
}
if err := c.ShouldBindQuery(request); err != nil {
ctl.logger.Error().Err(err).Msg("RequestBindErr")
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request query parameters"})
return false
}
if shouldBindJSON(c) {
if err := c.ShouldBindJSON(request); err != nil {
ctl.logger.Error().Err(err).Msg("RequestBindErr")
c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request body"})
return false
}
}
validator := validation.NewGenericValidator()
validator.Validate(helper.StructToMap(request), request.Schema())
if validator.HasErrors() {
ctl.logger.Error().Any("request", request).Any("error", validator.GetErrors()).Msg("validatorHasErrors")
c.JSON(http.StatusBadRequest, gin.H{"errors": validator.GetErrors()})
return false
}
return true
}