@absolutejs/auth 0.26.0-beta.3 → 0.26.0-beta.4
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/dist/audit/types.d.ts +1 -1
- package/dist/index.d.ts +4958 -3
- package/dist/index.js +2175 -1076
- package/dist/index.js.map +23 -5
- package/dist/organizations/config.d.ts +46 -0
- package/dist/organizations/inMemoryOrganizationStore.d.ts +2 -0
- package/dist/organizations/operations.d.ts +32 -0
- package/dist/organizations/postgresOrganizationStore.d.ts +412 -0
- package/dist/organizations/routes.d.ts +299 -0
- package/dist/organizations/types.d.ts +44 -0
- package/dist/passwordless/config.d.ts +42 -0
- package/dist/passwordless/inMemoryPasswordlessTokenStore.d.ts +2 -0
- package/dist/passwordless/postgresPasswordlessTokenStore.d.ts +66 -0
- package/dist/passwordless/routes.d.ts +163 -0
- package/dist/passwordless/types.d.ts +9 -0
- package/dist/roles/config.d.ts +27 -0
- package/dist/roles/inMemoryRoleStore.d.ts +2 -0
- package/dist/roles/operations.d.ts +8 -0
- package/dist/roles/postgresRoleStore.d.ts +102 -0
- package/dist/roles/resolver.d.ts +17 -0
- package/dist/roles/routes.d.ts +106 -0
- package/dist/roles/types.d.ts +14 -0
- package/dist/types.d.ts +23 -0
- package/dist/webhooks/config.d.ts +21 -0
- package/dist/webhooks/dispatcher.d.ts +3 -0
- package/dist/webhooks/sign.d.ts +11 -0
- package/dist/webhooks/types.d.ts +11 -0
- package/package.json +1 -1
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { type AnyPgDatabase } from '../stores/postgres';
|
|
2
|
+
import type { RoleStore } from './types';
|
|
3
|
+
export declare const rolesTable: import("drizzle-orm/pg-core").PgTableWithColumns<{
|
|
4
|
+
name: "auth_roles";
|
|
5
|
+
schema: undefined;
|
|
6
|
+
columns: {
|
|
7
|
+
created_at_ms: import("drizzle-orm/pg-core").PgColumn<{
|
|
8
|
+
name: "created_at_ms";
|
|
9
|
+
tableName: "auth_roles";
|
|
10
|
+
dataType: "number";
|
|
11
|
+
columnType: "PgBigInt53";
|
|
12
|
+
data: number;
|
|
13
|
+
driverParam: string | number;
|
|
14
|
+
notNull: true;
|
|
15
|
+
hasDefault: false;
|
|
16
|
+
isPrimaryKey: false;
|
|
17
|
+
isAutoincrement: false;
|
|
18
|
+
hasRuntimeDefault: false;
|
|
19
|
+
enumValues: undefined;
|
|
20
|
+
baseColumn: never;
|
|
21
|
+
identity: undefined;
|
|
22
|
+
generated: undefined;
|
|
23
|
+
}, {}, {}>;
|
|
24
|
+
organization_id: import("drizzle-orm/pg-core").PgColumn<{
|
|
25
|
+
name: "organization_id";
|
|
26
|
+
tableName: "auth_roles";
|
|
27
|
+
dataType: "string";
|
|
28
|
+
columnType: "PgVarchar";
|
|
29
|
+
data: string;
|
|
30
|
+
driverParam: string;
|
|
31
|
+
notNull: true;
|
|
32
|
+
hasDefault: true;
|
|
33
|
+
isPrimaryKey: false;
|
|
34
|
+
isAutoincrement: false;
|
|
35
|
+
hasRuntimeDefault: false;
|
|
36
|
+
enumValues: [string, ...string[]];
|
|
37
|
+
baseColumn: never;
|
|
38
|
+
identity: undefined;
|
|
39
|
+
generated: undefined;
|
|
40
|
+
}, {}, {
|
|
41
|
+
length: 255;
|
|
42
|
+
}>;
|
|
43
|
+
permissions: import("drizzle-orm/pg-core").PgColumn<{
|
|
44
|
+
name: "permissions";
|
|
45
|
+
tableName: "auth_roles";
|
|
46
|
+
dataType: "json";
|
|
47
|
+
columnType: "PgJsonb";
|
|
48
|
+
data: string[];
|
|
49
|
+
driverParam: unknown;
|
|
50
|
+
notNull: true;
|
|
51
|
+
hasDefault: true;
|
|
52
|
+
isPrimaryKey: false;
|
|
53
|
+
isAutoincrement: false;
|
|
54
|
+
hasRuntimeDefault: false;
|
|
55
|
+
enumValues: undefined;
|
|
56
|
+
baseColumn: never;
|
|
57
|
+
identity: undefined;
|
|
58
|
+
generated: undefined;
|
|
59
|
+
}, {}, {
|
|
60
|
+
$type: string[];
|
|
61
|
+
}>;
|
|
62
|
+
slug: import("drizzle-orm/pg-core").PgColumn<{
|
|
63
|
+
name: "slug";
|
|
64
|
+
tableName: "auth_roles";
|
|
65
|
+
dataType: "string";
|
|
66
|
+
columnType: "PgVarchar";
|
|
67
|
+
data: string;
|
|
68
|
+
driverParam: string;
|
|
69
|
+
notNull: true;
|
|
70
|
+
hasDefault: false;
|
|
71
|
+
isPrimaryKey: false;
|
|
72
|
+
isAutoincrement: false;
|
|
73
|
+
hasRuntimeDefault: false;
|
|
74
|
+
enumValues: [string, ...string[]];
|
|
75
|
+
baseColumn: never;
|
|
76
|
+
identity: undefined;
|
|
77
|
+
generated: undefined;
|
|
78
|
+
}, {}, {
|
|
79
|
+
length: 128;
|
|
80
|
+
}>;
|
|
81
|
+
updated_at_ms: import("drizzle-orm/pg-core").PgColumn<{
|
|
82
|
+
name: "updated_at_ms";
|
|
83
|
+
tableName: "auth_roles";
|
|
84
|
+
dataType: "number";
|
|
85
|
+
columnType: "PgBigInt53";
|
|
86
|
+
data: number;
|
|
87
|
+
driverParam: string | number;
|
|
88
|
+
notNull: true;
|
|
89
|
+
hasDefault: false;
|
|
90
|
+
isPrimaryKey: false;
|
|
91
|
+
isAutoincrement: false;
|
|
92
|
+
hasRuntimeDefault: false;
|
|
93
|
+
enumValues: undefined;
|
|
94
|
+
baseColumn: never;
|
|
95
|
+
identity: undefined;
|
|
96
|
+
generated: undefined;
|
|
97
|
+
}, {}, {}>;
|
|
98
|
+
};
|
|
99
|
+
dialect: "pg";
|
|
100
|
+
}>;
|
|
101
|
+
export declare const createNeonRoleStore: (databaseUrl: string) => RoleStore;
|
|
102
|
+
export declare const createPostgresRoleStore: (db: AnyPgDatabase) => RoleStore;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OrganizationStore } from '../organizations/types';
|
|
2
|
+
import type { OrganizationId } from '../tenancy';
|
|
3
|
+
import type { RoleStore } from './types';
|
|
4
|
+
export declare const createMembershipPermissionResolver: <UserType>({ getUserId, organizationStore, roleStore }: {
|
|
5
|
+
getUserId: (user: UserType) => string;
|
|
6
|
+
organizationStore: OrganizationStore;
|
|
7
|
+
roleStore: RoleStore;
|
|
8
|
+
}) => ({ organizationId, permission, user }: {
|
|
9
|
+
organizationId?: OrganizationId;
|
|
10
|
+
permission: string;
|
|
11
|
+
user: UserType;
|
|
12
|
+
}) => Promise<boolean>;
|
|
13
|
+
export declare const resolvePermissions: ({ organizationId, roleStore, roles }: {
|
|
14
|
+
organizationId?: OrganizationId;
|
|
15
|
+
roleStore: RoleStore;
|
|
16
|
+
roles: string[];
|
|
17
|
+
}) => Promise<Set<string>>;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Elysia } from 'elysia';
|
|
2
|
+
import type { SessionRecord } from '../types';
|
|
3
|
+
import { type RolesRouteProps } from './config';
|
|
4
|
+
export declare const roleRoutes: <UserType>({ authSessionStore, canManageRoles, emit, getUserId, onRolesAssigned, organizationStore, roleStore, rolesRoute }: RolesRouteProps<UserType>) => Elysia<"", {
|
|
5
|
+
decorator: {};
|
|
6
|
+
store: {
|
|
7
|
+
session: SessionRecord<UserType>;
|
|
8
|
+
unregisteredSession: import("..").UnregisteredSessionRecord;
|
|
9
|
+
};
|
|
10
|
+
derive: {};
|
|
11
|
+
resolve: {};
|
|
12
|
+
}, {
|
|
13
|
+
typebox: {};
|
|
14
|
+
error: {};
|
|
15
|
+
}, {
|
|
16
|
+
schema: {};
|
|
17
|
+
standaloneSchema: {};
|
|
18
|
+
macro: {};
|
|
19
|
+
macroFn: {};
|
|
20
|
+
parser: {};
|
|
21
|
+
response: {};
|
|
22
|
+
}, {
|
|
23
|
+
[x: string]: {
|
|
24
|
+
":organizationId": {
|
|
25
|
+
get: {
|
|
26
|
+
body: unknown;
|
|
27
|
+
params: {
|
|
28
|
+
organizationId: string;
|
|
29
|
+
};
|
|
30
|
+
query: unknown;
|
|
31
|
+
headers: unknown;
|
|
32
|
+
response: {
|
|
33
|
+
200: {
|
|
34
|
+
readonly roles: readonly import("./types").Role[];
|
|
35
|
+
};
|
|
36
|
+
401: "Authentication required";
|
|
37
|
+
403: "Cannot manage roles";
|
|
38
|
+
422: {
|
|
39
|
+
type: "validation";
|
|
40
|
+
on: string;
|
|
41
|
+
summary?: string;
|
|
42
|
+
message?: string;
|
|
43
|
+
found?: unknown;
|
|
44
|
+
property?: string;
|
|
45
|
+
expected?: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
} & {
|
|
52
|
+
[x: string]: {
|
|
53
|
+
":organizationId": {
|
|
54
|
+
members: {
|
|
55
|
+
":userId": {
|
|
56
|
+
put: {
|
|
57
|
+
body: {
|
|
58
|
+
roles: string[];
|
|
59
|
+
};
|
|
60
|
+
params: {
|
|
61
|
+
userId: string;
|
|
62
|
+
organizationId: string;
|
|
63
|
+
};
|
|
64
|
+
query: unknown;
|
|
65
|
+
headers: unknown;
|
|
66
|
+
response: {
|
|
67
|
+
200: {
|
|
68
|
+
readonly roles: string[];
|
|
69
|
+
};
|
|
70
|
+
401: "Authentication required";
|
|
71
|
+
403: "Cannot manage roles";
|
|
72
|
+
404: "Membership not found";
|
|
73
|
+
422: {
|
|
74
|
+
type: "validation";
|
|
75
|
+
on: string;
|
|
76
|
+
summary?: string;
|
|
77
|
+
message?: string;
|
|
78
|
+
found?: unknown;
|
|
79
|
+
property?: string;
|
|
80
|
+
expected?: string;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
}, {
|
|
89
|
+
derive: {};
|
|
90
|
+
resolve: {};
|
|
91
|
+
schema: {};
|
|
92
|
+
standaloneSchema: {};
|
|
93
|
+
response: {};
|
|
94
|
+
}, {
|
|
95
|
+
derive: {};
|
|
96
|
+
resolve: {};
|
|
97
|
+
schema: {};
|
|
98
|
+
standaloneSchema: {};
|
|
99
|
+
response: {};
|
|
100
|
+
} & {
|
|
101
|
+
derive: {};
|
|
102
|
+
resolve: {};
|
|
103
|
+
schema: {};
|
|
104
|
+
standaloneSchema: {};
|
|
105
|
+
response: {};
|
|
106
|
+
}>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { OrganizationId } from '../tenancy';
|
|
2
|
+
export type Role = {
|
|
3
|
+
createdAt: number;
|
|
4
|
+
organizationId?: OrganizationId;
|
|
5
|
+
permissions: string[];
|
|
6
|
+
slug: string;
|
|
7
|
+
updatedAt: number;
|
|
8
|
+
};
|
|
9
|
+
export type RoleStore = {
|
|
10
|
+
deleteRole: (slug: string, organizationId?: OrganizationId) => Promise<void>;
|
|
11
|
+
getRole: (slug: string, organizationId?: OrganizationId) => Promise<Role | undefined>;
|
|
12
|
+
listRoles: (organizationId?: OrganizationId) => Promise<Role[]>;
|
|
13
|
+
saveRole: (role: Role) => Promise<void>;
|
|
14
|
+
};
|
package/dist/types.d.ts
CHANGED
|
@@ -9,11 +9,15 @@ import type { AuthIdentityConflict } from './errors';
|
|
|
9
9
|
import type { AuthHtmxConfig, AuthHtmxUser } from './htmx/types';
|
|
10
10
|
import type { LockoutConfig } from './lockout/config';
|
|
11
11
|
import type { MfaConfig } from './mfa/config';
|
|
12
|
+
import type { OrganizationsConfig } from './organizations/config';
|
|
13
|
+
import type { PasswordlessConfig } from './passwordless/config';
|
|
14
|
+
import type { RolesConfig } from './roles/config';
|
|
12
15
|
import type { ScimConfig } from './scim/config';
|
|
13
16
|
import type { SessionsConfig } from './session/sessionsConfig';
|
|
14
17
|
import type { AuthSessionStore } from './session/types';
|
|
15
18
|
import type { SSOConfig } from './sso/config';
|
|
16
19
|
import type { WebAuthnConfig } from './webauthn/config';
|
|
20
|
+
import type { WebhooksConfig } from './webhooks/config';
|
|
17
21
|
export type AuthIntent = 'login' | 'link_identity' | 'link_connector';
|
|
18
22
|
export type OAuth2ProviderClientConfiguration<Provider extends ProviderOption> = {
|
|
19
23
|
credentials: CredentialsFor<Provider>;
|
|
@@ -183,6 +187,11 @@ export type AuthConfig<UserType> = {
|
|
|
183
187
|
* mounts register / verify-email / login / reset-password routes that produce the
|
|
184
188
|
* same `SessionData<UserType>` as OAuth, transparent to `protectRoute`. */
|
|
185
189
|
credentials?: CredentialsConfig<UserType>;
|
|
190
|
+
/** Passwordless login: magic links + email/SMS OTP. When present, mounts the magic-link flow
|
|
191
|
+
* (if `onSendMagicLink` is set) and/or the OTP flow (if `onSendOtp` is set) under
|
|
192
|
+
* `{passwordlessRoute}`; each verify route resolves the email to a user and mints the same
|
|
193
|
+
* `SessionData<UserType>` as every other flow. */
|
|
194
|
+
passwordless?: PasswordlessConfig<UserType>;
|
|
186
195
|
/** Multi-factor auth (TOTP + backup codes). When present alongside `credentials`,
|
|
187
196
|
* `auth()` auto-wires the login MFA gate, mounts the enroll/challenge routes, and
|
|
188
197
|
* promotes the parked session once a factor is verified. */
|
|
@@ -203,6 +212,15 @@ export type AuthConfig<UserType> = {
|
|
|
203
212
|
* mounts `{scimRoute}/Users` (+ `/ServiceProviderConfig`) with per-org bearer-token auth via
|
|
204
213
|
* `scimTokenStore`, and maps SCIM resources to the consumer's user store through hooks. */
|
|
205
214
|
scim?: ScimConfig;
|
|
215
|
+
/** First-class multi-tenancy (the WorkOS model). When present, mounts organization +
|
|
216
|
+
* membership + invitation routes under `{organizationsRoute}`: list the caller's orgs, create
|
|
217
|
+
* one (caller becomes owner), invite/accept/revoke by email, and list/remove members. Ties the
|
|
218
|
+
* bare `organizationId` used by SSO/SCIM/RBAC into a real tenant model with org-scoped roles. */
|
|
219
|
+
organizations?: OrganizationsConfig<UserType>;
|
|
220
|
+
/** Org-scoped roles & permissions (builds on `organizations`). When present, mounts routes to
|
|
221
|
+
* list an org's role definitions and set a member's roles. Pair with
|
|
222
|
+
* `createMembershipPermissionResolver` to make `authorization.hasPermission` turnkey. */
|
|
223
|
+
roles?: RolesConfig<UserType>;
|
|
206
224
|
/** Role-based / attribute-based access control (E4). When present, `auth()` exposes a
|
|
207
225
|
* `protectPermission(check, handler)` derive (alongside `protectRoute`) that delegates the
|
|
208
226
|
* decision to your `hasPermission` hook — the package stays schema-agnostic about roles. */
|
|
@@ -217,6 +235,11 @@ export type AuthConfig<UserType> = {
|
|
|
217
235
|
* → mints the same `SessionData<UserType>`). A `webauthnAdapter` wraps a vetted library (e.g.
|
|
218
236
|
* `@simplewebauthn/server`); the package never bundles the WebAuthn crypto. */
|
|
219
237
|
webauthn?: WebAuthnConfig<UserType>;
|
|
238
|
+
/** Signed outbound webhooks. When present, every emitted auth event (the audit taxonomy) is
|
|
239
|
+
* HMAC-signed (Standard Webhooks scheme) and POSTed to each endpoint. Delivery is best-effort
|
|
240
|
+
* and isolated per endpoint; configuring this alone (without `audit`) is enough to turn on
|
|
241
|
+
* event emission. PII redaction (`audit.redact`) applies before delivery. */
|
|
242
|
+
webhooks?: WebhooksConfig;
|
|
220
243
|
/** Enable the built-in HTMX fragment routes (login, identities, connectors,
|
|
221
244
|
* account, signout, delete-account). Supply provider display data + the
|
|
222
245
|
* identity/connector data actions; the package owns the route wiring and
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { WebhookEndpoint, WebhookEvent } from './types';
|
|
2
|
+
export declare const DEFAULT_WEBHOOK_TIMEOUT_MS: number;
|
|
3
|
+
export type WebhookFetch = (url: string, init: {
|
|
4
|
+
body: string;
|
|
5
|
+
headers: Record<string, string>;
|
|
6
|
+
method: string;
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
ok: boolean;
|
|
10
|
+
status: number;
|
|
11
|
+
}>;
|
|
12
|
+
export type WebhooksConfig = {
|
|
13
|
+
endpoints: WebhookEndpoint[];
|
|
14
|
+
fetch?: WebhookFetch;
|
|
15
|
+
onDeliveryError?: (context: {
|
|
16
|
+
endpoint: WebhookEndpoint;
|
|
17
|
+
error: unknown;
|
|
18
|
+
event: WebhookEvent;
|
|
19
|
+
}) => void | Promise<void>;
|
|
20
|
+
timeoutMs?: number;
|
|
21
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const signWebhook: ({ id, payload, secret, timestamp }: {
|
|
2
|
+
id: string;
|
|
3
|
+
payload: string;
|
|
4
|
+
secret: string;
|
|
5
|
+
timestamp: string;
|
|
6
|
+
}) => Promise<string>;
|
|
7
|
+
export declare const verifyWebhookSignature: ({ headers, payload, secret }: {
|
|
8
|
+
headers: Record<string, string | undefined>;
|
|
9
|
+
payload: string;
|
|
10
|
+
secret: string;
|
|
11
|
+
}) => Promise<boolean>;
|
package/package.json
CHANGED