diff --git a/cmd/kratos-admin/wire_gen.go b/cmd/kratos-admin/wire_gen.go index 8eca50e..2728a4c 100644 --- a/cmd/kratos-admin/wire_gen.go +++ b/cmd/kratos-admin/wire_gen.go @@ -71,34 +71,43 @@ func wireApp(confServer *conf.Server, runtime *conf.Runtime, logger *slog.Logger auditUsecase := biz.NewAuditUsecase(auditRepo) auditService := service.NewAuditService(auditUsecase) audit := handler.NewAudit(auditService) - settingsRepo := data.NewSettingsRepo(dataData) - settingsUsecase := biz.NewSettingsUsecase(settingsRepo) + securityRepo := data.NewSecurityRepo(dataData) + securityUsecase := biz.NewSecurityUsecase(securityRepo) cache := data.NewCache(dataData) - settingsService := service.NewSettingsService(settingsUsecase, runtime, cache) + apiTokenRepo := data.NewAPITokenRepo(dataData) + tokenUsecase := biz.NewTokenUsecase(apiTokenRepo) + tokenService := service.NewTokenService(tokenUsecase, runtime) + securityService := service.NewSecurityService(securityUsecase, runtime, cache, tokenService) exportRepo := data.NewExportRepo(dataData) exportUsecase := biz.NewExportUsecase(exportRepo) exportService := service.NewExportService(exportUsecase) - export := handler.NewExport(settingsService, exportService) + export := handler.NewExport(securityService, exportService) versionRepo := data.NewVersionRepo(dataData) versionUsecase := biz.NewVersionUsecase(versionRepo) versionService := service.NewVersionService(versionUsecase) version := handler.NewVersion(versionService) - dictionary := handler.NewDictionary(settingsService) - parameter := handler.NewParameter(settingsService) - apiToken := handler.NewAPIToken(settingsService) + dictionaryRepo := data.NewDictionaryRepo(dataData) + dictionaryUsecase := biz.NewDictionaryUsecase(dictionaryRepo) + dictionaryService := service.NewDictionaryService(dictionaryUsecase) + dictionary := handler.NewDictionary(dictionaryService) + parameterRepo := data.NewParameterRepo(dataData) + parameterUsecase := biz.NewParameterUsecase(parameterRepo) + parameterService := service.NewParameterService(parameterUsecase) + parameter := handler.NewParameter(parameterService) + apiToken := handler.NewAPIToken(tokenService) initializationRepo := data.NewInitializationRepo(dataData) systemConfigUsecase := biz.NewSystemConfigUsecase(initializationRepo) systemConfigService := service.NewSystemConfigService(systemConfigUsecase, runtime) - systemConfig := handler.NewSystemConfig(systemConfigService, settingsService, taskScheduler) + systemConfig := handler.NewSystemConfig(systemConfigService, securityService, taskScheduler) userRepo := data.NewUserRepo(dataData) userUsecase := biz.NewUserUsecase(userRepo) - authService := service.NewAuthService(userUsecase, runtime, settingsService) - public := handler.NewPublic(runtime, authService, systemConfigService, settingsService, auditService, taskScheduler) - userService := service.NewUserService(userUsecase, settingsService) + authService := service.NewAuthService(userUsecase, runtime, securityService) + public := handler.NewPublic(runtime, authService, systemConfigService, securityService, auditService, taskScheduler) + userService := service.NewUserService(userUsecase, securityService) user := handler.NewUser(userService, authService) navigation := handler.NewNavigation(userService) - session := handler.NewSession(settingsService) - engine := server.NewGinEngine(runtime, accessService, authority, menu, api, permission, organization, announcement, email, task, media, audit, export, version, dictionary, parameter, apiToken, systemConfig, public, user, navigation, session, settingsService, auditService, logger) + session := handler.NewSession(tokenService) + engine := server.NewGinEngine(runtime, accessService, authority, menu, api, permission, organization, announcement, email, task, media, audit, export, version, dictionary, parameter, apiToken, systemConfig, public, user, navigation, session, securityService, tokenService, auditService, logger) httpServer := server.NewGinServer(confServer, engine) app := newApp(logger, httpServer, taskScheduler) return app, func() { diff --git a/internal/biz/api_token.go b/internal/biz/api_token.go index b71870b..0f312bd 100644 --- a/internal/biz/api_token.go +++ b/internal/biz/api_token.go @@ -29,7 +29,13 @@ type APITokenRepo interface { IsTokenDisabled(context.Context, string) (bool, error) } -func (uc *SettingsUsecase) PrepareAPIToken(ctx context.Context, userID, authorityID uint, days int) (*User, time.Duration, error) { +type TokenUsecase struct{ APITokenRepo } + +func NewTokenUsecase(repo APITokenRepo) *TokenUsecase { + return &TokenUsecase{APITokenRepo: repo} +} + +func (uc *TokenUsecase) PrepareAPIToken(ctx context.Context, userID, authorityID uint, days int) (*User, time.Duration, error) { user, allowed, err := uc.UserHasAuthority(ctx, userID, authorityID) if err != nil { return nil, 0, err @@ -44,6 +50,6 @@ func (uc *SettingsUsecase) PrepareAPIToken(ctx context.Context, userID, authorit return user, duration, nil } -func (uc *SettingsUsecase) DisableToken(ctx context.Context, id uint) error { - return uc.SettingsRepo.DisableAndBlacklistAPIToken(ctx, id) +func (uc *TokenUsecase) DisableToken(ctx context.Context, id uint) error { + return uc.APITokenRepo.DisableAndBlacklistAPIToken(ctx, id) } diff --git a/internal/biz/biz.go b/internal/biz/biz.go index 6499bfb..e273ff1 100644 --- a/internal/biz/biz.go +++ b/internal/biz/biz.go @@ -3,4 +3,4 @@ package biz import "github.com/google/wire" // ProviderSet is biz providers. -var ProviderSet = wire.NewSet(NewUserUsecase, NewSystemConfigUsecase, NewAccessUsecase, NewMenuUsecase, NewOrganizationUsecase, NewSettingsUsecase, NewVersionUsecase, NewExportUsecase, NewAuditUsecase, NewTaskUsecase, NewMediaUsecase, NewAnnouncementUsecase, NewEmailUsecase) +var ProviderSet = wire.NewSet(NewUserUsecase, NewSystemConfigUsecase, NewAccessUsecase, NewMenuUsecase, NewOrganizationUsecase, NewDictionaryUsecase, NewParameterUsecase, NewTokenUsecase, NewSecurityUsecase, NewVersionUsecase, NewExportUsecase, NewAuditUsecase, NewTaskUsecase, NewMediaUsecase, NewAnnouncementUsecase, NewEmailUsecase) diff --git a/internal/biz/dictionary.go b/internal/biz/dictionary.go index 92ac4e9..8ec4591 100644 --- a/internal/biz/dictionary.go +++ b/internal/biz/dictionary.go @@ -57,6 +57,12 @@ type DictionaryRepo interface { DictionaryDetailRepo } +type DictionaryUsecase struct{ DictionaryRepo } + +func NewDictionaryUsecase(repo DictionaryRepo) *DictionaryUsecase { + return &DictionaryUsecase{DictionaryRepo: repo} +} + type DictionaryMetadataRepo interface { CreateDictionary(context.Context, *Dictionary) error ImportDictionary(context.Context, *Dictionary, []*DictionaryDetail) error @@ -67,11 +73,11 @@ type DictionaryMetadataRepo interface { ListDictionaries(context.Context, int, int, string, string, bool) ([]*Dictionary, int64, error) } -func (uc *SettingsUsecase) ImportDictionary(ctx context.Context, dictionary *Dictionary, details []*DictionaryDetail) error { - return uc.SettingsRepo.ImportDictionary(ctx, dictionary, details) +func (uc *DictionaryUsecase) ImportDictionary(ctx context.Context, dictionary *Dictionary, details []*DictionaryDetail) error { + return uc.DictionaryRepo.ImportDictionary(ctx, dictionary, details) } -func (uc *SettingsUsecase) DictionaryDetailsByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]*DictionaryDetail, error) { +func (uc *DictionaryUsecase) DictionaryDetailsByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]*DictionaryDetail, error) { items, _, err := uc.ListDictionaryDetails(ctx, 0, 0, DictionaryDetailFilter{DictionaryID: dictionaryID}) if err != nil { return nil, err diff --git a/internal/biz/parameter.go b/internal/biz/parameter.go index a89d850..e16f578 100644 --- a/internal/biz/parameter.go +++ b/internal/biz/parameter.go @@ -24,3 +24,9 @@ type ParameterRepo interface { FindParameter(context.Context, uint, string) (*SystemParameter, error) ListParameters(context.Context, int, int, *SystemParameter) ([]*SystemParameter, int64, error) } + +type ParameterUsecase struct{ ParameterRepo } + +func NewParameterUsecase(repo ParameterRepo) *ParameterUsecase { + return &ParameterUsecase{ParameterRepo: repo} +} diff --git a/internal/biz/security.go b/internal/biz/security.go index ee5bce0..622b8a5 100644 --- a/internal/biz/security.go +++ b/internal/biz/security.go @@ -33,11 +33,17 @@ type SecurityRepo interface { SaveSecurityConfig(context.Context, *SecurityConfig) error } -func (uc *SettingsUsecase) UpdateSecurity(ctx context.Context, value *SecurityConfig) error { +type SecurityUsecase struct{ SecurityRepo } + +func NewSecurityUsecase(repo SecurityRepo) *SecurityUsecase { + return &SecurityUsecase{SecurityRepo: repo} +} + +func (uc *SecurityUsecase) UpdateSecurity(ctx context.Context, value *SecurityConfig) error { return uc.SaveSecurityConfig(ctx, value) } -func (uc *SettingsUsecase) ValidatePassword(value *SecurityConfig, password string) error { +func (uc *SecurityUsecase) ValidatePassword(value *SecurityConfig, password string) error { if len([]rune(password)) < value.PwdMinLength { return errors.New("密码长度不足") } diff --git a/internal/biz/settings.go b/internal/biz/settings.go deleted file mode 100644 index ac7901b..0000000 --- a/internal/biz/settings.go +++ /dev/null @@ -1,14 +0,0 @@ -package biz - -type SettingsRepo interface { - DictionaryRepo - ParameterRepo - APITokenRepo - SecurityRepo -} - -type SettingsUsecase struct{ SettingsRepo } - -func NewSettingsUsecase(repo SettingsRepo) *SettingsUsecase { - return &SettingsUsecase{SettingsRepo: repo} -} diff --git a/internal/data/data.go b/internal/data/data.go index 9f7f4d7..de3a857 100644 --- a/internal/data/data.go +++ b/internal/data/data.go @@ -13,7 +13,7 @@ import ( "kra/internal/conf" ) -var ProviderSet = wire.NewSet(NewData, NewUserRepo, NewInitializationRepo, NewAccessRepo, NewMenuRepo, NewOrganizationRepo, NewSettingsRepo, NewVersionRepo, NewExportRepo, NewAuditRepo, NewTaskRepo, NewMediaRepo, NewAnnouncementRepo, NewEmailRepo, NewCache, NewFileStorage) +var ProviderSet = wire.NewSet(NewData, NewUserRepo, NewInitializationRepo, NewAccessRepo, NewMenuRepo, NewOrganizationRepo, NewDictionaryRepo, NewParameterRepo, NewAPITokenRepo, NewSecurityRepo, NewVersionRepo, NewExportRepo, NewAuditRepo, NewTaskRepo, NewMediaRepo, NewAnnouncementRepo, NewEmailRepo, NewCache, NewFileStorage) type Data struct { initMu sync.Mutex diff --git a/internal/data/settings.go b/internal/data/settings.go index 9f128a0..3b02aed 100644 --- a/internal/data/settings.go +++ b/internal/data/settings.go @@ -4,4 +4,10 @@ import "kra/internal/biz" type settingsRepo struct{ data *Data } -func NewSettingsRepo(data *Data) biz.SettingsRepo { return &settingsRepo{data: data} } +func NewDictionaryRepo(data *Data) biz.DictionaryRepo { return &settingsRepo{data: data} } + +func NewParameterRepo(data *Data) biz.ParameterRepo { return &settingsRepo{data: data} } + +func NewAPITokenRepo(data *Data) biz.APITokenRepo { return &settingsRepo{data: data} } + +func NewSecurityRepo(data *Data) biz.SecurityRepo { return &settingsRepo{data: data} } diff --git a/internal/server/gin.go b/internal/server/gin.go index 9a924a4..7caa7f6 100644 --- a/internal/server/gin.go +++ b/internal/server/gin.go @@ -20,10 +20,10 @@ import ( kratoshttp "github.com/go-kratos/kratos/v3/transport/http" ) -func NewGinEngine(runtime *conf.Runtime, access *service.AccessService, authority *handler.Authority, menu *handler.Menu, api *handler.API, permission *handler.Permission, organization *handler.Organization, announcement *handler.Announcement, email *handler.Email, task *handler.Task, media *handler.Media, auditHandler *handler.Audit, export *handler.Export, version *handler.Version, dictionary *handler.Dictionary, parameter *handler.Parameter, apiToken *handler.APIToken, systemConfig *handler.SystemConfig, publicHandler *handler.Public, user *handler.User, navigation *handler.Navigation, session *handler.Session, settings *service.SettingsService, audit *service.AuditService, logger *slog.Logger) *gin.Engine { +func NewGinEngine(runtime *conf.Runtime, access *service.AccessService, authority *handler.Authority, menu *handler.Menu, api *handler.API, permission *handler.Permission, organization *handler.Organization, announcement *handler.Announcement, email *handler.Email, task *handler.Task, media *handler.Media, auditHandler *handler.Audit, export *handler.Export, version *handler.Version, dictionary *handler.Dictionary, parameter *handler.Parameter, apiToken *handler.APIToken, systemConfig *handler.SystemConfig, publicHandler *handler.Public, user *handler.User, navigation *handler.Navigation, session *handler.Session, security *service.SecurityService, tokens *service.TokenService, audit *service.AuditService, logger *slog.Logger) *gin.Engine { gin.SetMode(gin.ReleaseMode) engine := gin.New() - engine.Use(servermiddleware.RequestMeta(), servermiddleware.Recovery(audit, logger), servermiddleware.AccessLog(runtime, logger), servermiddleware.ErrorAudit(audit), servermiddleware.SecurityRateLimit(settings), servermiddleware.OperationAudit(runtime, audit)) + engine.Use(servermiddleware.RequestMeta(), servermiddleware.Recovery(audit, logger), servermiddleware.AccessLog(runtime, logger), servermiddleware.ErrorAudit(audit), servermiddleware.SecurityRateLimit(security), servermiddleware.OperationAudit(runtime, audit)) prefix := "" config := runtime.Admin() @@ -35,7 +35,7 @@ func NewGinEngine(runtime *conf.Runtime, access *service.AccessService, authorit serverrouter.RegisterPublic(public, engine, publicHandler) private := engine.Group(prefix) - private.Use(servermiddleware.Auth(runtime, settings), servermiddleware.MustChangePassword(), servermiddleware.AccessControl(runtime, access, audit)) + private.Use(servermiddleware.Auth(runtime, security, tokens), servermiddleware.MustChangePassword(), servermiddleware.AccessControl(runtime, access, audit)) serverrouter.RegisterUser(private, user) serverrouter.RegisterNavigation(private, navigation) serverrouter.RegisterSession(private, session) diff --git a/internal/server/handler/api_token.go b/internal/server/handler/api_token.go index 7bad7cb..b88ce94 100644 --- a/internal/server/handler/api_token.go +++ b/internal/server/handler/api_token.go @@ -9,10 +9,10 @@ import ( ) type APIToken struct { - service *service.SettingsService + service *service.TokenService } -func NewAPIToken(service *service.SettingsService) *APIToken { +func NewAPIToken(service *service.TokenService) *APIToken { return &APIToken{service: service} } diff --git a/internal/server/handler/dictionary.go b/internal/server/handler/dictionary.go index b3c9fef..2167e67 100644 --- a/internal/server/handler/dictionary.go +++ b/internal/server/handler/dictionary.go @@ -11,9 +11,9 @@ import ( "github.com/gin-gonic/gin" ) -type Dictionary struct{ service *service.SettingsService } +type Dictionary struct{ service *service.DictionaryService } -func NewDictionary(service *service.SettingsService) *Dictionary { +func NewDictionary(service *service.DictionaryService) *Dictionary { return &Dictionary{service: service} } diff --git a/internal/server/handler/export.go b/internal/server/handler/export.go index 5c3f6ee..40c50e4 100644 --- a/internal/server/handler/export.go +++ b/internal/server/handler/export.go @@ -16,11 +16,11 @@ import ( ) type Export struct { - settings *service.SettingsService + settings *service.SecurityService service *service.ExportService } -func NewExport(settings *service.SettingsService, export *service.ExportService) *Export { +func NewExport(settings *service.SecurityService, export *service.ExportService) *Export { return &Export{settings: settings, service: export} } diff --git a/internal/server/handler/parameter.go b/internal/server/handler/parameter.go index e0595f4..e078bed 100644 --- a/internal/server/handler/parameter.go +++ b/internal/server/handler/parameter.go @@ -11,10 +11,10 @@ import ( ) type Parameter struct { - service *service.SettingsService + service *service.ParameterService } -func NewParameter(service *service.SettingsService) *Parameter { +func NewParameter(service *service.ParameterService) *Parameter { return &Parameter{service: service} } diff --git a/internal/server/handler/public.go b/internal/server/handler/public.go index f87820d..1297483 100644 --- a/internal/server/handler/public.go +++ b/internal/server/handler/public.go @@ -21,14 +21,14 @@ import ( type Public struct { auth *service.AuthService system *service.SystemConfigService - settings *service.SettingsService + settings *service.SecurityService audit *service.AuditService scheduler *worker.TaskScheduler runtime *conf.Runtime store *captchaStore } -func NewPublic(runtime *conf.Runtime, auth *service.AuthService, system *service.SystemConfigService, settings *service.SettingsService, audit *service.AuditService, scheduler *worker.TaskScheduler) *Public { +func NewPublic(runtime *conf.Runtime, auth *service.AuthService, system *service.SystemConfigService, settings *service.SecurityService, audit *service.AuditService, scheduler *worker.TaskScheduler) *Public { return &Public{auth: auth, system: system, settings: settings, audit: audit, scheduler: scheduler, runtime: runtime, store: &captchaStore{service: settings, runtime: runtime}} } @@ -131,7 +131,7 @@ func (h *Public) Login(c *gin.Context) { httpx.Write(c, httpx.CodeSuccess, result, "登录成功") } -func ensureLoginIPCounter(ctx context.Context, settings *service.SettingsService, ip string, expiration time.Duration) (int, error) { +func ensureLoginIPCounter(ctx context.Context, settings *service.SecurityService, ip string, expiration time.Duration) (int, error) { value, exists, err := settings.CacheGet(ctx, ip) if err != nil { return 0, err @@ -195,7 +195,7 @@ func (h *Public) InitializeDatabase(engine *gin.Engine) gin.HandlerFunc { } type captchaStore struct { - service *service.SettingsService + service *service.SecurityService runtime *conf.Runtime } diff --git a/internal/server/handler/session.go b/internal/server/handler/session.go index ef2ca34..17219c4 100644 --- a/internal/server/handler/session.go +++ b/internal/server/handler/session.go @@ -7,15 +7,15 @@ import ( "github.com/gin-gonic/gin" ) -type Session struct{ settings *service.SettingsService } +type Session struct{ tokens *service.TokenService } -func NewSession(settings *service.SettingsService) *Session { return &Session{settings: settings} } +func NewSession(tokens *service.TokenService) *Session { return &Session{tokens: tokens} } func (h *Session) Logout(c *gin.Context) { token := c.GetHeader("x-token") if token == "" { token, _ = c.Cookie("x-token") } - if err := h.settings.BlacklistToken(c.Request.Context(), token); err != nil { + if err := h.tokens.BlacklistToken(c.Request.Context(), token); err != nil { httpx.Fail(c, "jwt作废失败") return } diff --git a/internal/server/handler/system_config.go b/internal/server/handler/system_config.go index 98df491..ddc8b2b 100644 --- a/internal/server/handler/system_config.go +++ b/internal/server/handler/system_config.go @@ -17,11 +17,11 @@ import ( type SystemConfig struct { system *service.SystemConfigService - settings *service.SettingsService + settings *service.SecurityService scheduler *worker.TaskScheduler } -func NewSystemConfig(system *service.SystemConfigService, settings *service.SettingsService, scheduler *worker.TaskScheduler) *SystemConfig { +func NewSystemConfig(system *service.SystemConfigService, settings *service.SecurityService, scheduler *worker.TaskScheduler) *SystemConfig { return &SystemConfig{system: system, settings: settings, scheduler: scheduler} } diff --git a/internal/server/middleware/auth.go b/internal/server/middleware/auth.go index 825b987..9c360b1 100644 --- a/internal/server/middleware/auth.go +++ b/internal/server/middleware/auth.go @@ -25,7 +25,7 @@ type refreshedToken struct { expiresAt int64 } -func Auth(runtime *conf.Runtime, settings *service.SettingsService) gin.HandlerFunc { +func Auth(runtime *conf.Runtime, security *service.SecurityService, tokens *service.TokenService) gin.HandlerFunc { return func(c *gin.Context) { token := c.GetHeader("x-token") if token == "" { @@ -57,7 +57,7 @@ func Auth(runtime *conf.Runtime, settings *service.SettingsService) gin.HandlerF httpx.NoAuth(c, message) return } - if disabled, checkErr := settings.IsTokenDisabled(c.Request.Context(), token); checkErr != nil || disabled { + if disabled, checkErr := tokens.IsTokenDisabled(c.Request.Context(), token); checkErr != nil || disabled { httpx.SetTokenCookie(c, "", -1) httpx.NoAuth(c, "您的帐户异地登陆或令牌失效") return @@ -82,7 +82,7 @@ func Auth(runtime *conf.Runtime, settings *service.SettingsService) gin.HandlerF if generateErr != nil { return nil, generateErr } - if rotateErr := settings.RotateActiveToken(c.Request.Context(), claims.Username, token, newToken, expires); rotateErr != nil { + if rotateErr := security.RotateActiveToken(c.Request.Context(), claims.Username, token, newToken, expires); rotateErr != nil { return nil, rotateErr } return refreshedToken{token: newToken, expiresAt: newClaims.ExpiresAt.Unix()}, nil diff --git a/internal/server/middleware/rate_limit.go b/internal/server/middleware/rate_limit.go index cc3c1d2..d70e78a 100644 --- a/internal/server/middleware/rate_limit.go +++ b/internal/server/middleware/rate_limit.go @@ -10,7 +10,7 @@ import ( "github.com/gin-gonic/gin" ) -func SecurityRateLimit(settings *service.SettingsService) gin.HandlerFunc { +func SecurityRateLimit(settings *service.SecurityService) gin.HandlerFunc { return func(c *gin.Context) { path := strings.TrimSuffix(c.Request.URL.Path, "/") if !strings.HasSuffix(path, "/base/login") && !strings.HasSuffix(path, "/base/captcha") { diff --git a/internal/service/api_token.go b/internal/service/api_token.go index ea00ed7..5d51332 100644 --- a/internal/service/api_token.go +++ b/internal/service/api_token.go @@ -5,9 +5,19 @@ import ( "time" "kra/internal/biz" + "kra/internal/conf" "kra/pkg/adminauth" ) +type TokenService struct { + uc *biz.TokenUsecase + runtime *conf.Runtime +} + +func NewTokenService(uc *biz.TokenUsecase, runtime *conf.Runtime) *TokenService { + return &TokenService{uc: uc, runtime: runtime} +} + func tokenDTO(v *biz.APIToken) map[string]any { var user any = nil if v.User != nil { @@ -16,7 +26,7 @@ func tokenDTO(v *biz.APIToken) map[string]any { return map[string]any{"ID": v.ID, "CreatedAt": v.CreatedAt, "UpdatedAt": v.UpdatedAt, "DeletedAt": nil, "userId": v.UserID, "authorityId": v.AuthorityID, "token": v.Token, "status": v.Status, "expiresAt": v.ExpiresAt, "remark": v.Remark, "user": user} } -func (s *SettingsService) CreateAPIToken(ctx context.Context, userID, authorityID uint, days int, remark string) (string, error) { +func (s *TokenService) CreateAPIToken(ctx context.Context, userID, authorityID uint, days int, remark string) (string, error) { user, duration, err := s.uc.PrepareAPIToken(ctx, userID, authorityID, days) if err != nil { return "", err @@ -43,7 +53,7 @@ func (s *SettingsService) CreateAPIToken(ctx context.Context, userID, authorityI } return token, nil } -func (s *SettingsService) APITokens(ctx context.Context, page, size int, userID uint, status *bool) ([]map[string]any, int64, error) { +func (s *TokenService) APITokens(ctx context.Context, page, size int, userID uint, status *bool) ([]map[string]any, int64, error) { items, total, err := s.uc.ListAPITokens(ctx, page, size, userID, status) if err != nil { return nil, 0, err @@ -54,12 +64,12 @@ func (s *SettingsService) APITokens(ctx context.Context, page, size int, userID } return out, total, nil } -func (s *SettingsService) DisableAPIToken(ctx context.Context, id uint) error { +func (s *TokenService) DisableAPIToken(ctx context.Context, id uint) error { return s.uc.DisableToken(ctx, id) } -func (s *SettingsService) BlacklistToken(ctx context.Context, token string) error { +func (s *TokenService) BlacklistToken(ctx context.Context, token string) error { return s.uc.BlacklistToken(ctx, token) } -func (s *SettingsService) IsTokenDisabled(ctx context.Context, token string) (bool, error) { +func (s *TokenService) IsTokenDisabled(ctx context.Context, token string) (bool, error) { return s.uc.IsTokenDisabled(ctx, token) } diff --git a/internal/service/authentication.go b/internal/service/authentication.go index 6f75a38..859dc7e 100644 --- a/internal/service/authentication.go +++ b/internal/service/authentication.go @@ -24,10 +24,10 @@ type LoginResult struct { type AuthService struct { uc *biz.UserUsecase runtime *conf.Runtime - settings *SettingsService + settings *SecurityService } -func NewAuthService(uc *biz.UserUsecase, runtime *conf.Runtime, settings *SettingsService) *AuthService { +func NewAuthService(uc *biz.UserUsecase, runtime *conf.Runtime, settings *SecurityService) *AuthService { return &AuthService{uc: uc, runtime: runtime, settings: settings} } diff --git a/internal/service/dictionary.go b/internal/service/dictionary.go index 2329164..3ceb274 100644 --- a/internal/service/dictionary.go +++ b/internal/service/dictionary.go @@ -7,6 +7,12 @@ import ( "kra/internal/service/dto" ) +type DictionaryService struct{ uc *biz.DictionaryUsecase } + +func NewDictionaryService(uc *biz.DictionaryUsecase) *DictionaryService { + return &DictionaryService{uc: uc} +} + func dictionaryDomain(value *dto.DictionaryRequest) *biz.Dictionary { status := true if value.Status != nil { @@ -14,14 +20,14 @@ func dictionaryDomain(value *dto.DictionaryRequest) *biz.Dictionary { } return &biz.Dictionary{ID: value.ID, Name: value.Name, Type: value.Type, Status: status, Desc: value.Description, ParentID: value.ParentID} } -func (s *SettingsService) CreateDictionaryRequest(ctx context.Context, req *dto.DictionaryRequest) (map[string]any, error) { +func (s *DictionaryService) CreateDictionaryRequest(ctx context.Context, req *dto.DictionaryRequest) (map[string]any, error) { value := dictionaryDomain(req) if err := s.CreateDictionary(ctx, value); err != nil { return nil, err } return dictionaryDTO(value), nil } -func (s *SettingsService) UpdateDictionaryRequest(ctx context.Context, req *dto.DictionaryRequest) error { +func (s *DictionaryService) UpdateDictionaryRequest(ctx context.Context, req *dto.DictionaryRequest) error { return s.UpdateDictionary(ctx, dictionaryDomain(req)) } func dictionaryDTO(v *biz.Dictionary) map[string]any { @@ -35,7 +41,7 @@ func dictionaryDTO(v *biz.Dictionary) map[string]any { } return map[string]any{"ID": v.ID, "CreatedAt": v.CreatedAt, "UpdatedAt": v.UpdatedAt, "DeletedAt": nil, "name": v.Name, "type": v.Type, "status": v.Status, "desc": v.Desc, "parentID": v.ParentID, "children": children, "sysDictionaryDetails": details} } -func (s *SettingsService) Dictionaries(ctx context.Context, page, size int, name, typ string, details bool) ([]map[string]any, int64, error) { +func (s *DictionaryService) Dictionaries(ctx context.Context, page, size int, name, typ string, details bool) ([]map[string]any, int64, error) { items, total, err := s.uc.ListDictionaries(ctx, page, size, name, typ, details) if err != nil { return nil, 0, err @@ -46,27 +52,27 @@ func (s *SettingsService) Dictionaries(ctx context.Context, page, size int, name } return out, total, nil } -func (s *SettingsService) Dictionary(ctx context.Context, id uint, typ string, status *bool, details bool) (map[string]any, error) { +func (s *DictionaryService) Dictionary(ctx context.Context, id uint, typ string, status *bool, details bool) (map[string]any, error) { v, err := s.uc.FindDictionary(ctx, id, typ, status, details) if err != nil { return nil, err } return dictionaryDTO(v), nil } -func (s *SettingsService) ExportDictionary(ctx context.Context, id uint) (map[string]any, error) { +func (s *DictionaryService) ExportDictionary(ctx context.Context, id uint) (map[string]any, error) { v, err := s.uc.ExportDictionary(ctx, id) if err != nil { return nil, err } return dictionaryDTO(v), nil } -func (s *SettingsService) CreateDictionary(ctx context.Context, v *biz.Dictionary) error { +func (s *DictionaryService) CreateDictionary(ctx context.Context, v *biz.Dictionary) error { return s.uc.CreateDictionary(ctx, v) } -func (s *SettingsService) UpdateDictionary(ctx context.Context, v *biz.Dictionary) error { +func (s *DictionaryService) UpdateDictionary(ctx context.Context, v *biz.Dictionary) error { return s.uc.UpdateDictionary(ctx, v) } -func (s *SettingsService) DeleteDictionary(ctx context.Context, id uint) error { +func (s *DictionaryService) DeleteDictionary(ctx context.Context, id uint) error { return s.uc.DeleteDictionary(ctx, id) } @@ -77,10 +83,10 @@ func detailDomain(value *dto.DictionaryDetailRequest) *biz.DictionaryDetail { } return &biz.DictionaryDetail{ID: value.ID, Label: value.Label, Value: value.Value, Extend: value.Extend, Status: status, Sort: value.Sort, DictionaryID: value.DictionaryID, ParentID: value.ParentID, Level: value.Level, Path: value.Path} } -func (s *SettingsService) CreateDictionaryDetailRequest(ctx context.Context, req *dto.DictionaryDetailRequest) error { +func (s *DictionaryService) CreateDictionaryDetailRequest(ctx context.Context, req *dto.DictionaryDetailRequest) error { return s.CreateDictionaryDetail(ctx, detailDomain(req)) } -func (s *SettingsService) UpdateDictionaryDetailRequest(ctx context.Context, req *dto.DictionaryDetailRequest) error { +func (s *DictionaryService) UpdateDictionaryDetailRequest(ctx context.Context, req *dto.DictionaryDetailRequest) error { return s.UpdateDictionaryDetail(ctx, detailDomain(req)) } func detailDTO(v *biz.DictionaryDetail) map[string]any { @@ -90,7 +96,7 @@ func detailDTO(v *biz.DictionaryDetail) map[string]any { } return map[string]any{"ID": v.ID, "CreatedAt": v.CreatedAt, "UpdatedAt": v.UpdatedAt, "DeletedAt": nil, "label": v.Label, "value": v.Value, "extend": v.Extend, "status": v.Status, "sort": v.Sort, "sysDictionaryID": v.DictionaryID, "parentID": v.ParentID, "level": v.Level, "path": v.Path, "disabled": !v.Status, "children": children} } -func (s *SettingsService) DictionaryDetails(ctx context.Context, page, size int, filter biz.DictionaryDetailFilter) ([]map[string]any, int64, error) { +func (s *DictionaryService) DictionaryDetails(ctx context.Context, page, size int, filter biz.DictionaryDetailFilter) ([]map[string]any, int64, error) { items, total, err := s.uc.ListDictionaryDetails(ctx, page, size, filter) if err != nil { return nil, 0, err @@ -101,14 +107,14 @@ func (s *SettingsService) DictionaryDetails(ctx context.Context, page, size int, } return out, total, nil } -func (s *SettingsService) DictionaryDetail(ctx context.Context, id uint) (map[string]any, error) { +func (s *DictionaryService) DictionaryDetail(ctx context.Context, id uint) (map[string]any, error) { v, err := s.uc.FindDictionaryDetail(ctx, id) if err != nil { return nil, err } return detailDTO(v), nil } -func (s *SettingsService) DictionaryTree(ctx context.Context, id uint, typ string) ([]map[string]any, error) { +func (s *DictionaryService) DictionaryTree(ctx context.Context, id uint, typ string) ([]map[string]any, error) { items, err := s.uc.DictionaryDetailTree(ctx, id, typ) if err != nil { return nil, err @@ -119,12 +125,12 @@ func (s *SettingsService) DictionaryTree(ctx context.Context, id uint, typ strin } return out, nil } -func (s *SettingsService) CreateDictionaryDetail(ctx context.Context, v *biz.DictionaryDetail) error { +func (s *DictionaryService) CreateDictionaryDetail(ctx context.Context, v *biz.DictionaryDetail) error { return s.uc.CreateDictionaryDetail(ctx, v) } -func (s *SettingsService) UpdateDictionaryDetail(ctx context.Context, v *biz.DictionaryDetail) error { +func (s *DictionaryService) UpdateDictionaryDetail(ctx context.Context, v *biz.DictionaryDetail) error { return s.uc.UpdateDictionaryDetail(ctx, v) } -func (s *SettingsService) DeleteDictionaryDetail(ctx context.Context, id uint) error { +func (s *DictionaryService) DeleteDictionaryDetail(ctx context.Context, id uint) error { return s.uc.DeleteDictionaryDetail(ctx, id) } diff --git a/internal/service/dictionary_import.go b/internal/service/dictionary_import.go index 0bdbf3b..f7d5415 100644 --- a/internal/service/dictionary_import.go +++ b/internal/service/dictionary_import.go @@ -9,7 +9,7 @@ import ( "kra/internal/service/dto" ) -func (s *SettingsService) ImportDictionaryJSON(ctx context.Context, raw string) error { +func (s *DictionaryService) ImportDictionaryJSON(ctx context.Context, raw string) error { var payload struct { Name string `json:"name"` Type string `json:"type"` @@ -27,7 +27,7 @@ func (s *SettingsService) ImportDictionaryJSON(ctx context.Context, raw string) } return s.uc.ImportDictionary(ctx, dictionary, details) } -func (s *SettingsService) DictionaryDetailsByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]map[string]any, error) { +func (s *DictionaryService) DictionaryDetailsByParent(ctx context.Context, dictionaryID uint, parentID *uint, includeChildren bool) ([]map[string]any, error) { items, err := s.uc.DictionaryDetailsByParent(ctx, dictionaryID, parentID, includeChildren) if err != nil { return nil, err diff --git a/internal/service/parameter.go b/internal/service/parameter.go index b184067..fc7841c 100644 --- a/internal/service/parameter.go +++ b/internal/service/parameter.go @@ -8,22 +8,28 @@ import ( "kra/internal/service/dto" ) +type ParameterService struct{ uc *biz.ParameterUsecase } + +func NewParameterService(uc *biz.ParameterUsecase) *ParameterService { + return &ParameterService{uc: uc} +} + func parameterDomain(value *dto.SystemParameterRequest) *biz.SystemParameter { return &biz.SystemParameter{ID: value.ID, Name: value.Name, Key: value.Key, Value: value.Value, Desc: value.Description} } -func (s *SettingsService) CreateParameterRequest(ctx context.Context, req *dto.SystemParameterRequest) error { +func (s *ParameterService) CreateParameterRequest(ctx context.Context, req *dto.SystemParameterRequest) error { return s.CreateParameter(ctx, parameterDomain(req)) } -func (s *SettingsService) UpdateParameterRequest(ctx context.Context, req *dto.SystemParameterRequest) error { +func (s *ParameterService) UpdateParameterRequest(ctx context.Context, req *dto.SystemParameterRequest) error { return s.UpdateParameter(ctx, parameterDomain(req)) } -func (s *SettingsService) ParametersFilter(ctx context.Context, page, size int, name, key string, start, end *time.Time) ([]map[string]any, int64, error) { +func (s *ParameterService) ParametersFilter(ctx context.Context, page, size int, name, key string, start, end *time.Time) ([]map[string]any, int64, error) { return s.Parameters(ctx, page, size, &biz.SystemParameter{Name: name, Key: key, StartCreatedAt: start, EndCreatedAt: end}) } func parameterDTO(v *biz.SystemParameter) map[string]any { return map[string]any{"ID": v.ID, "CreatedAt": v.CreatedAt, "UpdatedAt": v.UpdatedAt, "DeletedAt": nil, "name": v.Name, "key": v.Key, "value": v.Value, "desc": v.Desc} } -func (s *SettingsService) Parameters(ctx context.Context, page, size int, q *biz.SystemParameter) ([]map[string]any, int64, error) { +func (s *ParameterService) Parameters(ctx context.Context, page, size int, q *biz.SystemParameter) ([]map[string]any, int64, error) { items, total, err := s.uc.ListParameters(ctx, page, size, q) if err != nil { return nil, 0, err @@ -34,19 +40,19 @@ func (s *SettingsService) Parameters(ctx context.Context, page, size int, q *biz } return out, total, nil } -func (s *SettingsService) Parameter(ctx context.Context, id uint, key string) (map[string]any, error) { +func (s *ParameterService) Parameter(ctx context.Context, id uint, key string) (map[string]any, error) { v, err := s.uc.FindParameter(ctx, id, key) if err != nil { return nil, err } return parameterDTO(v), nil } -func (s *SettingsService) CreateParameter(ctx context.Context, v *biz.SystemParameter) error { +func (s *ParameterService) CreateParameter(ctx context.Context, v *biz.SystemParameter) error { return s.uc.CreateParameter(ctx, v) } -func (s *SettingsService) UpdateParameter(ctx context.Context, v *biz.SystemParameter) error { +func (s *ParameterService) UpdateParameter(ctx context.Context, v *biz.SystemParameter) error { return s.uc.UpdateParameter(ctx, v) } -func (s *SettingsService) DeleteParameters(ctx context.Context, ids []uint) error { +func (s *ParameterService) DeleteParameters(ctx context.Context, ids []uint) error { return s.uc.DeleteParameters(ctx, ids) } diff --git a/internal/service/security.go b/internal/service/security.go index 058e05d..3f95b51 100644 --- a/internal/service/security.go +++ b/internal/service/security.go @@ -10,7 +10,7 @@ import ( func securityDTO(v *biz.SecurityConfig) map[string]any { return map[string]any{"ID": v.ID, "captchaOpen": v.CaptchaOpen, "captchaTimeout": v.CaptchaTimeout, "keyLong": v.KeyLong, "imgWidth": v.ImgWidth, "imgHeight": v.ImgHeight, "pwdMinLength": v.PwdMinLength, "pwdRequireUpper": v.PwdRequireUpper, "pwdRequireLower": v.PwdRequireLower, "pwdRequireDigit": v.PwdRequireDigit, "pwdRequireSpecial": v.PwdRequireSpecial, "limitEnable": v.LimitEnable, "limitWindow": v.LimitWindow, "limitCount": v.LimitCount, "lockEnable": v.LockEnable, "lockThreshold": v.LockThreshold, "lockDuration": v.LockDuration, "pwdExpireEnable": v.PwdExpireEnable, "pwdExpireDays": v.PwdExpireDays, "forceNewUserChangePassword": v.ForceNewUserChangePassword} } -func (s *SettingsService) CurrentSecurity(ctx context.Context) (*biz.SecurityConfig, error) { +func (s *SecurityService) CurrentSecurity(ctx context.Context) (*biz.SecurityConfig, error) { s.securityMu.RLock() if s.securityCache != nil { copy := *s.securityCache @@ -28,14 +28,14 @@ func (s *SettingsService) CurrentSecurity(ctx context.Context) (*biz.SecurityCon s.securityMu.Unlock() return ©, nil } -func (s *SettingsService) Security(ctx context.Context) (map[string]any, error) { +func (s *SecurityService) Security(ctx context.Context) (map[string]any, error) { value, err := s.CurrentSecurity(ctx) if err != nil { return nil, err } return securityDTO(value), nil } -func (s *SettingsService) SaveSecurity(ctx context.Context, value *biz.SecurityConfig) (map[string]any, error) { +func (s *SecurityService) SaveSecurity(ctx context.Context, value *biz.SecurityConfig) (map[string]any, error) { if err := s.uc.UpdateSecurity(ctx, value); err != nil { return nil, err } @@ -44,7 +44,7 @@ func (s *SettingsService) SaveSecurity(ctx context.Context, value *biz.SecurityC s.securityMu.Unlock() return securityDTO(value), nil } -func (s *SettingsService) SaveSecurityRequest(ctx context.Context, value *dto.SecurityConfigRequest) (map[string]any, error) { +func (s *SecurityService) SaveSecurityRequest(ctx context.Context, value *dto.SecurityConfigRequest) (map[string]any, error) { return s.SaveSecurity(ctx, &biz.SecurityConfig{ ID: value.ID, CaptchaOpen: value.CaptchaOpen, CaptchaTimeout: value.CaptchaTimeout, KeyLong: value.KeyLong, ImgWidth: value.ImgWidth, ImgHeight: value.ImgHeight, @@ -57,7 +57,7 @@ func (s *SettingsService) SaveSecurityRequest(ctx context.Context, value *dto.Se ForceNewUserChangePassword: value.ForceNewUserChangePassword, }) } -func (s *SettingsService) ValidatePassword(ctx context.Context, password string) error { +func (s *SecurityService) ValidatePassword(ctx context.Context, password string) error { cfg, err := s.CurrentSecurity(ctx) if err != nil { return err diff --git a/internal/service/settings.go b/internal/service/security_session.go similarity index 59% rename from internal/service/settings.go rename to internal/service/security_session.go index e863b23..e167852 100644 --- a/internal/service/settings.go +++ b/internal/service/security_session.go @@ -9,42 +9,43 @@ import ( "kra/internal/conf" ) -type SettingsService struct { - uc *biz.SettingsUsecase +type SecurityService struct { + uc *biz.SecurityUsecase runtime *conf.Runtime securityMu sync.RWMutex securityCache *biz.SecurityConfig cache biz.Cache + tokens *TokenService } -func NewSettingsService(uc *biz.SettingsUsecase, runtime *conf.Runtime, cache biz.Cache) *SettingsService { - return &SettingsService{uc: uc, runtime: runtime, cache: cache} +func NewSecurityService(uc *biz.SecurityUsecase, runtime *conf.Runtime, cache biz.Cache, tokens *TokenService) *SecurityService { + return &SecurityService{uc: uc, runtime: runtime, cache: cache, tokens: tokens} } -func (s *SettingsService) CacheGet(ctx context.Context, key string) (string, bool, error) { +func (s *SecurityService) CacheGet(ctx context.Context, key string) (string, bool, error) { return s.cache.Get(ctx, key) } -func (s *SettingsService) CacheSet(ctx context.Context, key, value string, expiration time.Duration) error { +func (s *SecurityService) CacheSet(ctx context.Context, key, value string, expiration time.Duration) error { return s.cache.Set(ctx, key, value, expiration) } -func (s *SettingsService) CacheDelete(ctx context.Context, key string) error { +func (s *SecurityService) CacheDelete(ctx context.Context, key string) error { return s.cache.Delete(ctx, key) } -func (s *SettingsService) CacheIncrement(ctx context.Context, key string, expiration time.Duration) (int64, error) { +func (s *SecurityService) CacheIncrement(ctx context.Context, key string, expiration time.Duration) (int64, error) { return s.cache.Increment(ctx, key, expiration) } -func (s *SettingsService) UseMultipoint() bool { +func (s *SecurityService) UseMultipoint() bool { config := s.runtime.Admin() return config != nil && config.System != nil && config.System.UseMultipoint } func activeTokenKey(username string) string { return "jwt:active:" + username } -func (s *SettingsService) ActiveTokenMatches(ctx context.Context, username, token string) (bool, error) { +func (s *SecurityService) ActiveTokenMatches(ctx context.Context, username, token string) (bool, error) { if !s.UseMultipoint() { return true, nil } @@ -52,12 +53,12 @@ func (s *SettingsService) ActiveTokenMatches(ctx context.Context, username, toke return ok && active == token, err } -func (s *SettingsService) RotateActiveToken(ctx context.Context, username, oldToken, newToken string, expiration time.Duration) error { +func (s *SecurityService) RotateActiveToken(ctx context.Context, username, oldToken, newToken string, expiration time.Duration) error { if !s.UseMultipoint() { return nil } if oldToken != "" && oldToken != newToken { - if err := s.BlacklistToken(ctx, oldToken); err != nil { + if err := s.tokens.BlacklistToken(ctx, oldToken); err != nil { return err } } diff --git a/internal/service/service.go b/internal/service/service.go index c73090e..0d6fa43 100644 --- a/internal/service/service.go +++ b/internal/service/service.go @@ -3,4 +3,4 @@ package service import "github.com/google/wire" // ProviderSet is service providers. -var ProviderSet = wire.NewSet(NewAuthService, NewUserService, NewSystemConfigService, NewAccessService, NewMenuService, NewOrganizationService, NewSettingsService, NewVersionService, NewExportService, NewAuditService, NewTaskService, NewMediaService, NewAnnouncementService, NewEmailService) +var ProviderSet = wire.NewSet(NewAuthService, NewUserService, NewSystemConfigService, NewAccessService, NewMenuService, NewOrganizationService, NewDictionaryService, NewParameterService, NewTokenService, NewSecurityService, NewVersionService, NewExportService, NewAuditService, NewTaskService, NewMediaService, NewAnnouncementService, NewEmailService) diff --git a/internal/service/task.go b/internal/service/task.go index 0a2c92b..30cfaf9 100644 --- a/internal/service/task.go +++ b/internal/service/task.go @@ -44,9 +44,6 @@ func (s *TaskService) Delete(ctx context.Context, id uint) error { func (s *TaskService) Toggle(ctx context.Context, id uint, enabled bool) error { return s.uc.ToggleTask(ctx, id, enabled) } -func (s *TaskService) Task(ctx context.Context, id uint) (*biz.TimedTask, error) { - return s.uc.FindTask(ctx, id) -} func taskDTO(v *biz.TimedTask, next *time.Time) map[string]any { return map[string]any{"ID": v.ID, "CreatedAt": v.CreatedAt, "UpdatedAt": v.UpdatedAt, "DeletedAt": nil, "name": v.Name, "description": v.Description, "spec": v.Spec, "withSeconds": v.WithSeconds, "executorType": v.ExecutorType, "methodName": v.MethodName, "params": json.RawMessage(v.Params), "httpUrl": v.HTTPURL, "httpMethod": v.HTTPMethod, "httpHeader": json.RawMessage(v.HTTPHeader), "httpBody": v.HTTPBody, "httpAllowPrivate": v.HTTPAllowPrivate, "enabled": v.Enabled, "nextRunAt": next} } @@ -67,12 +64,6 @@ func (s *TaskService) Tasks(ctx context.Context, page, size int, q *biz.TimedTas return out, total, nil } -// ScheduledTasks is the typed internal contract used by the scheduler and -// deliberately bypasses transport response maps. -func (s *TaskService) ScheduledTasks(ctx context.Context) ([]*biz.TimedTask, error) { - items, _, err := s.uc.ListTasks(ctx, 0, 0, nil) - return items, err -} func (s *TaskService) Logs(ctx context.Context, page, size int, taskID uint, status string) ([]map[string]any, int64, error) { items, total, err := s.uc.ListTaskLogs(ctx, page, size, taskID, status) if err != nil { diff --git a/internal/service/user.go b/internal/service/user.go index 2970e8b..0d64725 100644 --- a/internal/service/user.go +++ b/internal/service/user.go @@ -17,10 +17,10 @@ type UserInput struct { type UserService struct { uc *biz.UserUsecase - settings *SettingsService + settings *SecurityService } -func NewUserService(uc *biz.UserUsecase, settings *SettingsService) *UserService { +func NewUserService(uc *biz.UserUsecase, settings *SecurityService) *UserService { return &UserService{uc: uc, settings: settings} }