@mdguggenbichler/slugbase-core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/dist/app-factory.d.ts +17 -0
- package/backend/dist/app-factory.d.ts.map +1 -0
- package/backend/dist/app-factory.js +106 -0
- package/backend/dist/app-factory.js.map +1 -0
- package/backend/dist/auth/authorization.d.ts +25 -0
- package/backend/dist/auth/authorization.d.ts.map +1 -0
- package/backend/dist/auth/authorization.js +100 -0
- package/backend/dist/auth/authorization.js.map +1 -0
- package/backend/dist/auth/jwt.d.ts +5 -0
- package/backend/dist/auth/jwt.d.ts.map +1 -0
- package/backend/dist/auth/jwt.js +34 -0
- package/backend/dist/auth/jwt.js.map +1 -0
- package/backend/dist/auth/oidc.d.ts +4 -0
- package/backend/dist/auth/oidc.d.ts.map +1 -0
- package/backend/dist/auth/oidc.js +201 -0
- package/backend/dist/auth/oidc.js.map +1 -0
- package/backend/dist/config/cloud-providers.d.ts +18 -0
- package/backend/dist/config/cloud-providers.d.ts.map +1 -0
- package/backend/dist/config/cloud-providers.js +60 -0
- package/backend/dist/config/cloud-providers.js.map +1 -0
- package/backend/dist/config/cookies.d.ts +17 -0
- package/backend/dist/config/cookies.d.ts.map +1 -0
- package/backend/dist/config/cookies.js +26 -0
- package/backend/dist/config/cookies.js.map +1 -0
- package/backend/dist/config/mode.d.ts +7 -0
- package/backend/dist/config/mode.d.ts.map +1 -0
- package/backend/dist/config/mode.js +7 -0
- package/backend/dist/config/mode.js.map +1 -0
- package/backend/dist/config/swagger.d.ts +2 -0
- package/backend/dist/config/swagger.d.ts.map +1 -0
- package/backend/dist/config/swagger.js +76 -0
- package/backend/dist/config/swagger.js.map +1 -0
- package/backend/dist/config.d.ts +29 -0
- package/backend/dist/config.d.ts.map +1 -0
- package/backend/dist/config.js +41 -0
- package/backend/dist/config.js.map +1 -0
- package/backend/dist/db/index.d.ts +14 -0
- package/backend/dist/db/index.d.ts.map +1 -0
- package/backend/dist/db/index.js +114 -0
- package/backend/dist/db/index.js.map +1 -0
- package/backend/dist/db/migrate-slug-nullable.d.ts +10 -0
- package/backend/dist/db/migrate-slug-nullable.d.ts.map +1 -0
- package/backend/dist/db/migrate-slug-nullable.js +87 -0
- package/backend/dist/db/migrate-slug-nullable.js.map +1 -0
- package/backend/dist/db/migrations/001_migrate_slug_nullable.d.ts +10 -0
- package/backend/dist/db/migrations/001_migrate_slug_nullable.d.ts.map +1 -0
- package/backend/dist/db/migrations/001_migrate_slug_nullable.js +103 -0
- package/backend/dist/db/migrations/001_migrate_slug_nullable.js.map +1 -0
- package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.d.ts +11 -0
- package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.d.ts.map +1 -0
- package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.js +92 -0
- package/backend/dist/db/migrations/002_add_oidc_custom_endpoints.js.map +1 -0
- package/backend/dist/db/migrations/003_add_bookmark_features.d.ts +5 -0
- package/backend/dist/db/migrations/003_add_bookmark_features.d.ts.map +1 -0
- package/backend/dist/db/migrations/003_add_bookmark_features.js +98 -0
- package/backend/dist/db/migrations/003_add_bookmark_features.js.map +1 -0
- package/backend/dist/db/migrations/004_make_slug_globally_unique.d.ts +12 -0
- package/backend/dist/db/migrations/004_make_slug_globally_unique.d.ts.map +1 -0
- package/backend/dist/db/migrations/004_make_slug_globally_unique.js +152 -0
- package/backend/dist/db/migrations/004_make_slug_globally_unique.js.map +1 -0
- package/backend/dist/db/migrations/005_add_email_verification.d.ts +5 -0
- package/backend/dist/db/migrations/005_add_email_verification.d.ts.map +1 -0
- package/backend/dist/db/migrations/005_add_email_verification.js +102 -0
- package/backend/dist/db/migrations/005_add_email_verification.js.map +1 -0
- package/backend/dist/db/migrations/006_refresh_tokens.d.ts +9 -0
- package/backend/dist/db/migrations/006_refresh_tokens.d.ts.map +1 -0
- package/backend/dist/db/migrations/006_refresh_tokens.js +61 -0
- package/backend/dist/db/migrations/006_refresh_tokens.js.map +1 -0
- package/backend/dist/db/migrations/007_password_reset_token_hash.d.ts +10 -0
- package/backend/dist/db/migrations/007_password_reset_token_hash.d.ts.map +1 -0
- package/backend/dist/db/migrations/007_password_reset_token_hash.js +40 -0
- package/backend/dist/db/migrations/007_password_reset_token_hash.js.map +1 -0
- package/backend/dist/db/migrations/008_slug_preferences.d.ts +8 -0
- package/backend/dist/db/migrations/008_slug_preferences.d.ts.map +1 -0
- package/backend/dist/db/migrations/008_slug_preferences.js +24 -0
- package/backend/dist/db/migrations/008_slug_preferences.js.map +1 -0
- package/backend/dist/db/migrations/009_signup_email_verified.d.ts +5 -0
- package/backend/dist/db/migrations/009_signup_email_verified.d.ts.map +1 -0
- package/backend/dist/db/migrations/009_signup_email_verified.js +79 -0
- package/backend/dist/db/migrations/009_signup_email_verified.js.map +1 -0
- package/backend/dist/db/migrations/010_organizations.d.ts +5 -0
- package/backend/dist/db/migrations/010_organizations.d.ts.map +1 -0
- package/backend/dist/db/migrations/010_organizations.js +113 -0
- package/backend/dist/db/migrations/010_organizations.js.map +1 -0
- package/backend/dist/db/migrations/011_org_scoped_teams.d.ts +11 -0
- package/backend/dist/db/migrations/011_org_scoped_teams.d.ts.map +1 -0
- package/backend/dist/db/migrations/011_org_scoped_teams.js +59 -0
- package/backend/dist/db/migrations/011_org_scoped_teams.js.map +1 -0
- package/backend/dist/db/migrations/012_org_invitations_token_hash.d.ts +10 -0
- package/backend/dist/db/migrations/012_org_invitations_token_hash.d.ts.map +1 -0
- package/backend/dist/db/migrations/012_org_invitations_token_hash.js +40 -0
- package/backend/dist/db/migrations/012_org_invitations_token_hash.js.map +1 -0
- package/backend/dist/db/migrations/013_signup_verification_token_hash.d.ts +10 -0
- package/backend/dist/db/migrations/013_signup_verification_token_hash.d.ts.map +1 -0
- package/backend/dist/db/migrations/013_signup_verification_token_hash.js +39 -0
- package/backend/dist/db/migrations/013_signup_verification_token_hash.js.map +1 -0
- package/backend/dist/db/migrations/014_stats_indexes.d.ts +8 -0
- package/backend/dist/db/migrations/014_stats_indexes.d.ts.map +1 -0
- package/backend/dist/db/migrations/014_stats_indexes.js +19 -0
- package/backend/dist/db/migrations/014_stats_indexes.js.map +1 -0
- package/backend/dist/db/migrations/015_api_tokens.d.ts +9 -0
- package/backend/dist/db/migrations/015_api_tokens.d.ts.map +1 -0
- package/backend/dist/db/migrations/015_api_tokens.js +48 -0
- package/backend/dist/db/migrations/015_api_tokens.js.map +1 -0
- package/backend/dist/db/migrations/016_free_plan_grace_ends_at.d.ts +9 -0
- package/backend/dist/db/migrations/016_free_plan_grace_ends_at.d.ts.map +1 -0
- package/backend/dist/db/migrations/016_free_plan_grace_ends_at.js +50 -0
- package/backend/dist/db/migrations/016_free_plan_grace_ends_at.js.map +1 -0
- package/backend/dist/db/migrations/017_ai_suggestions.d.ts +11 -0
- package/backend/dist/db/migrations/017_ai_suggestions.d.ts.map +1 -0
- package/backend/dist/db/migrations/017_ai_suggestions.js +78 -0
- package/backend/dist/db/migrations/017_ai_suggestions.js.map +1 -0
- package/backend/dist/db/migrations/018_ai_cache_output_language.d.ts +10 -0
- package/backend/dist/db/migrations/018_ai_cache_output_language.d.ts.map +1 -0
- package/backend/dist/db/migrations/018_ai_cache_output_language.js +89 -0
- package/backend/dist/db/migrations/018_ai_cache_output_language.js.map +1 -0
- package/backend/dist/db/migrations/019_ai_suggestion_usage.d.ts +10 -0
- package/backend/dist/db/migrations/019_ai_suggestion_usage.d.ts.map +1 -0
- package/backend/dist/db/migrations/019_ai_suggestion_usage.js +47 -0
- package/backend/dist/db/migrations/019_ai_suggestion_usage.js.map +1 -0
- package/backend/dist/db/migrations/020_tenant_scope.d.ts +5 -0
- package/backend/dist/db/migrations/020_tenant_scope.d.ts.map +1 -0
- package/backend/dist/db/migrations/020_tenant_scope.js +105 -0
- package/backend/dist/db/migrations/020_tenant_scope.js.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_010_organizations.d.ts +5 -0
- package/backend/dist/db/migrations/_legacy_cloud_010_organizations.d.ts.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_010_organizations.js +113 -0
- package/backend/dist/db/migrations/_legacy_cloud_010_organizations.js.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.d.ts +11 -0
- package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.d.ts.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.js +59 -0
- package/backend/dist/db/migrations/_legacy_cloud_011_org_scoped_teams.js.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.d.ts +10 -0
- package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.d.ts.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.js +40 -0
- package/backend/dist/db/migrations/_legacy_cloud_012_org_invitations_token_hash.js.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.d.ts +9 -0
- package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.d.ts.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.js +50 -0
- package/backend/dist/db/migrations/_legacy_cloud_016_free_plan_grace_ends_at.js.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.d.ts +11 -0
- package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.d.ts.map +1 -0
- package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.js +78 -0
- package/backend/dist/db/migrations/_legacy_cloud_017_ai_suggestions.js.map +1 -0
- package/backend/dist/db/migrations/index.d.ts +22 -0
- package/backend/dist/db/migrations/index.d.ts.map +1 -0
- package/backend/dist/db/migrations/index.js +194 -0
- package/backend/dist/db/migrations/index.js.map +1 -0
- package/backend/dist/db/pool.d.ts +13 -0
- package/backend/dist/db/pool.d.ts.map +1 -0
- package/backend/dist/db/pool.js +41 -0
- package/backend/dist/db/pool.js.map +1 -0
- package/backend/dist/db/seed-data.d.ts +66 -0
- package/backend/dist/db/seed-data.d.ts.map +1 -0
- package/backend/dist/db/seed-data.js +394 -0
- package/backend/dist/db/seed-data.js.map +1 -0
- package/backend/dist/db/seed.d.ts +19 -0
- package/backend/dist/db/seed.d.ts.map +1 -0
- package/backend/dist/db/seed.js +406 -0
- package/backend/dist/db/seed.js.map +1 -0
- package/backend/dist/index.d.ts +3 -0
- package/backend/dist/index.d.ts.map +1 -0
- package/backend/dist/index.js +64 -0
- package/backend/dist/index.js.map +1 -0
- package/backend/dist/instrument.d.ts +2 -0
- package/backend/dist/instrument.d.ts.map +1 -0
- package/backend/dist/instrument.js +16 -0
- package/backend/dist/instrument.js.map +1 -0
- package/backend/dist/load-env.d.ts +2 -0
- package/backend/dist/load-env.d.ts.map +1 -0
- package/backend/dist/load-env.js +33 -0
- package/backend/dist/load-env.js.map +1 -0
- package/backend/dist/middleware/auth.d.ts +23 -0
- package/backend/dist/middleware/auth.d.ts.map +1 -0
- package/backend/dist/middleware/auth.js +69 -0
- package/backend/dist/middleware/auth.js.map +1 -0
- package/backend/dist/middleware/error-handler.d.ts +11 -0
- package/backend/dist/middleware/error-handler.d.ts.map +1 -0
- package/backend/dist/middleware/error-handler.js +40 -0
- package/backend/dist/middleware/error-handler.js.map +1 -0
- package/backend/dist/middleware/security.d.ts +26 -0
- package/backend/dist/middleware/security.d.ts.map +1 -0
- package/backend/dist/middleware/security.js +162 -0
- package/backend/dist/middleware/security.js.map +1 -0
- package/backend/dist/middleware/stats-auth.d.ts +7 -0
- package/backend/dist/middleware/stats-auth.d.ts.map +1 -0
- package/backend/dist/middleware/stats-auth.js +20 -0
- package/backend/dist/middleware/stats-auth.js.map +1 -0
- package/backend/dist/middleware/tenant.d.ts +3 -0
- package/backend/dist/middleware/tenant.d.ts.map +1 -0
- package/backend/dist/middleware/tenant.js +13 -0
- package/backend/dist/middleware/tenant.js.map +1 -0
- package/backend/dist/register-routes.d.ts +12 -0
- package/backend/dist/register-routes.d.ts.map +1 -0
- package/backend/dist/register-routes.js +59 -0
- package/backend/dist/register-routes.js.map +1 -0
- package/backend/dist/routes/admin/demo-reset.d.ts +8 -0
- package/backend/dist/routes/admin/demo-reset.d.ts.map +1 -0
- package/backend/dist/routes/admin/demo-reset.js +66 -0
- package/backend/dist/routes/admin/demo-reset.js.map +1 -0
- package/backend/dist/routes/admin/settings.d.ts +3 -0
- package/backend/dist/routes/admin/settings.d.ts.map +1 -0
- package/backend/dist/routes/admin/settings.js +452 -0
- package/backend/dist/routes/admin/settings.js.map +1 -0
- package/backend/dist/routes/admin/stats.d.ts +7 -0
- package/backend/dist/routes/admin/stats.d.ts.map +1 -0
- package/backend/dist/routes/admin/stats.js +66 -0
- package/backend/dist/routes/admin/stats.js.map +1 -0
- package/backend/dist/routes/admin/teams.d.ts +3 -0
- package/backend/dist/routes/admin/teams.d.ts.map +1 -0
- package/backend/dist/routes/admin/teams.js +509 -0
- package/backend/dist/routes/admin/teams.js.map +1 -0
- package/backend/dist/routes/admin/users.d.ts +3 -0
- package/backend/dist/routes/admin/users.d.ts.map +1 -0
- package/backend/dist/routes/admin/users.js +525 -0
- package/backend/dist/routes/admin/users.js.map +1 -0
- package/backend/dist/routes/auth.d.ts +3 -0
- package/backend/dist/routes/auth.d.ts.map +1 -0
- package/backend/dist/routes/auth.js +992 -0
- package/backend/dist/routes/auth.js.map +1 -0
- package/backend/dist/routes/billing.d.ts +8 -0
- package/backend/dist/routes/billing.d.ts.map +1 -0
- package/backend/dist/routes/billing.js +481 -0
- package/backend/dist/routes/billing.js.map +1 -0
- package/backend/dist/routes/bookmarks.d.ts +3 -0
- package/backend/dist/routes/bookmarks.d.ts.map +1 -0
- package/backend/dist/routes/bookmarks.js +1593 -0
- package/backend/dist/routes/bookmarks.js.map +1 -0
- package/backend/dist/routes/config.d.ts +7 -0
- package/backend/dist/routes/config.d.ts.map +1 -0
- package/backend/dist/routes/config.js +52 -0
- package/backend/dist/routes/config.js.map +1 -0
- package/backend/dist/routes/contact.d.ts +9 -0
- package/backend/dist/routes/contact.d.ts.map +1 -0
- package/backend/dist/routes/contact.js +99 -0
- package/backend/dist/routes/contact.js.map +1 -0
- package/backend/dist/routes/csrf.d.ts +3 -0
- package/backend/dist/routes/csrf.d.ts.map +1 -0
- package/backend/dist/routes/csrf.js +39 -0
- package/backend/dist/routes/csrf.js.map +1 -0
- package/backend/dist/routes/dashboard.d.ts +3 -0
- package/backend/dist/routes/dashboard.d.ts.map +1 -0
- package/backend/dist/routes/dashboard.js +212 -0
- package/backend/dist/routes/dashboard.js.map +1 -0
- package/backend/dist/routes/email-verification.d.ts +3 -0
- package/backend/dist/routes/email-verification.d.ts.map +1 -0
- package/backend/dist/routes/email-verification.js +124 -0
- package/backend/dist/routes/email-verification.js.map +1 -0
- package/backend/dist/routes/folders.d.ts +3 -0
- package/backend/dist/routes/folders.d.ts.map +1 -0
- package/backend/dist/routes/folders.js +524 -0
- package/backend/dist/routes/folders.js.map +1 -0
- package/backend/dist/routes/go-helpers.d.ts +18 -0
- package/backend/dist/routes/go-helpers.d.ts.map +1 -0
- package/backend/dist/routes/go-helpers.js +64 -0
- package/backend/dist/routes/go-helpers.js.map +1 -0
- package/backend/dist/routes/go.d.ts +23 -0
- package/backend/dist/routes/go.d.ts.map +1 -0
- package/backend/dist/routes/go.js +361 -0
- package/backend/dist/routes/go.js.map +1 -0
- package/backend/dist/routes/health.d.ts +6 -0
- package/backend/dist/routes/health.d.ts.map +1 -0
- package/backend/dist/routes/health.js +79 -0
- package/backend/dist/routes/health.js.map +1 -0
- package/backend/dist/routes/invitations.d.ts +3 -0
- package/backend/dist/routes/invitations.d.ts.map +1 -0
- package/backend/dist/routes/invitations.js +172 -0
- package/backend/dist/routes/invitations.js.map +1 -0
- package/backend/dist/routes/oidc-providers.d.ts +3 -0
- package/backend/dist/routes/oidc-providers.d.ts.map +1 -0
- package/backend/dist/routes/oidc-providers.js +495 -0
- package/backend/dist/routes/oidc-providers.js.map +1 -0
- package/backend/dist/routes/organizations.d.ts +3 -0
- package/backend/dist/routes/organizations.d.ts.map +1 -0
- package/backend/dist/routes/organizations.js +538 -0
- package/backend/dist/routes/organizations.js.map +1 -0
- package/backend/dist/routes/password-reset.d.ts +3 -0
- package/backend/dist/routes/password-reset.d.ts.map +1 -0
- package/backend/dist/routes/password-reset.js +212 -0
- package/backend/dist/routes/password-reset.js.map +1 -0
- package/backend/dist/routes/redirect.d.ts +3 -0
- package/backend/dist/routes/redirect.d.ts.map +1 -0
- package/backend/dist/routes/redirect.js +124 -0
- package/backend/dist/routes/redirect.js.map +1 -0
- package/backend/dist/routes/tags.d.ts +3 -0
- package/backend/dist/routes/tags.d.ts.map +1 -0
- package/backend/dist/routes/tags.js +302 -0
- package/backend/dist/routes/tags.js.map +1 -0
- package/backend/dist/routes/teams.d.ts +3 -0
- package/backend/dist/routes/teams.d.ts.map +1 -0
- package/backend/dist/routes/teams.js +60 -0
- package/backend/dist/routes/teams.js.map +1 -0
- package/backend/dist/routes/tokens.d.ts +3 -0
- package/backend/dist/routes/tokens.d.ts.map +1 -0
- package/backend/dist/routes/tokens.js +157 -0
- package/backend/dist/routes/tokens.js.map +1 -0
- package/backend/dist/routes/users.d.ts +3 -0
- package/backend/dist/routes/users.d.ts.map +1 -0
- package/backend/dist/routes/users.js +199 -0
- package/backend/dist/routes/users.js.map +1 -0
- package/backend/dist/services/ai-suggestions.d.ts +29 -0
- package/backend/dist/services/ai-suggestions.d.ts.map +1 -0
- package/backend/dist/services/ai-suggestions.js +163 -0
- package/backend/dist/services/ai-suggestions.js.map +1 -0
- package/backend/dist/services/api-tokens.d.ts +66 -0
- package/backend/dist/services/api-tokens.d.ts.map +1 -0
- package/backend/dist/services/api-tokens.js +129 -0
- package/backend/dist/services/api-tokens.js.map +1 -0
- package/backend/dist/services/fetch-page-metadata.d.ts +15 -0
- package/backend/dist/services/fetch-page-metadata.d.ts.map +1 -0
- package/backend/dist/services/fetch-page-metadata.js +205 -0
- package/backend/dist/services/fetch-page-metadata.js.map +1 -0
- package/backend/dist/services/stats.d.ts +73 -0
- package/backend/dist/services/stats.d.ts.map +1 -0
- package/backend/dist/services/stats.js +145 -0
- package/backend/dist/services/stats.js.map +1 -0
- package/backend/dist/types/oidc-provider.d.ts +17 -0
- package/backend/dist/types/oidc-provider.d.ts.map +1 -0
- package/backend/dist/types/oidc-provider.js +2 -0
- package/backend/dist/types/oidc-provider.js.map +1 -0
- package/backend/dist/types.d.ts +86 -0
- package/backend/dist/types.d.ts.map +1 -0
- package/backend/dist/types.js +2 -0
- package/backend/dist/types.js.map +1 -0
- package/backend/dist/utils/ai-feature.d.ts +23 -0
- package/backend/dist/utils/ai-feature.d.ts.map +1 -0
- package/backend/dist/utils/ai-feature.js +62 -0
- package/backend/dist/utils/ai-feature.js.map +1 -0
- package/backend/dist/utils/email.d.ts +40 -0
- package/backend/dist/utils/email.d.ts.map +1 -0
- package/backend/dist/utils/email.js +456 -0
- package/backend/dist/utils/email.js.map +1 -0
- package/backend/dist/utils/encryption.d.ts +18 -0
- package/backend/dist/utils/encryption.d.ts.map +1 -0
- package/backend/dist/utils/encryption.js +95 -0
- package/backend/dist/utils/encryption.js.map +1 -0
- package/backend/dist/utils/env-validation.d.ts +6 -0
- package/backend/dist/utils/env-validation.d.ts.map +1 -0
- package/backend/dist/utils/env-validation.js +51 -0
- package/backend/dist/utils/env-validation.js.map +1 -0
- package/backend/dist/utils/jwt.d.ts +20 -0
- package/backend/dist/utils/jwt.d.ts.map +1 -0
- package/backend/dist/utils/jwt.js +48 -0
- package/backend/dist/utils/jwt.js.map +1 -0
- package/backend/dist/utils/org-cleanup.d.ts +6 -0
- package/backend/dist/utils/org-cleanup.d.ts.map +1 -0
- package/backend/dist/utils/org-cleanup.js +37 -0
- package/backend/dist/utils/org-cleanup.js.map +1 -0
- package/backend/dist/utils/organizations.d.ts +12 -0
- package/backend/dist/utils/organizations.d.ts.map +1 -0
- package/backend/dist/utils/organizations.js +24 -0
- package/backend/dist/utils/organizations.js.map +1 -0
- package/backend/dist/utils/plan-errors.d.ts +18 -0
- package/backend/dist/utils/plan-errors.d.ts.map +1 -0
- package/backend/dist/utils/plan-errors.js +21 -0
- package/backend/dist/utils/plan-errors.js.map +1 -0
- package/backend/dist/utils/refresh-token.d.ts +31 -0
- package/backend/dist/utils/refresh-token.d.ts.map +1 -0
- package/backend/dist/utils/refresh-token.js +63 -0
- package/backend/dist/utils/refresh-token.js.map +1 -0
- package/backend/dist/utils/session-store.d.ts +46 -0
- package/backend/dist/utils/session-store.d.ts.map +1 -0
- package/backend/dist/utils/session-store.js +222 -0
- package/backend/dist/utils/session-store.js.map +1 -0
- package/backend/dist/utils/tenant.d.ts +5 -0
- package/backend/dist/utils/tenant.d.ts.map +1 -0
- package/backend/dist/utils/tenant.js +12 -0
- package/backend/dist/utils/tenant.js.map +1 -0
- package/backend/dist/utils/user-key.d.ts +24 -0
- package/backend/dist/utils/user-key.d.ts.map +1 -0
- package/backend/dist/utils/user-key.js +116 -0
- package/backend/dist/utils/user-key.js.map +1 -0
- package/backend/dist/utils/validation.d.ts +91 -0
- package/backend/dist/utils/validation.d.ts.map +1 -0
- package/backend/dist/utils/validation.js +337 -0
- package/backend/dist/utils/validation.js.map +1 -0
- package/backend/index.js +15 -0
- package/frontend/index.js +5 -0
- package/frontend/index.tsx +7 -0
- package/package.json +16 -0
- package/types/index.js +4 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the Express app with middleware (security, CORS, session, passport, tenant, CSRF, Swagger).
|
|
3
|
+
* Does NOT mount API routes, static files, or error handlers — those are added by registerCoreRoutes and the app entry.
|
|
4
|
+
*/
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import { DatabaseSessionStore } from './utils/session-store.js';
|
|
7
|
+
export interface CreateAppOptions {
|
|
8
|
+
/** If provided, used instead of the default single-tenant middleware. Used by cloud to set req.tenantId from org/session. */
|
|
9
|
+
tenantMiddleware?: (req: express.Request, res: express.Response, next: express.NextFunction) => void;
|
|
10
|
+
/** Database-backed session store (must be created after DB init). */
|
|
11
|
+
sessionStore: InstanceType<typeof DatabaseSessionStore>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Build Express app with all core middleware. Call registerCoreRoutes(app, deps) next to mount API routes.
|
|
15
|
+
*/
|
|
16
|
+
export declare function createApp(options: CreateAppOptions): express.Express;
|
|
17
|
+
//# sourceMappingURL=app-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-factory.d.ts","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,OAAO,MAAM,SAAS,CAAC;AAgB9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGhE,MAAM,WAAW,gBAAgB;IAC/B,6HAA6H;IAC7H,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,YAAY,KAAK,IAAI,CAAC;IACrG,qEAAqE;IACrE,YAAY,EAAE,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC;CACzD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAsGpE"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates the Express app with middleware (security, CORS, session, passport, tenant, CSRF, Swagger).
|
|
3
|
+
* Does NOT mount API routes, static files, or error handlers — those are added by registerCoreRoutes and the app entry.
|
|
4
|
+
*/
|
|
5
|
+
import express from 'express';
|
|
6
|
+
import cors from 'cors';
|
|
7
|
+
import cookieParser from 'cookie-parser';
|
|
8
|
+
import session from 'express-session';
|
|
9
|
+
import passport from 'passport';
|
|
10
|
+
import swaggerUi from 'swagger-ui-express';
|
|
11
|
+
import { setupOIDC } from './auth/oidc.js';
|
|
12
|
+
import { setupJWT } from './auth/jwt.js';
|
|
13
|
+
import { setupSecurityHeaders, generalRateLimiter, } from './middleware/security.js';
|
|
14
|
+
import { tenantMiddleware } from './middleware/tenant.js';
|
|
15
|
+
import { swaggerSpec } from './config/swagger.js';
|
|
16
|
+
import { csrfProtection } from './middleware/security.js';
|
|
17
|
+
import csrfRoutes from './routes/csrf.js';
|
|
18
|
+
/**
|
|
19
|
+
* Build Express app with all core middleware. Call registerCoreRoutes(app, deps) next to mount API routes.
|
|
20
|
+
*/
|
|
21
|
+
export function createApp(options) {
|
|
22
|
+
const { sessionStore, tenantMiddleware: customTenantMiddleware } = options;
|
|
23
|
+
const app = express();
|
|
24
|
+
app.set('trust proxy', 1);
|
|
25
|
+
app.use(setupSecurityHeaders());
|
|
26
|
+
const frontendUrl = process.env.FRONTEND_URL || 'http://localhost:3000';
|
|
27
|
+
const allowedOriginsBase = [
|
|
28
|
+
frontendUrl,
|
|
29
|
+
'http://localhost:3000',
|
|
30
|
+
'http://localhost:3001',
|
|
31
|
+
'http://127.0.0.1:3000',
|
|
32
|
+
'http://127.0.0.1:3001',
|
|
33
|
+
];
|
|
34
|
+
const extraOrigins = (process.env.CORS_EXTRA_ORIGINS || '')
|
|
35
|
+
.split(',')
|
|
36
|
+
.map((o) => o.trim())
|
|
37
|
+
.filter(Boolean);
|
|
38
|
+
const allowedOrigins = [...new Set([...allowedOriginsBase, ...extraOrigins])];
|
|
39
|
+
app.use(cors({
|
|
40
|
+
origin: (origin, callback) => {
|
|
41
|
+
if (!origin)
|
|
42
|
+
return callback(null, true);
|
|
43
|
+
if (allowedOrigins.includes(origin))
|
|
44
|
+
return callback(null, true);
|
|
45
|
+
if (process.env.NODE_ENV === 'development' && origin.includes('localhost'))
|
|
46
|
+
return callback(null, true);
|
|
47
|
+
callback(new Error('Not allowed by CORS'));
|
|
48
|
+
},
|
|
49
|
+
credentials: true,
|
|
50
|
+
}));
|
|
51
|
+
app.use(express.json({ limit: '10mb' }));
|
|
52
|
+
app.use(express.urlencoded({ extended: true, limit: '10mb' }));
|
|
53
|
+
app.use(cookieParser());
|
|
54
|
+
const DEFAULT_SESSION_SECRET = 'slugbase-session-secret-change-in-production';
|
|
55
|
+
const sessionSecret = process.env.SESSION_SECRET || process.env.JWT_SECRET || DEFAULT_SESSION_SECRET;
|
|
56
|
+
if (process.env.NODE_ENV === 'production' && sessionSecret === DEFAULT_SESSION_SECRET) {
|
|
57
|
+
throw new Error('Cannot use default session secret in production. Set SESSION_SECRET.');
|
|
58
|
+
}
|
|
59
|
+
const baseUrl = process.env.BASE_URL || 'http://localhost:5000';
|
|
60
|
+
const isHttps = baseUrl.startsWith('https://');
|
|
61
|
+
const isProduction = process.env.NODE_ENV === 'production' && isHttps;
|
|
62
|
+
app.use(session({
|
|
63
|
+
secret: sessionSecret,
|
|
64
|
+
resave: false,
|
|
65
|
+
saveUninitialized: true,
|
|
66
|
+
name: 'slugbase.sid',
|
|
67
|
+
store: sessionStore,
|
|
68
|
+
cookie: {
|
|
69
|
+
httpOnly: true,
|
|
70
|
+
secure: isProduction,
|
|
71
|
+
sameSite: 'lax',
|
|
72
|
+
maxAge: 10 * 60 * 1000,
|
|
73
|
+
path: '/',
|
|
74
|
+
},
|
|
75
|
+
}));
|
|
76
|
+
app.use(generalRateLimiter);
|
|
77
|
+
app.use(customTenantMiddleware ?? tenantMiddleware);
|
|
78
|
+
setupOIDC();
|
|
79
|
+
setupJWT();
|
|
80
|
+
app.use(passport.initialize());
|
|
81
|
+
app.use(passport.session());
|
|
82
|
+
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, {
|
|
83
|
+
customCss: '.swagger-ui .topbar { display: none }',
|
|
84
|
+
customSiteTitle: 'SlugBase API Documentation',
|
|
85
|
+
}));
|
|
86
|
+
app.use('/api/csrf-token', csrfRoutes);
|
|
87
|
+
app.use((req, res, next) => {
|
|
88
|
+
if (['GET', 'HEAD', 'OPTIONS'].includes(req.method))
|
|
89
|
+
return next();
|
|
90
|
+
if (req.path.startsWith('/api/password-reset') ||
|
|
91
|
+
req.path === '/api/auth/setup' ||
|
|
92
|
+
req.path === '/api/auth/refresh' ||
|
|
93
|
+
req.path === '/api/auth/register' ||
|
|
94
|
+
req.path === '/api/auth/verify-signup' ||
|
|
95
|
+
req.path === '/api/auth/resend-signup-verification' ||
|
|
96
|
+
req.path === '/api/auth/request-signup-resend' ||
|
|
97
|
+
req.path === '/api/health' ||
|
|
98
|
+
req.path === '/api/csrf-token' ||
|
|
99
|
+
req.path.startsWith('/api-docs')) {
|
|
100
|
+
return next();
|
|
101
|
+
}
|
|
102
|
+
csrfProtection(req, res, next);
|
|
103
|
+
});
|
|
104
|
+
return app;
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=app-factory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-factory.js","sourceRoot":"","sources":["../src/app-factory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized authorization: can user access or modify a resource?
|
|
3
|
+
* Used by bookmarks, folders, and tags routes to avoid duplicated checks and IDOR.
|
|
4
|
+
*/
|
|
5
|
+
/** Get team IDs the user is a member of (for share checks). */
|
|
6
|
+
export declare function getTeamIdsForUser(userId: string, tenantId?: string): Promise<string[]>;
|
|
7
|
+
/** Legacy compatibility helper; org scoping is removed in selfhost-core. */
|
|
8
|
+
export declare function getTeamIdsForUserInOrg(userId: string, _orgId: string, tenantId?: string): Promise<string[]>;
|
|
9
|
+
/**
|
|
10
|
+
* Can the user read this bookmark? (owner, or shared via user/team/folder)
|
|
11
|
+
* @param _orgId - Legacy arg kept for compatibility.
|
|
12
|
+
*/
|
|
13
|
+
export declare function canAccessBookmark(userId: string, bookmarkId: string, _orgId?: string | null, tenantId?: string): Promise<boolean>;
|
|
14
|
+
/** Can the user update/delete this bookmark? (owner only) */
|
|
15
|
+
export declare function canModifyBookmark(userId: string, bookmarkId: string, tenantId?: string): Promise<boolean>;
|
|
16
|
+
/**
|
|
17
|
+
* Can the user read this folder? (owner or shared via user/team)
|
|
18
|
+
* @param _orgId - Legacy arg kept for compatibility.
|
|
19
|
+
*/
|
|
20
|
+
export declare function canAccessFolder(userId: string, folderId: string, _orgId?: string | null, tenantId?: string): Promise<boolean>;
|
|
21
|
+
/** Can the user update/delete this folder? (owner only) */
|
|
22
|
+
export declare function canModifyFolder(userId: string, folderId: string, tenantId?: string): Promise<boolean>;
|
|
23
|
+
/** Can the user read this tag? (owner only; tags are not shared) */
|
|
24
|
+
export declare function canAccessTag(userId: string, tagId: string, tenantId?: string): Promise<boolean>;
|
|
25
|
+
//# sourceMappingURL=authorization.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.d.ts","sourceRoot":"","sources":["../../src/auth/authorization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAgBH,+DAA+D;AAC/D,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAKvG;AAED,4EAA4E;AAC5E,wBAAsB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAE5H;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CA2BlJ;AAED,6DAA6D;AAC7D,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAI1H;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAkB9I;AAED,2DAA2D;AAC3D,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAItH;AAED,oEAAoE;AACpE,wBAAsB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAIhH"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Centralized authorization: can user access or modify a resource?
|
|
3
|
+
* Used by bookmarks, folders, and tags routes to avoid duplicated checks and IDOR.
|
|
4
|
+
*/
|
|
5
|
+
import { queryOne, query } from '../db/index.js';
|
|
6
|
+
const DB_TYPE = process.env.DB_TYPE || 'sqlite';
|
|
7
|
+
/** Convert ? placeholders to $1, $2 for PostgreSQL */
|
|
8
|
+
function toPg(sql) {
|
|
9
|
+
let n = 0;
|
|
10
|
+
return sql.replace(/\?/g, () => `$${++n}`);
|
|
11
|
+
}
|
|
12
|
+
function runSql(sql, params) {
|
|
13
|
+
return DB_TYPE === 'postgresql' ? [toPg(sql), params] : [sql, params];
|
|
14
|
+
}
|
|
15
|
+
/** Get team IDs the user is a member of (for share checks). */
|
|
16
|
+
export async function getTeamIdsForUser(userId, tenantId = 'default') {
|
|
17
|
+
const [q, p] = runSql('SELECT team_id FROM team_members WHERE user_id = ? AND tenant_id = ?', [userId, tenantId]);
|
|
18
|
+
const rows = await query(q, p);
|
|
19
|
+
const list = Array.isArray(rows) ? rows : rows ? [rows] : [];
|
|
20
|
+
return list.map((r) => r.team_id);
|
|
21
|
+
}
|
|
22
|
+
/** Legacy compatibility helper; org scoping is removed in selfhost-core. */
|
|
23
|
+
export async function getTeamIdsForUserInOrg(userId, _orgId, tenantId = 'default') {
|
|
24
|
+
return getTeamIdsForUser(userId, tenantId);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Can the user read this bookmark? (owner, or shared via user/team/folder)
|
|
28
|
+
* @param _orgId - Legacy arg kept for compatibility.
|
|
29
|
+
*/
|
|
30
|
+
export async function canAccessBookmark(userId, bookmarkId, _orgId, tenantId = 'default') {
|
|
31
|
+
const teamIds = await getTeamIdsForUser(userId, tenantId);
|
|
32
|
+
const teamPlaceholders = teamIds.length > 0 ? teamIds.map(() => '?').join(',') : 'NULL';
|
|
33
|
+
const busCondition = 'bus.user_id = ?';
|
|
34
|
+
const fusCondition = 'fus.user_id = ?';
|
|
35
|
+
const sql = `
|
|
36
|
+
SELECT 1 FROM bookmarks b
|
|
37
|
+
LEFT JOIN bookmark_user_shares bus ON b.id = bus.bookmark_id
|
|
38
|
+
LEFT JOIN bookmark_team_shares bts ON b.id = bts.bookmark_id
|
|
39
|
+
LEFT JOIN bookmark_folders bf ON b.id = bf.bookmark_id
|
|
40
|
+
LEFT JOIN folder_user_shares fus ON bf.folder_id = fus.folder_id
|
|
41
|
+
LEFT JOIN folder_team_shares fts ON bf.folder_id = fts.folder_id
|
|
42
|
+
WHERE b.id = ? AND b.tenant_id = ? AND (b.user_id = ?
|
|
43
|
+
OR ${busCondition}
|
|
44
|
+
OR (bts.team_id IN (${teamPlaceholders}) AND bts.team_id IS NOT NULL)
|
|
45
|
+
OR ${fusCondition}
|
|
46
|
+
OR (fts.team_id IN (${teamPlaceholders}) AND fts.team_id IS NOT NULL AND bf.folder_id IS NOT NULL))
|
|
47
|
+
`;
|
|
48
|
+
const params = [bookmarkId, tenantId, userId];
|
|
49
|
+
params.push(userId, userId);
|
|
50
|
+
if (teamIds.length > 0) {
|
|
51
|
+
params.push(...teamIds);
|
|
52
|
+
params.push(...teamIds);
|
|
53
|
+
}
|
|
54
|
+
const [q, p] = runSql(sql, params);
|
|
55
|
+
const row = await queryOne(q, p);
|
|
56
|
+
return !!row;
|
|
57
|
+
}
|
|
58
|
+
/** Can the user update/delete this bookmark? (owner only) */
|
|
59
|
+
export async function canModifyBookmark(userId, bookmarkId, tenantId = 'default') {
|
|
60
|
+
const [q, p] = runSql('SELECT 1 FROM bookmarks WHERE id = ? AND user_id = ? AND tenant_id = ?', [bookmarkId, userId, tenantId]);
|
|
61
|
+
const row = await queryOne(q, p);
|
|
62
|
+
return !!row;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Can the user read this folder? (owner or shared via user/team)
|
|
66
|
+
* @param _orgId - Legacy arg kept for compatibility.
|
|
67
|
+
*/
|
|
68
|
+
export async function canAccessFolder(userId, folderId, _orgId, tenantId = 'default') {
|
|
69
|
+
const teamIds = await getTeamIdsForUser(userId, tenantId);
|
|
70
|
+
const teamPlaceholders = teamIds.length > 0 ? teamIds.map(() => '?').join(',') : 'NULL';
|
|
71
|
+
const fusCondition = 'fus.user_id = ?';
|
|
72
|
+
const sql = `
|
|
73
|
+
SELECT 1 FROM folders f
|
|
74
|
+
LEFT JOIN folder_user_shares fus ON f.id = fus.folder_id
|
|
75
|
+
LEFT JOIN folder_team_shares fts ON f.id = fts.folder_id
|
|
76
|
+
WHERE f.id = ? AND f.tenant_id = ? AND (f.user_id = ?
|
|
77
|
+
OR ${fusCondition}
|
|
78
|
+
OR (fts.team_id IN (${teamPlaceholders}) AND fts.team_id IS NOT NULL))
|
|
79
|
+
`;
|
|
80
|
+
const params = [folderId, tenantId, userId];
|
|
81
|
+
params.push(userId);
|
|
82
|
+
if (teamIds.length > 0)
|
|
83
|
+
params.push(...teamIds);
|
|
84
|
+
const [q, p] = runSql(sql, params);
|
|
85
|
+
const row = await queryOne(q, p);
|
|
86
|
+
return !!row;
|
|
87
|
+
}
|
|
88
|
+
/** Can the user update/delete this folder? (owner only) */
|
|
89
|
+
export async function canModifyFolder(userId, folderId, tenantId = 'default') {
|
|
90
|
+
const [q, p] = runSql('SELECT 1 FROM folders WHERE id = ? AND user_id = ? AND tenant_id = ?', [folderId, userId, tenantId]);
|
|
91
|
+
const row = await queryOne(q, p);
|
|
92
|
+
return !!row;
|
|
93
|
+
}
|
|
94
|
+
/** Can the user read this tag? (owner only; tags are not shared) */
|
|
95
|
+
export async function canAccessTag(userId, tagId, tenantId = 'default') {
|
|
96
|
+
const [q, p] = runSql('SELECT 1 FROM tags WHERE id = ? AND user_id = ? AND tenant_id = ?', [tagId, userId, tenantId]);
|
|
97
|
+
const row = await queryOne(q, p);
|
|
98
|
+
return !!row;
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=authorization.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"authorization.js","sourceRoot":"","sources":["../../src/auth/authorization.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,QAAQ,CAAC;AAEhD,sDAAsD;AACtD,SAAS,IAAI,CAAC,GAAW;IACvB,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,MAAM,CAAC,GAAW,EAAE,MAAa;IACxC,OAAO,OAAO,KAAK,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACxE,CAAC;AAED,+DAA+D;AAC/D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,WAAmB,SAAS;IAClF,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,sEAAsE,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAClH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7D,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AACzC,CAAC;AAED,4EAA4E;AAC5E,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,MAAc,EAAE,MAAc,EAAE,WAAmB,SAAS;IACvG,OAAO,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,UAAkB,EAAE,MAAsB,EAAE,WAAmB,SAAS;IAC9H,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACxF,MAAM,YAAY,GAAG,iBAAiB,CAAC;IACvC,MAAM,YAAY,GAAG,iBAAiB,CAAC;IACvC,MAAM,GAAG,GAAG;;;;;;;;WAQH,YAAY;4BACK,gBAAgB;WACjC,YAAY;4BACK,gBAAgB;GACzC,CAAC;IACF,MAAM,MAAM,GAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrD,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC;AACf,CAAC;AAED,6DAA6D;AAC7D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAc,EAAE,UAAkB,EAAE,WAAmB,SAAS;IACtG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,wEAAwE,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChI,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,QAAgB,EAAE,MAAsB,EAAE,WAAmB,SAAS;IAC1H,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1D,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACxF,MAAM,YAAY,GAAG,iBAAiB,CAAC;IACvC,MAAM,GAAG,GAAG;;;;;WAKH,YAAY;4BACK,gBAAgB;GACzC,CAAC;IACF,MAAM,MAAM,GAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;IACnD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpB,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;IAChD,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC;AACf,CAAC;AAED,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,QAAgB,EAAE,WAAmB,SAAS;IAClG,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,sEAAsE,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC5H,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC;AACf,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAc,EAAE,KAAa,EAAE,WAAmB,SAAS;IAC5F,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,mEAAmE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjC,OAAO,CAAC,CAAC,GAAG,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.d.ts","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,wBAAgB,QAAQ,SAwBvB"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import passport from 'passport';
|
|
2
|
+
import { Strategy as JwtStrategy } from 'passport-jwt';
|
|
3
|
+
import { queryOne } from '../db/index.js';
|
|
4
|
+
import { extractTokenFromRequest } from '../utils/jwt.js';
|
|
5
|
+
// JWT_SECRET is validated at startup via validateEnvironmentVariables()
|
|
6
|
+
// This will throw if not set, preventing insecure defaults
|
|
7
|
+
const JWT_SECRET = process.env.JWT_SECRET;
|
|
8
|
+
if (!JWT_SECRET) {
|
|
9
|
+
throw new Error('JWT_SECRET environment variable is required. Please set it before starting the server.');
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Setup JWT strategy for Passport
|
|
13
|
+
*/
|
|
14
|
+
export function setupJWT() {
|
|
15
|
+
passport.use('jwt', new JwtStrategy({
|
|
16
|
+
jwtFromRequest: (req) => extractTokenFromRequest(req),
|
|
17
|
+
secretOrKey: JWT_SECRET,
|
|
18
|
+
algorithms: ['HS256'],
|
|
19
|
+
passReqToCallback: true,
|
|
20
|
+
}, async (req, payload, done) => {
|
|
21
|
+
try {
|
|
22
|
+
// Fetch fresh user data from database
|
|
23
|
+
const user = await queryOne('SELECT * FROM users WHERE id = ?', [payload.id]);
|
|
24
|
+
if (!user) {
|
|
25
|
+
return done(null, false);
|
|
26
|
+
}
|
|
27
|
+
return done(null, user);
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
return done(error, false);
|
|
31
|
+
}
|
|
32
|
+
}));
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/auth/jwt.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,QAAQ,IAAI,WAAW,EAAc,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAC;AAE1D,wEAAwE;AACxE,2DAA2D;AAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAoB,CAAC;AACpD,IAAI,CAAC,UAAU,EAAE,CAAC;IAChB,MAAM,IAAI,KAAK,CAAC,wFAAwF,CAAC,CAAC;AAC5G,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ;IACtB,QAAQ,CAAC,GAAG,CACV,KAAK,EACL,IAAI,WAAW,CACb;QACE,cAAc,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,uBAAuB,CAAC,GAAG,CAAC;QACrD,WAAW,EAAE,UAAU;QACvB,UAAU,EAAE,CAAC,OAAO,CAAC;QACrB,iBAAiB,EAAE,IAAI;KACxB,EACD,KAAK,EAAE,GAAQ,EAAE,OAAY,EAAE,IAAS,EAAE,EAAE;QAC1C,IAAI,CAAC;YACH,sCAAsC;YACtC,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,kCAAkC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;YAC9E,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3B,CAAC;YACD,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC,CACF,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../../src/auth/oidc.ts"],"names":[],"mappings":"AASA,wBAAgB,SAAS,SAgBxB;AAkKD,wBAAsB,kBAAkB,CAAC,QAAQ,GAAE,MAA6B,iBAe/E;AAGD,wBAAsB,oBAAoB,kBAsBzC"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import passport from 'passport';
|
|
2
|
+
import { Strategy as OpenIDConnectStrategy } from 'passport-openidconnect';
|
|
3
|
+
import { queryOne, execute, query } from '../db/index.js';
|
|
4
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
5
|
+
import { decrypt } from '../utils/encryption.js';
|
|
6
|
+
import { generateUserKey } from '../utils/user-key.js';
|
|
7
|
+
import { getDefaultTenantId } from '../utils/tenant.js';
|
|
8
|
+
export function setupOIDC() {
|
|
9
|
+
// Serialization for OIDC OAuth flow (sessions are only used during OAuth redirect)
|
|
10
|
+
// After OAuth completes, we convert to JWT and destroy the session
|
|
11
|
+
passport.serializeUser((user, done) => {
|
|
12
|
+
// Store minimal user info in session (only needed during OAuth flow)
|
|
13
|
+
done(null, user.id);
|
|
14
|
+
});
|
|
15
|
+
passport.deserializeUser(async (id, done) => {
|
|
16
|
+
try {
|
|
17
|
+
const user = await queryOne('SELECT * FROM users WHERE id = ?', [id]);
|
|
18
|
+
done(null, user);
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
done(error, null);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
/** Register a single OIDC strategy from DB-backed configuration. */
|
|
26
|
+
async function registerOIDCStrategy(provider, clientSecret) {
|
|
27
|
+
if (!provider.client_id || !clientSecret || !provider.issuer_url || !provider.provider_key) {
|
|
28
|
+
throw new Error(`Missing required fields for provider ${provider.provider_key || provider.id}`);
|
|
29
|
+
}
|
|
30
|
+
const verifyFunction = async (iss, profile, context, idToken, accessToken, refreshToken, params, cb) => {
|
|
31
|
+
// Extract sub from profile (profile.id is the sub claim) - do this before try block so it's available in catch
|
|
32
|
+
const sub = profile.id || profile.sub;
|
|
33
|
+
if (!sub) {
|
|
34
|
+
console.error(`[OIDC] No sub found in profile for provider: ${provider.provider_key}`);
|
|
35
|
+
return cb(new Error('Sub claim is required for OIDC authentication'), null);
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const email = profile.emails?.[0]?.value || profile.email;
|
|
39
|
+
if (!email) {
|
|
40
|
+
console.error(`[OIDC] No email found in profile for provider: ${provider.provider_key}`);
|
|
41
|
+
return cb(new Error('Email is required for OIDC authentication'), null);
|
|
42
|
+
}
|
|
43
|
+
// Use email as primary identifier - check if user exists by email
|
|
44
|
+
let user = await queryOne('SELECT * FROM users WHERE email = ?', [email]);
|
|
45
|
+
if (user) {
|
|
46
|
+
// User exists - update OIDC info if not set
|
|
47
|
+
if (!user.oidc_sub || !user.oidc_provider) {
|
|
48
|
+
await execute('UPDATE users SET oidc_sub = ?, oidc_provider = ? WHERE id = ?', [sub, provider.provider_key, user.id]);
|
|
49
|
+
user = await queryOne('SELECT * FROM users WHERE id = ?', [user.id]);
|
|
50
|
+
}
|
|
51
|
+
// If user exists with different OIDC provider, that's fine - email is the identifier
|
|
52
|
+
return cb(null, user);
|
|
53
|
+
}
|
|
54
|
+
// User doesn't exist - check if auto-creation is enabled
|
|
55
|
+
// Handle both SQLite (0/1) and PostgreSQL (true/false) boolean values
|
|
56
|
+
// Also handle string representations from database queries
|
|
57
|
+
const autoCreateValue = provider.auto_create_users;
|
|
58
|
+
const autoCreate = autoCreateValue === true ||
|
|
59
|
+
autoCreateValue === 1 ||
|
|
60
|
+
autoCreateValue === '1' ||
|
|
61
|
+
(autoCreateValue !== false &&
|
|
62
|
+
autoCreateValue !== 0 &&
|
|
63
|
+
autoCreateValue !== '0' &&
|
|
64
|
+
autoCreateValue !== null &&
|
|
65
|
+
autoCreateValue !== undefined);
|
|
66
|
+
if (!autoCreate) {
|
|
67
|
+
console.error('OIDC auto-creation disabled. Provider:', provider.provider_key, 'auto_create_users:', autoCreateValue);
|
|
68
|
+
return cb(new Error('AUTO_CREATE_DISABLED'), null);
|
|
69
|
+
}
|
|
70
|
+
// Create new user
|
|
71
|
+
const userId = uuidv4();
|
|
72
|
+
let userKey = await generateUserKey();
|
|
73
|
+
const name = profile.displayName || profile.name || email;
|
|
74
|
+
// Determine user role
|
|
75
|
+
let isAdmin = false;
|
|
76
|
+
const defaultRole = provider.default_role || 'user';
|
|
77
|
+
if (defaultRole === 'admin') {
|
|
78
|
+
isAdmin = true;
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Check if this is the first user (auto-admin for first user, regardless of default_role)
|
|
82
|
+
const userCount = await queryOne('SELECT COUNT(*) as count FROM users', []);
|
|
83
|
+
isAdmin = !userCount || parseInt(userCount.count) === 0;
|
|
84
|
+
}
|
|
85
|
+
// Retry logic for user_key collisions (should be extremely rare)
|
|
86
|
+
let retries = 0;
|
|
87
|
+
const maxRetries = 3;
|
|
88
|
+
while (retries < maxRetries) {
|
|
89
|
+
try {
|
|
90
|
+
await execute(`INSERT INTO users (id, email, name, user_key, is_admin, oidc_sub, oidc_provider)
|
|
91
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`, [userId, email, name, userKey, isAdmin, sub, provider.provider_key]);
|
|
92
|
+
break; // Success, exit retry loop
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
// If user_key collision, generate new key and retry
|
|
96
|
+
if (error.message && (error.message.includes('UNIQUE constraint') || error.message.includes('duplicate'))
|
|
97
|
+
&& error.message.includes('user_key')) {
|
|
98
|
+
retries++;
|
|
99
|
+
if (retries >= maxRetries) {
|
|
100
|
+
return cb(new Error('Failed to create user. Please try again.'), null);
|
|
101
|
+
}
|
|
102
|
+
userKey = await generateUserKey();
|
|
103
|
+
continue; // Retry with new key
|
|
104
|
+
}
|
|
105
|
+
// For other errors (like email duplicate), throw to outer catch
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
user = await queryOne('SELECT * FROM users WHERE id = ?', [userId]);
|
|
110
|
+
return cb(null, user);
|
|
111
|
+
}
|
|
112
|
+
catch (error) {
|
|
113
|
+
console.error(`[OIDC] Error during user creation/update:`, {
|
|
114
|
+
message: error.message,
|
|
115
|
+
stack: error.stack,
|
|
116
|
+
name: error.name,
|
|
117
|
+
});
|
|
118
|
+
// Handle unique constraint violation (email already exists)
|
|
119
|
+
if (error.message && (error.message.includes('UNIQUE constraint') || error.message.includes('duplicate'))) {
|
|
120
|
+
// Try to get the existing user by email
|
|
121
|
+
const existingUser = await queryOne('SELECT * FROM users WHERE email = ?', [profile.emails?.[0]?.value || profile.email]);
|
|
122
|
+
if (existingUser) {
|
|
123
|
+
// Update OIDC info for existing user
|
|
124
|
+
await execute('UPDATE users SET oidc_sub = ?, oidc_provider = ? WHERE id = ?', [sub, provider.provider_key, existingUser.id]);
|
|
125
|
+
const updatedUser = await queryOne('SELECT * FROM users WHERE id = ?', [existingUser.id]);
|
|
126
|
+
return cb(null, updatedUser);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
console.error(`[OIDC] Fatal error, cannot proceed:`, error);
|
|
130
|
+
return cb(error, null);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const baseUrl = process.env.BASE_URL || 'http://localhost:5000';
|
|
134
|
+
const callbackURL = `${baseUrl}/api/auth/${provider.provider_key}/callback`;
|
|
135
|
+
const authorizationURL = provider.authorization_url || `${provider.issuer_url}/authorize`;
|
|
136
|
+
const tokenURL = provider.token_url || `${provider.issuer_url}/token`;
|
|
137
|
+
const userInfoURL = provider.userinfo_url || `${provider.issuer_url}/userinfo`;
|
|
138
|
+
const strategyConfig = {
|
|
139
|
+
issuer: provider.issuer_url,
|
|
140
|
+
authorizationURL,
|
|
141
|
+
tokenURL,
|
|
142
|
+
userInfoURL,
|
|
143
|
+
clientID: provider.client_id,
|
|
144
|
+
clientSecret,
|
|
145
|
+
callbackURL,
|
|
146
|
+
scope: (typeof provider.scopes === 'string' ? provider.scopes : '').split(' ').filter(Boolean),
|
|
147
|
+
skipUserProfile: false,
|
|
148
|
+
};
|
|
149
|
+
passport.use(provider.provider_key, new OpenIDConnectStrategy(strategyConfig, verifyFunction));
|
|
150
|
+
}
|
|
151
|
+
class DatabaseOidcConfigProvider {
|
|
152
|
+
async getProviders(tenantId) {
|
|
153
|
+
const providers = await query('SELECT id, provider_key, client_id, client_secret, issuer_url, authorization_url, token_url, userinfo_url, scopes, auto_create_users, default_role FROM oidc_providers WHERE tenant_id = ?', [tenantId]);
|
|
154
|
+
return Array.isArray(providers) ? providers : (providers ? [providers] : []);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
const oidcProviderStore = new DatabaseOidcConfigProvider();
|
|
158
|
+
export async function loadOIDCStrategies(tenantId = getDefaultTenantId()) {
|
|
159
|
+
try {
|
|
160
|
+
const providersList = await oidcProviderStore.getProviders(tenantId);
|
|
161
|
+
if (providersList.length === 0)
|
|
162
|
+
return;
|
|
163
|
+
for (const provider of providersList) {
|
|
164
|
+
try {
|
|
165
|
+
const decryptedSecret = decrypt(provider.client_secret);
|
|
166
|
+
await registerOIDCStrategy(provider, decryptedSecret);
|
|
167
|
+
}
|
|
168
|
+
catch (providerError) {
|
|
169
|
+
console.error(`Error loading OIDC provider ${provider.provider_key || provider.id}:`, providerError.message || providerError);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
console.error('Error loading OIDC strategies:', error.message || error);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
export async function reloadOIDCStrategies() {
|
|
178
|
+
try {
|
|
179
|
+
// Remove existing strategies (except 'jwt' which is our JWT strategy)
|
|
180
|
+
// Use a type assertion to access internal strategies map
|
|
181
|
+
const strategies = Object.keys(passport._strategies || {});
|
|
182
|
+
strategies.forEach((key) => {
|
|
183
|
+
if (key !== 'jwt') {
|
|
184
|
+
try {
|
|
185
|
+
passport.unuse(key);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
// Ignore errors when removing strategies
|
|
189
|
+
console.warn(`Could not remove OIDC strategy ${key}:`, error.message || error);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
});
|
|
193
|
+
// Reload from database
|
|
194
|
+
await loadOIDCStrategies();
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
console.error('Error reloading OIDC strategies:', error.message || error);
|
|
198
|
+
// Don't throw - allow the operation to continue even if strategy reload fails
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=oidc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.js","sourceRoot":"","sources":["../../src/auth/oidc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLOUD mode: fixed OIDC providers from environment (Google, Microsoft, GitHub).
|
|
3
|
+
* Only include providers where both client_id and client_secret are set.
|
|
4
|
+
*/
|
|
5
|
+
export interface CloudProviderConfig {
|
|
6
|
+
provider_key: string;
|
|
7
|
+
client_id: string;
|
|
8
|
+
client_secret: string;
|
|
9
|
+
issuer_url: string;
|
|
10
|
+
authorization_url?: string;
|
|
11
|
+
token_url?: string;
|
|
12
|
+
userinfo_url?: string;
|
|
13
|
+
scopes: string;
|
|
14
|
+
auto_create_users: boolean;
|
|
15
|
+
default_role: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function getCloudProviders(): CloudProviderConfig[];
|
|
18
|
+
//# sourceMappingURL=cloud-providers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloud-providers.d.ts","sourceRoot":"","sources":["../../src/config/cloud-providers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,iBAAiB,EAAE,OAAO,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;CACtB;AASD,wBAAgB,iBAAiB,IAAI,mBAAmB,EAAE,CAoDzD"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLOUD mode: fixed OIDC providers from environment (Google, Microsoft, GitHub).
|
|
3
|
+
* Only include providers where both client_id and client_secret are set.
|
|
4
|
+
*/
|
|
5
|
+
const GOOGLE_ISSUER = 'https://accounts.google.com';
|
|
6
|
+
const MICROSOFT_TENANT = process.env.OIDC_MICROSOFT_TENANT || 'common';
|
|
7
|
+
const MICROSOFT_ISSUER = `https://login.microsoftonline.com/${MICROSOFT_TENANT}/v2.0`;
|
|
8
|
+
const GITHUB_AUTH = 'https://github.com/login/oauth/authorize';
|
|
9
|
+
const GITHUB_TOKEN = 'https://github.com/login/oauth/access_token';
|
|
10
|
+
const GITHUB_USER = 'https://api.github.com/user';
|
|
11
|
+
export function getCloudProviders() {
|
|
12
|
+
const providers = [];
|
|
13
|
+
const googleId = process.env.OIDC_GOOGLE_CLIENT_ID?.trim();
|
|
14
|
+
const googleSecret = process.env.OIDC_GOOGLE_CLIENT_SECRET?.trim();
|
|
15
|
+
if (googleId && googleSecret) {
|
|
16
|
+
providers.push({
|
|
17
|
+
provider_key: 'google',
|
|
18
|
+
client_id: googleId,
|
|
19
|
+
client_secret: googleSecret,
|
|
20
|
+
issuer_url: GOOGLE_ISSUER,
|
|
21
|
+
scopes: 'openid profile email',
|
|
22
|
+
auto_create_users: true,
|
|
23
|
+
default_role: 'user',
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
const msId = process.env.OIDC_MICROSOFT_CLIENT_ID?.trim();
|
|
27
|
+
const msSecret = process.env.OIDC_MICROSOFT_CLIENT_SECRET?.trim();
|
|
28
|
+
if (msId && msSecret) {
|
|
29
|
+
providers.push({
|
|
30
|
+
provider_key: 'microsoft',
|
|
31
|
+
client_id: msId,
|
|
32
|
+
client_secret: msSecret,
|
|
33
|
+
issuer_url: MICROSOFT_ISSUER,
|
|
34
|
+
authorization_url: `${MICROSOFT_ISSUER}/authorize`,
|
|
35
|
+
token_url: `${MICROSOFT_ISSUER}/token`,
|
|
36
|
+
userinfo_url: 'https://graph.microsoft.com/oidc/userinfo',
|
|
37
|
+
scopes: 'openid profile email',
|
|
38
|
+
auto_create_users: true,
|
|
39
|
+
default_role: 'user',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const ghId = process.env.OIDC_GITHUB_CLIENT_ID?.trim();
|
|
43
|
+
const ghSecret = process.env.OIDC_GITHUB_CLIENT_SECRET?.trim();
|
|
44
|
+
if (ghId && ghSecret) {
|
|
45
|
+
providers.push({
|
|
46
|
+
provider_key: 'github',
|
|
47
|
+
client_id: ghId,
|
|
48
|
+
client_secret: ghSecret,
|
|
49
|
+
issuer_url: 'https://github.com',
|
|
50
|
+
authorization_url: GITHUB_AUTH,
|
|
51
|
+
token_url: GITHUB_TOKEN,
|
|
52
|
+
userinfo_url: GITHUB_USER,
|
|
53
|
+
scopes: 'openid user:email',
|
|
54
|
+
auto_create_users: true,
|
|
55
|
+
default_role: 'user',
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return providers;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=cloud-providers.js.map
|