feat(admin): add super admin initialization endpoint
Add POST /api/v1/admin/setup-super-admin endpoint to initialize the first super admin. The endpoint can only be used once - after a super admin exists, subsequent requests are rejected. Requires valid setup_secret configured via APP_SETUP_SECRET environment variable or setup_secret in config file.
This commit is contained in:
@@ -110,6 +110,7 @@ jobs:
|
|||||||
-e APP_GRPC_ENABLED=true \
|
-e APP_GRPC_ENABLED=true \
|
||||||
-e APP_GRPC_PORT=50051 \
|
-e APP_GRPC_PORT=50051 \
|
||||||
-e APP_SERVER_MODE=release \
|
-e APP_SERVER_MODE=release \
|
||||||
|
-e "APP_SETUP_SECRET=${{ secrets.SETUP_SECRET }}" \
|
||||||
${IMAGE}
|
${IMAGE}
|
||||||
|
|
||||||
echo "=== Waiting for startup ==="
|
echo "=== Waiting for startup ==="
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ func ProvideRouter(
|
|||||||
verificationHandler *handler.VerificationHandler,
|
verificationHandler *handler.VerificationHandler,
|
||||||
adminVerificationHandler *handler.AdminVerificationHandler,
|
adminVerificationHandler *handler.AdminVerificationHandler,
|
||||||
adminProfileAuditHandler *handler.AdminProfileAuditHandler,
|
adminProfileAuditHandler *handler.AdminProfileAuditHandler,
|
||||||
|
setupHandler *handler.SetupHandler,
|
||||||
logService *service.LogService,
|
logService *service.LogService,
|
||||||
activityService service.UserActivityService,
|
activityService service.UserActivityService,
|
||||||
casbinService service.CasbinService,
|
casbinService service.CasbinService,
|
||||||
@@ -91,6 +92,7 @@ func ProvideRouter(
|
|||||||
verificationHandler,
|
verificationHandler,
|
||||||
adminVerificationHandler,
|
adminVerificationHandler,
|
||||||
adminProfileAuditHandler,
|
adminProfileAuditHandler,
|
||||||
|
setupHandler,
|
||||||
logService,
|
logService,
|
||||||
activityService,
|
activityService,
|
||||||
casbinService,
|
casbinService,
|
||||||
|
|||||||
@@ -138,8 +138,10 @@ func InitializeApp() (*App, error) {
|
|||||||
adminVerificationService := wire.ProvideAdminVerificationService(verificationRepository, userRepository)
|
adminVerificationService := wire.ProvideAdminVerificationService(verificationRepository, userRepository)
|
||||||
adminVerificationHandler := wire.ProvideAdminVerificationHandler(adminVerificationService, userRepository)
|
adminVerificationHandler := wire.ProvideAdminVerificationHandler(adminVerificationService, userRepository)
|
||||||
adminProfileAuditHandler := handler.NewAdminProfileAuditHandler(userProfileAuditService)
|
adminProfileAuditHandler := handler.NewAdminProfileAuditHandler(userProfileAuditService)
|
||||||
|
setupService := wire.ProvideSetupService(userRepository, roleRepository, casbinService, config)
|
||||||
|
setupHandler := wire.ProvideSetupHandler(setupService)
|
||||||
wsHandler := wire.ProvideWSHandler(hub, chatService, groupService, jwtService, callService, userRepository)
|
wsHandler := wire.ProvideWSHandler(hub, chatService, groupService, jwtService, callService, userRepository)
|
||||||
router := ProvideRouter(userRepository, userHandler, postHandler, commentHandler, messageHandler, notificationHandler, uploadHandler, jwtService, pushHandler, systemMessageHandler, groupHandler, stickerHandler, voteHandler, channelHandler, scheduleHandler, roleHandler, adminUserHandler, adminPostHandler, adminCommentHandler, adminGroupHandler, adminDashboardHandler, adminLogHandler, qrCodeHandler, materialHandler, callHandler, reportHandler, adminReportHandler, verificationHandler, adminVerificationHandler, adminProfileAuditHandler, logService, userActivityService, casbinService, wsHandler)
|
router := ProvideRouter(userRepository, userHandler, postHandler, commentHandler, messageHandler, notificationHandler, uploadHandler, jwtService, pushHandler, systemMessageHandler, groupHandler, stickerHandler, voteHandler, channelHandler, scheduleHandler, roleHandler, adminUserHandler, adminPostHandler, adminCommentHandler, adminGroupHandler, adminDashboardHandler, adminLogHandler, qrCodeHandler, materialHandler, callHandler, reportHandler, adminReportHandler, verificationHandler, adminVerificationHandler, adminProfileAuditHandler, setupHandler, logService, userActivityService, casbinService, wsHandler)
|
||||||
hotRankWorker := wire.ProvideHotRankWorker(config, postRepository, cache)
|
hotRankWorker := wire.ProvideHotRankWorker(config, postRepository, cache)
|
||||||
app := NewApp(config, db, router, pushService, hotRankWorker, server, logger)
|
app := NewApp(config, db, router, pushService, hotRankWorker, server, logger)
|
||||||
return app, nil
|
return app, nil
|
||||||
@@ -179,6 +181,7 @@ func ProvideRouter(
|
|||||||
verificationHandler *handler.VerificationHandler,
|
verificationHandler *handler.VerificationHandler,
|
||||||
adminVerificationHandler *handler.AdminVerificationHandler,
|
adminVerificationHandler *handler.AdminVerificationHandler,
|
||||||
adminProfileAuditHandler *handler.AdminProfileAuditHandler,
|
adminProfileAuditHandler *handler.AdminProfileAuditHandler,
|
||||||
|
setupHandler *handler.SetupHandler,
|
||||||
logService *service.LogService,
|
logService *service.LogService,
|
||||||
activityService service.UserActivityService,
|
activityService service.UserActivityService,
|
||||||
casbinService service.CasbinService,
|
casbinService service.CasbinService,
|
||||||
@@ -215,6 +218,7 @@ func ProvideRouter(
|
|||||||
verificationHandler,
|
verificationHandler,
|
||||||
adminVerificationHandler,
|
adminVerificationHandler,
|
||||||
adminProfileAuditHandler,
|
adminProfileAuditHandler,
|
||||||
|
setupHandler,
|
||||||
logService,
|
logService,
|
||||||
activityService,
|
activityService,
|
||||||
casbinService,
|
casbinService,
|
||||||
|
|||||||
@@ -262,3 +262,9 @@ casbin:
|
|||||||
# 环境变量: APP_REPORT_AUTO_HIDE_THRESHOLD
|
# 环境变量: APP_REPORT_AUTO_HIDE_THRESHOLD
|
||||||
report:
|
report:
|
||||||
auto_hide_threshold: 3 # 自动隐藏阈值,举报次数达到此数值时自动隐藏内容
|
auto_hide_threshold: 3 # 自动隐藏阈值,举报次数达到此数值时自动隐藏内容
|
||||||
|
|
||||||
|
# 初始化超级管理员密钥
|
||||||
|
# 环境变量: APP_SETUP_SECRET
|
||||||
|
# 设置后可使用 POST /api/v1/admin/setup-super-admin 接口初始化第一位超级管理员
|
||||||
|
# 该接口只能使用一次,一旦系统中存在超级管理员,此接口将永久拒绝请求
|
||||||
|
setup_secret: ""
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Config struct {
|
|||||||
WebRTC WebRTCConfig `mapstructure:"webrtc"`
|
WebRTC WebRTCConfig `mapstructure:"webrtc"`
|
||||||
Report ReportConfig `mapstructure:"report"`
|
Report ReportConfig `mapstructure:"report"`
|
||||||
Sensitive SensitiveConfig `mapstructure:"sensitive"`
|
Sensitive SensitiveConfig `mapstructure:"sensitive"`
|
||||||
|
SetupSecret string `mapstructure:"setup_secret"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load 加载配置文件
|
// Load 加载配置文件
|
||||||
@@ -170,6 +171,7 @@ func Load(configPath string) (*Config, error) {
|
|||||||
})
|
})
|
||||||
// Report 默认值
|
// Report 默认值
|
||||||
viper.SetDefault("report.auto_hide_threshold", 3)
|
viper.SetDefault("report.auto_hide_threshold", 3)
|
||||||
|
viper.SetDefault("setup_secret", "")
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
return nil, fmt.Errorf("failed to read config: %w", err)
|
return nil, fmt.Errorf("failed to read config: %w", err)
|
||||||
@@ -269,6 +271,8 @@ func Load(configPath string) (*Config, error) {
|
|||||||
cfg.Sensitive.LoadFromRedis, _ = strconv.ParseBool(getEnvOrDefault("APP_SENSITIVE_LOAD_FROM_REDIS", fmt.Sprintf("%t", cfg.Sensitive.LoadFromRedis)))
|
cfg.Sensitive.LoadFromRedis, _ = strconv.ParseBool(getEnvOrDefault("APP_SENSITIVE_LOAD_FROM_REDIS", fmt.Sprintf("%t", cfg.Sensitive.LoadFromRedis)))
|
||||||
cfg.Sensitive.RedisKeyPrefix = getEnvOrDefault("APP_SENSITIVE_REDIS_KEY_PREFIX", cfg.Sensitive.RedisKeyPrefix)
|
cfg.Sensitive.RedisKeyPrefix = getEnvOrDefault("APP_SENSITIVE_REDIS_KEY_PREFIX", cfg.Sensitive.RedisKeyPrefix)
|
||||||
|
|
||||||
|
cfg.SetupSecret = getEnvOrDefault("APP_SETUP_SECRET", cfg.SetupSecret)
|
||||||
|
|
||||||
// 安全检查:生产模式必须设置JWT密钥
|
// 安全检查:生产模式必须设置JWT密钥
|
||||||
if cfg.Server.Mode != "debug" {
|
if cfg.Server.Mode != "debug" {
|
||||||
if cfg.JWT.Secret == "" || cfg.JWT.Secret == "your-jwt-secret-key-change-in-production" {
|
if cfg.JWT.Secret == "" || cfg.JWT.Secret == "your-jwt-secret-key-change-in-production" {
|
||||||
|
|||||||
@@ -135,6 +135,11 @@ var (
|
|||||||
ErrAlreadyVerified = &AppError{Code: "ALREADY_VERIFIED", Message: "已完成身份认证,无需重复申请"}
|
ErrAlreadyVerified = &AppError{Code: "ALREADY_VERIFIED", Message: "已完成身份认证,无需重复申请"}
|
||||||
ErrVerificationAlreadyHandled = &AppError{Code: "VERIFICATION_ALREADY_HANDLED", Message: "该认证申请已被处理"}
|
ErrVerificationAlreadyHandled = &AppError{Code: "VERIFICATION_ALREADY_HANDLED", Message: "该认证申请已被处理"}
|
||||||
ErrVerificationRequired = &AppError{Code: "VERIFICATION_REQUIRED", Message: "需要完成身份认证"}
|
ErrVerificationRequired = &AppError{Code: "VERIFICATION_REQUIRED", Message: "需要完成身份认证"}
|
||||||
|
|
||||||
|
// 初始化相关错误
|
||||||
|
ErrSetupAlreadyCompleted = &AppError{Code: "SETUP_ALREADY_COMPLETED", Message: "超级管理员已初始化,无法重复设置"}
|
||||||
|
ErrInvalidSetupSecret = &AppError{Code: "INVALID_SETUP_SECRET", Message: "初始化密钥无效"}
|
||||||
|
ErrSetupSecretNotConfigured = &AppError{Code: "SETUP_SECRET_NOT_CONFIGURED", Message: "未配置初始化密钥,无法使用此接口"}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Wrap 包装错误
|
// Wrap 包装错误
|
||||||
|
|||||||
38
internal/handler/setup_handler.go
Normal file
38
internal/handler/setup_handler.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"with_you/internal/pkg/response"
|
||||||
|
"with_you/internal/service"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SetupHandler struct {
|
||||||
|
setupService service.SetupService
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSetupHandler(setupService service.SetupService) *SetupHandler {
|
||||||
|
return &SetupHandler{
|
||||||
|
setupService: setupService,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *SetupHandler) SetupSuperAdmin(c *gin.Context) {
|
||||||
|
type SetupSuperAdminRequest struct {
|
||||||
|
UserID string `json:"user_id" binding:"required"`
|
||||||
|
SetupSecret string `json:"setup_secret" binding:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var req SetupSuperAdminRequest
|
||||||
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
|
response.BadRequest(c, "user_id and setup_secret are required")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := h.setupService.SetupSuperAdmin(c.Request.Context(), req.UserID, req.SetupSecret); err != nil {
|
||||||
|
response.HandleError(c, err, "failed to setup super admin")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
response.SuccessWithMessage(c, "超级管理员设置成功", nil)
|
||||||
|
}
|
||||||
@@ -161,7 +161,8 @@ func statusCodeFromAppErrorCode(code string) int {
|
|||||||
return http.StatusBadRequest
|
return http.StatusBadRequest
|
||||||
case "FORBIDDEN", "NOT_GROUP_MEMBER", "NOT_GROUP_ADMIN", "NOT_GROUP_OWNER",
|
case "FORBIDDEN", "NOT_GROUP_MEMBER", "NOT_GROUP_ADMIN", "NOT_GROUP_OWNER",
|
||||||
"USER_BANNED", "USER_BLOCKED", "MUTED", "MUTE_ALL_ENABLED",
|
"USER_BANNED", "USER_BLOCKED", "MUTED", "MUTE_ALL_ENABLED",
|
||||||
"SCHEDULE_FORBIDDEN", "UNAUTHORIZED_NOTIFICATION":
|
"SCHEDULE_FORBIDDEN", "UNAUTHORIZED_NOTIFICATION",
|
||||||
|
"SETUP_ALREADY_COMPLETED":
|
||||||
return http.StatusForbidden
|
return http.StatusForbidden
|
||||||
case "BAD_REQUEST", "INVALID_USERNAME", "INVALID_EMAIL", "INVALID_PHONE",
|
case "BAD_REQUEST", "INVALID_USERNAME", "INVALID_EMAIL", "INVALID_PHONE",
|
||||||
"WEAK_PASSWORD", "USERNAME_EXISTS", "EMAIL_EXISTS", "PHONE_EXISTS",
|
"WEAK_PASSWORD", "USERNAME_EXISTS", "EMAIL_EXISTS", "PHONE_EXISTS",
|
||||||
@@ -171,7 +172,8 @@ func statusCodeFromAppErrorCode(code string) int {
|
|||||||
"CANNOT_JOIN", "JOIN_REQUEST_PENDING", "GROUP_REQUEST_HANDLED",
|
"CANNOT_JOIN", "JOIN_REQUEST_PENDING", "GROUP_REQUEST_HANDLED",
|
||||||
"NOT_REQUEST_TARGET", "NO_ELIGIBLE_INVITEE", "NOT_MUTUAL_FOLLOW",
|
"NOT_REQUEST_TARGET", "NO_ELIGIBLE_INVITEE", "NOT_MUTUAL_FOLLOW",
|
||||||
"INVITE_NOT_ACCEPTED", "STICKER_ALREADY_EXISTS", "INVALID_STICKER_URL",
|
"INVITE_NOT_ACCEPTED", "STICKER_ALREADY_EXISTS", "INVALID_STICKER_URL",
|
||||||
"INVALID_SCHEDULE_PAYLOAD", "SCHEDULE_COLOR_DUPLICATED":
|
"INVALID_SCHEDULE_PAYLOAD", "SCHEDULE_COLOR_DUPLICATED",
|
||||||
|
"INVALID_SETUP_SECRET", "SETUP_SECRET_NOT_CONFIGURED":
|
||||||
return http.StatusBadRequest
|
return http.StatusBadRequest
|
||||||
case "VERIFICATION_CODE_TOO_FREQUENT":
|
case "VERIFICATION_CODE_TOO_FREQUENT":
|
||||||
return http.StatusTooManyRequests
|
return http.StatusTooManyRequests
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ type Router struct {
|
|||||||
verificationHandler *handler.VerificationHandler
|
verificationHandler *handler.VerificationHandler
|
||||||
adminVerificationHandler *handler.AdminVerificationHandler
|
adminVerificationHandler *handler.AdminVerificationHandler
|
||||||
adminProfileAuditHandler *handler.AdminProfileAuditHandler
|
adminProfileAuditHandler *handler.AdminProfileAuditHandler
|
||||||
|
setupHandler *handler.SetupHandler
|
||||||
wsHandler *handler.WSHandler
|
wsHandler *handler.WSHandler
|
||||||
logService *service.LogService
|
logService *service.LogService
|
||||||
jwtService *service.JWTService
|
jwtService *service.JWTService
|
||||||
@@ -80,6 +81,7 @@ func New(
|
|||||||
verificationHandler *handler.VerificationHandler,
|
verificationHandler *handler.VerificationHandler,
|
||||||
adminVerificationHandler *handler.AdminVerificationHandler,
|
adminVerificationHandler *handler.AdminVerificationHandler,
|
||||||
adminProfileAuditHandler *handler.AdminProfileAuditHandler,
|
adminProfileAuditHandler *handler.AdminProfileAuditHandler,
|
||||||
|
setupHandler *handler.SetupHandler,
|
||||||
logService *service.LogService,
|
logService *service.LogService,
|
||||||
activityService service.UserActivityService,
|
activityService service.UserActivityService,
|
||||||
casbinService service.CasbinService,
|
casbinService service.CasbinService,
|
||||||
@@ -121,6 +123,7 @@ func New(
|
|||||||
verificationHandler: verificationHandler,
|
verificationHandler: verificationHandler,
|
||||||
adminVerificationHandler: adminVerificationHandler,
|
adminVerificationHandler: adminVerificationHandler,
|
||||||
adminProfileAuditHandler: adminProfileAuditHandler,
|
adminProfileAuditHandler: adminProfileAuditHandler,
|
||||||
|
setupHandler: setupHandler,
|
||||||
logService: logService,
|
logService: logService,
|
||||||
jwtService: jwtService,
|
jwtService: jwtService,
|
||||||
casbinService: casbinService,
|
casbinService: casbinService,
|
||||||
@@ -157,6 +160,11 @@ func (r *Router) setupRoutes() {
|
|||||||
auth.POST("/refresh", r.userHandler.RefreshToken)
|
auth.POST("/refresh", r.userHandler.RefreshToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化超级管理员(公开接口,只能使用一次)
|
||||||
|
if r.setupHandler != nil {
|
||||||
|
v1.POST("/admin/setup-super-admin", r.setupHandler.SetupSuperAdmin)
|
||||||
|
}
|
||||||
|
|
||||||
// 需要认证的路由
|
// 需要认证的路由
|
||||||
authMiddleware := middleware.Auth(r.jwtService)
|
authMiddleware := middleware.Auth(r.jwtService)
|
||||||
|
|
||||||
|
|||||||
63
internal/service/setup_service.go
Normal file
63
internal/service/setup_service.go
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
apperrors "with_you/internal/errors"
|
||||||
|
"with_you/internal/model"
|
||||||
|
"with_you/internal/repository"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SetupService interface {
|
||||||
|
SetupSuperAdmin(ctx context.Context, userID, setupSecret string) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type setupService struct {
|
||||||
|
userRepo repository.UserRepository
|
||||||
|
roleRepo repository.RoleRepository
|
||||||
|
casbinSvc CasbinService
|
||||||
|
setupSecret string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSetupService(
|
||||||
|
userRepo repository.UserRepository,
|
||||||
|
roleRepo repository.RoleRepository,
|
||||||
|
casbinSvc CasbinService,
|
||||||
|
setupSecret string,
|
||||||
|
) SetupService {
|
||||||
|
return &setupService{
|
||||||
|
userRepo: userRepo,
|
||||||
|
roleRepo: roleRepo,
|
||||||
|
casbinSvc: casbinSvc,
|
||||||
|
setupSecret: setupSecret,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *setupService) SetupSuperAdmin(ctx context.Context, userID, setupSecret string) error {
|
||||||
|
if s.setupSecret == "" {
|
||||||
|
return apperrors.ErrSetupSecretNotConfigured
|
||||||
|
}
|
||||||
|
|
||||||
|
if setupSecret != s.setupSecret {
|
||||||
|
return apperrors.ErrInvalidSetupSecret
|
||||||
|
}
|
||||||
|
|
||||||
|
count, err := s.roleRepo.GetRoleUserCount(ctx, model.RoleSuperAdmin)
|
||||||
|
if err != nil {
|
||||||
|
return apperrors.ErrInternal
|
||||||
|
}
|
||||||
|
if count > 0 {
|
||||||
|
return apperrors.ErrSetupAlreadyCompleted
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := s.userRepo.GetByID(userID)
|
||||||
|
if err != nil {
|
||||||
|
return apperrors.ErrUserNotFound
|
||||||
|
}
|
||||||
|
|
||||||
|
if user.Status == model.UserStatusBanned {
|
||||||
|
return apperrors.ErrUserBanned
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.casbinSvc.AddRoleForUser(ctx, user.ID, model.RoleSuperAdmin)
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ var HandlerSet = wire.NewSet(
|
|||||||
ProvideScheduleHandler,
|
ProvideScheduleHandler,
|
||||||
ProvideWSHandler,
|
ProvideWSHandler,
|
||||||
ProvideAdminVerificationHandler,
|
ProvideAdminVerificationHandler,
|
||||||
|
ProvideSetupHandler,
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideUserHandler(
|
func ProvideUserHandler(
|
||||||
@@ -108,3 +109,9 @@ func ProvideAdminVerificationHandler(
|
|||||||
) *handler.AdminVerificationHandler {
|
) *handler.AdminVerificationHandler {
|
||||||
return handler.NewAdminVerificationHandler(adminVerificationService, userRepo)
|
return handler.NewAdminVerificationHandler(adminVerificationService, userRepo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ProvideSetupHandler(
|
||||||
|
setupService service.SetupService,
|
||||||
|
) *handler.SetupHandler {
|
||||||
|
return handler.NewSetupHandler(setupService)
|
||||||
|
}
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ var ServiceSet = wire.NewSet(
|
|||||||
ProvideAdminVerificationService,
|
ProvideAdminVerificationService,
|
||||||
ProvideSensitiveService,
|
ProvideSensitiveService,
|
||||||
ProvideUserProfileAuditService,
|
ProvideUserProfileAuditService,
|
||||||
|
ProvideSetupService,
|
||||||
|
|
||||||
// 日志服务
|
// 日志服务
|
||||||
ProvideAsyncLogManager,
|
ProvideAsyncLogManager,
|
||||||
@@ -476,3 +477,12 @@ func ProvideUserProfileAuditService(
|
|||||||
) service.UserProfileAuditService {
|
) service.UserProfileAuditService {
|
||||||
return service.NewUserProfileAuditService(auditRepo, userRepo, hookManager, moderationHooks)
|
return service.NewUserProfileAuditService(auditRepo, userRepo, hookManager, moderationHooks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ProvideSetupService(
|
||||||
|
userRepo repository.UserRepository,
|
||||||
|
roleRepo repository.RoleRepository,
|
||||||
|
casbinSvc service.CasbinService,
|
||||||
|
cfg *config.Config,
|
||||||
|
) service.SetupService {
|
||||||
|
return service.NewSetupService(userRepo, roleRepo, casbinSvc, cfg.SetupSecret)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user