diff --git a/api/docs.go b/api/docs.go index 9334f0ab..f43862d9 100644 --- a/api/docs.go +++ b/api/docs.go @@ -491,6 +491,22 @@ const docTemplate = `{ "responses": {} } }, + "/configs/captcha": { + "get": { + "description": "Captcha 配置查询", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Config" + ], + "summary": "Captcha 配置查询", + "responses": {} + } + }, "/games/": { "get": { "security": [ @@ -2408,6 +2424,10 @@ const docTemplate = `{ "description": "The user's password. Crypt.", "type": "string" }, + "remote_ip": { + "description": "The user's remote ip.", + "type": "string" + }, "teams": { "description": "The user's teams.", "type": "array", diff --git a/api/swagger.json b/api/swagger.json index dd976859..fc0e3f7e 100644 --- a/api/swagger.json +++ b/api/swagger.json @@ -482,6 +482,22 @@ "responses": {} } }, + "/configs/captcha": { + "get": { + "description": "Captcha 配置查询", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Config" + ], + "summary": "Captcha 配置查询", + "responses": {} + } + }, "/games/": { "get": { "security": [ @@ -2399,6 +2415,10 @@ "description": "The user's password. Crypt.", "type": "string" }, + "remote_ip": { + "description": "The user's remote ip.", + "type": "string" + }, "teams": { "description": "The user's teams.", "type": "array", diff --git a/api/swagger.yaml b/api/swagger.yaml index a63c233c..42dedadc 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -381,6 +381,9 @@ definitions: password: description: The user's password. Crypt. type: string + remote_ip: + description: The user's remote ip. + type: string teams: description: The user's teams. items: @@ -1082,6 +1085,17 @@ paths: summary: 更新配置 tags: - Config + /configs/captcha: + get: + consumes: + - application/json + description: Captcha 配置查询 + produces: + - application/json + responses: {} + summary: Captcha 配置查询 + tags: + - Config /games/: get: consumes: diff --git a/internal/app/config/application.go b/internal/app/config/application.go index a11ada66..254a5930 100644 --- a/internal/app/config/application.go +++ b/internal/app/config/application.go @@ -54,7 +54,7 @@ type ApplicationCfg struct { SiteKey string `yaml:"site_key" json:"site_key" mapstructure:"site_key"` SecretKey string `yaml:"secret_key" json:"secret_key" mapstructure:"secret_key"` Threshold float64 `yaml:"threshold" json:"threshold" mapstructure:"threshold"` - } `yaml:"re_captcha" json:"re_captcha" mapstructure:"re_captcha"` + } `yaml:"recaptcha" json:"recaptcha" mapstructure:"recaptcha"` Turnstile struct { URL string `yaml:"url" json:"url" mapstructure:"url"` SiteKey string `yaml:"site_key" json:"site_key" mapstructure:"site_key"` diff --git a/internal/controller/config.go b/internal/controller/config.go index f172b132..b2cb93ae 100644 --- a/internal/controller/config.go +++ b/internal/controller/config.go @@ -1,6 +1,7 @@ package controller import ( + "github.com/elabosak233/cloudsdale/internal/app/config" "github.com/elabosak233/cloudsdale/internal/model/request" "github.com/elabosak233/cloudsdale/internal/service" "github.com/elabosak233/cloudsdale/internal/utils/validator" @@ -11,6 +12,7 @@ import ( type IConfigController interface { Find(ctx *gin.Context) Update(ctx *gin.Context) + FindCaptcha(ctx *gin.Context) } type ConfigController struct { @@ -33,7 +35,7 @@ func NewConfigController(appService *service.Service) IConfigController { func (c *ConfigController) Find(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{ "code": http.StatusOK, - "data": c.configService.FindAll(), + "data": *(config.PltCfg()), }) } @@ -68,3 +70,26 @@ func (c *ConfigController) Update(ctx *gin.Context) { }) } } + +// FindCaptcha +// @Summary Captcha 配置查询 +// @Description Captcha 配置查询 +// @Tags Config +// @Accept json +// @Produce json +// @Router /configs/captcha [get] +func (c *ConfigController) FindCaptcha(ctx *gin.Context) { + ctx.JSON(http.StatusOK, gin.H{ + "code": http.StatusOK, + "data": map[string]any{ + "enabled": config.AppCfg().Captcha.Enabled, + "provider": config.AppCfg().Captcha.Provider, + "turnstile": map[string]any{ + "site_key": config.AppCfg().Captcha.Turnstile.SiteKey, + }, + "recaptcha": map[string]any{ + "site_key": config.AppCfg().Captcha.ReCaptcha.SiteKey, + }, + }, + }) +} diff --git a/internal/controller/user.go b/internal/controller/user.go index 59ace780..75b7505c 100644 --- a/internal/controller/user.go +++ b/internal/controller/user.go @@ -70,6 +70,10 @@ func (c *UserController) Login(ctx *gin.Context) { zap.L().Warn(fmt.Sprintf("User %s login failed", user.Username), zap.Uint("user_id", user.ID)) return } + _ = c.userService.Update(request.UserUpdateRequest{ + ID: user.ID, + RemoteIP: ctx.RemoteIP(), + }) tokenString, err := c.userService.GetJwtTokenByID(user) if err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{ diff --git a/internal/extension/casbin/policy.go b/internal/extension/casbin/policy.go index 81a10c30..e2e78136 100644 --- a/internal/extension/casbin/policy.go +++ b/internal/extension/casbin/policy.go @@ -43,7 +43,7 @@ func initDefaultPolicy() { {"user", "/api/pods/{id}", "DELETE"}, {"guest", "/api/", "GET"}, - {"guest", "/api/configs/", "GET"}, + {"guest", "/api/configs/*", "GET"}, {"guest", "/api/categories/", "GET"}, {"guest", "/api/users/", "GET"}, {"guest", "/api/users/register", "POST"}, diff --git a/internal/middleware/frontend.go b/internal/middleware/frontend.go index 945b5d88..314372b0 100644 --- a/internal/middleware/frontend.go +++ b/internal/middleware/frontend.go @@ -1,6 +1,8 @@ package middleware import ( + "github.com/elabosak233/cloudsdale/internal/app/config" + "github.com/elabosak233/cloudsdale/internal/utils" "github.com/gin-gonic/gin" "net/http" "os" @@ -8,9 +10,26 @@ import ( "strings" ) +func index(ctx *gin.Context) { + filePath := filepath.Join(utils.FrontendPath, "index.html") + indexContent, err := os.ReadFile(filePath) + if err != nil { + ctx.JSON(http.StatusInternalServerError, gin.H{ + "code": http.StatusInternalServerError, + "msg": "Error reading index.html", + }) + ctx.Abort() + return + } + indexContentStr := string(indexContent) + indexContentStr = strings.ReplaceAll(indexContentStr, "{{ Cloudsdale.Title }}", config.PltCfg().Site.Title) + ctx.Header("Content-Type", "text/html; charset=utf-8") + ctx.String(http.StatusOK, indexContentStr) + ctx.Abort() +} + func Frontend(urlPrefix string) gin.HandlerFunc { - root := "./dist" - fileServer := http.FileServer(http.Dir(root)) + fileServer := http.FileServer(http.Dir(utils.FrontendPath)) if !strings.HasSuffix(urlPrefix, "/") { urlPrefix = urlPrefix + "/" } @@ -20,14 +39,17 @@ func Frontend(urlPrefix string) gin.HandlerFunc { ctx.Next() } else { ctx.Set("skip_logging", true) - filePath := filepath.Join(root, ctx.Request.URL.Path) + filePath := filepath.Join(utils.FrontendPath, ctx.Request.URL.Path) _, err := os.Stat(filePath) if err == nil { - http.StripPrefix(staticServerPrefix, fileServer).ServeHTTP(ctx.Writer, ctx.Request) - ctx.Abort() + if ctx.Request.URL.Path == "/" || ctx.Request.URL.Path == "/index.html" { + index(ctx) + } else { + http.StripPrefix(staticServerPrefix, fileServer).ServeHTTP(ctx.Writer, ctx.Request) + ctx.Abort() + } } else if os.IsNotExist(err) { - http.ServeFile(ctx.Writer, ctx.Request, filepath.Join(root, "index.html")) - ctx.Abort() + index(ctx) } else { ctx.Next() } diff --git a/internal/model/request/user_request.go b/internal/model/request/user_request.go index c6957bbe..2475210b 100644 --- a/internal/model/request/user_request.go +++ b/internal/model/request/user_request.go @@ -41,6 +41,7 @@ type UserUpdateRequest struct { Password string `binding:"omitempty,min=6" json:"password,omitempty"` Email string `binding:"omitempty,email" json:"email,omitempty"` Group string `json:"group"` + RemoteIP string `json:"-"` } type UserDeleteRequest struct { diff --git a/internal/model/user.go b/internal/model/user.go index 66307609..5bd18303 100644 --- a/internal/model/user.go +++ b/internal/model/user.go @@ -17,6 +17,7 @@ type User struct { Avatar *File `gorm:"-" json:"avatar"` // The user's avatar. Group string `gorm:"column:group;varchar(16);not null;" json:"group,omitempty"` // The user's group. Password string `gorm:"column:password;type:varchar(255);not null" json:"password,omitempty"` // The user's password. Crypt. + RemoteIP string `gorm:"column:remote_ip;type:varchar(32)" json:"remote_ip,omitempty"` // The user's remote ip. CreatedAt int64 `gorm:"autoUpdateTime:milli" json:"created_at,omitempty"` // The user's creation time. UpdatedAt int64 `gorm:"autoUpdateTime:milli" json:"updated_at,omitempty"` // The user's last update time. Teams []*Team `gorm:"many2many:user_teams;" json:"teams,omitempty"` // The user's teams. diff --git a/internal/router/config.go b/internal/router/config.go index 2636d806..d5451814 100644 --- a/internal/router/config.go +++ b/internal/router/config.go @@ -24,4 +24,5 @@ func NewConfigRouter(configRouter *gin.RouterGroup, configController controller. func (c *ConfigRouter) Register() { c.router.GET("/", c.controller.Find) c.router.PUT("/", c.controller.Update) + c.router.GET("/captcha", c.controller.FindCaptcha) } diff --git a/internal/service/config.go b/internal/service/config.go index 2d988db5..cda13fd3 100644 --- a/internal/service/config.go +++ b/internal/service/config.go @@ -7,7 +7,6 @@ import ( ) type IConfigService interface { - FindAll() (cfg config.PlatformCfg) Update(req request.ConfigUpdateRequest) (err error) } @@ -18,10 +17,6 @@ func NewConfigService(appRepository *repository.Repository) IConfigService { return &ConfigService{} } -func (c *ConfigService) FindAll() (cfg config.PlatformCfg) { - return *(config.PltCfg()) -} - func (c *ConfigService) Update(req request.ConfigUpdateRequest) (err error) { config.PltCfg().Site.Title = req.Site.Title config.PltCfg().Site.Description = req.Site.Description diff --git a/internal/utils/const.go b/internal/utils/const.go index dbc5e2d9..8da27a26 100644 --- a/internal/utils/const.go +++ b/internal/utils/const.go @@ -12,4 +12,5 @@ const ( MediaPath = "./media" FilesPath = "./files" CapturesPath = "./captures" + FrontendPath = "./dist" ) diff --git a/web/index.html b/web/index.html index d6e3e903..9e453ecd 100644 --- a/web/index.html +++ b/web/index.html @@ -4,7 +4,7 @@ -