mirror of
https://github.com/veops/oneterm.git
synced 2025-10-05 07:16:57 +08:00
199 lines
6.6 KiB
Go
199 lines
6.6 KiB
Go
package controller
|
|
|
|
import (
|
|
"net/http"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/spf13/cast"
|
|
|
|
"github.com/veops/oneterm/internal/acl"
|
|
"github.com/veops/oneterm/internal/model"
|
|
"github.com/veops/oneterm/internal/service"
|
|
pkgErrors "github.com/veops/oneterm/pkg/errors"
|
|
)
|
|
|
|
var (
|
|
timeTemplateService = service.NewTimeTemplateService()
|
|
)
|
|
|
|
// CreateTimeTemplate godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Param template body model.TimeTemplate true "time template"
|
|
// @Success 200 {object} HttpResponse
|
|
// @Router /time_template [post]
|
|
func (c *Controller) CreateTimeTemplate(ctx *gin.Context) {
|
|
// Time templates require admin permission - no ACL needed
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
if !acl.IsAdmin(currentUser) {
|
|
ctx.AbortWithError(http.StatusForbidden, &pkgErrors.ApiError{Code: pkgErrors.ErrNoPerm, Data: map[string]any{"perm": "admin"}})
|
|
return
|
|
}
|
|
|
|
template := &model.TimeTemplate{}
|
|
doCreate(ctx, false, template, "", timeTemplatePreHooks...)
|
|
}
|
|
|
|
// DeleteTimeTemplate godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Param id path int true "template id"
|
|
// @Success 200 {object} HttpResponse
|
|
// @Router /time_template/:id [delete]
|
|
func (c *Controller) DeleteTimeTemplate(ctx *gin.Context) {
|
|
// Time templates require admin permission - no ACL needed
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
if !acl.IsAdmin(currentUser) {
|
|
ctx.AbortWithError(http.StatusForbidden, &pkgErrors.ApiError{Code: pkgErrors.ErrNoPerm, Data: map[string]any{"perm": "admin"}})
|
|
return
|
|
}
|
|
|
|
doDelete(ctx, false, &model.TimeTemplate{}, "", timeTemplateDeleteChecks...)
|
|
}
|
|
|
|
// UpdateTimeTemplate godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Param id path int true "template id"
|
|
// @Param template body model.TimeTemplate true "time template"
|
|
// @Success 200 {object} HttpResponse
|
|
// @Router /time_template/:id [put]
|
|
func (c *Controller) UpdateTimeTemplate(ctx *gin.Context) {
|
|
// Time templates require admin permission - no ACL needed
|
|
currentUser, _ := acl.GetSessionFromCtx(ctx)
|
|
if !acl.IsAdmin(currentUser) {
|
|
ctx.AbortWithError(http.StatusForbidden, &pkgErrors.ApiError{Code: pkgErrors.ErrNoPerm, Data: map[string]any{"perm": "admin"}})
|
|
return
|
|
}
|
|
|
|
template := &model.TimeTemplate{}
|
|
doUpdate(ctx, false, template, "", timeTemplatePreHooks...)
|
|
}
|
|
|
|
// GetTimeTemplates godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Param page_index query int false "page index"
|
|
// @Param page_size query int false "page size"
|
|
// @Param search query string false "search by name or description"
|
|
// @Param category query string false "template category"
|
|
// @Param active query bool false "filter by active status"
|
|
// @Param info query bool false "info mode"
|
|
// @Success 200 {object} HttpResponse{data=[]model.TimeTemplate}
|
|
// @Router /time_template [get]
|
|
func (c *Controller) GetTimeTemplates(ctx *gin.Context) {
|
|
info := cast.ToBool(ctx.Query("info"))
|
|
|
|
// Build base query using service layer with all filters
|
|
db, err := timeTemplateService.BuildQuery(ctx)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &pkgErrors.ApiError{Code: pkgErrors.ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
doGet(ctx, !info, db, "", timeTemplatePostHooks...)
|
|
}
|
|
|
|
// GetBuiltInTimeTemplates godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Success 200 {object} HttpResponse{data=[]model.TimeTemplate}
|
|
// @Router /time_template/builtin [get]
|
|
func (c *Controller) GetBuiltInTimeTemplates(ctx *gin.Context) {
|
|
templates, err := timeTemplateService.GetBuiltInTemplates(ctx)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &pkgErrors.ApiError{Code: pkgErrors.ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, NewHttpResponseWithData(templates))
|
|
}
|
|
|
|
// CheckTimeAccess godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Param request body CheckTimeAccessRequest true "time access check request"
|
|
// @Success 200 {object} HttpResponse{data=CheckTimeAccessResponse}
|
|
// @Router /time_template/check [post]
|
|
func (c *Controller) CheckTimeAccess(ctx *gin.Context) {
|
|
var req CheckTimeAccessRequest
|
|
if err := ctx.ShouldBindBodyWithJSON(&req); err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, &pkgErrors.ApiError{Code: pkgErrors.ErrInvalidArgument})
|
|
return
|
|
}
|
|
|
|
allowed, err := timeTemplateService.CheckTimeAccess(ctx, req.TemplateID, req.Timezone)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &pkgErrors.ApiError{Code: pkgErrors.ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
response := CheckTimeAccessResponse{
|
|
Allowed: allowed,
|
|
TemplateID: req.TemplateID,
|
|
Timezone: req.Timezone,
|
|
CheckedAt: "now",
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, NewHttpResponseWithData(response))
|
|
}
|
|
|
|
// InitBuiltInTemplates godoc
|
|
//
|
|
// @Tags time_template
|
|
// @Success 200 {object} HttpResponse
|
|
// @Router /time_template/init [post]
|
|
func (c *Controller) InitBuiltInTemplates(ctx *gin.Context) {
|
|
if err := timeTemplateService.InitializeBuiltInTemplates(ctx); err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &pkgErrors.ApiError{Code: pkgErrors.ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
|
|
ctx.JSON(http.StatusOK, NewHttpResponseWithData("Built-in time templates initialized successfully"))
|
|
}
|
|
|
|
// CheckTimeAccessRequest represents a time access check request
|
|
type CheckTimeAccessRequest struct {
|
|
TemplateID int `json:"template_id" binding:"required,gt=0"`
|
|
Timezone string `json:"timezone"`
|
|
}
|
|
|
|
// CheckTimeAccessResponse represents a time access check response
|
|
type CheckTimeAccessResponse struct {
|
|
Allowed bool `json:"allowed"`
|
|
TemplateID int `json:"template_id"`
|
|
Timezone string `json:"timezone"`
|
|
CheckedAt string `json:"checked_at"`
|
|
}
|
|
|
|
// Time template hooks
|
|
var (
|
|
timeTemplatePreHooks = []preHook[*model.TimeTemplate]{
|
|
func(ctx *gin.Context, data *model.TimeTemplate) {
|
|
if err := timeTemplateService.ValidateTimeTemplate(data); err != nil {
|
|
ctx.AbortWithError(http.StatusBadRequest, &pkgErrors.ApiError{Code: pkgErrors.ErrInvalidArgument, Data: map[string]any{"err": err.Error()}})
|
|
}
|
|
},
|
|
}
|
|
|
|
timeTemplatePostHooks = []postHook[*model.TimeTemplate]{
|
|
func(ctx *gin.Context, data []*model.TimeTemplate) {
|
|
// Add any post-processing logic here
|
|
},
|
|
}
|
|
|
|
timeTemplateDeleteChecks = []deleteCheck{
|
|
func(ctx *gin.Context, id int) {
|
|
// Check if template is built-in
|
|
template, err := timeTemplateService.GetTimeTemplate(ctx, id)
|
|
if err != nil {
|
|
ctx.AbortWithError(http.StatusInternalServerError, &pkgErrors.ApiError{Code: pkgErrors.ErrInternal, Data: map[string]any{"err": err}})
|
|
return
|
|
}
|
|
if template != nil && template.IsBuiltIn {
|
|
ctx.AbortWithError(http.StatusBadRequest, &pkgErrors.ApiError{Code: pkgErrors.ErrInvalidArgument, Data: map[string]any{"err": "cannot delete built-in time template"}})
|
|
}
|
|
},
|
|
}
|
|
)
|