@foir/sdk 0.23.0 → 0.25.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 +223 -154
- package/dist/app/client.d.ts +52 -4
- package/dist/app/contract/proto/apps/v1/apps_pb.d.ts +104 -99
- package/dist/app/contract/proto/apps/v1/discovery_pb.d.ts +10 -10
- package/dist/app/index.d.ts +1 -1
- package/dist/app.js +37 -3
- package/dist/auth/auth.d.ts +78 -15
- package/dist/auth/hosted.d.ts +5 -0
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/operations.d.ts +66 -12
- package/dist/auth/ops.d.ts +8 -1
- package/dist/auth/session-client.d.ts +5 -0
- package/dist/auth-session.js +3 -2
- package/dist/auth.js +51 -9
- package/dist/components/EditorProvider.d.ts +1 -1
- package/dist/next.js +11 -1
- package/dist/push.js +11 -1
- package/dist/react.js +14 -3
- package/dist/server/events-client.d.ts +2 -2
- package/dist/server.js +2 -2
- package/package.json +1 -1
package/dist/app.js
CHANGED
|
@@ -352,6 +352,20 @@ function createAppClient(config) {
|
|
|
352
352
|
const refuse = (message) => {
|
|
353
353
|
throw new FoirRequestError(`[foir] ${message}`);
|
|
354
354
|
};
|
|
355
|
+
const POOL_FIELDS = "organizationId poolId source sourceOrganizationId people";
|
|
356
|
+
async function poolOf(name, document) {
|
|
357
|
+
const answer = await field(name, document, {});
|
|
358
|
+
if (!answer?.poolId || !answer.organizationId || answer.source !== "OWN" && answer.source !== "ANCESTOR" && answer.source !== "PROJECT") {
|
|
359
|
+
return refuse(`${name} reported no error and answered no pool`);
|
|
360
|
+
}
|
|
361
|
+
return {
|
|
362
|
+
organizationId: answer.organizationId,
|
|
363
|
+
poolId: answer.poolId,
|
|
364
|
+
source: answer.source,
|
|
365
|
+
sourceOrganizationId: answer.sourceOrganizationId ?? null,
|
|
366
|
+
people: answer.people ?? null
|
|
367
|
+
};
|
|
368
|
+
}
|
|
355
369
|
let surface;
|
|
356
370
|
function served() {
|
|
357
371
|
surface ??= withFoirRetry(async () => {
|
|
@@ -825,9 +839,20 @@ function createAppClient(config) {
|
|
|
825
839
|
if (settings.modelKey.trim() === "") return refuse("an organisation's settings name the model they are a record of");
|
|
826
840
|
input.settings = { modelKey: settings.modelKey.trim(), data: settings.data };
|
|
827
841
|
}
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
842
|
+
const first = organization.firstMember;
|
|
843
|
+
if (first !== void 0) {
|
|
844
|
+
if ("email" in first) {
|
|
845
|
+
const email = first.email.trim();
|
|
846
|
+
if (email === "") return refuse("a first member made by address names the address");
|
|
847
|
+
input.firstMember = {
|
|
848
|
+
email,
|
|
849
|
+
...first.firstName !== void 0 ? { firstName: first.firstName } : {},
|
|
850
|
+
...first.lastName !== void 0 ? { lastName: first.lastName } : {}
|
|
851
|
+
};
|
|
852
|
+
} else {
|
|
853
|
+
if (first.userId === "") return refuse("a first member names a user");
|
|
854
|
+
input.firstMember = { userId: first.userId };
|
|
855
|
+
}
|
|
831
856
|
}
|
|
832
857
|
if (organization.ownPool === true) input.ownPool = true;
|
|
833
858
|
const answered = settings === void 0 ? "organizationId status" : "organizationId settingsRecordId status";
|
|
@@ -853,6 +878,15 @@ function createAppClient(config) {
|
|
|
853
878
|
deletionScheduledAt: answer.deletionScheduledAt ?? null,
|
|
854
879
|
organizations: (answer.organizations ?? []).map((o) => ({ id: o.id, name: o.name }))
|
|
855
880
|
};
|
|
881
|
+
},
|
|
882
|
+
async pool() {
|
|
883
|
+
return poolOf("organizationPool", `query AppOrganizationPool { organizationPool { ${POOL_FIELDS} } }`);
|
|
884
|
+
},
|
|
885
|
+
async startPool() {
|
|
886
|
+
return poolOf("startOrganizationPool", `mutation AppStartOrganizationPool { startOrganizationPool { ${POOL_FIELDS} } }`);
|
|
887
|
+
},
|
|
888
|
+
async dropPool() {
|
|
889
|
+
return poolOf("dropOrganizationPool", `mutation AppDropOrganizationPool { dropOrganizationPool { ${POOL_FIELDS} } }`);
|
|
856
890
|
}
|
|
857
891
|
},
|
|
858
892
|
notifications: {
|
package/dist/auth/auth.d.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { type FoirEnv } from '../graphql/foir-request';
|
|
19
19
|
import { type AuthOpName, type AuthOpOptions } from './ops';
|
|
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
|
|
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 MyAddress, type MyDataExport, type MyFactor, type StepUp, type FactorEnrollment, type MySignInMethod, type NewPersonalAccessToken, type ProviderCallbackInput, type ProviderLoginInput, type ProviderLoginResult, type ProviderOTPVerifyInput, type ProviderToken, type SignupContext } from './operations';
|
|
21
21
|
import type { TypedDocumentNode } from '@graphql-typed-document-node/core';
|
|
22
22
|
/** An access token + its rotating refresh token. */
|
|
23
23
|
export interface FoirAuthTokens {
|
|
@@ -125,8 +125,14 @@ export declare function getDefaultAuthProvider(env: FoirEnv): Promise<DefaultAut
|
|
|
125
125
|
* so a self-hosted frontend can render the right signup surface proactively.
|
|
126
126
|
*/
|
|
127
127
|
export declare function signupContext(env: FoirEnv): Promise<SignupContext>;
|
|
128
|
-
/**
|
|
129
|
-
|
|
128
|
+
/**
|
|
129
|
+
* Join the project's sign-up waitlist. The project must be in waitlist mode.
|
|
130
|
+
* Resolves `true` for every address: the server answers identically whether
|
|
131
|
+
* the address was queued, was already let in, or already has an account, on
|
|
132
|
+
* purpose, so this endpoint cannot be used to test what an address holds. What
|
|
133
|
+
* differs is only the email the address is sent.
|
|
134
|
+
*/
|
|
135
|
+
export declare function joinWaitlist(env: FoirEnv, email: string): Promise<boolean>;
|
|
130
136
|
/**
|
|
131
137
|
* Send a password-reset email. Resolves `true` whether or not the address has
|
|
132
138
|
* an account: the server answers identically either way, on purpose, so this
|
|
@@ -148,8 +154,6 @@ export declare function resetPassword(env: FoirEnv, vars: {
|
|
|
148
154
|
token: string;
|
|
149
155
|
newPassword: string;
|
|
150
156
|
}): Promise<AuthResult>;
|
|
151
|
-
/** Redeem an emailed verification token. */
|
|
152
|
-
export declare function verifyEmail(env: FoirEnv, token: string): Promise<boolean>;
|
|
153
157
|
/**
|
|
154
158
|
* Change the calling user's password. Requires the current password as well
|
|
155
159
|
* as the bearer, so a stolen token alone cannot take the account over.
|
|
@@ -164,10 +168,12 @@ export declare function updatePassword(env: FoirEnv, vars: {
|
|
|
164
168
|
*/
|
|
165
169
|
export declare function currentUser(env: FoirEnv, options?: AuthOpOptions): Promise<CurrentUser | null>;
|
|
166
170
|
/**
|
|
167
|
-
* The
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* user
|
|
171
|
+
* The token of the provider the calling user signed in through, kept for the
|
|
172
|
+
* sign-in the request belongs to and renewed by the server when it is due:
|
|
173
|
+
* near its stated expiry, or with no expiry stated. `null` when there is no
|
|
174
|
+
* user token on the request; `linked: false` with `reauthenticate: true` when
|
|
175
|
+
* nothing is kept for this sign-in (it did not pass through the provider, or
|
|
176
|
+
* its token was ended), and the user signs in through the provider again.
|
|
171
177
|
*
|
|
172
178
|
* Pass `forceRefresh` after the provider refused the token it was last given:
|
|
173
179
|
* the server renews it then, at most once a minute for one user and provider.
|
|
@@ -178,20 +184,33 @@ export declare function myProviderToken(env: FoirEnv, providerKey: string, optio
|
|
|
178
184
|
forceRefresh?: boolean;
|
|
179
185
|
}): Promise<ProviderToken | null>;
|
|
180
186
|
/**
|
|
181
|
-
* End the
|
|
182
|
-
* clear local session state — {@link signOut} is the
|
|
187
|
+
* End the sign-in's provider tokens server-side: this device's, and no other
|
|
188
|
+
* device's. This does NOT clear local session state — {@link signOut} is the
|
|
189
|
+
* pairing that does both.
|
|
183
190
|
*/
|
|
184
191
|
export declare function logout(env: FoirEnv, options?: AuthOpOptions): Promise<boolean>;
|
|
185
192
|
/**
|
|
186
193
|
* Delete the calling user's account and their owned records and files.
|
|
187
|
-
* Irreversible. `password` is required for
|
|
188
|
-
*
|
|
189
|
-
*
|
|
194
|
+
* Irreversible. `password` is required for an account that holds one. An
|
|
195
|
+
* account with none sets `confirm`, on a sign-in made in the last ten minutes:
|
|
196
|
+
* an older one is refused, and the user signs in again. The server enforces
|
|
197
|
+
* the re-auth gate and fails closed.
|
|
190
198
|
*/
|
|
191
199
|
export declare function deleteMyAccount(env: FoirEnv, vars: {
|
|
192
200
|
confirm: boolean;
|
|
193
201
|
password?: string;
|
|
194
202
|
}, options?: AuthOpOptions): Promise<DeleteAccountResult>;
|
|
203
|
+
/**
|
|
204
|
+
* End the calling user's own membership where the request stands: the
|
|
205
|
+
* organization `orgId` names, or, with none, the project's own. Every role
|
|
206
|
+
* they hold there ends with it; their account and what they made stay.
|
|
207
|
+
* `false` when they held no membership there.
|
|
208
|
+
*
|
|
209
|
+
* Refused where it would leave an organization with nobody who can staff it,
|
|
210
|
+
* or leave them nowhere to sign in: a person keeps one membership in the
|
|
211
|
+
* project, and {@link deleteMyAccount} is how they leave altogether.
|
|
212
|
+
*/
|
|
213
|
+
export declare function leaveMembership(env: FoirEnv, options?: AuthOpOptions): Promise<boolean>;
|
|
195
214
|
/**
|
|
196
215
|
* Change the calling user's own name, picture or language. It asks no
|
|
197
216
|
* permission: these are theirs.
|
|
@@ -228,6 +247,41 @@ export declare function createPersonalAccessToken(env: FoirEnv, vars: {
|
|
|
228
247
|
name: string;
|
|
229
248
|
expiresInDays: number;
|
|
230
249
|
}, options?: AuthOpOptions): Promise<NewPersonalAccessToken>;
|
|
250
|
+
/** The email addresses the calling user is known by, the one their account uses first. */
|
|
251
|
+
export declare function myAddresses(env: FoirEnv, options?: AuthOpOptions): Promise<MyAddress[]>;
|
|
252
|
+
/**
|
|
253
|
+
* Send a code to an address the calling user is adding to their account, and
|
|
254
|
+
* answer when it stops working (ISO-8601, ten minutes on). The address is kept
|
|
255
|
+
* by {@link proveMyAddress}. `password` is their current one; an account with
|
|
256
|
+
* none needs a sign-in in the last ten minutes instead. At most five codes an
|
|
257
|
+
* hour.
|
|
258
|
+
*/
|
|
259
|
+
export declare function addMyAddress(env: FoirEnv, vars: {
|
|
260
|
+
email: string;
|
|
261
|
+
password?: string;
|
|
262
|
+
}, options?: AuthOpOptions): Promise<string>;
|
|
263
|
+
/**
|
|
264
|
+
* Keep the address a code was sent to, as proven. Refused where another
|
|
265
|
+
* account in the project holds the address: nobody's address is taken.
|
|
266
|
+
*/
|
|
267
|
+
export declare function proveMyAddress(env: FoirEnv, vars: {
|
|
268
|
+
email: string;
|
|
269
|
+
code: string;
|
|
270
|
+
}, options?: AuthOpOptions): Promise<MyAddress>;
|
|
271
|
+
/** Make one of the calling user's proven addresses the one their account uses. */
|
|
272
|
+
export declare function makeMyAddressPrimary(env: FoirEnv, email: string, options?: AuthOpOptions): Promise<MyAddress>;
|
|
273
|
+
/**
|
|
274
|
+
* Remove one of the calling user's addresses. The one their account uses
|
|
275
|
+
* stays: make another primary first.
|
|
276
|
+
*/
|
|
277
|
+
export declare function removeMyAddress(env: FoirEnv, email: string, options?: AuthOpOptions): Promise<boolean>;
|
|
278
|
+
/**
|
|
279
|
+
* A copy of the calling user's own data: their account (profile, addresses,
|
|
280
|
+
* memberships and roles, sign-in providers, authorised apps, sessions and
|
|
281
|
+
* notification preferences) and everything deleting it would erase, the
|
|
282
|
+
* records and files they own.
|
|
283
|
+
*/
|
|
284
|
+
export declare function exportMyData(env: FoirEnv, options?: AuthOpOptions): Promise<MyDataExport>;
|
|
231
285
|
/** The providers the calling user signs in with. */
|
|
232
286
|
export declare function mySignInMethods(env: FoirEnv, options?: AuthOpOptions): Promise<MySignInMethod[]>;
|
|
233
287
|
/**
|
|
@@ -288,6 +342,15 @@ export declare function removeFactor(env: FoirEnv, vars: {
|
|
|
288
342
|
kind: string;
|
|
289
343
|
id: string;
|
|
290
344
|
}, options?: AuthOpOptions): Promise<boolean>;
|
|
345
|
+
/**
|
|
346
|
+
* Rename one of the calling user's security keys or passkeys. A name proves
|
|
347
|
+
* nothing and admits nobody, so no step-up is asked.
|
|
348
|
+
*/
|
|
349
|
+
export declare function renameFactor(env: FoirEnv, vars: {
|
|
350
|
+
kind: 'security_key' | 'passkey';
|
|
351
|
+
id: string;
|
|
352
|
+
name: string;
|
|
353
|
+
}, options?: AuthOpOptions): Promise<MyFactor>;
|
|
291
354
|
/**
|
|
292
355
|
* Make the calling user new recovery codes, with an elevated handle from
|
|
293
356
|
* {@link completeStepUp}. They replace any held and are answered here once.
|
|
@@ -328,7 +391,7 @@ export declare function myOrganizations(env: FoirEnv, vars?: {
|
|
|
328
391
|
* membership together.
|
|
329
392
|
*
|
|
330
393
|
* `parentId` FOUNDS A CHILD, which is what lets the people you serve create their own
|
|
331
|
-
* sub-tenants with no
|
|
394
|
+
* sub-tenants with no manager in the loop — a reseller adding a client, a
|
|
332
395
|
* franchise adding a branch. It is resolved against the caller's own
|
|
333
396
|
* MEMBERSHIPS, not merely against the project: on this lane "an organization
|
|
334
397
|
* that exists" is not the question, "one you operate" is, and anything else is
|
package/dist/auth/hosted.d.ts
CHANGED
|
@@ -21,6 +21,11 @@ export interface HostedLoginConfig {
|
|
|
21
21
|
sessionPath?: string;
|
|
22
22
|
/** RP-initiated logout path on the front door. Default `/session/end-session`. */
|
|
23
23
|
endSessionPath?: string;
|
|
24
|
+
/**
|
|
25
|
+
* The app the bearer is for, when it is not the app the login domain fronts.
|
|
26
|
+
* Default: the domain's own app.
|
|
27
|
+
*/
|
|
28
|
+
clientId?: string;
|
|
24
29
|
}
|
|
25
30
|
/**
|
|
26
31
|
* Build the redirect URL to the hosted front door, forwarding a best-effort
|
package/dist/auth/index.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* the caller's own manifest advertises, through the same op transport
|
|
11
11
|
* `@foir/sdk/data` uses, so `graphql` is not on this module's path at all.
|
|
12
12
|
*/
|
|
13
|
-
export { login, register, requestOTP, loginWithOTP, refreshTokens, loginWithProvider, providerCallback, providerVerifyOTP, providerSignInRefusalOf, signInRefusalOf, confirmProviderLink, resendProviderLinkCode, getAuthProviders, getAuthConfig, getDefaultAuthProvider, signupContext, joinWaitlist, requestPasswordReset, resetPassword, updatePassword,
|
|
13
|
+
export { login, register, requestOTP, loginWithOTP, refreshTokens, loginWithProvider, providerCallback, providerVerifyOTP, providerSignInRefusalOf, signInRefusalOf, confirmProviderLink, resendProviderLinkCode, getAuthProviders, getAuthConfig, getDefaultAuthProvider, signupContext, joinWaitlist, requestPasswordReset, resetPassword, updatePassword, currentUser, myProviderToken, logout, deleteMyAccount, leaveMembership, updateMyProfile, myAuthorizedApps, revokeAuthorizedApp, mySessions, endMySession, myAddresses, addMyAddress, proveMyAddress, makeMyAddressPrimary, removeMyAddress, exportMyData, signOutEverywhere, createPersonalAccessToken, mySignInMethods, connectSignInMethod, disconnectSignInMethod, myFactors, beginStepUp, completeStepUp, beginFactorEnrollment, completeFactorEnrollment, removeFactor, renameFactor, makeRecoveryCodes, myOrganizations, registerOrganization, saveSession, clearSession, getSessionToken, getSessionUser, signInWithPassword, signUpWithPassword, signInWithOTP, resetPasswordAndSignIn, refreshSession, refreshSessionOnce, signOut, authedRequest, authedOp, requireAuth, } from './auth';
|
|
14
14
|
export type { FoirAuthTokens, FoirUser, SessionAdapter, RequireAuthOptions, } from './auth';
|
|
15
15
|
export { userAccess, getSessionAccess, hasRole, hasScope, requireRole, requireScope, FoirAccessDeniedError, } from './access';
|
|
16
16
|
export type { FoirAccess, FoirAccessDenial } from './access';
|
|
@@ -21,4 +21,4 @@ export { hostedLoginUrl, hostedLogoutUrl, fetchHostedSession, hostedSignInNotice
|
|
|
21
21
|
export type { HostedLoginConfig, HostedSession, HostedSessionResult, HostedSignInNotice } from './hosted';
|
|
22
22
|
export { createFoirSessionClient } from './session-client';
|
|
23
23
|
export type { FoirSessionClient, FoirSessionConfig, FoirSessionUser, } from './session-client';
|
|
24
|
-
export type { AuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode,
|
|
24
|
+
export type { AuthResult, ProviderLoginResult, AuthProviderPublic, ProviderLoginInput, ProviderCallbackInput, ProviderOTPVerifyInput, SignupContext, SignupMode, AuthConfig, AuthConfigProvider, DefaultAuthProvider, CurrentUser, ProviderToken, ProviderTokenRefresh, DeleteAccountResult, MyOrganization, MyProfile, MyProfileChange, AuthorizedApp, MySession, MyAddress, MyDataExport, NewPersonalAccessToken, MySignInMethod, MyFactor, StepUp, FactorEnrollment, } from './operations';
|
|
@@ -76,13 +76,6 @@ export type SignupMode = 'PUBLIC' | 'RESTRICTED' | 'WAITLIST' | 'CLOSED';
|
|
|
76
76
|
export interface SignupContext {
|
|
77
77
|
signupMode: SignupMode;
|
|
78
78
|
}
|
|
79
|
-
/** The queued (or existing pending) entry a waitlist join returns. */
|
|
80
|
-
export interface WaitlistJoinResult {
|
|
81
|
-
id: string;
|
|
82
|
-
email: string;
|
|
83
|
-
/** Waitlist lifecycle status; PENDING on a fresh join. */
|
|
84
|
-
status: string;
|
|
85
|
-
}
|
|
86
79
|
/** One provider as it appears inside {@link AuthConfig}. */
|
|
87
80
|
export interface AuthConfigProvider {
|
|
88
81
|
key: string;
|
|
@@ -126,13 +119,15 @@ export interface CurrentUser {
|
|
|
126
119
|
/** What a provider token read did about the token's freshness. */
|
|
127
120
|
export type ProviderTokenRefresh = 'NOT_ATTEMPTED' | 'REFRESHED' | 'FAILED' | 'HELD_BACK';
|
|
128
121
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
122
|
+
* The token of the provider the calling user signed in through. It belongs to
|
|
123
|
+
* the sign-in that obtained it: a sign-in on another device keeps its own, and
|
|
124
|
+
* signing out ends it. `myProviderToken` answers `null` when there is no user
|
|
125
|
+
* token on the request, and `linked: false` with `reauthenticate: true` when
|
|
126
|
+
* nothing is kept for this sign-in.
|
|
132
127
|
*/
|
|
133
128
|
export interface ProviderToken {
|
|
134
129
|
providerKey: string;
|
|
135
|
-
/** False when
|
|
130
|
+
/** False when nothing is kept for the sign-in the request belongs to; every token field is then null. */
|
|
136
131
|
linked: boolean;
|
|
137
132
|
accessToken: string | null;
|
|
138
133
|
refreshToken: string | null;
|
|
@@ -148,7 +143,11 @@ export interface ProviderToken {
|
|
|
148
143
|
refresh: ProviderTokenRefresh | null;
|
|
149
144
|
/** Where a failed refresh failed, such as `"refresh grant"`. */
|
|
150
145
|
refreshFailure: string | null;
|
|
151
|
-
/**
|
|
146
|
+
/**
|
|
147
|
+
* Only the user signing in with the provider again mends the connection:
|
|
148
|
+
* nothing is kept for this sign-in, or the provider will not renew it. Show
|
|
149
|
+
* them the way to sign in through the provider, not an empty page.
|
|
150
|
+
*/
|
|
152
151
|
reauthenticate: boolean;
|
|
153
152
|
}
|
|
154
153
|
/** What a self-serve account deletion removed. */
|
|
@@ -201,6 +200,61 @@ export interface MySession {
|
|
|
201
200
|
/** Whether it is the session making the request. */
|
|
202
201
|
current: boolean;
|
|
203
202
|
}
|
|
203
|
+
/** An email address the calling user is known by. */
|
|
204
|
+
export interface MyAddress {
|
|
205
|
+
email: string;
|
|
206
|
+
/** Whether it is the address their account uses: shown for them, and where mail to them goes. */
|
|
207
|
+
primary: boolean;
|
|
208
|
+
/** Whether they proved they hold it. Every address they added is proven. */
|
|
209
|
+
proven: boolean;
|
|
210
|
+
/** ISO-8601. */
|
|
211
|
+
addedAt: string | null;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The calling user's copy of their own data, the `foir.my-data.v1` document:
|
|
215
|
+
* their account and everything deleting it would erase. No password, code or
|
|
216
|
+
* token value is in it.
|
|
217
|
+
*/
|
|
218
|
+
export interface MyDataExport {
|
|
219
|
+
format: 'foir.my-data.v1';
|
|
220
|
+
/** ISO-8601. */
|
|
221
|
+
exportedAt: string;
|
|
222
|
+
account: Record<string, unknown> & {
|
|
223
|
+
id: string;
|
|
224
|
+
pool: string;
|
|
225
|
+
poolKind: string;
|
|
226
|
+
status: string;
|
|
227
|
+
};
|
|
228
|
+
addresses: Array<{
|
|
229
|
+
email: string;
|
|
230
|
+
primary: boolean;
|
|
231
|
+
proven: boolean;
|
|
232
|
+
addedAt?: string;
|
|
233
|
+
}>;
|
|
234
|
+
memberships: Array<Record<string, unknown> & {
|
|
235
|
+
roles: string[];
|
|
236
|
+
}>;
|
|
237
|
+
signInMethods: Array<Record<string, unknown>>;
|
|
238
|
+
authorizedApps: Array<Record<string, unknown>>;
|
|
239
|
+
sessions: Array<Record<string, unknown>>;
|
|
240
|
+
notificationPreferences: Array<Record<string, unknown>>;
|
|
241
|
+
/** The records the user owns, each with the content it holds now. */
|
|
242
|
+
records: Array<{
|
|
243
|
+
id: string;
|
|
244
|
+
model: string;
|
|
245
|
+
key?: string;
|
|
246
|
+
project: string;
|
|
247
|
+
data: Record<string, unknown>;
|
|
248
|
+
}>;
|
|
249
|
+
/** The files the user owns; their bytes are fetched from `url`. */
|
|
250
|
+
files: Array<{
|
|
251
|
+
id: string;
|
|
252
|
+
name: string;
|
|
253
|
+
mimeType: string;
|
|
254
|
+
size: number;
|
|
255
|
+
url: string;
|
|
256
|
+
}>;
|
|
257
|
+
}
|
|
204
258
|
/** A personal access token just made: its value is shown here once. */
|
|
205
259
|
export interface NewPersonalAccessToken {
|
|
206
260
|
token: MySession;
|
package/dist/auth/ops.d.ts
CHANGED
|
@@ -55,14 +55,20 @@ export declare const AUTH_OPS: {
|
|
|
55
55
|
readonly requestPasswordReset: "requestPasswordReset";
|
|
56
56
|
readonly resetPassword: "resetPassword";
|
|
57
57
|
readonly updatePassword: "updatePassword";
|
|
58
|
-
readonly verifyEmail: "verifyEmail";
|
|
59
58
|
readonly deleteMyAccount: "deleteMyAccount";
|
|
59
|
+
readonly leaveMembership: "leaveMembership";
|
|
60
60
|
readonly updateMyProfile: "updateMyProfile";
|
|
61
61
|
readonly myAuthorizedApps: "myAuthorizedApps";
|
|
62
62
|
readonly revokeAuthorizedApp: "revokeAuthorizedApp";
|
|
63
63
|
readonly mySessions: "mySessions";
|
|
64
64
|
readonly endMySession: "endMySession";
|
|
65
65
|
readonly signOutEverywhere: "signOutEverywhere";
|
|
66
|
+
readonly myAddresses: "myAddresses";
|
|
67
|
+
readonly addMyAddress: "addMyAddress";
|
|
68
|
+
readonly proveMyAddress: "proveMyAddress";
|
|
69
|
+
readonly makeMyAddressPrimary: "makeMyAddressPrimary";
|
|
70
|
+
readonly removeMyAddress: "removeMyAddress";
|
|
71
|
+
readonly exportMyData: "exportMyData";
|
|
66
72
|
readonly createPersonalAccessToken: "createPersonalAccessToken";
|
|
67
73
|
readonly mySignInMethods: "mySignInMethods";
|
|
68
74
|
readonly connectSignInMethod: "connectSignInMethod";
|
|
@@ -73,6 +79,7 @@ export declare const AUTH_OPS: {
|
|
|
73
79
|
readonly beginFactorEnrollment: "beginFactorEnrollment";
|
|
74
80
|
readonly completeFactorEnrollment: "completeFactorEnrollment";
|
|
75
81
|
readonly removeFactor: "removeFactor";
|
|
82
|
+
readonly renameFactor: "renameFactor";
|
|
76
83
|
readonly makeRecoveryCodes: "makeRecoveryCodes";
|
|
77
84
|
readonly myOrganizations: "myOrganizations";
|
|
78
85
|
readonly registerOrganization: "registerOrganization";
|
|
@@ -37,6 +37,11 @@ export interface FoirSessionConfig {
|
|
|
37
37
|
sessionPath?: string;
|
|
38
38
|
/** Logout path. Default `/session/logout`. */
|
|
39
39
|
logoutPath?: string;
|
|
40
|
+
/**
|
|
41
|
+
* The app the bearer is for, when it is not the app the login domain fronts.
|
|
42
|
+
* Default: the domain's own app.
|
|
43
|
+
*/
|
|
44
|
+
clientId?: string;
|
|
40
45
|
/** Seconds before expiry to re-exchange. Default 60. */
|
|
41
46
|
refreshSkewSeconds?: number;
|
|
42
47
|
/**
|
package/dist/auth-session.js
CHANGED
|
@@ -5,8 +5,9 @@ var DEFAULT_REFRESH_SKEW_SECONDS = 60;
|
|
|
5
5
|
var MIN_REFRESH_DELAY_MS = 5e3;
|
|
6
6
|
var CSRF_HEADER = { "X-Foir-Session": "1" };
|
|
7
7
|
function createFoirSessionClient(config) {
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const forApp = config.clientId ? `?client_id=${encodeURIComponent(config.clientId)}` : "";
|
|
9
|
+
const sessionUrl = `${trimSlash(config.loginOrigin)}${config.sessionPath ?? DEFAULT_SESSION_PATH}${forApp}`;
|
|
10
|
+
const logoutUrl = `${trimSlash(config.loginOrigin)}${config.logoutPath ?? DEFAULT_LOGOUT_PATH}${forApp}`;
|
|
10
11
|
const skewMs = (config.refreshSkewSeconds ?? DEFAULT_REFRESH_SKEW_SECONDS) * 1e3;
|
|
11
12
|
let cached = null;
|
|
12
13
|
let inflight = null;
|
package/dist/auth.js
CHANGED
|
@@ -1093,8 +1093,9 @@ var AUTH_OPS = {
|
|
|
1093
1093
|
requestPasswordReset: "requestPasswordReset",
|
|
1094
1094
|
resetPassword: "resetPassword",
|
|
1095
1095
|
updatePassword: "updatePassword",
|
|
1096
|
-
verifyEmail: "verifyEmail",
|
|
1097
1096
|
deleteMyAccount: "deleteMyAccount",
|
|
1097
|
+
// Ending their own membership where the request stands.
|
|
1098
|
+
leaveMembership: "leaveMembership",
|
|
1098
1099
|
// The user's own profile, and the apps they have agreed may act for them.
|
|
1099
1100
|
updateMyProfile: "updateMyProfile",
|
|
1100
1101
|
myAuthorizedApps: "myAuthorizedApps",
|
|
@@ -1104,6 +1105,14 @@ var AUTH_OPS = {
|
|
|
1104
1105
|
mySessions: "mySessions",
|
|
1105
1106
|
endMySession: "endMySession",
|
|
1106
1107
|
signOutEverywhere: "signOutEverywhere",
|
|
1108
|
+
// Their email addresses: one added is kept once the code it was sent proves it.
|
|
1109
|
+
myAddresses: "myAddresses",
|
|
1110
|
+
addMyAddress: "addMyAddress",
|
|
1111
|
+
proveMyAddress: "proveMyAddress",
|
|
1112
|
+
makeMyAddressPrimary: "makeMyAddressPrimary",
|
|
1113
|
+
removeMyAddress: "removeMyAddress",
|
|
1114
|
+
// A copy of their own data.
|
|
1115
|
+
exportMyData: "exportMyData",
|
|
1107
1116
|
createPersonalAccessToken: "createPersonalAccessToken",
|
|
1108
1117
|
mySignInMethods: "mySignInMethods",
|
|
1109
1118
|
connectSignInMethod: "connectSignInMethod",
|
|
@@ -1115,6 +1124,7 @@ var AUTH_OPS = {
|
|
|
1115
1124
|
beginFactorEnrollment: "beginFactorEnrollment",
|
|
1116
1125
|
completeFactorEnrollment: "completeFactorEnrollment",
|
|
1117
1126
|
removeFactor: "removeFactor",
|
|
1127
|
+
renameFactor: "renameFactor",
|
|
1118
1128
|
makeRecoveryCodes: "makeRecoveryCodes",
|
|
1119
1129
|
// The organizations the caller may stand in. Nothing selects one: a request
|
|
1120
1130
|
// names the organization it acts in (`orgId` or `orgUrl` below), and the
|
|
@@ -1266,9 +1276,6 @@ async function requestPasswordReset(env, email, options) {
|
|
|
1266
1276
|
async function resetPassword(env, vars) {
|
|
1267
1277
|
return authOp(env, AUTH_OPS.resetPassword, vars);
|
|
1268
1278
|
}
|
|
1269
|
-
async function verifyEmail(env, token) {
|
|
1270
|
-
return authOp(env, AUTH_OPS.verifyEmail, { token });
|
|
1271
|
-
}
|
|
1272
1279
|
async function updatePassword(env, vars, options) {
|
|
1273
1280
|
return authOp(env, AUTH_OPS.updatePassword, vars, options);
|
|
1274
1281
|
}
|
|
@@ -1286,6 +1293,9 @@ async function logout(env, options) {
|
|
|
1286
1293
|
async function deleteMyAccount(env, vars, options) {
|
|
1287
1294
|
return authOp(env, AUTH_OPS.deleteMyAccount, vars, options);
|
|
1288
1295
|
}
|
|
1296
|
+
async function leaveMembership(env, options) {
|
|
1297
|
+
return authOp(env, AUTH_OPS.leaveMembership, void 0, options);
|
|
1298
|
+
}
|
|
1289
1299
|
async function updateMyProfile(env, change, options) {
|
|
1290
1300
|
return authOp(env, AUTH_OPS.updateMyProfile, change, options);
|
|
1291
1301
|
}
|
|
@@ -1307,6 +1317,24 @@ async function signOutEverywhere(env, vars = {}, options) {
|
|
|
1307
1317
|
async function createPersonalAccessToken(env, vars, options) {
|
|
1308
1318
|
return authOp(env, AUTH_OPS.createPersonalAccessToken, vars, options);
|
|
1309
1319
|
}
|
|
1320
|
+
async function myAddresses(env, options) {
|
|
1321
|
+
return authOp(env, AUTH_OPS.myAddresses, void 0, options);
|
|
1322
|
+
}
|
|
1323
|
+
async function addMyAddress(env, vars, options) {
|
|
1324
|
+
return authOp(env, AUTH_OPS.addMyAddress, vars, options);
|
|
1325
|
+
}
|
|
1326
|
+
async function proveMyAddress(env, vars, options) {
|
|
1327
|
+
return authOp(env, AUTH_OPS.proveMyAddress, vars, options);
|
|
1328
|
+
}
|
|
1329
|
+
async function makeMyAddressPrimary(env, email, options) {
|
|
1330
|
+
return authOp(env, AUTH_OPS.makeMyAddressPrimary, { email }, options);
|
|
1331
|
+
}
|
|
1332
|
+
async function removeMyAddress(env, email, options) {
|
|
1333
|
+
return authOp(env, AUTH_OPS.removeMyAddress, { email }, options);
|
|
1334
|
+
}
|
|
1335
|
+
async function exportMyData(env, options) {
|
|
1336
|
+
return authOp(env, AUTH_OPS.exportMyData, void 0, options);
|
|
1337
|
+
}
|
|
1310
1338
|
async function mySignInMethods(env, options) {
|
|
1311
1339
|
return authOp(env, AUTH_OPS.mySignInMethods, void 0, options);
|
|
1312
1340
|
}
|
|
@@ -1334,6 +1362,9 @@ async function completeFactorEnrollment(env, vars, options) {
|
|
|
1334
1362
|
async function removeFactor(env, vars, options) {
|
|
1335
1363
|
return authOp(env, AUTH_OPS.removeFactor, vars, options);
|
|
1336
1364
|
}
|
|
1365
|
+
async function renameFactor(env, vars, options) {
|
|
1366
|
+
return authOp(env, AUTH_OPS.renameFactor, vars, options);
|
|
1367
|
+
}
|
|
1337
1368
|
async function makeRecoveryCodes(env, elevatedHandle, options) {
|
|
1338
1369
|
return authOp(env, AUTH_OPS.makeRecoveryCodes, { elevatedHandle }, options);
|
|
1339
1370
|
}
|
|
@@ -1792,7 +1823,7 @@ async function fetchHostedSession(request, config) {
|
|
|
1792
1823
|
if (!match) return { outcome: "signed-out", reason: "no-cookie" };
|
|
1793
1824
|
let res;
|
|
1794
1825
|
try {
|
|
1795
|
-
res = await fetch(`${config.loginOrigin}${sessionPath}`, {
|
|
1826
|
+
res = await fetch(`${config.loginOrigin}${sessionPath}${forApp(config.clientId)}`, {
|
|
1796
1827
|
headers: {
|
|
1797
1828
|
Cookie: `${cookieName}=${match[1]}`,
|
|
1798
1829
|
"X-Foir-Session": "1"
|
|
@@ -1867,6 +1898,9 @@ var REFUSAL_MESSAGES = {
|
|
|
1867
1898
|
function refusalMessage(code) {
|
|
1868
1899
|
return REFUSAL_MESSAGES[code] ?? "The sign-in couldn\u2019t be finished. Try again.";
|
|
1869
1900
|
}
|
|
1901
|
+
function forApp(clientId) {
|
|
1902
|
+
return clientId ? `?client_id=${encodeURIComponent(clientId)}` : "";
|
|
1903
|
+
}
|
|
1870
1904
|
|
|
1871
1905
|
// src/auth/session-client.ts
|
|
1872
1906
|
var DEFAULT_SESSION_PATH2 = "/session/token";
|
|
@@ -1875,8 +1909,9 @@ var DEFAULT_REFRESH_SKEW_SECONDS = 60;
|
|
|
1875
1909
|
var MIN_REFRESH_DELAY_MS = 5e3;
|
|
1876
1910
|
var CSRF_HEADER = { "X-Foir-Session": "1" };
|
|
1877
1911
|
function createFoirSessionClient(config) {
|
|
1878
|
-
const
|
|
1879
|
-
const
|
|
1912
|
+
const forApp2 = config.clientId ? `?client_id=${encodeURIComponent(config.clientId)}` : "";
|
|
1913
|
+
const sessionUrl = `${trimSlash(config.loginOrigin)}${config.sessionPath ?? DEFAULT_SESSION_PATH2}${forApp2}`;
|
|
1914
|
+
const logoutUrl = `${trimSlash(config.loginOrigin)}${config.logoutPath ?? DEFAULT_LOGOUT_PATH}${forApp2}`;
|
|
1880
1915
|
const skewMs = (config.refreshSkewSeconds ?? DEFAULT_REFRESH_SKEW_SECONDS) * 1e3;
|
|
1881
1916
|
let cached = null;
|
|
1882
1917
|
let inflight = null;
|
|
@@ -2007,6 +2042,7 @@ export {
|
|
|
2007
2042
|
FoirAccessDeniedError,
|
|
2008
2043
|
FoirAuthDowngradedError,
|
|
2009
2044
|
FoirSessionExpiredError,
|
|
2045
|
+
addMyAddress,
|
|
2010
2046
|
authedOp,
|
|
2011
2047
|
authedRequest,
|
|
2012
2048
|
beginFactorEnrollment,
|
|
@@ -2022,6 +2058,7 @@ export {
|
|
|
2022
2058
|
deleteMyAccount,
|
|
2023
2059
|
disconnectSignInMethod,
|
|
2024
2060
|
endMySession,
|
|
2061
|
+
exportMyData,
|
|
2025
2062
|
fetchHostedSession,
|
|
2026
2063
|
getAuthConfig,
|
|
2027
2064
|
getAuthProviders,
|
|
@@ -2035,17 +2072,21 @@ export {
|
|
|
2035
2072
|
hostedLogoutUrl,
|
|
2036
2073
|
hostedSignInNoticeOf,
|
|
2037
2074
|
joinWaitlist,
|
|
2075
|
+
leaveMembership,
|
|
2038
2076
|
login,
|
|
2039
2077
|
loginWithOTP,
|
|
2040
2078
|
loginWithProvider,
|
|
2041
2079
|
logout,
|
|
2080
|
+
makeMyAddressPrimary,
|
|
2042
2081
|
makeRecoveryCodes,
|
|
2082
|
+
myAddresses,
|
|
2043
2083
|
myAuthorizedApps,
|
|
2044
2084
|
myFactors,
|
|
2045
2085
|
myOrganizations,
|
|
2046
2086
|
myProviderToken,
|
|
2047
2087
|
mySessions,
|
|
2048
2088
|
mySignInMethods,
|
|
2089
|
+
proveMyAddress,
|
|
2049
2090
|
providerCallback,
|
|
2050
2091
|
providerSignInRefusalOf,
|
|
2051
2092
|
providerVerifyOTP,
|
|
@@ -2055,6 +2096,8 @@ export {
|
|
|
2055
2096
|
register,
|
|
2056
2097
|
registerOrganization,
|
|
2057
2098
|
removeFactor,
|
|
2099
|
+
removeMyAddress,
|
|
2100
|
+
renameFactor,
|
|
2058
2101
|
requestOTP,
|
|
2059
2102
|
requestPasswordReset,
|
|
2060
2103
|
requireAuth,
|
|
@@ -2074,6 +2117,5 @@ export {
|
|
|
2074
2117
|
signupContext,
|
|
2075
2118
|
updateMyProfile,
|
|
2076
2119
|
updatePassword,
|
|
2077
|
-
userAccess
|
|
2078
|
-
verifyEmail
|
|
2120
|
+
userAccess
|
|
2079
2121
|
};
|
|
@@ -11,7 +11,7 @@ export interface EditorProviderProps {
|
|
|
11
11
|
children: ReactNode;
|
|
12
12
|
/**
|
|
13
13
|
* Parent window origin for postMessage validation.
|
|
14
|
-
* Must be an explicit origin (e.g., 'https://
|
|
14
|
+
* Must be an explicit origin (e.g., 'https://console.example.com').
|
|
15
15
|
* Falls back to VITE_PARENT_ORIGIN or NEXT_PUBLIC_PARENT_ORIGIN env var.
|
|
16
16
|
*/
|
|
17
17
|
parentOrigin?: string;
|
package/dist/next.js
CHANGED
|
@@ -973,8 +973,9 @@ var AUTH_OPS = {
|
|
|
973
973
|
requestPasswordReset: "requestPasswordReset",
|
|
974
974
|
resetPassword: "resetPassword",
|
|
975
975
|
updatePassword: "updatePassword",
|
|
976
|
-
verifyEmail: "verifyEmail",
|
|
977
976
|
deleteMyAccount: "deleteMyAccount",
|
|
977
|
+
// Ending their own membership where the request stands.
|
|
978
|
+
leaveMembership: "leaveMembership",
|
|
978
979
|
// The user's own profile, and the apps they have agreed may act for them.
|
|
979
980
|
updateMyProfile: "updateMyProfile",
|
|
980
981
|
myAuthorizedApps: "myAuthorizedApps",
|
|
@@ -984,6 +985,14 @@ var AUTH_OPS = {
|
|
|
984
985
|
mySessions: "mySessions",
|
|
985
986
|
endMySession: "endMySession",
|
|
986
987
|
signOutEverywhere: "signOutEverywhere",
|
|
988
|
+
// Their email addresses: one added is kept once the code it was sent proves it.
|
|
989
|
+
myAddresses: "myAddresses",
|
|
990
|
+
addMyAddress: "addMyAddress",
|
|
991
|
+
proveMyAddress: "proveMyAddress",
|
|
992
|
+
makeMyAddressPrimary: "makeMyAddressPrimary",
|
|
993
|
+
removeMyAddress: "removeMyAddress",
|
|
994
|
+
// A copy of their own data.
|
|
995
|
+
exportMyData: "exportMyData",
|
|
987
996
|
createPersonalAccessToken: "createPersonalAccessToken",
|
|
988
997
|
mySignInMethods: "mySignInMethods",
|
|
989
998
|
connectSignInMethod: "connectSignInMethod",
|
|
@@ -995,6 +1004,7 @@ var AUTH_OPS = {
|
|
|
995
1004
|
beginFactorEnrollment: "beginFactorEnrollment",
|
|
996
1005
|
completeFactorEnrollment: "completeFactorEnrollment",
|
|
997
1006
|
removeFactor: "removeFactor",
|
|
1007
|
+
renameFactor: "renameFactor",
|
|
998
1008
|
makeRecoveryCodes: "makeRecoveryCodes",
|
|
999
1009
|
// The organizations the caller may stand in. Nothing selects one: a request
|
|
1000
1010
|
// names the organization it acts in (`orgId` or `orgUrl` below), and the
|