@happyvertical/smrt-users 0.30.0
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/AGENTS.md +85 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +459 -0
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/chunks/TerminalAuthService-DoAMQ_yn.js +5118 -0
- package/dist/chunks/TerminalAuthService-DoAMQ_yn.js.map +1 -0
- package/dist/chunks/index-DkoYIvIu.js +169 -0
- package/dist/chunks/index-DkoYIvIu.js.map +1 -0
- package/dist/collections/CliAuthRequestCollection.d.ts +19 -0
- package/dist/collections/CliAuthRequestCollection.d.ts.map +1 -0
- package/dist/collections/GroupCollection.d.ts +17 -0
- package/dist/collections/GroupCollection.d.ts.map +1 -0
- package/dist/collections/GroupMemberCollection.d.ts +43 -0
- package/dist/collections/GroupMemberCollection.d.ts.map +1 -0
- package/dist/collections/GroupRoleCollection.d.ts +33 -0
- package/dist/collections/GroupRoleCollection.d.ts.map +1 -0
- package/dist/collections/MagicLinkTokenCollection.d.ts +26 -0
- package/dist/collections/MagicLinkTokenCollection.d.ts.map +1 -0
- package/dist/collections/MembershipCollection.d.ts +38 -0
- package/dist/collections/MembershipCollection.d.ts.map +1 -0
- package/dist/collections/MembershipOverrideCollection.d.ts +55 -0
- package/dist/collections/MembershipOverrideCollection.d.ts.map +1 -0
- package/dist/collections/PermissionCollection.d.ts +34 -0
- package/dist/collections/PermissionCollection.d.ts.map +1 -0
- package/dist/collections/RoleCollection.d.ts +29 -0
- package/dist/collections/RoleCollection.d.ts.map +1 -0
- package/dist/collections/RolePermissionCollection.d.ts +33 -0
- package/dist/collections/RolePermissionCollection.d.ts.map +1 -0
- package/dist/collections/SessionCollection.d.ts +82 -0
- package/dist/collections/SessionCollection.d.ts.map +1 -0
- package/dist/collections/TenantCollection.d.ts +119 -0
- package/dist/collections/TenantCollection.d.ts.map +1 -0
- package/dist/collections/TenantPermissionOverrideCollection.d.ts +111 -0
- package/dist/collections/TenantPermissionOverrideCollection.d.ts.map +1 -0
- package/dist/collections/UserCollection.d.ts +116 -0
- package/dist/collections/UserCollection.d.ts.map +1 -0
- package/dist/collections/index.d.ts +19 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1482 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +5216 -0
- package/dist/models/CliAuthRequest.d.ts +25 -0
- package/dist/models/CliAuthRequest.d.ts.map +1 -0
- package/dist/models/Group.d.ts +34 -0
- package/dist/models/Group.d.ts.map +1 -0
- package/dist/models/GroupMember.d.ts +29 -0
- package/dist/models/GroupMember.d.ts.map +1 -0
- package/dist/models/GroupRole.d.ts +29 -0
- package/dist/models/GroupRole.d.ts.map +1 -0
- package/dist/models/MagicLinkToken.d.ts +22 -0
- package/dist/models/MagicLinkToken.d.ts.map +1 -0
- package/dist/models/Membership.d.ts +48 -0
- package/dist/models/Membership.d.ts.map +1 -0
- package/dist/models/MembershipOverride.d.ts +50 -0
- package/dist/models/MembershipOverride.d.ts.map +1 -0
- package/dist/models/Permission.d.ts +79 -0
- package/dist/models/Permission.d.ts.map +1 -0
- package/dist/models/Role.d.ts +67 -0
- package/dist/models/Role.d.ts.map +1 -0
- package/dist/models/RolePermission.d.ts +29 -0
- package/dist/models/RolePermission.d.ts.map +1 -0
- package/dist/models/Session.d.ts +105 -0
- package/dist/models/Session.d.ts.map +1 -0
- package/dist/models/Tenant.d.ts +138 -0
- package/dist/models/Tenant.d.ts.map +1 -0
- package/dist/models/TenantPermissionOverride.d.ts +74 -0
- package/dist/models/TenantPermissionOverride.d.ts.map +1 -0
- package/dist/models/User.d.ts +72 -0
- package/dist/models/User.d.ts.map +1 -0
- package/dist/models/index.d.ts +19 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/playground.d.ts +2 -0
- package/dist/playground.d.ts.map +1 -0
- package/dist/playground.js +139 -0
- package/dist/playground.js.map +1 -0
- package/dist/services/MagicLinkService.d.ts +84 -0
- package/dist/services/MagicLinkService.d.ts.map +1 -0
- package/dist/services/OidcLoginService.d.ts +134 -0
- package/dist/services/OidcLoginService.d.ts.map +1 -0
- package/dist/services/PermissionCatalogService.d.ts +62 -0
- package/dist/services/PermissionCatalogService.d.ts.map +1 -0
- package/dist/services/PermissionResolver.d.ts +150 -0
- package/dist/services/PermissionResolver.d.ts.map +1 -0
- package/dist/services/PostgresPermissionPolicies.d.ts +29 -0
- package/dist/services/PostgresPermissionPolicies.d.ts.map +1 -0
- package/dist/services/SessionPermissionContext.d.ts +43 -0
- package/dist/services/SessionPermissionContext.d.ts.map +1 -0
- package/dist/services/SessionService.d.ts +139 -0
- package/dist/services/SessionService.d.ts.map +1 -0
- package/dist/services/TenantService.d.ts +135 -0
- package/dist/services/TenantService.d.ts.map +1 -0
- package/dist/services/TerminalAuthService.d.ts +189 -0
- package/dist/services/TerminalAuthService.d.ts.map +1 -0
- package/dist/services/index.d.ts +14 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +2744 -0
- package/dist/svelte/components/InviteUserModal.svelte +351 -0
- package/dist/svelte/components/InviteUserModal.svelte.d.ts +17 -0
- package/dist/svelte/components/InviteUserModal.svelte.d.ts.map +1 -0
- package/dist/svelte/components/UserAvatar.svelte +105 -0
- package/dist/svelte/components/UserAvatar.svelte.d.ts +10 -0
- package/dist/svelte/components/UserAvatar.svelte.d.ts.map +1 -0
- package/dist/svelte/components/UserCard.svelte +179 -0
- package/dist/svelte/components/UserCard.svelte.d.ts +18 -0
- package/dist/svelte/components/UserCard.svelte.d.ts.map +1 -0
- package/dist/svelte/components/UserForm.svelte +194 -0
- package/dist/svelte/components/UserForm.svelte.d.ts +18 -0
- package/dist/svelte/components/UserForm.svelte.d.ts.map +1 -0
- package/dist/svelte/components/UserList.svelte +107 -0
- package/dist/svelte/components/UserList.svelte.d.ts +20 -0
- package/dist/svelte/components/UserList.svelte.d.ts.map +1 -0
- package/dist/svelte/components/UserMenu.svelte +326 -0
- package/dist/svelte/components/UserMenu.svelte.d.ts +33 -0
- package/dist/svelte/components/UserMenu.svelte.d.ts.map +1 -0
- package/dist/svelte/components/__tests__/InviteUserModal.test.js +54 -0
- package/dist/svelte/components/__tests__/UserAvatar.test.js +31 -0
- package/dist/svelte/components/__tests__/UserCard.test.js +39 -0
- package/dist/svelte/components/__tests__/UserForm.test.js +50 -0
- package/dist/svelte/components/__tests__/UserList.test.js +48 -0
- package/dist/svelte/components/__tests__/UserMenu.test.js +38 -0
- package/dist/svelte/i18n.d.ts +15 -0
- package/dist/svelte/i18n.d.ts.map +1 -0
- package/dist/svelte/i18n.js +15 -0
- package/dist/svelte/index.d.ts +23 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +27 -0
- package/dist/svelte/playground.d.ts +151 -0
- package/dist/svelte/playground.d.ts.map +1 -0
- package/dist/svelte/playground.js +134 -0
- package/dist/sveltekit/index.d.ts +379 -0
- package/dist/sveltekit/index.d.ts.map +1 -0
- package/dist/sveltekit/resource-list-handler.d.ts +127 -0
- package/dist/sveltekit/resource-list-handler.d.ts.map +1 -0
- package/dist/sveltekit/types.d.ts +31 -0
- package/dist/sveltekit/types.d.ts.map +1 -0
- package/dist/sveltekit.d.ts +2 -0
- package/dist/sveltekit.d.ts.map +1 -0
- package/dist/sveltekit.js +978 -0
- package/dist/sveltekit.js.map +1 -0
- package/dist/types/index.d.ts +61 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/ui.d.ts +10 -0
- package/dist/ui.d.ts.map +1 -0
- package/dist/ui.js +75 -0
- package/dist/ui.js.map +1 -0
- package/package.json +97 -0
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { SmrtClassOptions } from '@happyvertical/smrt-core';
|
|
2
|
+
import { Membership } from '../models/Membership.js';
|
|
3
|
+
import { Tenant } from '../models/Tenant.js';
|
|
4
|
+
import { TenantPolicy } from '../types/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Result of tenant creation with ownership
|
|
7
|
+
*/
|
|
8
|
+
export interface TenantWithOwnershipResult {
|
|
9
|
+
tenant: Tenant;
|
|
10
|
+
membership: Membership;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Result of ensureTenantForUser
|
|
14
|
+
*/
|
|
15
|
+
export interface EnsureTenantResult {
|
|
16
|
+
/** The tenant (null if flexible mode and no existing tenant) */
|
|
17
|
+
tenant: Tenant | null;
|
|
18
|
+
/** The membership (null if no tenant) */
|
|
19
|
+
membership: Membership | null;
|
|
20
|
+
/** Whether a new tenant was created */
|
|
21
|
+
created: boolean;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* TenantService manages tenant creation with configurable policies.
|
|
25
|
+
*
|
|
26
|
+
* Policies:
|
|
27
|
+
* - `flexible`: No tenant created on signup, user can have zero tenants
|
|
28
|
+
* - `personal`: Auto-create personal tenant on first login, can delete all
|
|
29
|
+
* - `required`: Auto-create personal tenant, must keep at least one
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const tenantService = new TenantService(options, {
|
|
34
|
+
* mode: 'personal',
|
|
35
|
+
* maxTenants: 5,
|
|
36
|
+
* defaultName: 'My Workspace',
|
|
37
|
+
* });
|
|
38
|
+
* await tenantService.initialize();
|
|
39
|
+
*
|
|
40
|
+
* // During OIDC login
|
|
41
|
+
* const { tenant, membership, created } = await tenantService.ensureTenantForUser(
|
|
42
|
+
* user.id,
|
|
43
|
+
* { email: user.email, name: user.name }
|
|
44
|
+
* );
|
|
45
|
+
*
|
|
46
|
+
* // Creating additional tenants
|
|
47
|
+
* if (await tenantService.canCreateTenant(user.id)) {
|
|
48
|
+
* const { tenant } = await tenantService.createTenantWithOwnership(
|
|
49
|
+
* user.id,
|
|
50
|
+
* 'New Organization'
|
|
51
|
+
* );
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare class TenantService {
|
|
56
|
+
private options;
|
|
57
|
+
private policy;
|
|
58
|
+
private tenantCollection;
|
|
59
|
+
private membershipCollection;
|
|
60
|
+
private roleCollection;
|
|
61
|
+
constructor(options: SmrtClassOptions, policy?: TenantPolicy);
|
|
62
|
+
/**
|
|
63
|
+
* Initialize collections
|
|
64
|
+
*/
|
|
65
|
+
initialize(): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* Get the current policy
|
|
68
|
+
*/
|
|
69
|
+
getPolicy(): TenantPolicy;
|
|
70
|
+
/**
|
|
71
|
+
* Create a tenant and make the user the owner
|
|
72
|
+
*
|
|
73
|
+
* @param userId - The user to make owner
|
|
74
|
+
* @param name - Tenant name
|
|
75
|
+
* @param options - Optional slug override
|
|
76
|
+
* @returns The created tenant and membership
|
|
77
|
+
*/
|
|
78
|
+
createTenantWithOwnership(userId: string, name: string, options?: {
|
|
79
|
+
slug?: string;
|
|
80
|
+
}): Promise<TenantWithOwnershipResult>;
|
|
81
|
+
/**
|
|
82
|
+
* Check if a user can create a new tenant
|
|
83
|
+
*
|
|
84
|
+
* Returns false if maxTenants limit is reached (0 = unlimited)
|
|
85
|
+
*/
|
|
86
|
+
canCreateTenant(userId: string): Promise<boolean>;
|
|
87
|
+
/**
|
|
88
|
+
* Get a specific error message explaining why a tenant cannot be deleted.
|
|
89
|
+
*
|
|
90
|
+
* @returns Error message if deletion is not allowed, or null if allowed.
|
|
91
|
+
*/
|
|
92
|
+
private getDeleteTenantError;
|
|
93
|
+
/**
|
|
94
|
+
* Check if a user can delete a specific tenant
|
|
95
|
+
*
|
|
96
|
+
* Returns false if:
|
|
97
|
+
* - User is not an active member
|
|
98
|
+
* - User is not the owner
|
|
99
|
+
* - Policy is 'required' and this is the last tenant
|
|
100
|
+
*/
|
|
101
|
+
canDeleteTenant(userId: string, tenantId: string): Promise<boolean>;
|
|
102
|
+
/**
|
|
103
|
+
* Delete a tenant
|
|
104
|
+
*
|
|
105
|
+
* Note: This does not cascade delete related records (memberships, etc.).
|
|
106
|
+
* The caller should handle cleanup of related data if needed.
|
|
107
|
+
*
|
|
108
|
+
* @throws Error if user cannot delete the tenant (with specific reason)
|
|
109
|
+
*/
|
|
110
|
+
deleteTenant(userId: string, tenantId: string): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Ensure a tenant exists for the user based on policy
|
|
113
|
+
*
|
|
114
|
+
* Called during OIDC login to apply tenant policy:
|
|
115
|
+
* - `flexible`: Returns first existing tenant or null (no auto-create)
|
|
116
|
+
* - `personal`/`required`: Creates default tenant if none exists
|
|
117
|
+
*
|
|
118
|
+
* @param userId - The user ID
|
|
119
|
+
* @param userInfo - User info for naming the auto-created tenant
|
|
120
|
+
* @returns Tenant and membership (may be null in flexible mode)
|
|
121
|
+
*/
|
|
122
|
+
ensureTenantForUser(userId: string, userInfo: {
|
|
123
|
+
email?: string;
|
|
124
|
+
name?: string;
|
|
125
|
+
}): Promise<EnsureTenantResult>;
|
|
126
|
+
/**
|
|
127
|
+
* Get all tenants for a user (where they are owner)
|
|
128
|
+
*/
|
|
129
|
+
getOwnedTenants(userId: string): Promise<Tenant[]>;
|
|
130
|
+
/**
|
|
131
|
+
* Static factory method
|
|
132
|
+
*/
|
|
133
|
+
static create(options: SmrtClassOptions, policy?: TenantPolicy): Promise<TenantService>;
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=TenantService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TenantService.d.ts","sourceRoot":"","sources":["../../src/services/TenantService.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAIjE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAIL,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAE3B;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,yCAAyC;IACzC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,gBAAgB,CAAoB;IAC5C,OAAO,CAAC,oBAAoB,CAAwB;IACpD,OAAO,CAAC,cAAc,CAAkB;gBAE5B,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,YAAY;IAK5D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAajC;;OAEG;IACH,SAAS,IAAI,YAAY;IAIzB;;;;;;;OAOG;IACG,yBAAyB,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1B,OAAO,CAAC,yBAAyB,CAAC;IAmCrC;;;;OAIG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAsBvD;;;;OAIG;YACW,oBAAoB;IAwClC;;;;;;;OAOG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKzE;;;;;;;OAOG;IACG,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnE;;;;;;;;;;OAUG;IACG,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAC1C,OAAO,CAAC,kBAAkB,CAAC;IA+C9B;;OAEG;IACG,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAuBxD;;OAEG;WACU,MAAM,CACjB,OAAO,EAAE,gBAAgB,EACzB,MAAM,CAAC,EAAE,YAAY,GACpB,OAAO,CAAC,aAAa,CAAC;CAK1B"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { SmrtClassOptions } from '@happyvertical/smrt-core';
|
|
2
|
+
import { CliAuthRequestStatus, UsersCliAuthRequest } from '../models/CliAuthRequest.js';
|
|
3
|
+
import { User } from '../models/User.js';
|
|
4
|
+
import { SessionContext } from './SessionService.js';
|
|
5
|
+
/** Default polling interval the CLI should honour while waiting for approval. */
|
|
6
|
+
export declare const DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS = 2;
|
|
7
|
+
/** Default lifetime of a pending request (10 minutes). */
|
|
8
|
+
export declare const DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS: number;
|
|
9
|
+
/** Default lifetime of the session minted on approval (30 days). */
|
|
10
|
+
export declare const DEFAULT_CLI_SESSION_TTL_SECONDS: number;
|
|
11
|
+
/** Default cap on consecutive failed approve attempts per user before lockout. */
|
|
12
|
+
export declare const DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS = 5;
|
|
13
|
+
/** Default sliding window for counting failed approve attempts (5 minutes). */
|
|
14
|
+
export declare const DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS: number;
|
|
15
|
+
/**
|
|
16
|
+
* Options for {@link TerminalAuthService}.
|
|
17
|
+
*/
|
|
18
|
+
export interface TerminalAuthServiceOptions extends SmrtClassOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Cookie name passed through to {@link SessionService}. Should match the
|
|
21
|
+
* site's normal session cookie name so the same SessionService can
|
|
22
|
+
* resolve both browser cookies and CLI bearer tokens.
|
|
23
|
+
*/
|
|
24
|
+
sessionCookieName?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Prefix prepended to randomly generated user codes — purely for human
|
|
27
|
+
* recognition ("WG-1A2B3C4D"). Defaults to no prefix.
|
|
28
|
+
*/
|
|
29
|
+
userCodePrefix?: string;
|
|
30
|
+
/** TTL of a pending request, in seconds. */
|
|
31
|
+
requestTtlSeconds?: number;
|
|
32
|
+
/** TTL of the session minted on approval, in seconds. */
|
|
33
|
+
sessionTtlSeconds?: number;
|
|
34
|
+
/** Polling interval hint returned to clients. */
|
|
35
|
+
pollIntervalSeconds?: number;
|
|
36
|
+
/**
|
|
37
|
+
* Path on the site's origin where the approval page is mounted. Used to
|
|
38
|
+
* build the verification URL returned to the CLI. Defaults to
|
|
39
|
+
* `/terminal-login`.
|
|
40
|
+
*/
|
|
41
|
+
verificationPath?: string;
|
|
42
|
+
/** Whether the underlying SessionService should auto-extend on access. */
|
|
43
|
+
sessionAutoExtend?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Maximum consecutive failed approve attempts allowed per user inside the
|
|
46
|
+
* sliding window before the user is locked out from approving any further
|
|
47
|
+
* codes. Defaults to {@link DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS}.
|
|
48
|
+
*
|
|
49
|
+
* User codes are only 32 bits of entropy; without this throttle, an
|
|
50
|
+
* authenticated attacker could brute-force pending codes and hijack
|
|
51
|
+
* another user's CLI session by approving it themselves.
|
|
52
|
+
*/
|
|
53
|
+
maxApproveAttempts?: number;
|
|
54
|
+
/**
|
|
55
|
+
* Sliding window (seconds) over which {@link maxApproveAttempts} counts.
|
|
56
|
+
* Defaults to {@link DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS}.
|
|
57
|
+
*/
|
|
58
|
+
approveAttemptWindowSeconds?: number;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* What `createRequest` returns to the CLI.
|
|
62
|
+
*/
|
|
63
|
+
export interface CliAuthStartResult {
|
|
64
|
+
deviceCode: string;
|
|
65
|
+
expiresAt: string;
|
|
66
|
+
interval: number;
|
|
67
|
+
userCode: string;
|
|
68
|
+
verificationUrl: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* What `exchangeDeviceCode` returns to the polling CLI.
|
|
72
|
+
*/
|
|
73
|
+
export type CliAuthTokenResult = {
|
|
74
|
+
status: 'pending';
|
|
75
|
+
expiresAt: string;
|
|
76
|
+
interval: number;
|
|
77
|
+
} | {
|
|
78
|
+
status: 'expired';
|
|
79
|
+
} | {
|
|
80
|
+
status: 'approved';
|
|
81
|
+
accessToken: string;
|
|
82
|
+
expiresIn: number;
|
|
83
|
+
tokenType: 'Bearer';
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Inputs for `approveRequest`. The caller is responsible for authenticating
|
|
87
|
+
* the user via its existing browser session before calling this.
|
|
88
|
+
*/
|
|
89
|
+
export interface ApproveCliAuthRequestInput {
|
|
90
|
+
userCode: string;
|
|
91
|
+
user: Pick<User, 'id' | 'email'>;
|
|
92
|
+
tenantId: string | null | undefined;
|
|
93
|
+
ipAddress?: string;
|
|
94
|
+
userAgent?: string;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* High-level orchestration of the terminal device-code flow.
|
|
98
|
+
*/
|
|
99
|
+
export declare class TerminalAuthService {
|
|
100
|
+
private readonly options;
|
|
101
|
+
private readonly userCodePrefix;
|
|
102
|
+
private readonly requestTtlSeconds;
|
|
103
|
+
private readonly sessionTtlSeconds;
|
|
104
|
+
private readonly pollIntervalSeconds;
|
|
105
|
+
private readonly verificationPath;
|
|
106
|
+
private readonly maxApproveAttempts;
|
|
107
|
+
private readonly approveAttemptWindowMs;
|
|
108
|
+
private readonly failedApprovesByUser;
|
|
109
|
+
private requestCollection;
|
|
110
|
+
private sessionService;
|
|
111
|
+
constructor(options: TerminalAuthServiceOptions);
|
|
112
|
+
initialize(): Promise<void>;
|
|
113
|
+
static create(options: TerminalAuthServiceOptions): Promise<TerminalAuthService>;
|
|
114
|
+
private makeUserCode;
|
|
115
|
+
/**
|
|
116
|
+
* Generate a user code that is not currently in use by another *active*
|
|
117
|
+
* (pending or approved-but-unclaimed) request. Collisions are vanishingly
|
|
118
|
+
* rare (1 in 2^32 per attempt) but happen at scale; retrying keeps the
|
|
119
|
+
* affected CLI from being locked out.
|
|
120
|
+
*/
|
|
121
|
+
private makeUniqueUserCode;
|
|
122
|
+
/**
|
|
123
|
+
* Start a new request. Returns the device code the CLI keeps secret, the
|
|
124
|
+
* user code the human types into the browser, and the verification URL to
|
|
125
|
+
* open. The device code is stored only as a hash.
|
|
126
|
+
*/
|
|
127
|
+
createRequest(origin: string): Promise<CliAuthStartResult>;
|
|
128
|
+
/**
|
|
129
|
+
* Look up a request by user code. Performs lazy expiry: pending requests
|
|
130
|
+
* past their TTL are flipped to `expired` and persisted.
|
|
131
|
+
*/
|
|
132
|
+
getRequestForUserCode(userCode: string): Promise<UsersCliAuthRequest | null>;
|
|
133
|
+
/**
|
|
134
|
+
* Mark a pending request as approved and mint a bearer session bound to the
|
|
135
|
+
* approving user. Idempotent: re-approving an already-approved request is a
|
|
136
|
+
* no-op. Throws if the user/tenant are missing, the request is unknown, or
|
|
137
|
+
* the request has expired.
|
|
138
|
+
*/
|
|
139
|
+
approveRequest(input: ApproveCliAuthRequestInput): Promise<UsersCliAuthRequest>;
|
|
140
|
+
/**
|
|
141
|
+
* Throw {@link TerminalAuthRateLimitError} if the user has exceeded the
|
|
142
|
+
* configured failed-approve budget inside the current sliding window.
|
|
143
|
+
*/
|
|
144
|
+
private assertApproveRateLimit;
|
|
145
|
+
/** Increment the failed-approve counter for `userId`, starting the window if needed. */
|
|
146
|
+
private recordFailedApprove;
|
|
147
|
+
/**
|
|
148
|
+
* Exchange a device code (the secret the CLI keeps) for an access token
|
|
149
|
+
* once the request has been approved. Returns `{ status: 'pending' }` while
|
|
150
|
+
* the CLI should keep polling, and `{ status: 'expired' }` if the request
|
|
151
|
+
* was never approved within its TTL.
|
|
152
|
+
*/
|
|
153
|
+
exchangeDeviceCode(deviceCode: string): Promise<CliAuthTokenResult>;
|
|
154
|
+
/**
|
|
155
|
+
* Resolve a bearer token issued by this service into a full session
|
|
156
|
+
* context — load the user, permissions, and tenant just like the cookie
|
|
157
|
+
* path does. Returns `null` if the token is unknown, expired, or revoked.
|
|
158
|
+
*/
|
|
159
|
+
loadBearerSession(token: string): Promise<SessionContext | null>;
|
|
160
|
+
/**
|
|
161
|
+
* Revoke a bearer token (CLI logout). Returns true if a session was
|
|
162
|
+
* actually revoked.
|
|
163
|
+
*/
|
|
164
|
+
destroyBearerSession(token: string): Promise<boolean>;
|
|
165
|
+
/**
|
|
166
|
+
* Delete expired pending requests (cleanup job).
|
|
167
|
+
*/
|
|
168
|
+
cleanupExpiredRequests(): Promise<number>;
|
|
169
|
+
/** The default polling interval clients should use. Exposed for tests. */
|
|
170
|
+
get pollInterval(): number;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Error class for terminal auth failures the caller is expected to surface to
|
|
174
|
+
* the user (vs. unexpected internal errors).
|
|
175
|
+
*/
|
|
176
|
+
export declare class TerminalAuthError extends Error {
|
|
177
|
+
constructor(message: string);
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Thrown when a user has exceeded the configured failed-approve budget. The
|
|
181
|
+
* caller (SvelteKit handler, REST adapter, etc.) is expected to surface this
|
|
182
|
+
* as HTTP 429 with `Retry-After: retryAfterSeconds`.
|
|
183
|
+
*/
|
|
184
|
+
export declare class TerminalAuthRateLimitError extends TerminalAuthError {
|
|
185
|
+
readonly retryAfterSeconds: number;
|
|
186
|
+
constructor(message: string, retryAfterSeconds: number);
|
|
187
|
+
}
|
|
188
|
+
export type { CliAuthRequestStatus };
|
|
189
|
+
//# sourceMappingURL=TerminalAuthService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TerminalAuthService.d.ts","sourceRoot":"","sources":["../../src/services/TerminalAuthService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service exports for smrt-users
|
|
3
|
+
* @packageDocumentation
|
|
4
|
+
*/
|
|
5
|
+
export { MagicLinkError, type MagicLinkResult, MagicLinkService, type MagicLinkServiceOptions, type MagicLinkVerifyResult, } from './MagicLinkService.js';
|
|
6
|
+
export { type CreateAuthorizationUrlOptions, decodeOidcTransaction, encodeOidcTransaction, getUsersOidcConfig, type OidcCallbackResult, OidcLoginError, type OidcLoginResult, OidcLoginService, type OidcLoginServiceOptions, type OidcProviderConfig, type OidcProviderKind, type OidcProviderMetadata, type OidcProviderResolution, type OidcProviderResolutionOptions, type OidcTokenEndpointAuthMethod, type OidcTokenSet, type OidcTransaction, type ResolvedOidcProviderConfig, resolveOidcProviderConfig, type UsersOidcConfig, } from './OidcLoginService.js';
|
|
7
|
+
export { type PermissionCatalog, PermissionCatalogService, type PermissionCatalogSource, type PermissionCatalogSyncResult, type PermissionDefinition, type PostgresPermissionAction, type PostgresPermissionBinding, registerPermissionDefinitions, syncPermissionCatalog, type UsersConfig, } from './PermissionCatalogService.js';
|
|
8
|
+
export { type PermissionResolutionOptions, type PermissionResolutionResult, PermissionResolver, type TenantPermissionInheritanceResult, } from './PermissionResolver.js';
|
|
9
|
+
export { applyPostgresPermissionPolicies, type GeneratePostgresPermissionSqlResult, generatePostgresPermissionSql, type PostgresPermissionPolicyReportItem, type PostgresPermissionPolicyTarget, } from './PostgresPermissionPolicies.js';
|
|
10
|
+
export { getCurrentSessionPermissionContext, getRequestScopedDatabase, type SessionPermissionRuntimeContext, type SessionPermissionRuntimeOptions, withSessionPermissionContext, } from './SessionPermissionContext.js';
|
|
11
|
+
export { type SessionContext, SessionService, type SessionServiceOptions, } from './SessionService.js';
|
|
12
|
+
export { type EnsureTenantResult, TenantService, type TenantWithOwnershipResult, } from './TenantService.js';
|
|
13
|
+
export { type ApproveCliAuthRequestInput, type CliAuthStartResult, type CliAuthTokenResult, DEFAULT_CLI_AUTH_APPROVE_ATTEMPT_WINDOW_SECONDS, DEFAULT_CLI_AUTH_MAX_APPROVE_ATTEMPTS, DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, DEFAULT_CLI_SESSION_TTL_SECONDS, TerminalAuthError, TerminalAuthRateLimitError, TerminalAuthService, type TerminalAuthServiceOptions, } from './TerminalAuthService.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,cAAc,EACd,KAAK,eAAe,EACpB,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,6BAA6B,EAClC,qBAAqB,EACrB,qBAAqB,EACrB,kBAAkB,EAClB,KAAK,kBAAkB,EACvB,cAAc,EACd,KAAK,eAAe,EACpB,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,6BAA6B,EAClC,KAAK,2BAA2B,EAChC,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,yBAAyB,EACzB,KAAK,eAAe,GACrB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,KAAK,iBAAiB,EACtB,wBAAwB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,oBAAoB,EACzB,KAAK,wBAAwB,EAC7B,KAAK,yBAAyB,EAC9B,6BAA6B,EAC7B,qBAAqB,EACrB,KAAK,WAAW,GACjB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,EAC/B,kBAAkB,EAClB,KAAK,iCAAiC,GACvC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACL,+BAA+B,EAC/B,KAAK,mCAAmC,EACxC,6BAA6B,EAC7B,KAAK,kCAAkC,EACvC,KAAK,8BAA8B,GACpC,MAAM,iCAAiC,CAAC;AACzC,OAAO,EACL,kCAAkC,EAClC,wBAAwB,EACxB,KAAK,+BAA+B,EACpC,KAAK,+BAA+B,EACpC,4BAA4B,GAC7B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,KAAK,cAAc,EACnB,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,KAAK,kBAAkB,EACvB,aAAa,EACb,KAAK,yBAAyB,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,KAAK,0BAA0B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,+CAA+C,EAC/C,qCAAqC,EACrC,sCAAsC,EACtC,oCAAoC,EACpC,+BAA+B,EAC/B,iBAAiB,EACjB,0BAA0B,EAC1B,mBAAmB,EACnB,KAAK,0BAA0B,GAChC,MAAM,0BAA0B,CAAC"}
|