Initial commit: Open sourcing all of the Maple Open Technologies code.

This commit is contained in:
Bartlomiej Mika 2025-12-02 14:33:08 -05:00
commit 755d54a99d
2010 changed files with 448675 additions and 0 deletions

View file

@ -0,0 +1,108 @@
package app
import (
"context"
"go.uber.org/zap"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/scheduler"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/leaderelection"
)
// Application represents the main application
type Application struct {
cfg *config.Config
logger *zap.Logger
server *http.Server
leaderElection leaderelection.LeaderElection
quotaScheduler *scheduler.QuotaResetScheduler
ipCleanupScheduler *scheduler.IPCleanupScheduler
}
// ProvideApplication creates a new Application
func ProvideApplication(
cfg *config.Config,
logger *zap.Logger,
server *http.Server,
leaderElection leaderelection.LeaderElection,
quotaScheduler *scheduler.QuotaResetScheduler,
ipCleanupScheduler *scheduler.IPCleanupScheduler,
) *Application {
return &Application{
cfg: cfg,
logger: logger,
server: server,
leaderElection: leaderElection,
quotaScheduler: quotaScheduler,
ipCleanupScheduler: ipCleanupScheduler,
}
}
// Run starts the application
func (a *Application) Run(ctx context.Context) error {
a.logger.Info("")
a.logger.Info("╔═══════════════════════════════════════════════╗")
a.logger.Info("║ MaplePress Backend Starting... ║")
a.logger.Info("╚═══════════════════════════════════════════════╝")
a.logger.Info("",
zap.String("environment", a.cfg.App.Environment),
zap.String("version", a.cfg.App.Version))
a.logger.Info("")
// Start leader election in background if enabled
if a.cfg.LeaderElection.Enabled {
go func() {
a.logger.Info("starting leader election")
if err := a.leaderElection.Start(ctx); err != nil {
a.logger.Error("leader election stopped", zap.Error(err))
}
}()
} else {
a.logger.Warn("leader election is DISABLED - all schedulers will run on every instance")
}
// Start quota reset scheduler
if err := a.quotaScheduler.Start(); err != nil {
a.logger.Error("failed to start quota scheduler", zap.Error(err))
return err
}
// Start IP cleanup scheduler for GDPR compliance
if err := a.ipCleanupScheduler.Start(); err != nil {
a.logger.Error("failed to start IP cleanup scheduler", zap.Error(err))
return err
}
return a.server.Start()
}
// Shutdown gracefully shuts down the application
func (a *Application) Shutdown(ctx context.Context) error {
a.logger.Info("shutting down MaplePress Backend")
// Stop leader election first if enabled
if a.cfg.LeaderElection.Enabled {
a.logger.Info("stopping leader election")
if err := a.leaderElection.Stop(); err != nil {
a.logger.Error("failed to stop leader election", zap.Error(err))
}
}
// Stop quota scheduler
a.quotaScheduler.Stop()
// Stop IP cleanup scheduler
a.ipCleanupScheduler.Stop()
if err := a.server.Shutdown(ctx); err != nil {
a.logger.Error("failed to shutdown server", zap.Error(err))
return err
}
// Sync logger before exit
a.logger.Sync()
return nil
}

View file

@ -0,0 +1,224 @@
//go:build wireinject
// +build wireinject
package app
import (
"github.com/google/wire"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/config"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/http/middleware"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/admin"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/gateway"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/healthcheck"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/plugin"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/site"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/tenant"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/interface/http/handler/user"
siterepo "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/repo"
tenantrepo "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/repository/tenant"
userrepo "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/repository/user"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/scheduler"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service"
gatewaysvc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/gateway"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/ipcleanup"
pagesvc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/page"
securityeventservice "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/securityevent"
sitesvc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/site"
tenantsvc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/tenant"
usersvc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/service/user"
gatewayuc "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/gateway"
pageusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/page"
siteusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/site"
tenantusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/tenant"
userusecase "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/internal/usecase/user"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/cache"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/distributedmutex"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/dns"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/leaderelection"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/logger"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/ratelimit"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/search"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/security"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/security/apikey"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/security/ipcrypt"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/security/password"
rediscache "codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/storage/cache"
"codeberg.org/mapleopentech/monorepo/cloud/maplepress-backend/pkg/storage/database"
)
// InitializeApplication wires up all dependencies
func InitializeApplication(cfg *config.Config) (*Application, error) {
wire.Build(
// Infrastructure layer (pkg/)
logger.ProvideLogger,
database.ProvideCassandraSession,
// Cache layer
rediscache.ProvideRedisClient,
cache.ProvideRedisCache,
cache.ProvideCassandraCache,
cache.ProvideTwoTierCache,
// Security layer
security.ProvideJWTProvider,
password.NewPasswordProvider,
password.NewPasswordValidator,
password.NewBreachChecker, // CWE-521: Password breach checking
security.ProvideClientIPExtractor, // CWE-348: X-Forwarded-For validation
apikey.ProvideGenerator,
apikey.ProvideHasher,
ipcrypt.ProvideIPEncryptor, // CWE-359: IP encryption for GDPR compliance
// Meilisearch client
search.ProvideClient,
// DNS verifier (for domain ownership verification)
dns.ProvideVerifier,
// Rate limiter
ratelimit.ProvideLoginRateLimiter, // CWE-307: Login rate limiting and account lockout
// Distributed mutex (for race condition prevention)
distributedmutex.ProvideDistributedMutexAdapter,
// Leader election (for distributed scheduling)
leaderelection.ProvideLeaderElection,
// Repository layer (internal/repository/)
siterepo.NewSiteRepository,
siterepo.NewPageRepository,
tenantrepo.ProvideRepository,
userrepo.ProvideRepository,
// Use case layer (internal/usecase/)
// Tenant usecases - refactored to focused operations
tenantusecase.ProvideValidateTenantSlugUniqueUseCase,
tenantusecase.ProvideCreateTenantEntityUseCase,
tenantusecase.ProvideSaveTenantToRepoUseCase,
tenantusecase.ProvideGetTenantUseCase,
tenantusecase.ProvideDeleteTenantUseCase, // For SAGA compensation
// User usecases - refactored to focused operations
userusecase.ProvideValidateUserEmailUniqueUseCase,
userusecase.ProvideCreateUserEntityUseCase,
userusecase.ProvideSaveUserToRepoUseCase,
userusecase.ProvideGetUserUseCase,
userusecase.ProvideDeleteUserUseCase, // For SAGA compensation
// Gateway usecases - focused operations only (no orchestration)
// Register usecases (used by RegisterService)
gatewayuc.ProvideValidateRegistrationInputUseCase,
gatewayuc.ProvideCheckTenantSlugAvailabilityUseCase,
gatewayuc.ProvideCheckPasswordBreachUseCase, // CWE-521: Password breach checking
gatewayuc.ProvideHashPasswordUseCase,
// Login usecases (used by LoginUseCase)
gatewayuc.ProvideGetUserByEmailUseCase,
gatewayuc.ProvideVerifyPasswordUseCase,
gatewayuc.ProvideLoginUseCase,
// Site usecases - refactored to focused operations
siteusecase.ProvideValidateDomainUseCase,
siteusecase.ProvideGenerateAPIKeyUseCase,
siteusecase.ProvideGenerateVerificationTokenUseCase,
siteusecase.ProvideCreateSiteEntityUseCase,
siteusecase.ProvideSaveSiteToRepoUseCase,
siteusecase.ProvideGetSiteUseCase,
siteusecase.ProvideListSitesUseCase,
siteusecase.ProvideValidateSiteForDeletionUseCase,
siteusecase.ProvideDeleteSiteFromRepoUseCase,
siteusecase.ProvideUpdateSiteAPIKeyUseCase,
siteusecase.ProvideUpdateSiteAPIKeyToRepoUseCase,
siteusecase.ProvideAuthenticateAPIKeyUseCase,
siteusecase.ProvideVerifySiteUseCase,
// Page usecases - refactored to focused operations
// Sync usecases
pageusecase.ProvideValidateSiteUseCase,
pageusecase.ProvideEnsureSearchIndexUseCase,
pageusecase.ProvideCreatePageEntityUseCase,
pageusecase.ProvideUpsertPageUseCase,
pageusecase.ProvideIndexPageToSearchUseCase,
pageusecase.ProvideUpdateSiteUsageUseCase,
// Delete usecases
pageusecase.ProvideValidateSiteForDeletionUseCase,
pageusecase.ProvideDeletePagesFromRepoUseCase,
pageusecase.ProvideDeletePagesFromSearchUseCase,
// Search usecases
pageusecase.ProvideValidateSiteForSearchUseCase,
pageusecase.ProvideExecuteSearchQueryUseCase,
pageusecase.ProvideIncrementSearchCountUseCase,
// Status usecases
pageusecase.ProvideValidateSiteForStatusUseCase,
pageusecase.ProvideGetPageStatisticsUseCase,
pageusecase.ProvideGetSearchIndexStatusUseCase,
pageusecase.ProvideGetPageByIDUseCase,
siteusecase.ProvideResetMonthlyUsageUseCase,
// Service layer (internal/service/)
service.ProvideSessionService,
tenantsvc.ProvideCreateTenantService,
tenantsvc.ProvideGetTenantService,
usersvc.ProvideCreateUserService,
usersvc.ProvideGetUserService,
sitesvc.ProvideCreateSiteService,
sitesvc.ProvideGetSiteService,
sitesvc.ProvideListSitesService,
sitesvc.ProvideDeleteSiteService,
sitesvc.ProvideRotateAPIKeyService,
sitesvc.ProvideAuthenticateAPIKeyService,
sitesvc.ProvideVerifySiteService,
gatewaysvc.ProvideRegisterService,
gatewaysvc.ProvideLoginService,
gatewaysvc.ProvideRefreshTokenService,
pagesvc.NewSyncPagesService,
pagesvc.NewSearchPagesService,
pagesvc.NewDeletePagesService,
pagesvc.NewSyncStatusService,
ipcleanup.ProvideCleanupService, // CWE-359: IP cleanup for GDPR compliance
securityeventservice.ProvideSecurityEventLogger, // CWE-778: Security event logging
// Middleware layer
middleware.ProvideJWTMiddleware,
middleware.ProvideAPIKeyMiddleware,
middleware.ProvideRateLimitMiddlewares, // CWE-770: Registration and auth endpoints rate limiting
middleware.ProvideSecurityHeadersMiddleware,
middleware.ProvideRequestSizeLimitMiddleware, // CWE-770: Request size limits
// Handler layer (internal/interface/http/handler/)
healthcheck.ProvideHealthCheckHandler,
gateway.ProvideRegisterHandler,
gateway.ProvideLoginHandler,
gateway.ProvideRefreshTokenHandler,
gateway.ProvideHelloHandler,
gateway.ProvideMeHandler,
tenant.ProvideCreateHandler,
tenant.ProvideGetHandler,
user.ProvideCreateHandler,
user.ProvideGetHandler,
site.ProvideCreateHandler,
site.ProvideGetHandler,
site.ProvideListHandler,
site.ProvideDeleteHandler,
site.ProvideRotateAPIKeyHandler,
site.ProvideVerifySiteHandler,
plugin.ProvideStatusHandler,
plugin.ProvidePluginVerifyHandler,
plugin.ProvideVersionHandler,
plugin.ProvideSyncPagesHandler,
plugin.ProvideSearchPagesHandler,
plugin.ProvideDeletePagesHandler,
plugin.ProvideSyncStatusHandler,
admin.ProvideUnlockAccountHandler, // CWE-307: Admin account unlock
admin.ProvideAccountStatusHandler, // CWE-307: Admin account status check
// Scheduler layer (internal/scheduler/)
scheduler.ProvideQuotaResetScheduler,
scheduler.ProvideIPCleanupScheduler, // CWE-359: IP cleanup for GDPR compliance
// HTTP server (internal/interface/http/)
http.ProvideServer,
// Application
ProvideApplication,
)
return nil, nil
}