@foir/sdk 0.21.0 → 0.23.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/CHANGELOG.md +135 -1
- package/README.md +15 -15
- package/dist/app/client.d.ts +93 -86
- package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +14 -13
- package/dist/app/dispatch.d.ts +5 -5
- package/dist/app/errors.d.ts +17 -15
- package/dist/app/index.d.ts +4 -4
- package/dist/app/naming.d.ts +1 -1
- package/dist/app/ticket.d.ts +2 -2
- package/dist/app/vocabulary.generated.d.ts +2 -2
- package/dist/app-contract.js +3 -3
- package/dist/app.js +92 -90
- package/dist/auth/access.d.ts +19 -19
- package/dist/auth/auth.d.ts +251 -117
- package/dist/auth/grant-table.generated.d.ts +5 -4
- package/dist/auth/hosted.d.ts +38 -14
- package/dist/auth/index.d.ts +9 -9
- package/dist/auth/operations.d.ts +153 -33
- package/dist/auth/ops.d.ts +39 -21
- package/dist/auth/session-client.d.ts +3 -3
- package/dist/auth-session.js +3 -3
- package/dist/auth.js +400 -250
- package/dist/client.js +5 -8
- package/dist/codegen/preset.d.ts +1 -1
- package/dist/data/builtins.d.ts +26 -26
- package/dist/data/client.d.ts +3 -3
- package/dist/data/decimal.d.ts +1 -1
- package/dist/data/index.d.ts +1 -1
- package/dist/data/manifest.d.ts +1 -1
- package/dist/data/schema.d.ts +2 -2
- package/dist/data/transport.d.ts +14 -13
- package/dist/data/ws-transport.d.ts +1 -1
- package/dist/data.js +8 -11
- package/dist/graphql/content-client.d.ts +13 -13
- package/dist/index.js +1 -4
- package/dist/live/drift.d.ts +1 -1
- package/dist/media/screen-capture.d.ts +1 -1
- package/dist/next/index.d.ts +2 -2
- package/dist/next/session.d.ts +10 -10
- package/dist/next.js +78 -60
- package/dist/placement/index.d.ts +13 -13
- package/dist/placement.js +127 -116
- package/dist/push.js +62 -44
- package/dist/react/FoirFeedback.d.ts +2 -2
- package/dist/react/FoirProvider.d.ts +24 -24
- package/dist/react/SignIn.d.ts +4 -4
- package/dist/react/UserButton.d.ts +1 -1
- package/dist/react/feedback-notes.d.ts +8 -6
- package/dist/react/index.d.ts +3 -3
- package/dist/react.js +238 -209
- package/dist/realtime/index.d.ts +1 -1
- package/dist/server/callback-client.d.ts +4 -4
- package/dist/server/events-client.d.ts +21 -21
- package/dist/server/operation-types.d.ts +8 -8
- package/dist/server/require-scoped-token.d.ts +3 -3
- package/dist/server/types.d.ts +2 -2
- package/dist/server/verify-scoped-token.d.ts +3 -3
- package/dist/server.js +130 -126
- package/dist/transport/foir-http.d.ts +14 -14
- package/dist/transport/key-kind.d.ts +1 -12
- package/dist/types/index.d.ts +2 -2
- package/package.json +1 -1
package/dist/auth/auth.d.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Foir
|
|
2
|
+
* Foir sign-in for your app's users: framework-agnostic flows, token
|
|
3
|
+
* lifecycle, and guards.
|
|
3
4
|
*
|
|
4
5
|
* Session I/O is injected via {@link SessionAdapter} (no Hydrogen/React-Router
|
|
5
6
|
* coupling). Pre-login flows authenticate with the project `x-api-key`;
|
|
6
|
-
* post-login reads add the
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* post-login reads add the user's bearer. Anything project-specific about the
|
|
8
|
+
* user (a profile record, say) is resolved by a consumer-supplied
|
|
9
|
+
* `resolveUser`: the SDK never hardcodes a per-project profile shape.
|
|
9
10
|
*
|
|
10
11
|
* TRANSPORT. Every flow below addresses the server's generated `auth` namespace
|
|
11
12
|
* through `./ops`, which is `@foir/sdk/data`'s op transport. This module holds
|
|
@@ -16,23 +17,17 @@
|
|
|
16
17
|
*/
|
|
17
18
|
import { type FoirEnv } from '../graphql/foir-request';
|
|
18
19
|
import { type AuthOpName, type AuthOpOptions } from './ops';
|
|
19
|
-
import { type AuthConfig, type AuthProviderPublic, type CurrentUser, type
|
|
20
|
+
import { type AuthConfig, type AuthProviderPublic, type CurrentUser, type AuthResult, type DefaultAuthProvider, type AuthorizedApp, type DeleteAccountResult, type MyOrganization, type MyProfile, type MyProfileChange, type MySession, type MyFactor, type StepUp, type FactorEnrollment, type MySignInMethod, type NewPersonalAccessToken, type ProviderCallbackInput, type ProviderLoginInput, type ProviderLoginResult, type ProviderOTPVerifyInput, type ProviderToken, type SignupContext, type WaitlistJoinResult } from './operations';
|
|
20
21
|
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
21
22
|
/** An access token + its rotating refresh token. */
|
|
22
23
|
export interface FoirAuthTokens {
|
|
23
24
|
token: string;
|
|
24
25
|
refreshToken: string;
|
|
25
26
|
}
|
|
26
|
-
/** The
|
|
27
|
-
export interface FoirCustomer {
|
|
28
|
-
id: string;
|
|
29
|
-
email: string;
|
|
30
|
-
}
|
|
31
|
-
/** The resolved customer for a guarded surface. */
|
|
27
|
+
/** The signed-in user an auth result and a session carry. */
|
|
32
28
|
export interface FoirUser {
|
|
33
29
|
id: string;
|
|
34
30
|
email: string;
|
|
35
|
-
isAdmin: boolean;
|
|
36
31
|
}
|
|
37
32
|
/**
|
|
38
33
|
* Injected session store. Methods may be sync or async so consumers can plug
|
|
@@ -44,39 +39,80 @@ export interface SessionAdapter {
|
|
|
44
39
|
unset(key: string): void | Promise<void>;
|
|
45
40
|
}
|
|
46
41
|
/** Login with email + password. Requires the project to have passwords enabled. */
|
|
47
|
-
export declare function
|
|
42
|
+
export declare function login(env: FoirEnv, vars: {
|
|
48
43
|
email: string;
|
|
49
44
|
password: string;
|
|
50
|
-
}): Promise<
|
|
51
|
-
/** Register a new
|
|
52
|
-
export declare function
|
|
45
|
+
}): Promise<AuthResult>;
|
|
46
|
+
/** Register a new user with email + password. */
|
|
47
|
+
export declare function register(env: FoirEnv, vars: {
|
|
53
48
|
email: string;
|
|
54
49
|
password: string;
|
|
55
|
-
}): Promise<
|
|
56
|
-
/** Request a one-time password be emailed to the
|
|
57
|
-
export declare function
|
|
50
|
+
}): Promise<AuthResult>;
|
|
51
|
+
/** Request a one-time password be emailed to the user. */
|
|
52
|
+
export declare function requestOTP(env: FoirEnv, email: string): Promise<boolean>;
|
|
58
53
|
/** Complete an OTP login. */
|
|
59
|
-
export declare function
|
|
54
|
+
export declare function loginWithOTP(env: FoirEnv, vars: {
|
|
60
55
|
email: string;
|
|
61
56
|
otp: string;
|
|
62
|
-
}): Promise<
|
|
57
|
+
}): Promise<AuthResult>;
|
|
63
58
|
/** Rotate an access token using a refresh token. */
|
|
64
|
-
export declare function
|
|
59
|
+
export declare function refreshTokens(env: FoirEnv, refreshToken: string): Promise<AuthResult>;
|
|
65
60
|
/**
|
|
66
61
|
* Initiate provider (OAuth/OIDC) login — returns a `redirectUrl` to send the
|
|
67
62
|
* user to, or an inline `token` for non-redirect providers.
|
|
68
63
|
*/
|
|
69
|
-
export declare function
|
|
64
|
+
export declare function loginWithProvider(env: FoirEnv, input: ProviderLoginInput): Promise<ProviderLoginResult>;
|
|
70
65
|
/** Complete a provider login from the OAuth callback (`code`/`state`). */
|
|
71
|
-
export declare function
|
|
66
|
+
export declare function providerCallback(env: FoirEnv, input: ProviderCallbackInput): Promise<AuthResult>;
|
|
72
67
|
/** Verify an OTP issued by an external provider. */
|
|
73
|
-
export declare function
|
|
68
|
+
export declare function providerVerifyOTP(env: FoirEnv, input: ProviderOTPVerifyInput): Promise<AuthResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Why a provider sign-in did not finish, as the platform said it: a stable code
|
|
71
|
+
* your app shows its own words for (`signup_closed`, `provider_named_no_address`,
|
|
72
|
+
* `account_unavailable`, ...). When the code is `link_code_sent`, the sign-in
|
|
73
|
+
* named an address somebody already holds, through a provider that does not
|
|
74
|
+
* prove the address is theirs, and a code was sent to it: `pending` names the
|
|
75
|
+
* wait, and {@link confirmProviderLink} finishes the sign-in with that code.
|
|
76
|
+
* Null for any other failure.
|
|
77
|
+
*/
|
|
78
|
+
export declare function providerSignInRefusalOf(error: unknown): {
|
|
79
|
+
code: string;
|
|
80
|
+
pending?: string;
|
|
81
|
+
} | null;
|
|
82
|
+
/**
|
|
83
|
+
* Why a sign-in your app's own form sent was refused, as the platform said it:
|
|
84
|
+
* a stable code your app shows its own words for. `password_sign_in_off` from
|
|
85
|
+
* {@link login} or {@link register} where the project, or the app the sign-in
|
|
86
|
+
* came through, takes no password; `code_sign_in_off` from {@link requestOTP}
|
|
87
|
+
* or {@link loginWithOTP} where it takes no code. Null for any other failure.
|
|
88
|
+
*/
|
|
89
|
+
export declare function signInRefusalOf(error: unknown): {
|
|
90
|
+
code: string;
|
|
91
|
+
} | null;
|
|
92
|
+
/**
|
|
93
|
+
* Finish a provider sign-in that is waiting for the code sent to its address,
|
|
94
|
+
* connecting the provider to the account that holds the address. See
|
|
95
|
+
* {@link providerSignInRefusalOf}.
|
|
96
|
+
*/
|
|
97
|
+
export declare function confirmProviderLink(env: FoirEnv, input: {
|
|
98
|
+
pending: string;
|
|
99
|
+
code: string;
|
|
100
|
+
}): Promise<AuthResult>;
|
|
101
|
+
/**
|
|
102
|
+
* Send a new code for a provider sign-in that is waiting for one. The new code
|
|
103
|
+
* replaces the one before, and the answer names the new wait.
|
|
104
|
+
*/
|
|
105
|
+
export declare function resendProviderLinkCode(env: FoirEnv, input: {
|
|
106
|
+
pending: string;
|
|
107
|
+
}): Promise<{
|
|
108
|
+
pending: string;
|
|
109
|
+
}>;
|
|
74
110
|
/** List the project's configured auth providers (for a login UI). */
|
|
75
111
|
export declare function getAuthProviders(env: FoirEnv): Promise<AuthProviderPublic[]>;
|
|
76
112
|
/**
|
|
77
113
|
* Read the project's public auth configuration — which built-in methods are
|
|
78
114
|
* enabled and which external providers to offer. This is what a login screen
|
|
79
|
-
* renders itself from, before any
|
|
115
|
+
* renders itself from, before any user token exists.
|
|
80
116
|
*/
|
|
81
117
|
export declare function getAuthConfig(env: FoirEnv): Promise<AuthConfig>;
|
|
82
118
|
/**
|
|
@@ -85,55 +121,69 @@ export declare function getAuthConfig(env: FoirEnv): Promise<AuthConfig>;
|
|
|
85
121
|
*/
|
|
86
122
|
export declare function getDefaultAuthProvider(env: FoirEnv): Promise<DefaultAuthProvider | null>;
|
|
87
123
|
/**
|
|
88
|
-
* Read the project's
|
|
124
|
+
* Read the project's signup mode (public/restricted/waitlist/closed)
|
|
89
125
|
* so a self-hosted frontend can render the right signup surface proactively.
|
|
90
126
|
*/
|
|
91
|
-
export declare function
|
|
127
|
+
export declare function signupContext(env: FoirEnv): Promise<SignupContext>;
|
|
92
128
|
/** Join the project's signup waitlist. The project must be in waitlist mode. */
|
|
93
|
-
export declare function
|
|
129
|
+
export declare function joinWaitlist(env: FoirEnv, email: string): Promise<WaitlistJoinResult>;
|
|
94
130
|
/**
|
|
95
131
|
* Send a password-reset email. Resolves `true` whether or not the address has
|
|
96
132
|
* an account: the server answers identically either way, on purpose, so this
|
|
97
133
|
* endpoint cannot be used to test whether someone has signed up.
|
|
134
|
+
*
|
|
135
|
+
* `clientId` names your app. Where the email's link goes to Foir's hosted
|
|
136
|
+
* reset page (the project has no App base URL), the page then sends the user
|
|
137
|
+
* to your app's initiate login URL to sign in.
|
|
98
138
|
*/
|
|
99
|
-
export declare function
|
|
139
|
+
export declare function requestPasswordReset(env: FoirEnv, email: string, options?: {
|
|
140
|
+
clientId?: string;
|
|
141
|
+
}): Promise<boolean>;
|
|
100
142
|
/**
|
|
101
143
|
* Redeem an emailed reset token and set a new password. Returns a fresh session
|
|
102
|
-
*
|
|
144
|
+
* (resetting a password signs the user in), so pair it with
|
|
103
145
|
* {@link saveSession}, or use {@link resetPasswordAndSignIn} which does both.
|
|
104
146
|
*/
|
|
105
|
-
export declare function
|
|
147
|
+
export declare function resetPassword(env: FoirEnv, vars: {
|
|
106
148
|
token: string;
|
|
107
149
|
newPassword: string;
|
|
108
|
-
}): Promise<
|
|
150
|
+
}): Promise<AuthResult>;
|
|
109
151
|
/** Redeem an emailed verification token. */
|
|
110
|
-
export declare function
|
|
152
|
+
export declare function verifyEmail(env: FoirEnv, token: string): Promise<boolean>;
|
|
111
153
|
/**
|
|
112
|
-
* Change the calling
|
|
154
|
+
* Change the calling user's password. Requires the current password as well
|
|
113
155
|
* as the bearer, so a stolen token alone cannot take the account over.
|
|
114
156
|
*/
|
|
115
|
-
export declare function
|
|
157
|
+
export declare function updatePassword(env: FoirEnv, vars: {
|
|
116
158
|
currentPassword: string;
|
|
117
159
|
newPassword: string;
|
|
118
160
|
}, options?: AuthOpOptions): Promise<boolean>;
|
|
119
161
|
/**
|
|
120
|
-
* The calling
|
|
162
|
+
* The calling user, or `null` when the request carried no user token.
|
|
121
163
|
* An absent session is an answer rather than a failure, so this does not throw.
|
|
122
164
|
*/
|
|
123
165
|
export declare function currentUser(env: FoirEnv, options?: AuthOpOptions): Promise<CurrentUser | null>;
|
|
124
166
|
/**
|
|
125
|
-
* The stored upstream provider token for the calling
|
|
126
|
-
*
|
|
127
|
-
*
|
|
167
|
+
* The stored upstream provider token for the calling user, renewed by the
|
|
168
|
+
* server when it is due: near its stated expiry, or with no expiry stated.
|
|
169
|
+
* `null` when there is no user token on the request; `linked: false` when the
|
|
170
|
+
* user has none stored for that provider.
|
|
171
|
+
*
|
|
172
|
+
* Pass `forceRefresh` after the provider refused the token it was last given:
|
|
173
|
+
* the server renews it then, at most once a minute for one user and provider.
|
|
174
|
+
* `refresh` says what the read did, and `reauthenticate` says when only the
|
|
175
|
+
* user signing in with the provider again mends the connection.
|
|
128
176
|
*/
|
|
129
|
-
export declare function myProviderToken(env: FoirEnv, providerKey: string, options?: AuthOpOptions
|
|
177
|
+
export declare function myProviderToken(env: FoirEnv, providerKey: string, options?: AuthOpOptions & {
|
|
178
|
+
forceRefresh?: boolean;
|
|
179
|
+
}): Promise<ProviderToken | null>;
|
|
130
180
|
/**
|
|
131
181
|
* End the session server-side, revoking stored provider tokens. This does NOT
|
|
132
182
|
* clear local session state — {@link signOut} is the pairing that does both.
|
|
133
183
|
*/
|
|
134
|
-
export declare function
|
|
184
|
+
export declare function logout(env: FoirEnv, options?: AuthOpOptions): Promise<boolean>;
|
|
135
185
|
/**
|
|
136
|
-
* Delete the calling
|
|
186
|
+
* Delete the calling user's account and their owned records and files.
|
|
137
187
|
* Irreversible. `password` is required for password accounts and omitted for
|
|
138
188
|
* provider-only ones; the server enforces the actual re-auth gate and fails
|
|
139
189
|
* closed, so omitting it is refused rather than allowed.
|
|
@@ -143,60 +193,141 @@ export declare function deleteMyAccount(env: FoirEnv, vars: {
|
|
|
143
193
|
password?: string;
|
|
144
194
|
}, options?: AuthOpOptions): Promise<DeleteAccountResult>;
|
|
145
195
|
/**
|
|
146
|
-
*
|
|
196
|
+
* Change the calling user's own name, picture or language. It asks no
|
|
197
|
+
* permission: these are theirs.
|
|
198
|
+
*/
|
|
199
|
+
export declare function updateMyProfile(env: FoirEnv, change: MyProfileChange, options?: AuthOpOptions): Promise<MyProfile>;
|
|
200
|
+
/**
|
|
201
|
+
* The apps the calling user has agreed may act for them, and what each may
|
|
202
|
+
* carry: the list an account page shows with a way to take each one back.
|
|
203
|
+
*/
|
|
204
|
+
export declare function myAuthorizedApps(env: FoirEnv, options?: AuthOpOptions): Promise<AuthorizedApp[]>;
|
|
205
|
+
/**
|
|
206
|
+
* Take back an app's authority to act for the calling user. Its tokens for
|
|
207
|
+
* them stop working at once, and it has to ask them again.
|
|
208
|
+
*/
|
|
209
|
+
export declare function revokeAuthorizedApp(env: FoirEnv, id: string, options?: AuthOpOptions): Promise<boolean>;
|
|
210
|
+
/** Where the calling user is signed in, and the personal access tokens they hold. */
|
|
211
|
+
export declare function mySessions(env: FoirEnv, options?: AuthOpOptions): Promise<MySession[]>;
|
|
212
|
+
/** Sign the calling user out of one session, or revoke one of their tokens, by its id. */
|
|
213
|
+
export declare function endMySession(env: FoirEnv, id: string, options?: AuthOpOptions): Promise<boolean>;
|
|
214
|
+
/**
|
|
215
|
+
* Sign the calling user out of every session and every app, and answer how
|
|
216
|
+
* many sessions ended. Their personal access tokens stay. `keepThis` keeps the
|
|
217
|
+
* session making the request.
|
|
218
|
+
*/
|
|
219
|
+
export declare function signOutEverywhere(env: FoirEnv, vars?: {
|
|
220
|
+
keepThis?: boolean;
|
|
221
|
+
}, options?: AuthOpOptions): Promise<number>;
|
|
222
|
+
/**
|
|
223
|
+
* Make a personal access token for the calling user: a standing credential
|
|
224
|
+
* they present beside the app's key, as `Authorization: Bearer`. Its value is
|
|
225
|
+
* answered here once.
|
|
226
|
+
*/
|
|
227
|
+
export declare function createPersonalAccessToken(env: FoirEnv, vars: {
|
|
228
|
+
name: string;
|
|
229
|
+
expiresInDays: number;
|
|
230
|
+
}, options?: AuthOpOptions): Promise<NewPersonalAccessToken>;
|
|
231
|
+
/** The providers the calling user signs in with. */
|
|
232
|
+
export declare function mySignInMethods(env: FoirEnv, options?: AuthOpOptions): Promise<MySignInMethod[]>;
|
|
233
|
+
/**
|
|
234
|
+
* Start connecting one of the project's providers to the calling user's
|
|
235
|
+
* account, and answer the provider's address to send the browser to. It comes
|
|
236
|
+
* back to `returnTo` with `connected` or `connect_error` added.
|
|
237
|
+
*/
|
|
238
|
+
export declare function connectSignInMethod(env: FoirEnv, vars: {
|
|
239
|
+
provider: string;
|
|
240
|
+
returnTo: string;
|
|
241
|
+
}, options?: AuthOpOptions): Promise<string>;
|
|
242
|
+
/** Disconnect a provider from the calling user's account. */
|
|
243
|
+
export declare function disconnectSignInMethod(env: FoirEnv, provider: string, options?: AuthOpOptions): Promise<boolean>;
|
|
244
|
+
/** The second factors, passkeys and recovery codes the calling user holds. */
|
|
245
|
+
export declare function myFactors(env: FoirEnv, options?: AuthOpOptions): Promise<MyFactor[]>;
|
|
246
|
+
/**
|
|
247
|
+
* Begin proving a second factor with the calling user's password.
|
|
248
|
+
* {@link completeStepUp} finishes it; for a user who holds none, the answer's
|
|
249
|
+
* `elevatedHandle` is already the proof.
|
|
250
|
+
*/
|
|
251
|
+
export declare function beginStepUp(env: FoirEnv, password: string, options?: AuthOpOptions): Promise<StepUp>;
|
|
252
|
+
/**
|
|
253
|
+
* Prove a second factor with exactly one of a passkey's or security key's
|
|
254
|
+
* assertion, an authenticator app's code or a recovery code, which is then
|
|
255
|
+
* spent. The session making the request counts as two factors from here, and
|
|
256
|
+
* the answer is an elevated handle for one change to the user's factors in
|
|
257
|
+
* the next ten minutes.
|
|
258
|
+
*/
|
|
259
|
+
export declare function completeStepUp(env: FoirEnv, vars: {
|
|
260
|
+
handle: string;
|
|
261
|
+
webauthnAssertionJson?: string;
|
|
262
|
+
totpCode?: string;
|
|
263
|
+
recoveryCode?: string;
|
|
264
|
+
}, options?: AuthOpOptions): Promise<string>;
|
|
265
|
+
/**
|
|
266
|
+
* Begin adding `totp` (an authenticator app), `webauthn` (a security key held
|
|
267
|
+
* as a second factor) or `passkey` (a passkey that signs the user in on its
|
|
268
|
+
* own), with the `elevatedHandle` {@link beginStepUp} or
|
|
269
|
+
* {@link completeStepUp} answered.
|
|
270
|
+
*/
|
|
271
|
+
export declare function beginFactorEnrollment(env: FoirEnv, vars: {
|
|
272
|
+
method: 'webauthn' | 'totp' | 'passkey';
|
|
273
|
+
elevatedHandle: string;
|
|
274
|
+
}, options?: AuthOpOptions): Promise<FactorEnrollment>;
|
|
275
|
+
/**
|
|
276
|
+
* Finish adding a second factor, with the `navigator.credentials.create`
|
|
277
|
+
* result or the authenticator app's code.
|
|
278
|
+
*/
|
|
279
|
+
export declare function completeFactorEnrollment(env: FoirEnv, vars: {
|
|
280
|
+
handle: string;
|
|
281
|
+
webauthnAttestationJson?: string;
|
|
282
|
+
totpCode?: string;
|
|
283
|
+
name?: string;
|
|
284
|
+
}, options?: AuthOpOptions): Promise<boolean>;
|
|
285
|
+
/** Remove one of the calling user's factors, with an elevated handle from {@link completeStepUp}. */
|
|
286
|
+
export declare function removeFactor(env: FoirEnv, vars: {
|
|
287
|
+
elevatedHandle: string;
|
|
288
|
+
kind: string;
|
|
289
|
+
id: string;
|
|
290
|
+
}, options?: AuthOpOptions): Promise<boolean>;
|
|
291
|
+
/**
|
|
292
|
+
* Make the calling user new recovery codes, with an elevated handle from
|
|
293
|
+
* {@link completeStepUp}. They replace any held and are answered here once.
|
|
294
|
+
*/
|
|
295
|
+
export declare function makeRecoveryCodes(env: FoirEnv, elevatedHandle: string, options?: AuthOpOptions): Promise<string[]>;
|
|
296
|
+
/**
|
|
297
|
+
* The organizations this user may stand in.
|
|
147
298
|
*
|
|
148
|
-
* Answered from the
|
|
149
|
-
* hold one in and every organization beneath it, so
|
|
150
|
-
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
299
|
+
* Answered from the calling user's own memberships: each organization they
|
|
300
|
+
* hold one in and every organization beneath it, so the list is exactly the
|
|
301
|
+
* set a request of theirs may name, and a user with no memberships sees an
|
|
302
|
+
* empty list rather than a refusal. Requires the user's bearer. A user whose
|
|
303
|
+
* role holds `organizations:read` in the project is listed every organization
|
|
304
|
+
* of it instead, suspended ones included.
|
|
305
|
+
*
|
|
306
|
+
* A MEMBERSHIP REACHES DOWNWARD. Someone who is a member of an organization may
|
|
307
|
+
* stand in any organization beneath it without holding a row of their own
|
|
308
|
+
* there. The reverse never works: a membership at a branch stands in no
|
|
309
|
+
* ancestor and in no sibling branch, and a request naming either is refused as
|
|
310
|
+
* not-found, the same answer an organization that does not exist gets.
|
|
311
|
+
* {@link MyOrganization.role} names ONE of the roles that apply where the
|
|
312
|
+
* person stands (the membership held in the organization itself, when there is
|
|
313
|
+
* one); their authority there is the union of every membership that reaches
|
|
314
|
+
* it, together with their own roles in the project.
|
|
153
315
|
*/
|
|
154
316
|
export declare function myOrganizations(env: FoirEnv, vars?: {
|
|
155
317
|
first?: number;
|
|
156
318
|
after?: string;
|
|
157
319
|
}, options?: AuthOpOptions): Promise<MyOrganization[]>;
|
|
158
|
-
/**
|
|
159
|
-
* Stand in one of them, for this customer, until they choose otherwise.
|
|
160
|
-
*
|
|
161
|
-
* Set once — not per call. The selection is stored against the customer and
|
|
162
|
-
* resolved into the claim on every subsequent request, so nothing downstream
|
|
163
|
-
* takes an org argument. Pass an empty `orgId` to clear it and return to the
|
|
164
|
-
* project-shared view.
|
|
165
|
-
*
|
|
166
|
-
* The server authorises the choice against a live membership and refuses
|
|
167
|
-
* otherwise, so a caller cannot select their way into an organization they do
|
|
168
|
-
* not run.
|
|
169
|
-
*
|
|
170
|
-
* A MEMBERSHIP REACHES DOWNWARD, which is what "a live membership" means now
|
|
171
|
-
* that organizations nest. Someone who is a member of an organization may stand in any
|
|
172
|
-
* organization BENEATH it without holding a row of their own there, and
|
|
173
|
-
* {@link myOrganizations} offers exactly that set — so any id it returned can
|
|
174
|
-
* be passed here. The reverse never works: a membership at a branch stands in
|
|
175
|
-
* no ancestor and in no sibling branch, and both are refused as not-found,
|
|
176
|
-
* which is the same answer an organization that does not exist gets.
|
|
177
|
-
*
|
|
178
|
-
* WHAT STANDING THERE MEANS is every membership that reaches the organization
|
|
179
|
-
* selected. Reach a client through a membership above it and the role shown is
|
|
180
|
-
* that membership's; authority is the union of every membership that reaches
|
|
181
|
-
* it, together with the customer's own roles in the project.
|
|
182
|
-
* {@link MyOrganization.role} names ONE of those roles (the membership held in
|
|
183
|
-
* the organization itself, when there is one), so it is part of what the next
|
|
184
|
-
* request resolves and not the whole of it.
|
|
185
|
-
*/
|
|
186
|
-
export declare function selectOrganization(env: FoirEnv, vars: {
|
|
187
|
-
orgId: string;
|
|
188
|
-
}, options?: AuthOpOptions): Promise<SelectedOrganization>;
|
|
189
320
|
/**
|
|
190
321
|
* Found an organization, as its first member.
|
|
191
322
|
*
|
|
192
|
-
* The caller decides the NAME and, optionally, where it hangs
|
|
193
|
-
* else. The founder is the
|
|
323
|
+
* The caller decides the NAME and, optionally, where it hangs and where it
|
|
324
|
+
* lives — and nothing else. The founder is the user behind the bearer, the id is minted
|
|
194
325
|
* server-side the way a project's and a tenant's are, and the role they hold in
|
|
195
326
|
* the new organization is the one the PROJECT named in its settings
|
|
196
|
-
* (`
|
|
327
|
+
* (`organizationSignupRole`). The server creates the organization and that one
|
|
197
328
|
* membership together.
|
|
198
329
|
*
|
|
199
|
-
* `parentId` FOUNDS A CHILD, which is what lets
|
|
330
|
+
* `parentId` FOUNDS A CHILD, which is what lets the people you serve create their own
|
|
200
331
|
* sub-tenants with no administrator in the loop — a reseller adding a client, a
|
|
201
332
|
* franchise adding a branch. It is resolved against the caller's own
|
|
202
333
|
* MEMBERSHIPS, not merely against the project: on this lane "an organization
|
|
@@ -204,59 +335,66 @@ export declare function selectOrganization(env: FoirEnv, vars: {
|
|
|
204
335
|
* not-found. Omit it to found a root, which is what every registration did
|
|
205
336
|
* before organizations nested.
|
|
206
337
|
*
|
|
207
|
-
*
|
|
338
|
+
* `appBaseUrl` is where the organization's app lives, so an app that finds its
|
|
339
|
+
* organization from the page address (`orgUrl`) finds this one at once. It is
|
|
340
|
+
* held to the rule every organization address is: under the project's own app
|
|
341
|
+
* address or a domain the project verified, and not one another organization
|
|
342
|
+
* of the project holds.
|
|
343
|
+
*
|
|
344
|
+
* Exists on the wire only while the project's `organizationSignupEnabled` setting
|
|
208
345
|
* is on; a project that never opted in has no such field, and this refuses
|
|
209
346
|
* naming it. Returns the same entry `myOrganizations` would then list, role
|
|
210
|
-
* included, so the application can
|
|
347
|
+
* included, so the application can name it on its next request.
|
|
211
348
|
*/
|
|
212
349
|
export declare function registerOrganization(env: FoirEnv, vars: {
|
|
213
350
|
name: string;
|
|
214
351
|
parentId?: string;
|
|
352
|
+
appBaseUrl?: string;
|
|
215
353
|
}, options?: AuthOpOptions): Promise<MyOrganization>;
|
|
216
354
|
/**
|
|
217
|
-
* Persist an auth result to the session; returns the
|
|
355
|
+
* Persist an auth result to the session; returns the signed-in user.
|
|
218
356
|
*
|
|
219
|
-
* A result that names no
|
|
357
|
+
* A result that names no user keeps the identity already stored. A refresh
|
|
220
358
|
* rotates the tokens of a session that already knows who it belongs to, and a
|
|
221
|
-
* platform that answers a refresh without the
|
|
359
|
+
* platform that answers a refresh without the user must not blank that:
|
|
222
360
|
* {@link requireAuth} reads the stored identity, so a valid token beside an
|
|
223
361
|
* empty identity reads as signed out.
|
|
224
362
|
*/
|
|
225
|
-
export declare function saveSession(adapter: SessionAdapter, result:
|
|
363
|
+
export declare function saveSession(adapter: SessionAdapter, result: AuthResult): Promise<FoirUser>;
|
|
226
364
|
/** Clear all Foir auth keys from the session. */
|
|
227
365
|
export declare function clearSession(adapter: SessionAdapter): Promise<void>;
|
|
228
366
|
/** Read the stored access token (null when signed out). */
|
|
229
367
|
export declare function getSessionToken(adapter: SessionAdapter): Promise<string | null>;
|
|
230
|
-
/** Read the stored
|
|
231
|
-
export declare function
|
|
368
|
+
/** Read the stored user (null when signed out). */
|
|
369
|
+
export declare function getSessionUser(adapter: SessionAdapter): Promise<FoirUser | null>;
|
|
232
370
|
/** Login with email + password and persist the session. */
|
|
233
|
-
export declare function
|
|
371
|
+
export declare function signInWithPassword(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
234
372
|
email: string;
|
|
235
373
|
password: string;
|
|
236
|
-
}): Promise<
|
|
374
|
+
}): Promise<FoirUser>;
|
|
237
375
|
/** Register with email + password and persist the session. */
|
|
238
|
-
export declare function
|
|
376
|
+
export declare function signUpWithPassword(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
239
377
|
email: string;
|
|
240
378
|
password: string;
|
|
241
|
-
}): Promise<
|
|
379
|
+
}): Promise<FoirUser>;
|
|
242
380
|
/** Complete an OTP login and persist the session. */
|
|
243
|
-
export declare function
|
|
381
|
+
export declare function signInWithOTP(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
244
382
|
email: string;
|
|
245
383
|
otp: string;
|
|
246
|
-
}): Promise<
|
|
384
|
+
}): Promise<FoirUser>;
|
|
247
385
|
/**
|
|
248
386
|
* Complete a forgot-password flow: redeem the emailed token, set the new
|
|
249
387
|
* password, and persist the session the server mints. The peer of
|
|
250
|
-
* {@link
|
|
388
|
+
* {@link signInWithPassword} for the branch where the user cannot log in.
|
|
251
389
|
*/
|
|
252
390
|
export declare function resetPasswordAndSignIn(adapter: SessionAdapter, env: FoirEnv, vars: {
|
|
253
391
|
token: string;
|
|
254
392
|
newPassword: string;
|
|
255
|
-
}): Promise<
|
|
393
|
+
}): Promise<FoirUser>;
|
|
256
394
|
/**
|
|
257
395
|
* End the session on both sides: revoke it server-side, then clear local state.
|
|
258
396
|
*
|
|
259
|
-
* The local clear happens even when the server call fails.
|
|
397
|
+
* The local clear happens even when the server call fails. Someone who
|
|
260
398
|
* pressed sign-out and got a network error must not be left holding a session
|
|
261
399
|
* on the device in front of them — the token expires on its own, and the
|
|
262
400
|
* failure mode of clearing anyway (one orphaned provider token) is strictly
|
|
@@ -295,16 +433,18 @@ export declare function authedRequest<TData, TVariables>(adapter: SessionAdapter
|
|
|
295
433
|
* management, which is the half a generated namespace does not give you.
|
|
296
434
|
*/
|
|
297
435
|
export declare function authedOp<T>(adapter: SessionAdapter, env: FoirEnv, op: AuthOpName, args?: Record<string, unknown>): Promise<T>;
|
|
298
|
-
export interface RequireAuthOptions {
|
|
436
|
+
export interface RequireAuthOptions<TUser = FoirUser> {
|
|
299
437
|
/**
|
|
300
|
-
* Resolve the
|
|
301
|
-
*
|
|
302
|
-
*
|
|
438
|
+
* Resolve what the guarded surface needs about the user from the session:
|
|
439
|
+
* typically the project's own profile record, read through
|
|
440
|
+
* {@link authedRequest}. Without it the guard answers the {@link FoirUser}
|
|
441
|
+
* the session holds. What the user may do is a role or a scope: guard on
|
|
442
|
+
* those with {@link requireRole} and {@link requireScope}.
|
|
303
443
|
*/
|
|
304
444
|
resolveUser?: (ctx: {
|
|
305
445
|
token: string;
|
|
306
|
-
|
|
307
|
-
}) =>
|
|
446
|
+
user: FoirUser;
|
|
447
|
+
}) => TUser | Promise<TUser>;
|
|
308
448
|
/**
|
|
309
449
|
* Called when there's no valid session — throw your framework's redirect
|
|
310
450
|
* (e.g. `throw redirect(loginUrl)`). Must not return.
|
|
@@ -319,14 +459,8 @@ export interface RequireAuthOptions {
|
|
|
319
459
|
env?: FoirEnv;
|
|
320
460
|
}
|
|
321
461
|
/**
|
|
322
|
-
* Require a signed-in
|
|
323
|
-
*
|
|
324
|
-
*
|
|
462
|
+
* Require a signed-in user. Answers what `resolveUser` resolves (or the
|
|
463
|
+
* session's {@link FoirUser}), or invokes `onUnauthenticated` when there's no
|
|
464
|
+
* session.
|
|
325
465
|
*/
|
|
326
|
-
export declare function requireAuth(adapter: SessionAdapter, options: RequireAuthOptions): Promise<
|
|
327
|
-
export interface RequireAdminOptions extends RequireAuthOptions {
|
|
328
|
-
/** Called when the user is authenticated but not an admin. Must not return. */
|
|
329
|
-
onForbidden: () => never | Promise<never>;
|
|
330
|
-
}
|
|
331
|
-
/** Require a signed-in customer who is also an admin. */
|
|
332
|
-
export declare function requireAdmin(adapter: SessionAdapter, options: RequireAdminOptions): Promise<FoirUser>;
|
|
466
|
+
export declare function requireAuth<TUser = FoirUser>(adapter: SessionAdapter, options: RequireAuthOptions<TUser>): Promise<TUser>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
export type GrantReach = 'own' | 'named' | 'all';
|
|
2
|
+
export type GrantTarget = 'none' | 'model' | 'operation';
|
|
2
3
|
/**
|
|
3
|
-
* One permission: its name,
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* One permission: its name, what a grant of it may name, the reaches it may be
|
|
5
|
+
* granted at (none: only its bare form exists), and the grants a holder of it
|
|
6
|
+
* also holds.
|
|
6
7
|
*/
|
|
7
8
|
export type GrantTableRow = readonly [
|
|
8
9
|
name: string,
|
|
9
|
-
|
|
10
|
+
target: GrantTarget,
|
|
10
11
|
reaches: readonly GrantReach[],
|
|
11
12
|
implies: readonly string[]
|
|
12
13
|
];
|