template-monorepo/internal/svc/service_context.go

203 lines
6.3 KiB
Go

// Code scaffolded by goctl. Safe to edit.
// goctl 1.10.1
package svc
import (
"context"
"gateway/internal/config"
libmongo "gateway/internal/library/mongo"
redislib "gateway/internal/library/redis"
"gateway/internal/library/validate"
"gateway/internal/library/zitadel"
"gateway/internal/middleware"
authdomrepo "gateway/internal/model/auth/domain/repository"
domauth "gateway/internal/model/auth/domain/usecase"
authrepo "gateway/internal/model/auth/repository"
authusecase "gateway/internal/model/auth/usecase"
domrepo "gateway/internal/model/member/domain/repository"
dommember "gateway/internal/model/member/domain/usecase"
memberusecase "gateway/internal/model/member/usecase"
domnotif "gateway/internal/model/notification/domain/usecase"
notifusecase "gateway/internal/model/notification/usecase"
dompermrepo "gateway/internal/model/permission/domain/repository"
domperm "gateway/internal/model/permission/domain/usecase"
permusecase "gateway/internal/model/permission/usecase"
"gateway/internal/worker/notification_retry"
"github.com/zeromicro/go-zero/rest"
)
type ServiceContext struct {
Config config.Config
Validator validate.Validate
Redis *redislib.Client
AuthToken domauth.TokenUseCase
AuthInvite domauth.InviteUseCase
AuthRegistrationMeta domauth.RegistrationMetaUseCase
AuthRegistrationSession domauth.RegistrationSessionUseCase
AuthLoginSession domauth.LoginSessionUseCase
AuthLoginMFAChallenge domauth.LoginMFAChallengeUseCase
Zitadel *zitadel.Client
Notifier domnotif.NotifierUseCase
NotificationAdmin domnotif.AdminNotifierUseCase
NotificationRetry *notification_retry.Runner
MemberOTP dommember.OTPUseCase
MemberTOTP dommember.TOTPUseCase
MemberStepUp dommember.StepUpUseCase
MemberProfile dommember.ProfileUseCase
MemberLifecycle dommember.LifecycleUseCase
MemberProvisioning dommember.ProvisioningUseCase
MemberTenant dommember.TenantUseCase
MemberVerifyRate dommember.VerifyRateUseCase
MemberRepo domrepo.MemberRepository
PermissionCatalog domperm.PermissionUseCase
PermissionRole domperm.RoleUseCase
PermissionRolePermission domperm.RolePermissionUseCase
PermissionUserRole domperm.UserRoleUseCase
PermissionRoleMapping domperm.RoleMappingUseCase
PermissionAuthQuery domperm.AuthorizationQueryUseCase
PermissionRBAC domperm.RBACUseCase
PermissionRoleRepo dompermrepo.RoleRepository
permissionModule *permusecase.Module
// Middlewares mounted per route group via .api `middleware:` directive.
// AuthJWT enforces Bearer token (sets actor on ctx).
// CasbinRBAC enforces RBAC; must be chained AFTER AuthJWT.
AuthJWT rest.Middleware
CasbinRBAC rest.Middleware
}
func NewServiceContext(c config.Config) *ServiceContext {
v, err := validate.NewWithDefaultEN()
if err != nil {
panic(err)
}
rds, err := redislib.NewClient(c.Redis)
if err != nil {
panic(err)
}
sc := &ServiceContext{
Config: c,
Validator: v,
Redis: rds,
}
authCfg := c.Auth.Defaults()
if authCfg.Enabled() {
var revoke authdomrepo.TokenRevokeStore
if rds != nil && rds.Zero() != nil {
revoke = authrepo.NewRedisTokenRevokeStore(rds)
}
sc.AuthToken = authusecase.MustTokenUseCase(authusecase.TokenUseCaseParam{
Config: authCfg,
Revoke: revoke,
})
}
zClient, err := zitadel.NewClient(c.Zitadel)
if err != nil {
panic(err)
}
sc.Zitadel = zClient
if c.Mongo.Host != "" {
mod, err := notifusecase.NewModuleFromParam(notifusecase.FactoryParam{
MongoConf: &c.Mongo,
Redis: rds,
Config: c.Notification,
})
if err != nil {
panic(err)
}
sc.Notifier = mod.Notifier
sc.NotificationAdmin = mod.Admin
sc.NotificationRetry = notification_retry.NewRunner(mod.RetryWorker)
authMod, err := authusecase.NewModuleFromParam(authusecase.ModuleParam{
MongoConf: &c.Mongo,
Redis: rds,
})
if err != nil {
panic(err)
}
sc.AuthInvite = authMod.Invite
sc.AuthRegistrationMeta = authMod.RegistrationMeta
sc.AuthRegistrationSession = authMod.RegistrationSession
sc.AuthLoginSession = authMod.LoginSession
sc.AuthLoginMFAChallenge = authMod.LoginMFAChallenge
}
if rds != nil && rds.Zero() != nil {
var mongoConf *libmongo.Conf
if c.Mongo.Host != "" {
mongoConf = &c.Mongo
}
memberMod, err := memberusecase.NewModuleFromParam(memberusecase.ModuleParam{
Redis: rds,
MongoConf: mongoConf,
Config: c.Member,
})
if err != nil {
panic(err)
}
sc.MemberOTP = memberMod.OTP
sc.MemberTOTP = memberMod.TOTP
sc.MemberStepUp = memberMod.StepUp
sc.MemberProfile = memberMod.Profile
sc.MemberLifecycle = memberMod.Lifecycle
sc.MemberProvisioning = memberMod.Provisioning
sc.MemberTenant = memberMod.Tenant
sc.MemberVerifyRate = memberMod.VerifyRate
sc.MemberRepo = memberMod.Members
}
if c.Mongo.Host != "" {
permMod, err := permusecase.NewModuleFromParam(permusecase.FactoryParam{
MongoConf: &c.Mongo,
Redis: rds,
Config: c.Permission,
})
if err != nil {
panic(err)
}
sc.PermissionCatalog = permMod.Permission
sc.PermissionRole = permMod.Role
sc.PermissionRolePermission = permMod.RolePermission
sc.PermissionUserRole = permMod.UserRole
sc.PermissionRoleMapping = permMod.RoleMapping
sc.PermissionAuthQuery = permMod.AuthorizationQuery
sc.PermissionRBAC = permMod.RBAC
sc.PermissionRoleRepo = permMod.Roles
sc.permissionModule = permMod
}
// Wire middleware last so dependencies (AuthToken / PermissionRBAC)
// are populated. Each middleware tolerates nil deps (auth → 501,
// rbac → passthrough) so the gateway boots even with partial config.
sc.AuthJWT = middleware.NewAuthJWTMiddleware(sc.AuthToken).Handle
sc.CasbinRBAC = middleware.NewCasbinRBACMiddleware(sc.PermissionRBAC, middleware.CasbinRBACOptions{}).Handle
return sc
}
func (sc *ServiceContext) StartWorkers(ctx context.Context) {
if sc.NotificationRetry != nil {
sc.NotificationRetry.Start(ctx)
}
if sc.permissionModule != nil {
if err := sc.permissionModule.StartBackground(ctx); err != nil {
panic(err)
}
}
}
func (sc *ServiceContext) StopWorkers() {
if sc.NotificationRetry != nil {
sc.NotificationRetry.Stop()
}
if sc.permissionModule != nil {
sc.permissionModule.StopBackground()
}
}