Files

254 lines
8.4 KiB
Go

package bootstrap
import (
"context"
"fmt"
"net/http"
"github.com/italypaleale/francis/host/local"
"github.com/pocket-id/pocket-id/backend/internal/api"
"github.com/pocket-id/pocket-id/backend/internal/apikey"
"github.com/pocket-id/pocket-id/backend/internal/appconfig"
"github.com/pocket-id/pocket-id/backend/internal/auditlogs"
"github.com/pocket-id/pocket-id/backend/internal/common"
"github.com/pocket-id/pocket-id/backend/internal/devicelogin"
"github.com/pocket-id/pocket-id/backend/internal/email"
"github.com/pocket-id/pocket-id/backend/internal/emailverification"
"github.com/pocket-id/pocket-id/backend/internal/geolite"
"github.com/pocket-id/pocket-id/backend/internal/ldapsync"
"github.com/pocket-id/pocket-id/backend/internal/oidc"
"github.com/pocket-id/pocket-id/backend/internal/onetimeaccess"
"github.com/pocket-id/pocket-id/backend/internal/scimsync"
"github.com/pocket-id/pocket-id/backend/internal/service"
"github.com/pocket-id/pocket-id/backend/internal/storage"
"github.com/pocket-id/pocket-id/backend/internal/usersignup"
"github.com/pocket-id/pocket-id/backend/internal/webauthn"
"gorm.io/gorm"
)
type services struct {
appConfigService *appconfig.AppConfigService
appImagesService *service.AppImagesService
emailModule *email.Module
geoLiteModule *geolite.Module
auditLogService *service.AuditLogService
jwtService *service.JwtService
userService *service.UserService
customClaimService *service.CustomClaimService
oidcService *service.OidcService
userGroupService *service.UserGroupService
versionService *service.VersionService
fileStorage storage.FileStorage
apiKeyModule *apikey.Module
auditLogsModule *auditlogs.Module
deviceLoginModule *devicelogin.Module
ldapSyncModule *ldapsync.Module
scimSyncModule *scimsync.Module
oidcModule *oidc.Module
webauthnModule *webauthn.Module
userSignUpModule *usersignup.Module
oneTimeAccessModule *onetimeaccess.Module
emailVerificationModule *emailverification.Module
apiModule *api.Module
actors *local.Host
}
// Initializes all services
func initServices(
ctx context.Context,
db *gorm.DB,
instanceID string,
actors *local.Host,
httpClient *http.Client,
imageExtensions map[string]string,
fileStorage storage.FileStorage,
) (svc *services, err error) {
svc = &services{
actors: actors,
}
// Init the app config service
svc.appConfigService, err = appconfig.NewService(ctx, actors, db)
if err != nil {
return nil, fmt.Errorf("failed to create app config service: %w", err)
}
svc.fileStorage = fileStorage
svc.appImagesService = service.NewAppImagesService(imageExtensions, fileStorage)
svc.emailModule, err = email.New(db)
if err != nil {
return nil, fmt.Errorf("failed to create email module: %w", err)
}
svc.geoLiteModule, err = geolite.New(ctx, geolite.Dependencies{
HTTPClient: httpClient,
DBPath: common.EnvConfig.GeoLiteDBPath,
DownloadURL: common.EnvConfig.GeoLiteDBUrl,
LicenseKey: common.EnvConfig.MaxMindLicenseKey,
})
if err != nil {
return nil, fmt.Errorf("failed to create GeoLite module: %w", err)
}
svc.auditLogService = service.NewAuditLogService(db, svc.emailModule, svc.geoLiteModule, svc.appConfigService)
svc.auditLogsModule, err = auditlogs.New(auditlogs.Dependencies{
DB: db,
Actors: actors,
RetentionDays: common.EnvConfig.AuditLogRetentionDays,
// Disable in test environment
CleanupDisabled: common.EnvConfig.AppEnv.IsTest(),
})
if err != nil {
return nil, fmt.Errorf("failed to create audit logs module: %w", err)
}
svc.jwtService, err = service.NewJwtService(ctx, db, instanceID)
if err != nil {
return nil, fmt.Errorf("failed to create JWT service: %w", err)
}
svc.customClaimService = service.NewCustomClaimService(db)
svc.webauthnModule, err = webauthn.New(webauthn.Dependencies{
DB: db,
Actors: actors,
AppURL: common.EnvConfig.AppURL,
Signer: svc.jwtService,
AuditLog: svc.auditLogService,
AppConfig: svc.appConfigService,
// Disable in test environment
CleanupDisabled: common.EnvConfig.AppEnv.IsTest(),
})
if err != nil {
return nil, fmt.Errorf("failed to create WebAuthn module: %w", err)
}
svc.deviceLoginModule, err = devicelogin.New(devicelogin.Dependencies{
DB: db,
BaseURL: common.EnvConfig.AppURL,
Actors: actors,
Signer: svc.jwtService,
Reauth: svc.webauthnModule,
AuditLog: svc.auditLogService,
IPLocator: svc.geoLiteModule,
AppConfig: svc.appConfigService,
})
if err != nil {
return nil, fmt.Errorf("failed to create device login module: %w", err)
}
svc.scimSyncModule, err = scimsync.New(scimsync.Dependencies{
DB: db,
Actors: actors,
HTTPClient: httpClient,
// Disable in test environment
ScheduleDisabled: common.EnvConfig.AppEnv.IsTest(),
})
if err != nil {
return nil, fmt.Errorf("failed to create SCIM sync module: %w", err)
}
svc.apiModule = api.New(api.Dependencies{DB: db, Issuer: common.EnvConfig.AppURL})
svc.oidcModule, err = oidc.New(ctx, oidc.Dependencies{
DB: db,
Actors: actors,
HTTPClient: httpClient,
GetCIMDURLAllowlist: svc.appConfigService.GetCIMDURLAllowlist,
Config: oidc.Config{
BaseURL: common.EnvConfig.AppURL,
TokenBaseURL: common.EnvConfig.AppURL,
Secret: common.EnvConfig.EncryptionKey,
AllowInsecureCallbackURLs: common.EnvConfig.AllowInsecureCallbackURLs,
},
Signer: svc.jwtService,
CustomClaims: svc.customClaimService,
Reauth: svc.webauthnModule,
AuditLog: svc.auditLogService,
APIAccess: svc.apiModule,
// Disable in test environment
CleanupDisabled: common.EnvConfig.AppEnv.IsTest(),
})
if err != nil {
return nil, fmt.Errorf("failed to create OIDC module: %w", err)
}
svc.oidcService, err = service.NewOidcService(db, svc.jwtService, svc.oidcModule.Preview, svc.oidcModule, svc.scimSyncModule, httpClient, fileStorage)
if err != nil {
return nil, fmt.Errorf("failed to create OIDC service: %w", err)
}
svc.userGroupService = service.NewUserGroupService(db, svc.scimSyncModule)
svc.userService = service.NewUserService(db, svc.jwtService, svc.auditLogService, svc.customClaimService, svc.appImagesService, svc.scimSyncModule, fileStorage)
svc.ldapSyncModule, err = ldapsync.New(ldapsync.Dependencies{
DB: db,
Actors: actors,
HTTPClient: httpClient,
FileStorage: fileStorage,
Users: svc.userService,
Groups: svc.userGroupService,
AppConfig: svc.appConfigService,
ScimSync: svc.scimSyncModule,
// Disable in test environment
ScheduleDisabled: common.EnvConfig.AppEnv.IsTest(),
})
if err != nil {
return nil, fmt.Errorf("failed to create LDAP sync module: %w", err)
}
svc.apiKeyModule, err = apikey.New(ctx, apikey.Dependencies{
DB: db,
Actors: actors,
StaticApiKey: common.EnvConfig.StaticApiKey,
AppConfig: svc.appConfigService,
EmailSender: svc.emailModule,
CleanupDisabled: common.EnvConfig.AppEnv.IsTest(),
})
if err != nil {
return nil, fmt.Errorf("failed to create API key module: %w", err)
}
svc.userSignUpModule, err = usersignup.New(usersignup.Dependencies{
DB: db,
Actors: actors,
Signer: svc.jwtService,
AuditLog: svc.auditLogService,
UserCreator: svc.userService,
AppConfig: svc.appConfigService,
ScimSync: svc.scimSyncModule,
})
if err != nil {
return nil, fmt.Errorf("failed to create user signup module: %w", err)
}
svc.oneTimeAccessModule, err = onetimeaccess.New(onetimeaccess.Dependencies{
DB: db,
Actors: actors,
Signer: svc.jwtService,
AuditLog: svc.auditLogService,
UserProvider: svc.userService,
EmailSender: svc.emailModule,
AppConfig: svc.appConfigService,
})
if err != nil {
return nil, fmt.Errorf("failed to create one-time access module: %w", err)
}
svc.emailVerificationModule, err = emailverification.New(emailverification.Dependencies{
DB: db,
Actors: actors,
Users: svc.userService,
EmailSender: svc.emailModule,
AppConfig: svc.appConfigService,
AppURL: common.EnvConfig.AppURL,
})
if err != nil {
return nil, fmt.Errorf("failed to create email verification module: %w", err)
}
svc.versionService = service.NewVersionService(httpClient)
return svc, nil
}