package api import ( domainArticle "RenewCMS/internal/domain/article" domainImage "RenewCMS/internal/domain/image" domainInvite "RenewCMS/internal/domain/invite" domainMail "RenewCMS/internal/domain/mail" domainUser "RenewCMS/internal/domain/user" "RenewCMS/internal/infrastructure/config" "RenewCMS/internal/infrastructure/hashing" "RenewCMS/internal/infrastructure/mailer" "RenewCMS/internal/infrastructure/persistence/models" persistence "RenewCMS/internal/infrastructure/persistence/repositories" "RenewCMS/internal/infrastructure/useCases" "fmt" "os" "path/filepath" "github.com/glebarez/sqlite" "github.com/go-chi/jwtauth/v5" "gorm.io/gorm" ) type UseCases struct { Token *jwtauth.JWTAuth CreateArticleUseCase *useCases.CreateArticleUseCase GetArticleUseCase *useCases.GetArticleUseCase ListArticlesUseCase *useCases.ListArticlesUseCase UpdateArticleUseCase *useCases.UpdateArticleUseCase DeleteArticleUseCase *useCases.DeleteArticleUseCase GetUserUseCase *useCases.GetUserUseCase CreateUserUseCase *useCases.CreateUserUseCase AuthenticateUserUseCase *useCases.AuthenticateUserUseCase VerifyUserUseCase *useCases.VerifyUserUseCase CancelRegistrationUseCase *useCases.CancelRegistrationUseCase RequestPasswordResetUseCase *useCases.RequestPasswordResetUseCase ResetPasswordUseCase *useCases.ResetPasswordUseCase UpdateUserProfileUseCase *useCases.UpdateUserProfileUseCase ListUsersUseCase *useCases.ListUsersUseCase CreateInviteUseCase *useCases.CreateInviteUseCase ListUsersAndInvitesUseCase *useCases.ListUsersAndInvitesUseCase GetInviteUseCase *useCases.GetInviteUseCase AcceptInviteUseCase *useCases.AcceptInviteUseCase SendMailUseCase *useCases.SendMailUseCase CreateImageUseCase *useCases.CreateImageUseCase DeleteImageUseCase *useCases.DeleteImageUseCase GetSettingsUseCase *useCases.GetSettingsUseCase } type Repositories struct { ArticleRepo domainArticle.Repository UserRepo domainUser.Repository ImageRepo domainImage.Repository InviteRepo domainInvite.Repository MailRepo domainMail.Repository } const sqliteBusyTimeoutMs = 5000 func SQLiteDSN(dbName string) string { return fmt.Sprintf("%s?_pragma=busy_timeout(%d)", dbName, sqliteBusyTimeoutMs) } func getDb(dbName string) *gorm.DB { if err := os.MkdirAll(filepath.Dir(dbName), os.ModePerm); err != nil { panic("Unable to create necessary subdirectories: " + err.Error()) } db, err := gorm.Open(sqlite.Open(SQLiteDSN(dbName)), &gorm.Config{}) if err != nil { panic("Unable to open the database: " + err.Error()) } if err := db.AutoMigrate(&models.Article{}, &models.User{}, &models.Invite{}); err != nil { panic("Failed to migrate database: " + err.Error()) } return db } func getRepositories(db *gorm.DB, settings config.Settings) *Repositories { return &Repositories{ ArticleRepo: persistence.NewArticleRepository(db), UserRepo: persistence.NewUserRepository(db), ImageRepo: persistence.NewImageRepository(db, settings.UploadDir), InviteRepo: persistence.NewInviteRepository(db), MailRepo: mailer.NewMailRepository(settings.Smtp), } } func getUseCases(repos *Repositories, settings config.Settings) *UseCases { hasher := hashing.NewBcryptHasher() return &UseCases{ Token: jwtauth.New("HS256", []byte(settings.JWTSecret), nil), CreateArticleUseCase: useCases.NewCreateArticleUseCase(repos.ArticleRepo), GetArticleUseCase: useCases.NewGetArticleUseCase(repos.ArticleRepo), ListArticlesUseCase: useCases.NewListArticlesUseCase(repos.ArticleRepo), UpdateArticleUseCase: useCases.NewUpdateArticleUseCase(repos.ArticleRepo), DeleteArticleUseCase: useCases.NewDeleteArticleUseCase(repos.ArticleRepo, repos.ImageRepo), GetUserUseCase: useCases.NewGetUserUseCase(repos.UserRepo), CreateUserUseCase: useCases.NewCreateUserUseCase(repos.UserRepo, hasher, repos.MailRepo, settings.PublicURL), AuthenticateUserUseCase: useCases.NewAuthenticateUserUseCase(repos.UserRepo, hasher), VerifyUserUseCase: useCases.NewVerifyUserUseCase(repos.UserRepo, hasher), CancelRegistrationUseCase: useCases.NewCancelRegistrationUseCase(repos.UserRepo), RequestPasswordResetUseCase: useCases.NewRequestPasswordResetUseCase(repos.UserRepo, hasher, repos.MailRepo, settings.PublicURL), ResetPasswordUseCase: useCases.NewResetPasswordUseCase(repos.UserRepo, hasher), UpdateUserProfileUseCase: useCases.NewUpdateUserProfileUseCase(repos.UserRepo), ListUsersUseCase: useCases.NewListUsersUseCase(repos.UserRepo), CreateInviteUseCase: useCases.NewCreateInviteUseCase(repos.UserRepo, repos.InviteRepo, hasher, repos.MailRepo, settings.PublicURL), ListUsersAndInvitesUseCase: useCases.NewListUsersAndInvitesUseCase(repos.UserRepo, repos.InviteRepo), GetInviteUseCase: useCases.NewGetInviteUseCase(repos.InviteRepo, hasher), AcceptInviteUseCase: useCases.NewAcceptInviteUseCase(repos.UserRepo, repos.InviteRepo, hasher), SendMailUseCase: useCases.NewSendMailUseCase(repos.MailRepo), CreateImageUseCase: useCases.NewCreateImageUseCase(repos.ImageRepo), DeleteImageUseCase: useCases.NewDeleteImageUseCase(repos.ImageRepo), GetSettingsUseCase: useCases.NewGetSettingsUseCase(settings.Version), } } func InitContainer(settings config.Settings) (*UseCases, func() error) { db := getDb(settings.DBFile) repos := getRepositories(db, settings) return getUseCases(repos, settings), closeDb(db) } func closeDb(db *gorm.DB) func() error { return func() error { sqlDb, err := db.DB() if err != nil { return err } return sqlDb.Close() } }