package bootstrap import ( "context" "fmt" "haixun-backend/internal/config" libmongo "haixun-backend/internal/library/mongo" jobrepo "haixun-backend/internal/model/job/repository" memberrepo "haixun-backend/internal/model/member/repository" permissionrepo "haixun-backend/internal/model/permission/repository" permissionuc "haixun-backend/internal/model/permission/usecase" settingrepo "haixun-backend/internal/model/setting/repository" ) type InitOptions struct { TenantID string AdminEmail string AdminPass string DisplayName string } type InitReport struct { IndexesEnsured bool PermissionsSeeded bool RolePermissionsSeeded bool AdminUID string AdminCreated bool } func Init(ctx context.Context, cfg config.Config, opts InitOptions) (*InitReport, error) { if cfg.Mongo.URI == "" || cfg.Mongo.Database == "" { return nil, fmt.Errorf("mongo URI and database are required") } if opts.TenantID == "" { return nil, fmt.Errorf("tenant_id is required") } if opts.AdminEmail == "" || opts.AdminPass == "" { return nil, fmt.Errorf("admin email and password are required") } mongoClient, err := libmongo.NewClient(ctx, cfg.Mongo) if err != nil { return nil, fmt.Errorf("connect mongo: %w", err) } defer func() { _ = mongoClient.Close(ctx) }() db := mongoClient.Database() report := &InitReport{} settingRepository := settingrepo.NewMongoRepository(db) memberRepository := memberrepo.NewMongoRepository(db) permissionRepository := permissionrepo.NewMongoPermissionRepository(db) rolePermissionRepository := permissionrepo.NewMongoRolePermissionRepository(db) jobTemplateRepository := jobrepo.NewMongoTemplateRepository(db) jobRunRepository := jobrepo.NewMongoRunRepository(db) jobScheduleRepository := jobrepo.NewMongoScheduleRepository(db) jobEventRepository := jobrepo.NewMongoEventRepository(db) repos := []struct { name string fn func(context.Context) error }{ {"settings", settingRepository.EnsureIndexes}, {"members", memberRepository.EnsureIndexes}, {"permissions", permissionRepository.EnsureIndexes}, {"role_permissions", rolePermissionRepository.EnsureIndexes}, {"job_templates", jobTemplateRepository.EnsureIndexes}, {"job_runs", jobRunRepository.EnsureIndexes}, {"job_schedules", jobScheduleRepository.EnsureIndexes}, {"job_events", jobEventRepository.EnsureIndexes}, } for _, repo := range repos { if err := repo.fn(ctx); err != nil { return nil, fmt.Errorf("ensure %s indexes: %w", repo.name, err) } } report.IndexesEnsured = true permissionUseCase := permissionuc.NewUseCase(permissionRepository, rolePermissionRepository) if err := permissionUseCase.EnsureDefaultPermissions(ctx); err != nil { return nil, fmt.Errorf("seed permissions catalog: %w", err) } report.PermissionsSeeded = true if err := permissionUseCase.EnsureDefaultRolePermissions(ctx, opts.TenantID); err != nil { return nil, fmt.Errorf("seed role permissions: %w", err) } report.RolePermissionsSeeded = true admin, created, err := EnsureAdminMember(ctx, memberRepository, AdminOptions{ TenantID: opts.TenantID, Email: opts.AdminEmail, Password: opts.AdminPass, DisplayName: opts.DisplayName, }) if err != nil { return nil, err } report.AdminUID = admin.UID report.AdminCreated = created return report, nil }