数据源和 oss

This commit is contained in:
2026-08-13 23:17:55 +08:00
parent f1a0b17bb0
commit c4bf7ee03b
40 changed files with 1975 additions and 922 deletions
+35 -5
View File
@@ -34,7 +34,8 @@ func NewGinServer(c *conf.Server, config *conf.AdminBackend, svc *service.System
gin.SetMode(gin.ReleaseMode)
engine := gin.New()
engine.Use(ginRequestMeta(), emailErrorAlert(emails, logger), gin.Recovery(), securityRateLimit(svc, settings), operationAudit(audit))
if config != nil && config.Local != nil && config.Local.StorePath != "" {
localStorage := config == nil || config.Storage == nil || config.Storage.Type == "" || config.Storage.Type == "local"
if localStorage && config != nil && config.Local != nil && config.Local.StorePath != "" {
pathPrefix := "/" + strings.Trim(config.Local.PathPrefix, "/")
if pathPrefix != "/" {
engine.StaticFS(pathPrefix, filesOnly{FileSystem: http.Dir(config.Local.StorePath)})
@@ -51,11 +52,11 @@ func NewGinServer(c *conf.Server, config *conf.AdminBackend, svc *service.System
})
registerPublicRoutes(public, engine, config, svc, settings, access, audit)
private := engine.Group(prefix)
private.Use(jwtAuth(config, settings), accessControl(access, audit))
private.Use(jwtAuth(config, settings), mustChangePasswordGuard(), accessControl(access, audit))
registerPrivateRoutes(private, svc)
registerAccessRoutes(private, engine, access)
registerSettingsRoutes(private, public, settings)
registerSystemConfigRoutes(private, config, settings)
registerSystemConfigRoutes(private, config, svc, settings)
registerVersionRoutes(private, versions)
registerExportRoutes(private, public, svc, exports)
registerAuditRoutes(private, public, audit)
@@ -117,6 +118,22 @@ func currentClaims(c *gin.Context) *adminauth.Claims {
return result
}
func mustChangePasswordGuard() gin.HandlerFunc {
return func(c *gin.Context) {
claims := currentClaims(c)
if claims == nil || !claims.MustChangePwd {
c.Next()
return
}
path := strings.TrimSuffix(c.Request.URL.Path, "/")
if strings.HasSuffix(path, "/user/changePassword") || strings.HasSuffix(path, "/user/getUserInfo") || strings.HasSuffix(path, "/jwt/jsonInBlacklist") {
c.Next()
return
}
c.AbortWithStatusJSON(http.StatusConflict, response{Code: codePasswordChangeRequired, Data: gin.H{"needChangePassword": true}, Msg: "请先修改初始密码"})
}
}
func registerPublicRoutes(group *gin.RouterGroup, engine *gin.Engine, config *conf.AdminBackend, svc *service.SystemService, settings *service.SettingsService, access *service.AccessService, audit *service.AuditService) {
expiration := 3 * time.Minute
keyLong, width, height := 6, 240, 80
@@ -221,8 +238,13 @@ func registerPublicRoutes(group *gin.RouterGroup, engine *gin.Engine, config *co
writeResult(c, codeSuccess, gin.H{"needInit": !initialized}, message)
})
initGroup.POST("/initdb", func(c *gin.Context) {
if err := svc.Initialize(c.Request.Context()); err != nil {
fail(c, "自动创建数据库失败")
var input service.DatabaseInit
if err := c.ShouldBindJSON(&input); err != nil {
fail(c, "数据库初始化参数无效")
return
}
if err := svc.Initialize(c.Request.Context(), &input); err != nil {
fail(c, "自动创建数据库失败: "+err.Error())
return
}
routes := engine.Routes()
@@ -261,6 +283,10 @@ func incrementCached(ctx context.Context, svc *service.SystemService, key string
}
func securityRateLimit(svc *service.SystemService, settings *service.SettingsService) gin.HandlerFunc {
return func(c *gin.Context) {
if isBootstrapPath(c.Request.URL.Path) {
c.Next()
return
}
cfg, err := settings.CurrentSecurity(c.Request.Context())
if err != nil || cfg == nil || !cfg.LimitEnable {
c.Next()
@@ -281,6 +307,10 @@ func securityRateLimit(svc *service.SystemService, settings *service.SettingsSer
}
}
func isBootstrapPath(path string) bool {
return strings.HasSuffix(path, "/health") || strings.Contains(path, "/init/")
}
type captchaStore struct {
service *service.SystemService
expiration time.Duration