alepha 0.19.3 → 0.19.5
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/assets/swagger-ui/swagger-ui-bundle.js +1 -1
- package/dist/api/invitations/index.d.ts +790 -0
- package/dist/api/invitations/index.d.ts.map +1 -0
- package/dist/api/invitations/index.js +665 -0
- package/dist/api/invitations/index.js.map +1 -0
- package/dist/api/issues/index.d.ts +810 -0
- package/dist/api/issues/index.d.ts.map +1 -0
- package/dist/api/issues/index.js +447 -0
- package/dist/api/issues/index.js.map +1 -0
- package/dist/api/jobs/index.browser.js +8 -9
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +99 -43
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +257 -40
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js +0 -1
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +3 -3
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +0 -1
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +112 -1
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +90 -3
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +79 -12
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/{billing → api/payments}/index.d.ts +67 -49
- package/dist/api/payments/index.d.ts.map +1 -0
- package/dist/{billing → api/payments}/index.js +108 -74
- package/dist/api/payments/index.js.map +1 -0
- package/dist/api/subscriptions/index.d.ts +1692 -0
- package/dist/api/subscriptions/index.d.ts.map +1 -0
- package/dist/api/subscriptions/index.js +1870 -0
- package/dist/api/subscriptions/index.js.map +1 -0
- package/dist/api/users/index.d.ts +24 -2
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +176 -36
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +13 -13
- package/dist/api/workflows/index.browser.js +246 -0
- package/dist/api/workflows/index.browser.js.map +1 -0
- package/dist/api/workflows/index.d.ts +1618 -0
- package/dist/api/workflows/index.d.ts.map +1 -0
- package/dist/api/workflows/index.js +1504 -0
- package/dist/api/workflows/index.js.map +1 -0
- package/dist/captcha/index.d.ts +142 -0
- package/dist/captcha/index.d.ts.map +1 -0
- package/dist/captcha/index.js +177 -0
- package/dist/captcha/index.js.map +1 -0
- package/dist/cli/core/index.d.ts +126 -30
- package/dist/cli/core/index.d.ts.map +1 -1
- package/dist/cli/core/index.js +106 -67
- package/dist/cli/core/index.js.map +1 -1
- package/dist/cli/platform/index.d.ts +84 -10
- package/dist/cli/platform/index.d.ts.map +1 -1
- package/dist/cli/platform/index.js +92 -4
- package/dist/cli/platform/index.js.map +1 -1
- package/dist/cli/vendor/index.d.ts +60 -10
- package/dist/cli/vendor/index.d.ts.map +1 -1
- package/dist/cli/vendor/index.js +177 -45
- package/dist/cli/vendor/index.js.map +1 -1
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +2 -3
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +21 -2
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +33 -2
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +21 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +21 -2
- package/dist/core/index.native.js.map +1 -1
- package/dist/core/index.workerd.js +21 -2
- package/dist/core/index.workerd.js.map +1 -1
- package/dist/email/smtp/index.js +24 -8
- package/dist/email/smtp/index.js.map +1 -1
- package/dist/orm/core/index.browser.js +0 -18
- package/dist/orm/core/index.browser.js.map +1 -1
- package/dist/orm/core/index.bun.js +6 -23
- package/dist/orm/core/index.bun.js.map +1 -1
- package/dist/orm/core/index.d.ts +1 -13
- package/dist/orm/core/index.d.ts.map +1 -1
- package/dist/orm/core/index.js +6 -23
- package/dist/orm/core/index.js.map +1 -1
- package/dist/orm/postgres/index.bun.js +3 -3
- package/dist/orm/postgres/index.bun.js.map +1 -1
- package/dist/orm/postgres/index.d.ts.map +1 -1
- package/dist/orm/postgres/index.js +3 -3
- package/dist/orm/postgres/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +1 -0
- package/dist/react/i18n/index.d.ts.map +1 -1
- package/dist/react/i18n/index.js +8 -4
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/router/index.browser.js +25 -3
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +16 -1
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +25 -3
- package/dist/react/router/index.js.map +1 -1
- package/dist/security/index.d.ts +28 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +28 -0
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +145 -2
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +364 -63
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts.map +1 -1
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/websocket/index.d.ts.map +1 -1
- package/dist/websocket/index.js.map +1 -1
- package/package.json +47 -20
- package/src/api/invitations/__tests__/InvitationService.spec.ts +439 -0
- package/src/api/invitations/controllers/AdminInvitationController.ts +86 -0
- package/src/api/invitations/controllers/InvitationController.ts +84 -0
- package/src/api/invitations/entities/invitations.ts +33 -0
- package/src/api/invitations/index.ts +65 -0
- package/src/api/invitations/jobs/InvitationJobs.ts +37 -0
- package/src/api/invitations/providers/InvitationProvider.ts +45 -0
- package/src/api/invitations/schemas/createInvitationSchema.ts +12 -0
- package/src/api/invitations/schemas/invitationConfigAtom.ts +20 -0
- package/src/api/invitations/schemas/invitationQuerySchema.ts +15 -0
- package/src/api/invitations/schemas/invitationResourceSchema.ts +6 -0
- package/src/api/invitations/schemas/invitationWithResourceInfoSchema.ts +22 -0
- package/src/api/invitations/schemas/myInvitationsQuerySchema.ts +10 -0
- package/src/api/invitations/services/InvitationService.ts +556 -0
- package/src/api/issues/__tests__/IssueService.spec.ts +263 -0
- package/src/api/issues/controllers/AdminIssueController.ts +149 -0
- package/src/api/issues/controllers/IssueController.ts +44 -0
- package/src/api/issues/entities/issues.ts +49 -0
- package/src/api/issues/index.ts +53 -0
- package/src/api/issues/schemas/createIssueSchema.ts +13 -0
- package/src/api/issues/schemas/issueConfigAtom.ts +13 -0
- package/src/api/issues/schemas/issueQuerySchema.ts +18 -0
- package/src/api/issues/schemas/issueResourceSchema.ts +6 -0
- package/src/api/issues/schemas/myIssueQuerySchema.ts +10 -0
- package/src/api/issues/schemas/updateIssueSchema.ts +13 -0
- package/src/api/issues/services/IssueService.ts +264 -0
- package/src/api/jobs/__tests__/$job.spec.ts +876 -0
- package/src/api/jobs/controllers/AdminJobController.ts +44 -0
- package/src/api/jobs/entities/jobExecutionEntity.ts +0 -2
- package/src/api/jobs/index.ts +0 -3
- package/src/api/jobs/primitives/$job.ts +22 -11
- package/src/api/jobs/providers/JobProvider.ts +229 -19
- package/src/api/jobs/schemas/jobConfigAtom.ts +4 -0
- package/src/api/jobs/schemas/jobCronInfoSchema.ts +1 -0
- package/src/api/jobs/schemas/jobExecutionQuerySchema.ts +0 -1
- package/src/api/jobs/schemas/jobQueueDepthSchema.ts +1 -0
- package/src/api/jobs/schemas/jobRegistrationSchema.ts +1 -6
- package/src/api/jobs/services/JobService.ts +51 -12
- package/src/api/notifications/schemas/notificationQuerySchema.ts +0 -1
- package/src/api/parameters/__tests__/$parameter.spec.ts +327 -0
- package/src/api/parameters/controllers/AdminParameterController.ts +29 -3
- package/src/api/parameters/index.browser.ts +12 -0
- package/src/api/parameters/primitives/$parameter.ts +20 -3
- package/src/api/parameters/services/ParameterProvider.ts +48 -7
- package/src/{billing → api/payments}/__tests__/PaymentMethodService.spec.ts +32 -6
- package/src/api/payments/__tests__/PaymentService.spec.ts +279 -0
- package/src/{billing/controllers/AdminBillingController.ts → api/payments/controllers/AdminPaymentController.ts} +26 -21
- package/src/{billing/controllers/BillingController.ts → api/payments/controllers/PaymentController.ts} +23 -11
- package/src/{billing → api/payments}/entities/paymentIntents.ts +1 -0
- package/src/{billing/errors/BillingError.ts → api/payments/errors/PaymentError.ts} +1 -1
- package/src/{billing → api/payments}/index.ts +31 -25
- package/src/{billing/providers/MemoryBillingProvider.ts → api/payments/providers/MemoryPaymentProvider.ts} +4 -4
- package/src/{billing/providers/BillingProvider.ts → api/payments/providers/PaymentProvider.ts} +9 -2
- package/src/{billing → api/payments}/services/PaymentMethodService.ts +5 -5
- package/src/{billing/services/BillingService.ts → api/payments/services/PaymentService.ts} +94 -18
- package/src/api/subscriptions/__tests__/BillingService.spec.ts +218 -0
- package/src/api/subscriptions/__tests__/SubscriptionService.spec.ts +278 -0
- package/src/api/subscriptions/controllers/AdminSubscriptionController.ts +212 -0
- package/src/api/subscriptions/controllers/SubscriptionController.ts +189 -0
- package/src/api/subscriptions/entities/subscriptionEvents.ts +54 -0
- package/src/api/subscriptions/entities/subscriptions.ts +68 -0
- package/src/api/subscriptions/index.ts +144 -0
- package/src/api/subscriptions/jobs/SubscriptionJobs.ts +382 -0
- package/src/api/subscriptions/middleware/$requireLimit.ts +50 -0
- package/src/api/subscriptions/middleware/$requirePlan.ts +49 -0
- package/src/api/subscriptions/notifications/SubscriptionNotifications.ts +110 -0
- package/src/api/subscriptions/schemas/cancelSubscriptionSchema.ts +8 -0
- package/src/api/subscriptions/schemas/changePlanSchema.ts +9 -0
- package/src/api/subscriptions/schemas/createSubscriptionSchema.ts +11 -0
- package/src/api/subscriptions/schemas/entitlementsSchema.ts +21 -0
- package/src/api/subscriptions/schemas/mrrSchema.ts +13 -0
- package/src/api/subscriptions/schemas/planDefinitionSchema.ts +71 -0
- package/src/api/subscriptions/schemas/planResourceSchema.ts +25 -0
- package/src/api/subscriptions/schemas/subscriptionEventResourceSchema.ts +8 -0
- package/src/api/subscriptions/schemas/subscriptionQuerySchema.ts +19 -0
- package/src/api/subscriptions/schemas/subscriptionResourceSchema.ts +6 -0
- package/src/api/subscriptions/schemas/subscriptionSettingsSchema.ts +32 -0
- package/src/api/subscriptions/schemas/subscriptionStatsSchema.ts +23 -0
- package/src/api/subscriptions/services/BillingService.ts +437 -0
- package/src/api/subscriptions/services/SubscriptionConfig.ts +56 -0
- package/src/api/subscriptions/services/SubscriptionService.ts +867 -0
- package/src/api/subscriptions/services/UsageService.ts +118 -0
- package/src/api/users/__tests__/AdminUserController.spec.ts +80 -1
- package/src/api/users/__tests__/CredentialService.spec.ts +177 -0
- package/src/api/users/__tests__/EmailVerification.spec.ts +29 -18
- package/src/api/users/__tests__/PasswordReset.spec.ts +3 -0
- package/src/api/users/__tests__/RegistrationService.spec.ts +148 -1
- package/src/api/users/__tests__/SessionService.spec.ts +142 -1
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -1
- package/src/api/users/controllers/UserController.ts +3 -8
- package/src/api/users/notifications/UserNotifications.ts +23 -0
- package/src/api/users/primitives/$realm.ts +24 -0
- package/src/api/users/schemas/loginSchema.ts +1 -1
- package/src/api/users/services/CredentialService.ts +57 -7
- package/src/api/users/services/RegistrationService.ts +50 -11
- package/src/api/users/services/SessionService.ts +64 -9
- package/src/api/users/services/UserService.ts +21 -12
- package/src/api/workflows/__tests__/$workflow.spec.ts +616 -0
- package/src/api/workflows/controllers/AdminWorkflowController.ts +191 -0
- package/src/api/workflows/entities/workflowExecutions.ts +74 -0
- package/src/api/workflows/entities/workflowStepExecutions.ts +74 -0
- package/src/api/workflows/entities/workflowStepLogs.ts +13 -0
- package/src/api/workflows/index.browser.ts +22 -0
- package/src/api/workflows/index.ts +124 -0
- package/src/api/workflows/jobs/WorkflowJobs.ts +77 -0
- package/src/api/workflows/primitives/$workflow.ts +202 -0
- package/src/api/workflows/providers/WorkflowProvider.ts +1284 -0
- package/src/api/workflows/schemas/workflowActivitySchema.ts +15 -0
- package/src/api/workflows/schemas/workflowConfigAtom.ts +51 -0
- package/src/api/workflows/schemas/workflowExecutionDetailSchema.ts +18 -0
- package/src/api/workflows/schemas/workflowExecutionQuerySchema.ts +26 -0
- package/src/api/workflows/schemas/workflowExecutionResourceSchema.ts +30 -0
- package/src/api/workflows/schemas/workflowRegistrationSchema.ts +26 -0
- package/src/api/workflows/schemas/workflowStatsSchema.ts +16 -0
- package/src/api/workflows/schemas/workflowStepExecutionResourceSchema.ts +15 -0
- package/src/api/workflows/services/WorkflowService.ts +382 -0
- package/src/captcha/__tests__/MemoryCaptchaProvider.spec.ts +74 -0
- package/src/captcha/index.ts +33 -0
- package/src/captcha/providers/CaptchaProvider.ts +17 -0
- package/src/captcha/providers/MemoryCaptchaProvider.ts +65 -0
- package/src/captcha/providers/TurnstileCaptchaProvider.ts +125 -0
- package/src/cli/core/atoms/buildOptions.ts +57 -0
- package/src/cli/core/commands/build.ts +2 -0
- package/src/cli/core/providers/ViteDevServerProvider.ts +1 -1
- package/src/cli/core/services/ViteUtils.ts +5 -2
- package/src/cli/core/tasks/BuildClientTask.ts +3 -1
- package/src/cli/core/tasks/BuildCloudflareTask.ts +4 -0
- package/src/cli/core/tasks/BuildPwaTask.ts +81 -0
- package/src/cli/core/templates/webAppRouterTs.ts +5 -58
- package/src/cli/platform/adapters/CloudflareAdapter.ts +24 -0
- package/src/cli/platform/atoms/platformOptions.ts +19 -3
- package/src/cli/platform/hooks/PlatformHook.ts +51 -0
- package/src/cli/platform/index.ts +1 -0
- package/src/cli/platform/services/CloudflareApi.ts +22 -1
- package/src/cli/platform/services/PlatformOrchestrator.ts +67 -2
- package/src/cli/vendor/__tests__/VendorService.spec.ts +322 -178
- package/src/cli/vendor/commands/VendorCommand.ts +41 -38
- package/src/cli/vendor/services/VendorService.ts +234 -31
- package/src/command/__tests__/CliProvider.spec.ts +45 -0
- package/src/command/providers/CliProvider.ts +3 -4
- package/src/core/__tests__/TypeProvider.spec.ts +4 -2
- package/src/core/providers/SchemaValidator.ts +1 -1
- package/src/core/providers/TypeProvider.ts +46 -3
- package/src/orm/__tests__/enums.spec.ts +22 -29
- package/src/orm/__tests__/orm-showcase-tests.ts +430 -0
- package/src/orm/__tests__/orm-showcase.spec.ts +167 -0
- package/src/orm/core/providers/DatabaseTypeProvider.ts +0 -29
- package/src/orm/core/services/Repository.ts +20 -6
- package/src/orm/postgres/services/PostgresModelBuilder.ts +3 -6
- package/src/react/i18n/__tests__/I18nProvider.spec.ts +83 -0
- package/src/react/i18n/providers/I18nProvider.ts +12 -10
- package/src/react/router/__tests__/$page.browser.spec.tsx +157 -0
- package/src/react/router/providers/ReactBrowserProvider.ts +39 -0
- package/src/react/router/providers/ReactBrowserRouterProvider.ts +22 -0
- package/src/security/__tests__/$secure-combinations.spec.ts +945 -0
- package/src/security/primitives/$issuer.ts +3 -1
- package/src/security/primitives/$secure.ts +28 -0
- package/src/server/auth/index.ts +7 -0
- package/src/server/auth/primitives/$auth.ts +37 -3
- package/src/server/auth/primitives/$authApple.ts +114 -4
- package/src/server/auth/primitives/$authFacebook.ts +98 -0
- package/src/server/auth/primitives/$authFranceConnect.ts +105 -0
- package/src/server/auth/primitives/$authGithub.ts +22 -16
- package/src/server/auth/primitives/$authMicrosoft.ts +88 -0
- package/src/server/auth/providers/ServerAuthProvider.ts +197 -72
- package/src/server/cookies/providers/ServerCookiesProvider.ts +3 -0
- package/src/server/core/__tests__/ServerRouterProvider-errorHandler.spec.ts +1 -1
- package/src/websocket/providers/NodeWebSocketServerProvider.ts +3 -1
- package/dist/billing/index.d.ts.map +0 -1
- package/dist/billing/index.js.map +0 -1
- package/src/billing/__tests__/BillingService.spec.ts +0 -136
- /package/src/{billing → api/payments}/entities/paymentMethods.ts +0 -0
- /package/src/{billing → api/payments}/entities/refunds.ts +0 -0
- /package/src/{billing → api/payments}/schemas/intentSchemas.ts +0 -0
- /package/src/{billing → api/payments}/schemas/paymentMethodSchemas.ts +0 -0
- /package/src/{billing → api/payments}/schemas/refundSchemas.ts +0 -0
|
@@ -15,6 +15,7 @@ import { $client } from "alepha/server/links";
|
|
|
15
15
|
import { FileSystemProvider } from "alepha/system";
|
|
16
16
|
import { UserAudits } from "../audits/UserAudits.ts";
|
|
17
17
|
import type { UserEntity } from "../entities/users.ts";
|
|
18
|
+
import { UserNotifications } from "../notifications/UserNotifications.ts";
|
|
18
19
|
import { RealmProvider } from "../providers/RealmProvider.ts";
|
|
19
20
|
|
|
20
21
|
export class SessionService {
|
|
@@ -35,6 +36,14 @@ export class SessionService {
|
|
|
35
36
|
return undefined;
|
|
36
37
|
}
|
|
37
38
|
|
|
39
|
+
protected userNotifications(realmName?: string) {
|
|
40
|
+
const realm = this.realmProvider.getRealm(realmName);
|
|
41
|
+
if (realm.features.notifications) {
|
|
42
|
+
return this.alepha.inject(UserNotifications);
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
|
|
38
47
|
public users(userRealmName?: string) {
|
|
39
48
|
return this.realmProvider.userRepository(userRealmName);
|
|
40
49
|
}
|
|
@@ -141,16 +150,12 @@ export class SessionService {
|
|
|
141
150
|
// Truncate to leave room for suffix
|
|
142
151
|
candidate = candidate.slice(0, maxLength - 2);
|
|
143
152
|
|
|
144
|
-
// Check uniqueness (case-insensitive)
|
|
153
|
+
// Check uniqueness (case-insensitive exact match)
|
|
145
154
|
const isAvailable = async (name: string) => {
|
|
146
|
-
const existing = await users.
|
|
147
|
-
where: { username: {
|
|
148
|
-
limit: 1,
|
|
155
|
+
const existing = await users.findOne({
|
|
156
|
+
where: { username: { ilike: name } },
|
|
149
157
|
});
|
|
150
|
-
|
|
151
|
-
return !existing.some(
|
|
152
|
-
(u: any) => u.username?.toLowerCase() === name.toLowerCase(),
|
|
153
|
-
);
|
|
158
|
+
return !existing;
|
|
154
159
|
};
|
|
155
160
|
|
|
156
161
|
if (await isAvailable(candidate)) {
|
|
@@ -354,6 +359,23 @@ export class SessionService {
|
|
|
354
359
|
throw new InvalidCredentialsError();
|
|
355
360
|
}
|
|
356
361
|
|
|
362
|
+
// Check if user account is enabled
|
|
363
|
+
if (!user.enabled) {
|
|
364
|
+
this.log.warn("Login attempt for disabled account", {
|
|
365
|
+
userId: user.id,
|
|
366
|
+
realm: name,
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
await this.userAudits(userRealmName)?.recordAuth("login_failed", {
|
|
370
|
+
userRealm: name,
|
|
371
|
+
resourceId: user.id,
|
|
372
|
+
description: "Login attempt for disabled account",
|
|
373
|
+
metadata: { provider, username },
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
throw new InvalidCredentialsError();
|
|
377
|
+
}
|
|
378
|
+
|
|
357
379
|
// Account rate limit check (per-realm)
|
|
358
380
|
const accountKey = `login:account:${name}:${user.id}`;
|
|
359
381
|
const accountLocked = await this.isLoginLocked(
|
|
@@ -445,6 +467,15 @@ export class SessionService {
|
|
|
445
467
|
metadata: { userId: user.id },
|
|
446
468
|
},
|
|
447
469
|
);
|
|
470
|
+
|
|
471
|
+
// Notify user about account lockout
|
|
472
|
+
if (user.email) {
|
|
473
|
+
const lockoutMinutes = Math.round(loginRateLimit.windowMs / 60_000);
|
|
474
|
+
await this.userNotifications(userRealmName)?.accountLockout.push({
|
|
475
|
+
contact: user.email,
|
|
476
|
+
variables: { email: user.email, lockoutMinutes },
|
|
477
|
+
});
|
|
478
|
+
}
|
|
448
479
|
}
|
|
449
480
|
|
|
450
481
|
throw new InvalidCredentialsError();
|
|
@@ -512,6 +543,8 @@ export class SessionService {
|
|
|
512
543
|
public async refreshSession(refreshToken: string, userRealmName?: string) {
|
|
513
544
|
this.log.trace("Refreshing session");
|
|
514
545
|
|
|
546
|
+
// getOne() throws DbEntityNotFoundError if not found — never returns null.
|
|
547
|
+
// No null check needed here.
|
|
515
548
|
const session = await this.sessions(userRealmName).getOne({
|
|
516
549
|
where: {
|
|
517
550
|
refreshToken: { eq: refreshToken },
|
|
@@ -536,6 +569,16 @@ export class SessionService {
|
|
|
536
569
|
},
|
|
537
570
|
});
|
|
538
571
|
|
|
572
|
+
// Check if user account is still enabled
|
|
573
|
+
if (!user.enabled) {
|
|
574
|
+
this.log.warn("Session refresh for disabled account", {
|
|
575
|
+
userId: user.id,
|
|
576
|
+
sessionId: session.id,
|
|
577
|
+
});
|
|
578
|
+
await this.sessions(userRealmName).deleteById(session.id);
|
|
579
|
+
throw new UnauthorizedError("Account disabled");
|
|
580
|
+
}
|
|
581
|
+
|
|
539
582
|
// Auto-promote to admin if configured (handles "I promote you admin" case)
|
|
540
583
|
await this.ensureAdminRole(user, userRealmName);
|
|
541
584
|
|
|
@@ -636,11 +679,23 @@ export class SessionService {
|
|
|
636
679
|
|
|
637
680
|
const existing = await users.findOne({
|
|
638
681
|
where: {
|
|
682
|
+
realm: realm.name,
|
|
639
683
|
email: profile.email,
|
|
640
684
|
},
|
|
641
685
|
});
|
|
642
686
|
|
|
643
687
|
if (existing) {
|
|
688
|
+
// Refuse auto-link if the OAuth provider explicitly says email is not verified
|
|
689
|
+
if (profile.email_verified === false) {
|
|
690
|
+
this.log.warn(
|
|
691
|
+
"OAuth2 profile email not verified by provider, refusing auto-link",
|
|
692
|
+
{ provider, email: profile.email, userId: existing.id },
|
|
693
|
+
);
|
|
694
|
+
throw new BadRequestError(
|
|
695
|
+
"Cannot link account: email not verified by provider",
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
|
|
644
699
|
this.log.debug("Linking OAuth2 profile to existing user by email", {
|
|
645
700
|
provider,
|
|
646
701
|
profileSub: profile.sub,
|
|
@@ -692,7 +747,7 @@ export class SessionService {
|
|
|
692
747
|
email: profile.email,
|
|
693
748
|
// we trust the OAuth2 provider
|
|
694
749
|
emailVerified: true,
|
|
695
|
-
roles:
|
|
750
|
+
roles: realmSettings.defaultRoles,
|
|
696
751
|
});
|
|
697
752
|
|
|
698
753
|
if (profile.picture) {
|
|
@@ -49,7 +49,6 @@ export class UserService {
|
|
|
49
49
|
email: string,
|
|
50
50
|
userRealmName?: string,
|
|
51
51
|
method: "code" | "link" = "code",
|
|
52
|
-
verifyUrl?: string,
|
|
53
52
|
): Promise<boolean> {
|
|
54
53
|
this.log.trace("Requesting email verification", {
|
|
55
54
|
email,
|
|
@@ -84,12 +83,15 @@ export class UserService {
|
|
|
84
83
|
});
|
|
85
84
|
|
|
86
85
|
if (method === "link") {
|
|
87
|
-
// Build verification URL
|
|
88
|
-
const
|
|
86
|
+
// Build verification URL from realm settings (server-controlled, not user input)
|
|
87
|
+
const realm = this.realmProvider.getRealm(userRealmName);
|
|
88
|
+
const realmSettings = await realm.getSettings();
|
|
89
|
+
const baseUrl = realmSettings.verifyEmailUrl ?? "/verify-email";
|
|
90
|
+
const url = new URL(baseUrl, "http://localhost");
|
|
89
91
|
url.searchParams.set("email", email);
|
|
90
92
|
url.searchParams.set("token", verification.token);
|
|
91
|
-
const fullVerifyUrl =
|
|
92
|
-
? `${
|
|
93
|
+
const fullVerifyUrl = realmSettings.verifyEmailUrl
|
|
94
|
+
? `${baseUrl}${url.search}`
|
|
93
95
|
: url.pathname + url.search;
|
|
94
96
|
|
|
95
97
|
await this.userNotifications(userRealmName)?.emailVerificationLink.push(
|
|
@@ -270,13 +272,12 @@ export class UserService {
|
|
|
270
272
|
});
|
|
271
273
|
|
|
272
274
|
const realm = this.realmProvider.getRealm(userRealmName);
|
|
275
|
+
const realmSettings = await realm.getSettings();
|
|
273
276
|
|
|
274
|
-
//
|
|
275
|
-
|
|
276
|
-
// Check for existing user based on provided unique fields
|
|
277
|
+
// Check for existing user based on provided unique fields (scoped to realm)
|
|
277
278
|
if (data.username) {
|
|
278
279
|
const existingUser = await this.users(userRealmName).findOne({
|
|
279
|
-
where: { username: { ilike: data.username } },
|
|
280
|
+
where: { realm: realm.name, username: { ilike: data.username } },
|
|
280
281
|
});
|
|
281
282
|
|
|
282
283
|
if (existingUser) {
|
|
@@ -287,7 +288,7 @@ export class UserService {
|
|
|
287
288
|
|
|
288
289
|
if (data.email) {
|
|
289
290
|
const existingUser = await this.users(userRealmName).findOne({
|
|
290
|
-
where: { email: { eq: data.email } },
|
|
291
|
+
where: { realm: realm.name, email: { eq: data.email } },
|
|
291
292
|
});
|
|
292
293
|
|
|
293
294
|
if (existingUser) {
|
|
@@ -298,7 +299,7 @@ export class UserService {
|
|
|
298
299
|
|
|
299
300
|
if (data.phoneNumber) {
|
|
300
301
|
const existingUser = await this.users(userRealmName).findOne({
|
|
301
|
-
where: { phoneNumber: { eq: data.phoneNumber } },
|
|
302
|
+
where: { realm: realm.name, phoneNumber: { eq: data.phoneNumber } },
|
|
302
303
|
});
|
|
303
304
|
|
|
304
305
|
if (existingUser) {
|
|
@@ -311,7 +312,7 @@ export class UserService {
|
|
|
311
312
|
|
|
312
313
|
const user = await this.users(userRealmName).create({
|
|
313
314
|
...data,
|
|
314
|
-
roles: data.roles ??
|
|
315
|
+
roles: data.roles ?? realmSettings.defaultRoles,
|
|
315
316
|
realm: realm.name,
|
|
316
317
|
});
|
|
317
318
|
|
|
@@ -386,6 +387,14 @@ export class UserService {
|
|
|
386
387
|
this.log.trace("Deleting user", { id, userRealmName });
|
|
387
388
|
const user = await this.getUserById(id, userRealmName);
|
|
388
389
|
|
|
390
|
+
// Clean up related sessions and identities before deleting the user
|
|
391
|
+
await this.realmProvider
|
|
392
|
+
.sessionRepository(userRealmName)
|
|
393
|
+
.deleteMany({ userId: { eq: id } });
|
|
394
|
+
await this.realmProvider
|
|
395
|
+
.identityRepository(userRealmName)
|
|
396
|
+
.deleteMany({ userId: { eq: id } });
|
|
397
|
+
|
|
389
398
|
await this.users(userRealmName).deleteById(id);
|
|
390
399
|
this.log.info("User deleted", { userId: id });
|
|
391
400
|
|