alepha 0.15.4 → 0.15.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/README.md +26 -11
- package/dist/api/audits/index.d.ts +3 -3
- package/dist/api/audits/index.js +3 -3
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.d.ts +3 -3
- package/dist/api/files/index.js +3 -3
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.d.ts +47 -4
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +100 -5
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/keys/index.d.ts +3 -3
- package/dist/api/keys/index.js +3 -3
- package/dist/api/keys/index.js.map +1 -1
- package/dist/api/notifications/index.d.ts +3 -3
- package/dist/api/notifications/index.js +3 -3
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.d.ts +263 -263
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +31 -30
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.d.ts +373 -67
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +273 -72
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.d.ts +3 -3
- package/dist/api/verifications/index.js +3 -3
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/batch/index.d.ts +7 -7
- package/dist/batch/index.js +3 -3
- package/dist/batch/index.js.map +1 -1
- package/dist/bucket/index.d.ts +3 -3
- package/dist/bucket/index.js +6 -6
- package/dist/bucket/index.js.map +1 -1
- package/dist/cache/core/index.d.ts +3 -3
- package/dist/cache/core/index.js +3 -3
- package/dist/cache/core/index.js.map +1 -1
- package/dist/cli/index.d.ts +5607 -20
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +103 -89
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +11 -4
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +8 -6
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +4 -8
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +3 -3
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js.map +1 -1
- package/dist/datetime/index.d.ts +3 -3
- package/dist/datetime/index.js +3 -3
- package/dist/datetime/index.js.map +1 -1
- package/dist/email/index.d.ts +3 -3
- package/dist/email/index.js +8 -8
- package/dist/email/index.js.map +1 -1
- package/dist/fake/index.d.ts +3 -3
- package/dist/fake/index.js +3 -3
- package/dist/fake/index.js.map +1 -1
- package/dist/lock/core/index.d.ts +3 -3
- package/dist/lock/core/index.js +3 -3
- package/dist/lock/core/index.js.map +1 -1
- package/dist/logger/index.d.ts +3 -3
- package/dist/logger/index.js +6 -3
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.d.ts +3 -3
- package/dist/mcp/index.js +3 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.d.ts +12 -12
- package/dist/orm/index.js +4 -4
- package/dist/orm/index.js.map +1 -1
- package/dist/queue/core/index.d.ts +3 -3
- package/dist/queue/core/index.js +3 -3
- package/dist/queue/core/index.js.map +1 -1
- package/dist/react/auth/index.d.ts +3 -3
- package/dist/react/auth/index.js +3 -3
- package/dist/react/auth/index.js.map +1 -1
- package/dist/react/core/index.d.ts +3 -3
- package/dist/react/core/index.js +3 -3
- package/dist/react/core/index.js.map +1 -1
- package/dist/react/form/index.d.ts +3 -3
- package/dist/react/form/index.js +3 -3
- package/dist/react/form/index.js.map +1 -1
- package/dist/react/head/index.d.ts +3 -3
- package/dist/react/head/index.js +3 -3
- package/dist/react/head/index.js.map +1 -1
- package/dist/react/i18n/index.d.ts +3 -3
- package/dist/react/i18n/index.js +3 -3
- package/dist/react/i18n/index.js.map +1 -1
- package/dist/react/intro/index.css +337 -0
- package/dist/react/intro/index.css.map +1 -0
- package/dist/react/intro/index.d.ts +10 -0
- package/dist/react/intro/index.d.ts.map +1 -0
- package/dist/react/intro/index.js +222 -0
- package/dist/react/intro/index.js.map +1 -0
- package/dist/react/router/index.browser.js +2 -2
- package/dist/react/router/index.browser.js.map +1 -1
- package/dist/react/router/index.d.ts +1 -1
- package/dist/react/router/index.d.ts.map +1 -1
- package/dist/react/router/index.js +5 -5
- package/dist/react/router/index.js.map +1 -1
- package/dist/redis/index.d.ts +17 -17
- package/dist/redis/index.js +3 -3
- package/dist/redis/index.js.map +1 -1
- package/dist/retry/index.d.ts +3 -3
- package/dist/retry/index.js +3 -3
- package/dist/retry/index.js.map +1 -1
- package/dist/scheduler/index.d.ts +3 -3
- package/dist/scheduler/index.js +3 -3
- package/dist/scheduler/index.js.map +1 -1
- package/dist/security/index.d.ts +3 -3
- package/dist/security/index.js +5 -5
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +3 -3
- package/dist/server/auth/index.js +3 -3
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +3 -3
- package/dist/server/cache/index.js +3 -3
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +3 -3
- package/dist/server/compress/index.js +3 -3
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/cookies/index.d.ts +3 -3
- package/dist/server/cookies/index.js +3 -3
- package/dist/server/cookies/index.js.map +1 -1
- package/dist/server/core/index.d.ts +5 -16
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +13 -29
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/cors/index.d.ts +3 -3
- package/dist/server/cors/index.js +3 -3
- package/dist/server/cors/index.js.map +1 -1
- package/dist/server/health/index.d.ts +20 -20
- package/dist/server/health/index.js +3 -3
- package/dist/server/health/index.js.map +1 -1
- package/dist/server/helmet/index.d.ts +3 -3
- package/dist/server/helmet/index.js +3 -3
- package/dist/server/helmet/index.js.map +1 -1
- package/dist/server/links/index.d.ts +42 -42
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +3 -3
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/metrics/index.d.ts +3 -3
- package/dist/server/metrics/index.js +3 -3
- package/dist/server/metrics/index.js.map +1 -1
- package/dist/server/multipart/index.d.ts +3 -3
- package/dist/server/multipart/index.js +3 -3
- package/dist/server/multipart/index.js.map +1 -1
- package/dist/server/proxy/index.d.ts +3 -3
- package/dist/server/proxy/index.js +3 -3
- package/dist/server/proxy/index.js.map +1 -1
- package/dist/server/rate-limit/index.d.ts +3 -3
- package/dist/server/rate-limit/index.js +3 -3
- package/dist/server/rate-limit/index.js.map +1 -1
- package/dist/server/static/index.d.ts +3 -3
- package/dist/server/static/index.js +6 -6
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +3 -3
- package/dist/server/swagger/index.js +6 -6
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/sms/index.d.ts +3 -3
- package/dist/sms/index.js +6 -6
- package/dist/sms/index.js.map +1 -1
- package/dist/system/index.d.ts +3 -3
- package/dist/system/index.js +3 -3
- package/dist/system/index.js.map +1 -1
- package/dist/thread/index.d.ts +3 -3
- package/dist/thread/index.js +3 -3
- package/dist/thread/index.js.map +1 -1
- package/dist/topic/core/index.d.ts +3 -3
- package/dist/topic/core/index.js +3 -3
- package/dist/topic/core/index.js.map +1 -1
- package/dist/vite/index.d.ts +6284 -3
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/websocket/index.d.ts +3 -3
- package/dist/websocket/index.js +3 -3
- package/dist/websocket/index.js.map +1 -1
- package/package.json +7 -2
- package/src/api/audits/index.ts +3 -3
- package/src/api/files/index.ts +3 -3
- package/src/api/jobs/controllers/AdminJobController.ts +15 -2
- package/src/api/jobs/index.ts +4 -3
- package/src/api/jobs/services/JobAudits.spec.ts +89 -0
- package/src/api/jobs/services/JobAudits.ts +101 -0
- package/src/api/keys/index.ts +3 -3
- package/src/api/notifications/index.ts +3 -3
- package/src/api/parameters/index.ts +5 -3
- package/src/api/users/__tests__/ApiKeys-integration.spec.ts +1 -1
- package/src/api/users/__tests__/ApiKeys.spec.ts +1 -1
- package/src/api/users/__tests__/EmailVerification.spec.ts +16 -1
- package/src/api/users/__tests__/PasswordReset.spec.ts +11 -0
- package/src/api/users/atoms/realmAuthSettingsAtom.ts +10 -0
- package/src/api/users/index.ts +8 -9
- package/src/api/users/primitives/$realm.ts +117 -19
- package/src/api/users/providers/RealmProvider.ts +15 -7
- package/src/api/users/services/CredentialService.spec.ts +11 -0
- package/src/api/users/services/CredentialService.ts +47 -24
- package/src/api/users/services/IdentityService.ts +12 -4
- package/src/api/users/services/RegistrationService.spec.ts +11 -0
- package/src/api/users/services/RegistrationService.ts +33 -12
- package/src/api/users/services/SessionService.ts +83 -12
- package/src/api/users/services/UserAudits.ts +47 -0
- package/src/api/users/services/UserFiles.ts +19 -0
- package/src/api/users/services/UserJobs.spec.ts +107 -0
- package/src/api/users/services/UserJobs.ts +62 -0
- package/src/api/users/services/UserParameters.ts +23 -0
- package/src/api/users/services/UserService.ts +34 -17
- package/src/api/verifications/index.ts +3 -3
- package/src/batch/index.ts +3 -3
- package/src/bucket/index.ts +3 -3
- package/src/cache/core/index.ts +3 -3
- package/src/cli/commands/db.ts +9 -0
- package/src/cli/commands/init.spec.ts +2 -17
- package/src/cli/commands/init.ts +37 -1
- package/src/cli/providers/ViteDevServerProvider.ts +5 -2
- package/src/cli/services/AlephaCliUtils.ts +17 -0
- package/src/cli/services/PackageManagerUtils.ts +15 -1
- package/src/cli/services/ProjectScaffolder.ts +8 -13
- package/src/cli/templates/agentMd.ts +2 -25
- package/src/cli/templates/apiAppSecurityTs.ts +37 -2
- package/src/cli/templates/mainCss.ts +2 -32
- package/src/cli/templates/webAppRouterTs.ts +5 -5
- package/src/cli/templates/webHomeComponentTsx.ts +10 -0
- package/src/command/helpers/Runner.ts +14 -1
- package/src/command/index.ts +3 -3
- package/src/core/helpers/primitive.ts +0 -5
- package/src/core/index.ts +3 -3
- package/src/datetime/index.ts +3 -3
- package/src/email/index.ts +3 -3
- package/src/email/providers/LocalEmailProvider.ts +2 -2
- package/src/fake/index.ts +3 -3
- package/src/lock/core/index.ts +3 -3
- package/src/logger/index.ts +3 -3
- package/src/logger/providers/PrettyFormatterProvider.ts +7 -0
- package/src/mcp/index.ts +3 -3
- package/src/orm/index.ts +3 -3
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
- package/src/queue/core/index.ts +3 -3
- package/src/react/auth/index.ts +3 -3
- package/src/react/core/index.ts +3 -3
- package/src/react/form/index.ts +3 -3
- package/src/react/head/index.ts +3 -3
- package/src/react/i18n/index.ts +3 -3
- package/src/react/intro/components/GettingStarted.css +334 -0
- package/src/react/intro/components/GettingStarted.tsx +276 -0
- package/src/react/intro/index.ts +1 -0
- package/src/react/router/index.browser.ts +2 -0
- package/src/react/router/index.ts +2 -0
- package/src/redis/index.ts +3 -3
- package/src/retry/index.ts +3 -3
- package/src/router/index.ts +3 -3
- package/src/scheduler/index.ts +3 -3
- package/src/security/index.ts +3 -3
- package/src/security/providers/JwtProvider.ts +2 -2
- package/src/server/auth/index.ts +3 -3
- package/src/server/cache/index.ts +3 -3
- package/src/server/compress/index.ts +3 -3
- package/src/server/cookies/index.ts +3 -3
- package/src/server/core/index.ts +3 -3
- package/src/server/core/primitives/$action.spec.ts +3 -2
- package/src/server/core/primitives/$action.ts +6 -2
- package/src/server/core/providers/NodeHttpServerProvider.ts +2 -15
- package/src/server/core/providers/ServerProvider.ts +4 -2
- package/src/server/core/providers/ServerRouterProvider.ts +5 -27
- package/src/server/cors/index.ts +3 -3
- package/src/server/health/index.ts +3 -3
- package/src/server/helmet/index.ts +3 -3
- package/src/server/links/index.ts +3 -3
- package/src/server/metrics/index.ts +3 -3
- package/src/server/multipart/index.ts +3 -3
- package/src/server/proxy/index.ts +3 -3
- package/src/server/rate-limit/index.ts +3 -3
- package/src/server/static/index.ts +3 -3
- package/src/server/swagger/index.ts +3 -3
- package/src/sms/index.ts +3 -3
- package/src/system/index.ts +3 -3
- package/src/thread/index.ts +3 -3
- package/src/topic/core/index.ts +3 -3
- package/src/websocket/index.ts +3 -3
- package/src/cli/templates/webHelloComponentTsx.ts +0 -30
- /package/src/api/users/{notifications → services}/UserNotifications.ts +0 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { $audit, type AuditLogOptions } from "alepha/api/audits";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Job-specific audit service.
|
|
5
|
+
*
|
|
6
|
+
* Provides type-safe audit logging for job-related events.
|
|
7
|
+
* This service is lazy-loaded when the audits feature is enabled.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const jobAudits = alepha.inject(JobAudits);
|
|
12
|
+
* await jobAudits.logTrigger("my-job", { description: "Manually triggered" });
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export class JobAudits {
|
|
16
|
+
protected readonly audit = $audit({
|
|
17
|
+
type: "job",
|
|
18
|
+
description: "Background job execution events",
|
|
19
|
+
actions: ["trigger", "pause", "resume", "cancel", "schedule_change"],
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Log a manual job trigger event.
|
|
24
|
+
*/
|
|
25
|
+
public async logTrigger(
|
|
26
|
+
jobName: string,
|
|
27
|
+
options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
|
|
28
|
+
) {
|
|
29
|
+
await this.audit.log("trigger", {
|
|
30
|
+
...options,
|
|
31
|
+
resourceType: "job",
|
|
32
|
+
resourceId: jobName,
|
|
33
|
+
description: options.description ?? `Manually triggered job: ${jobName}`,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Log a job pause event.
|
|
39
|
+
*/
|
|
40
|
+
public async logPause(
|
|
41
|
+
jobName: string,
|
|
42
|
+
options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
|
|
43
|
+
) {
|
|
44
|
+
await this.audit.log("pause", {
|
|
45
|
+
...options,
|
|
46
|
+
resourceType: "job",
|
|
47
|
+
resourceId: jobName,
|
|
48
|
+
description: options.description ?? `Paused job: ${jobName}`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Log a job resume event.
|
|
54
|
+
*/
|
|
55
|
+
public async logResume(
|
|
56
|
+
jobName: string,
|
|
57
|
+
options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
|
|
58
|
+
) {
|
|
59
|
+
await this.audit.log("resume", {
|
|
60
|
+
...options,
|
|
61
|
+
resourceType: "job",
|
|
62
|
+
resourceId: jobName,
|
|
63
|
+
description: options.description ?? `Resumed job: ${jobName}`,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Log a job cancellation event.
|
|
69
|
+
*/
|
|
70
|
+
public async logCancel(
|
|
71
|
+
jobName: string,
|
|
72
|
+
options: Omit<AuditLogOptions, "resourceType" | "resourceId"> = {},
|
|
73
|
+
) {
|
|
74
|
+
await this.audit.log("cancel", {
|
|
75
|
+
...options,
|
|
76
|
+
resourceType: "job",
|
|
77
|
+
resourceId: jobName,
|
|
78
|
+
description: options.description ?? `Cancelled job: ${jobName}`,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Log a job schedule change event.
|
|
84
|
+
*/
|
|
85
|
+
public async logScheduleChange(
|
|
86
|
+
jobName: string,
|
|
87
|
+
options: Omit<AuditLogOptions, "resourceType" | "resourceId"> & {
|
|
88
|
+
oldCron?: string;
|
|
89
|
+
newCron?: string;
|
|
90
|
+
} = {},
|
|
91
|
+
) {
|
|
92
|
+
const { oldCron, newCron, ...rest } = options;
|
|
93
|
+
await this.audit.log("schedule_change", {
|
|
94
|
+
...rest,
|
|
95
|
+
resourceType: "job",
|
|
96
|
+
resourceId: jobName,
|
|
97
|
+
description: rest.description ?? `Changed schedule for job: ${jobName}`,
|
|
98
|
+
metadata: { oldCron, newCron, ...rest.metadata },
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
package/src/api/keys/index.ts
CHANGED
|
@@ -16,9 +16,9 @@ export * from "./schemas/revokeApiKeyResponseSchema.ts";
|
|
|
16
16
|
export * from "./services/ApiKeyService.ts";
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
|
-
* |
|
|
20
|
-
*
|
|
21
|
-
* |
|
|
19
|
+
* | Stability | Since | Runtime |
|
|
20
|
+
* |-----------|-------|---------|
|
|
21
|
+
* | 3 - stable | 0.11.0 | node, bun, workerd|
|
|
22
22
|
*
|
|
23
23
|
* API key management module for programmatic access.
|
|
24
24
|
*
|
|
@@ -25,9 +25,9 @@ export * from "./services/NotificationService.ts";
|
|
|
25
25
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
26
26
|
|
|
27
27
|
/**
|
|
28
|
-
* |
|
|
29
|
-
*
|
|
30
|
-
* |
|
|
28
|
+
* | Stability | Since | Runtime |
|
|
29
|
+
* |-----------|-------|---------|
|
|
30
|
+
* | 3 - stable | 0.10.0 | node, bun, workerd|
|
|
31
31
|
*
|
|
32
32
|
* User notification management.
|
|
33
33
|
*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
2
|
import { AdminConfigController } from "./controllers/AdminConfigController.ts";
|
|
3
|
+
import { $config } from "./primitives/$config.ts";
|
|
3
4
|
import { ConfigActivationScheduler } from "./schedulers/ConfigActivationScheduler.ts";
|
|
4
5
|
import { ConfigStore } from "./services/ConfigStore.ts";
|
|
5
6
|
|
|
@@ -19,9 +20,9 @@ export * from "./services/ConfigStore.ts";
|
|
|
19
20
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
20
21
|
|
|
21
22
|
/**
|
|
22
|
-
* |
|
|
23
|
-
*
|
|
24
|
-
* |
|
|
23
|
+
* | Stability | Since | Runtime |
|
|
24
|
+
* |-----------|-------|---------|
|
|
25
|
+
* | 3 - stable | 0.9.0 | node, bun, workerd|
|
|
25
26
|
*
|
|
26
27
|
* Application configuration management.
|
|
27
28
|
*
|
|
@@ -35,5 +36,6 @@ export * from "./services/ConfigStore.ts";
|
|
|
35
36
|
*/
|
|
36
37
|
export const AlephaApiParameters = $module({
|
|
37
38
|
name: "alepha.api.parameters",
|
|
39
|
+
primitives: [$config],
|
|
38
40
|
services: [ConfigStore, AdminConfigController, ConfigActivationScheduler],
|
|
39
41
|
});
|
|
@@ -5,7 +5,13 @@ import { AlephaEmail, MemoryEmailProvider } from "alepha/email";
|
|
|
5
5
|
import { AlephaSecurity } from "alepha/security";
|
|
6
6
|
import { BadRequestError } from "alepha/server";
|
|
7
7
|
import { describe, it } from "vitest";
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
AlephaApiUsers,
|
|
10
|
+
RealmProvider,
|
|
11
|
+
UserController,
|
|
12
|
+
UserNotifications,
|
|
13
|
+
UserService,
|
|
14
|
+
} from "../index.ts";
|
|
9
15
|
|
|
10
16
|
const setup = async () => {
|
|
11
17
|
const alepha = Alepha.create({
|
|
@@ -16,9 +22,18 @@ const setup = async () => {
|
|
|
16
22
|
alepha.with(AlephaEmail);
|
|
17
23
|
alepha.with(AlephaApiVerification);
|
|
18
24
|
alepha.with(AlephaApiUsers);
|
|
25
|
+
alepha.with(UserNotifications);
|
|
19
26
|
|
|
20
27
|
await alepha.start();
|
|
21
28
|
|
|
29
|
+
// Enable notifications for the default realm
|
|
30
|
+
const realmProvider = alepha.inject(RealmProvider);
|
|
31
|
+
realmProvider.register("default", {
|
|
32
|
+
features: {
|
|
33
|
+
notifications: true,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
22
37
|
const emailProvider = alepha.inject(MemoryEmailProvider);
|
|
23
38
|
emailProvider.records = [];
|
|
24
39
|
|
|
@@ -8,8 +8,10 @@ import { describe, it } from "vitest";
|
|
|
8
8
|
import {
|
|
9
9
|
AlephaApiUsers,
|
|
10
10
|
CredentialService,
|
|
11
|
+
RealmProvider,
|
|
11
12
|
SessionService,
|
|
12
13
|
UserController,
|
|
14
|
+
UserNotifications,
|
|
13
15
|
} from "../index.ts";
|
|
14
16
|
|
|
15
17
|
const setup = async () => {
|
|
@@ -21,9 +23,18 @@ const setup = async () => {
|
|
|
21
23
|
alepha.with(AlephaEmail);
|
|
22
24
|
alepha.with(AlephaApiVerification);
|
|
23
25
|
alepha.with(AlephaApiUsers);
|
|
26
|
+
alepha.with(UserNotifications);
|
|
24
27
|
|
|
25
28
|
await alepha.start();
|
|
26
29
|
|
|
30
|
+
// Enable notifications for the default realm
|
|
31
|
+
const realmProvider = alepha.inject(RealmProvider);
|
|
32
|
+
realmProvider.register("default", {
|
|
33
|
+
features: {
|
|
34
|
+
notifications: true,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
27
38
|
const emailProvider = alepha.inject(MemoryEmailProvider);
|
|
28
39
|
emailProvider.records = [];
|
|
29
40
|
|
|
@@ -62,6 +62,14 @@ export const realmAuthSettingsAtom = $atom({
|
|
|
62
62
|
resetPasswordAllowed: t.boolean({
|
|
63
63
|
description: "Enable forgot password functionality",
|
|
64
64
|
}),
|
|
65
|
+
adminEmails: t.array(t.email(), {
|
|
66
|
+
description:
|
|
67
|
+
"List of email addresses that are automatically promoted to admin role on login",
|
|
68
|
+
}),
|
|
69
|
+
adminUsernames: t.array(t.text(), {
|
|
70
|
+
description:
|
|
71
|
+
"List of usernames that are automatically promoted to admin role on login",
|
|
72
|
+
}),
|
|
65
73
|
passwordPolicy: t.object({
|
|
66
74
|
minLength: t.integer({
|
|
67
75
|
description: "Minimum password length",
|
|
@@ -97,6 +105,8 @@ export const realmAuthSettingsAtom = $atom({
|
|
|
97
105
|
resetPasswordAllowed: false,
|
|
98
106
|
firstNameLastNameEnabled: false,
|
|
99
107
|
firstNameLastNameRequired: false,
|
|
108
|
+
adminEmails: [],
|
|
109
|
+
adminUsernames: [],
|
|
100
110
|
// TODO: not implemented yet
|
|
101
111
|
passwordPolicy: {
|
|
102
112
|
minLength: 8,
|
package/src/api/users/index.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import { $module } from "alepha";
|
|
2
|
-
import { AlephaApiNotifications } from "alepha/api/notifications";
|
|
3
|
-
import { AlephaApiVerification } from "alepha/api/verifications";
|
|
4
2
|
import { AlephaEmail } from "alepha/email";
|
|
5
3
|
import { AlephaServerCompress } from "alepha/server/compress";
|
|
6
4
|
import { AlephaServerHelmet } from "alepha/server/helmet";
|
|
@@ -9,7 +7,6 @@ import { AdminSessionController } from "./controllers/AdminSessionController.ts"
|
|
|
9
7
|
import { AdminUserController } from "./controllers/AdminUserController.ts";
|
|
10
8
|
import { RealmController } from "./controllers/RealmController.ts";
|
|
11
9
|
import { UserController } from "./controllers/UserController.ts";
|
|
12
|
-
import { UserNotifications } from "./notifications/UserNotifications.ts";
|
|
13
10
|
import { RealmProvider } from "./providers/RealmProvider.ts";
|
|
14
11
|
import { CredentialService } from "./services/CredentialService.ts";
|
|
15
12
|
import { IdentityService } from "./services/IdentityService.ts";
|
|
@@ -52,14 +49,19 @@ export * from "./services/IdentityService.ts";
|
|
|
52
49
|
export * from "./services/RegistrationService.ts";
|
|
53
50
|
export * from "./services/SessionCrudService.ts";
|
|
54
51
|
export * from "./services/SessionService.ts";
|
|
52
|
+
export * from "./services/UserAudits.ts";
|
|
53
|
+
export * from "./services/UserFiles.ts";
|
|
54
|
+
export * from "./services/UserJobs.ts";
|
|
55
|
+
export * from "./services/UserNotifications.ts";
|
|
56
|
+
export * from "./services/UserParameters.ts";
|
|
55
57
|
export * from "./services/UserService.ts";
|
|
56
58
|
|
|
57
59
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
58
60
|
|
|
59
61
|
/**
|
|
60
|
-
* |
|
|
61
|
-
*
|
|
62
|
-
* |
|
|
62
|
+
* | Stability | Since | Runtime |
|
|
63
|
+
* |-----------|-------|---------|
|
|
64
|
+
* | 3 - stable | 0.5.0 | node, bun, workerd|
|
|
63
65
|
*
|
|
64
66
|
* Complete user management with multi-realm support for multi-tenant applications.
|
|
65
67
|
*
|
|
@@ -78,8 +80,6 @@ export * from "./services/UserService.ts";
|
|
|
78
80
|
export const AlephaApiUsers = $module({
|
|
79
81
|
name: "alepha.api.users",
|
|
80
82
|
services: [
|
|
81
|
-
AlephaApiVerification,
|
|
82
|
-
AlephaApiNotifications,
|
|
83
83
|
AlephaServerHelmet,
|
|
84
84
|
AlephaServerCompress,
|
|
85
85
|
AlephaEmail,
|
|
@@ -95,6 +95,5 @@ export const AlephaApiUsers = $module({
|
|
|
95
95
|
AdminSessionController,
|
|
96
96
|
AdminIdentityController,
|
|
97
97
|
RealmController,
|
|
98
|
-
UserNotifications,
|
|
99
98
|
],
|
|
100
99
|
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { $context } from "alepha";
|
|
2
|
-
import { AlephaApiAudits } from "alepha/api/audits";
|
|
3
|
-
import { AlephaApiFiles } from "alepha/api/files";
|
|
4
|
-
import { AlephaApiJobs } from "alepha/api/jobs";
|
|
5
2
|
import { AlephaApiKeys, ApiKeyService } from "alepha/api/keys";
|
|
3
|
+
import { AlephaApiVerification } from "alepha/api/verifications";
|
|
6
4
|
import type { Repository } from "alepha/orm";
|
|
7
5
|
import {
|
|
8
6
|
$issuer,
|
|
@@ -27,6 +25,11 @@ import type { sessions } from "../entities/sessions.ts";
|
|
|
27
25
|
import { DEFAULT_USER_REALM_NAME, type users } from "../entities/users.ts";
|
|
28
26
|
import { RealmProvider } from "../providers/RealmProvider.ts";
|
|
29
27
|
import { SessionService } from "../services/SessionService.ts";
|
|
28
|
+
import { UserAudits } from "../services/UserAudits.ts";
|
|
29
|
+
import { UserFiles } from "../services/UserFiles.ts";
|
|
30
|
+
import { UserJobs } from "../services/UserJobs.ts";
|
|
31
|
+
import { UserNotifications } from "../services/UserNotifications.ts";
|
|
32
|
+
import { UserParameters } from "../services/UserParameters.ts";
|
|
30
33
|
|
|
31
34
|
export type RealmPrimitive = IssuerPrimitive & WithLinkFn & WithLoginFn;
|
|
32
35
|
|
|
@@ -66,12 +69,50 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
66
69
|
options.settings.phoneEnabled = true;
|
|
67
70
|
}
|
|
68
71
|
|
|
72
|
+
// Merge features with defaults
|
|
73
|
+
const features: RealmFeatures = {
|
|
74
|
+
jobs: false,
|
|
75
|
+
notifications: false,
|
|
76
|
+
apiKeys: false,
|
|
77
|
+
parameters: false,
|
|
78
|
+
files: false,
|
|
79
|
+
audits: false,
|
|
80
|
+
organizations: false,
|
|
81
|
+
...options.features,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// When notifications are disabled, force verification-dependent settings to false
|
|
85
|
+
// These features require sending codes via email/SMS which won't work without notifications
|
|
86
|
+
if (!features.notifications) {
|
|
87
|
+
options.settings.verifyEmailRequired = false;
|
|
88
|
+
options.settings.verifyPhoneRequired = false;
|
|
89
|
+
options.settings.resetPasswordAllowed = false;
|
|
90
|
+
}
|
|
91
|
+
|
|
69
92
|
const realmRegistration = realmProvider.register(name, options);
|
|
70
93
|
|
|
71
|
-
//
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
94
|
+
// Enable features based on configuration
|
|
95
|
+
// Each feature registers its wrapper service which internally uses the module primitives
|
|
96
|
+
if (features.files) {
|
|
97
|
+
alepha.with(UserFiles);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (features.audits) {
|
|
101
|
+
alepha.with(UserAudits);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (features.jobs) {
|
|
105
|
+
alepha.with(UserJobs);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (features.notifications) {
|
|
109
|
+
alepha.with(AlephaApiVerification);
|
|
110
|
+
alepha.with(UserNotifications);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (features.parameters) {
|
|
114
|
+
alepha.with(UserParameters);
|
|
115
|
+
}
|
|
75
116
|
|
|
76
117
|
// Collect custom resolvers that will be registered during $issuer.onInit()
|
|
77
118
|
// This ensures they are registered AFTER the realm is created (not on the default test realm)
|
|
@@ -80,7 +121,7 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
80
121
|
];
|
|
81
122
|
|
|
82
123
|
// Enable API key authentication - must be added to customResolvers before $issuer() call
|
|
83
|
-
if (
|
|
124
|
+
if (features.apiKeys) {
|
|
84
125
|
alepha.with(AlephaApiKeys);
|
|
85
126
|
const apiKeyService = alepha.inject(ApiKeyService);
|
|
86
127
|
customResolvers.push(apiKeyService.createResolver());
|
|
@@ -176,6 +217,71 @@ export const $realm = (options: RealmOptions = {}): RealmPrimitive => {
|
|
|
176
217
|
|
|
177
218
|
// ---------------------------------------------------------------------------------------------------------------------
|
|
178
219
|
|
|
220
|
+
export interface RealmFeatures {
|
|
221
|
+
/**
|
|
222
|
+
* Enable job execution tracking and purge functionality.
|
|
223
|
+
*
|
|
224
|
+
* @default false
|
|
225
|
+
*/
|
|
226
|
+
jobs?: boolean;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Enable notification system for password reset, verification emails, etc.
|
|
230
|
+
*
|
|
231
|
+
* @default false
|
|
232
|
+
*/
|
|
233
|
+
notifications?: boolean;
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Enable API key authentication for programmatic access.
|
|
237
|
+
*
|
|
238
|
+
* When enabled, users can create API keys to access protected endpoints
|
|
239
|
+
* without using JWT tokens. API keys are useful for:
|
|
240
|
+
* - Programmatic access (CLI tools, scripts)
|
|
241
|
+
* - Long-lived authentication tokens
|
|
242
|
+
* - Third-party integrations (MCP servers)
|
|
243
|
+
*
|
|
244
|
+
* API keys can be passed via:
|
|
245
|
+
* - Query parameter: `?api_key=ak_xxx`
|
|
246
|
+
* - Bearer header: `Authorization: Bearer ak_xxx`
|
|
247
|
+
*
|
|
248
|
+
* @default false
|
|
249
|
+
*/
|
|
250
|
+
apiKeys?: boolean;
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Enable runtime configuration management.
|
|
254
|
+
*
|
|
255
|
+
* Allows configuring realm settings at runtime with versioning and scheduled activation.
|
|
256
|
+
*
|
|
257
|
+
* @default false
|
|
258
|
+
*/
|
|
259
|
+
parameters?: boolean;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Enable file management for avatar uploads and attachments.
|
|
263
|
+
*
|
|
264
|
+
* @default false
|
|
265
|
+
*/
|
|
266
|
+
files?: boolean;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Enable audit trail for compliance and event logging.
|
|
270
|
+
*
|
|
271
|
+
* @default false
|
|
272
|
+
*/
|
|
273
|
+
audits?: boolean;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Enable organization management to group users.
|
|
277
|
+
*
|
|
278
|
+
* @default false
|
|
279
|
+
*/
|
|
280
|
+
organizations?: boolean;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// ---------------------------------------------------------------------------------------------------------------------
|
|
284
|
+
|
|
179
285
|
export interface RealmOptions {
|
|
180
286
|
/**
|
|
181
287
|
* Secret key for signing tokens.
|
|
@@ -209,17 +315,9 @@ export interface RealmOptions {
|
|
|
209
315
|
};
|
|
210
316
|
|
|
211
317
|
/**
|
|
212
|
-
* Enable
|
|
213
|
-
*
|
|
214
|
-
* When enabled, users can create API keys to access protected endpoints
|
|
215
|
-
* without using JWT tokens. API keys are useful for:
|
|
216
|
-
* - Programmatic access (CLI tools, scripts)
|
|
217
|
-
* - Long-lived authentication tokens
|
|
218
|
-
* - Third-party integrations
|
|
318
|
+
* Enable or disable realm features.
|
|
219
319
|
*
|
|
220
|
-
*
|
|
221
|
-
* - Query parameter: `?api_key=ak_xxx`
|
|
222
|
-
* - Bearer header: `Authorization: Bearer ak_xxx`
|
|
320
|
+
* Features control which modules are loaded with the realm.
|
|
223
321
|
*/
|
|
224
|
-
|
|
322
|
+
features?: Partial<RealmFeatures>;
|
|
225
323
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { $inject, Alepha, AlephaError } from "alepha";
|
|
2
|
-
import { $bucket } from "alepha/bucket";
|
|
3
2
|
import { $repository, type Repository } from "alepha/orm";
|
|
4
3
|
import {
|
|
5
4
|
type RealmAuthSettings,
|
|
@@ -8,7 +7,7 @@ import {
|
|
|
8
7
|
import { identities } from "../entities/identities.ts";
|
|
9
8
|
import { sessions } from "../entities/sessions.ts";
|
|
10
9
|
import { DEFAULT_USER_REALM_NAME, users } from "../entities/users.ts";
|
|
11
|
-
import type { RealmOptions } from "../primitives/$realm.ts";
|
|
10
|
+
import type { RealmFeatures, RealmOptions } from "../primitives/$realm.ts";
|
|
12
11
|
|
|
13
12
|
export interface RealmRepositories {
|
|
14
13
|
identities: Repository<typeof identities.schema>;
|
|
@@ -20,6 +19,7 @@ export interface Realm {
|
|
|
20
19
|
name: string;
|
|
21
20
|
repositories: RealmRepositories;
|
|
22
21
|
settings: RealmAuthSettings;
|
|
22
|
+
features: RealmFeatures;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export class RealmProvider {
|
|
@@ -31,12 +31,19 @@ export class RealmProvider {
|
|
|
31
31
|
|
|
32
32
|
protected realms = new Map<string, Realm>();
|
|
33
33
|
|
|
34
|
-
public avatars = $bucket({
|
|
35
|
-
maxSize: 5 * 1024 * 1024, // 5 MB
|
|
36
|
-
mimeTypes: ["image/jpeg", "image/png", "image/gif", "image/webp"],
|
|
37
|
-
});
|
|
38
|
-
|
|
39
34
|
public register(realmName: string, realmOptions: RealmOptions = {}) {
|
|
35
|
+
// Merge features with defaults
|
|
36
|
+
const features: RealmFeatures = {
|
|
37
|
+
jobs: false,
|
|
38
|
+
notifications: false,
|
|
39
|
+
apiKeys: false,
|
|
40
|
+
parameters: false,
|
|
41
|
+
files: false,
|
|
42
|
+
audits: false,
|
|
43
|
+
organizations: false,
|
|
44
|
+
...realmOptions.features,
|
|
45
|
+
};
|
|
46
|
+
|
|
40
47
|
this.realms.set(realmName, {
|
|
41
48
|
name: realmName,
|
|
42
49
|
repositories: {
|
|
@@ -53,6 +60,7 @@ export class RealmProvider {
|
|
|
53
60
|
...realmOptions.settings?.passwordPolicy,
|
|
54
61
|
},
|
|
55
62
|
},
|
|
63
|
+
features,
|
|
56
64
|
});
|
|
57
65
|
return this.getRealm(realmName);
|
|
58
66
|
}
|
|
@@ -8,7 +8,9 @@ import { describe, it } from "vitest";
|
|
|
8
8
|
import {
|
|
9
9
|
AlephaApiUsers,
|
|
10
10
|
CredentialService,
|
|
11
|
+
RealmProvider,
|
|
11
12
|
SessionService,
|
|
13
|
+
UserNotifications,
|
|
12
14
|
UserService,
|
|
13
15
|
} from "../index.ts";
|
|
14
16
|
|
|
@@ -21,9 +23,18 @@ const setup = async () => {
|
|
|
21
23
|
alepha.with(AlephaEmail);
|
|
22
24
|
alepha.with(AlephaApiVerification);
|
|
23
25
|
alepha.with(AlephaApiUsers);
|
|
26
|
+
alepha.with(UserNotifications);
|
|
24
27
|
|
|
25
28
|
await alepha.start();
|
|
26
29
|
|
|
30
|
+
// Enable notifications for the default realm
|
|
31
|
+
const realmProvider = alepha.inject(RealmProvider);
|
|
32
|
+
realmProvider.register("default", {
|
|
33
|
+
features: {
|
|
34
|
+
notifications: true,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
|
|
27
38
|
const emailProvider = alepha.inject(MemoryEmailProvider);
|
|
28
39
|
emailProvider.records = [];
|
|
29
40
|
|