@foir/sdk 0.21.0 → 0.22.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 +84 -1
- package/README.md +9 -9
- package/dist/app/client.d.ts +90 -84
- 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 +11 -11
- 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 +216 -114
- package/dist/auth/hosted.d.ts +14 -14
- package/dist/auth/index.d.ts +7 -7
- package/dist/auth/operations.d.ts +128 -32
- 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 +234 -135
- package/dist/client.js +4 -4
- package/dist/data/builtins.d.ts +26 -26
- package/dist/data/client.d.ts +2 -2
- 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 +1 -1
- package/dist/data/transport.d.ts +10 -10
- package/dist/data/ws-transport.d.ts +1 -1
- package/dist/data.js +6 -6
- package/dist/graphql/content-client.d.ts +13 -13
- 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 +77 -56
- package/dist/placement/index.d.ts +13 -13
- package/dist/placement.js +9 -6
- package/dist/push.js +61 -40
- package/dist/react/FoirFeedback.d.ts +2 -2
- package/dist/react/FoirProvider.d.ts +23 -23
- package/dist/react/SignIn.d.ts +4 -4
- package/dist/react/UserButton.d.ts +1 -1
- package/dist/react/feedback-notes.d.ts +4 -4
- package/dist/react/index.d.ts +3 -3
- package/dist/react.js +119 -95
- package/dist/realtime/index.d.ts +1 -1
- package/dist/server/callback-client.d.ts +4 -4
- package/dist/server/events-client.d.ts +16 -16
- 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 +1 -1
- package/dist/server/verify-scoped-token.d.ts +3 -3
- package/dist/server.js +16 -13
- package/dist/transport/foir-http.d.ts +13 -13
- package/dist/types/index.d.ts +2 -2
- package/package.json +3 -3
package/dist/auth.js
CHANGED
|
@@ -217,8 +217,8 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
|
|
|
217
217
|
downgrade;
|
|
218
218
|
constructor(downgrade) {
|
|
219
219
|
super(
|
|
220
|
-
`[foir] your
|
|
221
|
-
{ graphQLErrors: [{ message: "
|
|
220
|
+
`[foir] your user token was ${downgrade.userToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
|
|
221
|
+
{ graphQLErrors: [{ message: "user token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
|
|
222
222
|
);
|
|
223
223
|
this.name = "FoirAuthDowngradedError";
|
|
224
224
|
this.downgrade = downgrade;
|
|
@@ -226,7 +226,7 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
|
|
|
226
226
|
};
|
|
227
227
|
var FoirSessionExpiredError = class extends FoirRequestError {
|
|
228
228
|
constructor(options) {
|
|
229
|
-
super("[foir] the
|
|
229
|
+
super("[foir] the user session has expired and could not be refreshed: sign in again", {
|
|
230
230
|
cause: options?.cause,
|
|
231
231
|
graphQLErrors: [{ message: "session expired", extensions: { code: "SESSION_EXPIRED" } }]
|
|
232
232
|
});
|
|
@@ -243,7 +243,7 @@ function reportAuthDowngrade(envelope) {
|
|
|
243
243
|
if (warnedDowngrade === downgrade.reason) return;
|
|
244
244
|
warnedDowngrade = downgrade.reason;
|
|
245
245
|
console.warn(
|
|
246
|
-
`[foir] your
|
|
246
|
+
`[foir] your user token was ${downgrade.userToken} (${downgrade.reason}) \u2014 this request was served as ${downgrade.servedAs}, so auth-targeted content resolved to its anonymous variant. ` + (downgrade.reason === "expired" ? "Re-exchange the token and retry." : "Check which credential you are sending.")
|
|
247
247
|
);
|
|
248
248
|
}
|
|
249
249
|
function refusePrunedDocument(json, options) {
|
|
@@ -1076,42 +1076,63 @@ var AUTH_OPS = {
|
|
|
1076
1076
|
authConfig: "authConfig",
|
|
1077
1077
|
authProviders: "authProviders",
|
|
1078
1078
|
defaultAuthProvider: "defaultAuthProvider",
|
|
1079
|
-
|
|
1079
|
+
signupContext: "signupContext",
|
|
1080
1080
|
// Post-credential self reads.
|
|
1081
1081
|
currentUser: "currentUser",
|
|
1082
1082
|
myProviderToken: "myProviderToken",
|
|
1083
|
-
// What the calling credential may do, and for a signed-in
|
|
1083
|
+
// What the calling credential may do, and for a signed-in user the roles
|
|
1084
1084
|
// they hold. `./access` reads it.
|
|
1085
1085
|
whoami: "whoami",
|
|
1086
1086
|
// Methods.
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1087
|
+
login: "login",
|
|
1088
|
+
register: "register",
|
|
1089
|
+
requestOTP: "requestOTP",
|
|
1090
|
+
loginWithOTP: "loginWithOTP",
|
|
1091
1091
|
// Session lifecycle.
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
// Password management and account lifecycle
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1092
|
+
refreshToken: "refreshToken",
|
|
1093
|
+
logout: "logout",
|
|
1094
|
+
joinWaitlist: "joinWaitlist",
|
|
1095
|
+
// Password management and account lifecycle.
|
|
1096
|
+
requestPasswordReset: "requestPasswordReset",
|
|
1097
|
+
resetPassword: "resetPassword",
|
|
1098
|
+
updatePassword: "updatePassword",
|
|
1099
|
+
verifyEmail: "verifyEmail",
|
|
1100
1100
|
deleteMyAccount: "deleteMyAccount",
|
|
1101
|
-
// The
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
//
|
|
1106
|
-
//
|
|
1101
|
+
// The user's own profile, and the apps they have agreed may act for them.
|
|
1102
|
+
updateMyProfile: "updateMyProfile",
|
|
1103
|
+
myAuthorizedApps: "myAuthorizedApps",
|
|
1104
|
+
revokeAuthorizedApp: "revokeAuthorizedApp",
|
|
1105
|
+
// Where they are signed in, their personal access tokens, and the
|
|
1106
|
+
// providers they sign in with.
|
|
1107
|
+
mySessions: "mySessions",
|
|
1108
|
+
endMySession: "endMySession",
|
|
1109
|
+
signOutEverywhere: "signOutEverywhere",
|
|
1110
|
+
createPersonalAccessToken: "createPersonalAccessToken",
|
|
1111
|
+
mySignInMethods: "mySignInMethods",
|
|
1112
|
+
connectSignInMethod: "connectSignInMethod",
|
|
1113
|
+
disconnectSignInMethod: "disconnectSignInMethod",
|
|
1114
|
+
// Their second factors. A change needs one proven first, by a step-up.
|
|
1115
|
+
myFactors: "myFactors",
|
|
1116
|
+
beginStepUp: "beginStepUp",
|
|
1117
|
+
completeStepUp: "completeStepUp",
|
|
1118
|
+
beginFactorEnrollment: "beginFactorEnrollment",
|
|
1119
|
+
completeFactorEnrollment: "completeFactorEnrollment",
|
|
1120
|
+
removeFactor: "removeFactor",
|
|
1121
|
+
makeRecoveryCodes: "makeRecoveryCodes",
|
|
1122
|
+
// The organizations the caller may stand in. Nothing selects one: a request
|
|
1123
|
+
// names the organization it acts in (`orgId` or `orgUrl` below), and the
|
|
1124
|
+
// platform checks the caller stands there every time.
|
|
1107
1125
|
myOrganizations: "myOrganizations",
|
|
1108
|
-
selectMyOrganization: "selectMyOrganization",
|
|
1109
1126
|
// Founding one. Present in a manifest only when the project opted in.
|
|
1110
|
-
|
|
1127
|
+
registerOrganization: "registerOrganization",
|
|
1111
1128
|
// External identity providers.
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1129
|
+
loginWithProvider: "loginWithProvider",
|
|
1130
|
+
providerCallback: "providerCallback",
|
|
1131
|
+
providerVerifyOTP: "providerVerifyOTP",
|
|
1132
|
+
// A provider sign-in that names an address somebody already holds, waiting
|
|
1133
|
+
// for the code sent to it.
|
|
1134
|
+
confirmProviderLink: "confirmProviderLink",
|
|
1135
|
+
resendProviderLinkCode: "resendProviderLinkCode"
|
|
1115
1136
|
};
|
|
1116
1137
|
function authClientConfig(env, options) {
|
|
1117
1138
|
const apiKey = resolveFoirApiKey(env);
|
|
@@ -1174,31 +1195,48 @@ function stripUndefined(args) {
|
|
|
1174
1195
|
// src/auth/auth.ts
|
|
1175
1196
|
var TOKEN_KEY = "foir:token";
|
|
1176
1197
|
var REFRESH_KEY = "foir:refreshToken";
|
|
1177
|
-
var
|
|
1198
|
+
var USER_ID_KEY = "foir:userId";
|
|
1178
1199
|
var EMAIL_KEY = "foir:email";
|
|
1179
|
-
async function
|
|
1180
|
-
return authOp(env, AUTH_OPS.
|
|
1200
|
+
async function login(env, vars) {
|
|
1201
|
+
return authOp(env, AUTH_OPS.login, vars);
|
|
1181
1202
|
}
|
|
1182
|
-
async function
|
|
1183
|
-
return authOp(env, AUTH_OPS.
|
|
1203
|
+
async function register(env, vars) {
|
|
1204
|
+
return authOp(env, AUTH_OPS.register, vars);
|
|
1184
1205
|
}
|
|
1185
|
-
async function
|
|
1186
|
-
return authOp(env, AUTH_OPS.
|
|
1206
|
+
async function requestOTP(env, email) {
|
|
1207
|
+
return authOp(env, AUTH_OPS.requestOTP, { email });
|
|
1187
1208
|
}
|
|
1188
|
-
async function
|
|
1189
|
-
return authOp(env, AUTH_OPS.
|
|
1209
|
+
async function loginWithOTP(env, vars) {
|
|
1210
|
+
return authOp(env, AUTH_OPS.loginWithOTP, vars);
|
|
1190
1211
|
}
|
|
1191
|
-
async function
|
|
1192
|
-
return authOp(env, AUTH_OPS.
|
|
1212
|
+
async function refreshTokens(env, refreshToken) {
|
|
1213
|
+
return authOp(env, AUTH_OPS.refreshToken, { refreshToken });
|
|
1193
1214
|
}
|
|
1194
|
-
async function
|
|
1195
|
-
return authOp(env, AUTH_OPS.
|
|
1215
|
+
async function loginWithProvider(env, input) {
|
|
1216
|
+
return authOp(env, AUTH_OPS.loginWithProvider, { input });
|
|
1196
1217
|
}
|
|
1197
|
-
async function
|
|
1198
|
-
return authOp(env, AUTH_OPS.
|
|
1218
|
+
async function providerCallback(env, input) {
|
|
1219
|
+
return authOp(env, AUTH_OPS.providerCallback, { input });
|
|
1199
1220
|
}
|
|
1200
|
-
async function
|
|
1201
|
-
return authOp(env, AUTH_OPS.
|
|
1221
|
+
async function providerVerifyOTP(env, input) {
|
|
1222
|
+
return authOp(env, AUTH_OPS.providerVerifyOTP, { input });
|
|
1223
|
+
}
|
|
1224
|
+
function providerSignInRefusalOf(error) {
|
|
1225
|
+
if (!(error instanceof FoirRequestError)) return null;
|
|
1226
|
+
for (const entry of error.graphQLErrors ?? []) {
|
|
1227
|
+
const value = entry.extensions?.providerSignIn;
|
|
1228
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) continue;
|
|
1229
|
+
const { code, pending } = value;
|
|
1230
|
+
if (typeof code !== "string") continue;
|
|
1231
|
+
return typeof pending === "string" && pending !== "" ? { code, pending } : { code };
|
|
1232
|
+
}
|
|
1233
|
+
return null;
|
|
1234
|
+
}
|
|
1235
|
+
async function confirmProviderLink(env, input) {
|
|
1236
|
+
return authOp(env, AUTH_OPS.confirmProviderLink, { input });
|
|
1237
|
+
}
|
|
1238
|
+
async function resendProviderLinkCode(env, input) {
|
|
1239
|
+
return authOp(env, AUTH_OPS.resendProviderLinkCode, { input });
|
|
1202
1240
|
}
|
|
1203
1241
|
async function getAuthProviders(env) {
|
|
1204
1242
|
return authOp(env, AUTH_OPS.authProviders);
|
|
@@ -1209,23 +1247,23 @@ async function getAuthConfig(env) {
|
|
|
1209
1247
|
async function getDefaultAuthProvider(env) {
|
|
1210
1248
|
return authOp(env, AUTH_OPS.defaultAuthProvider);
|
|
1211
1249
|
}
|
|
1212
|
-
async function
|
|
1213
|
-
return authOp(env, AUTH_OPS.
|
|
1250
|
+
async function signupContext(env) {
|
|
1251
|
+
return authOp(env, AUTH_OPS.signupContext);
|
|
1214
1252
|
}
|
|
1215
|
-
async function
|
|
1216
|
-
return authOp(env, AUTH_OPS.
|
|
1253
|
+
async function joinWaitlist(env, email) {
|
|
1254
|
+
return authOp(env, AUTH_OPS.joinWaitlist, { email });
|
|
1217
1255
|
}
|
|
1218
|
-
async function
|
|
1219
|
-
return authOp(env, AUTH_OPS.
|
|
1256
|
+
async function requestPasswordReset(env, email) {
|
|
1257
|
+
return authOp(env, AUTH_OPS.requestPasswordReset, { email });
|
|
1220
1258
|
}
|
|
1221
|
-
async function
|
|
1222
|
-
return authOp(env, AUTH_OPS.
|
|
1259
|
+
async function resetPassword(env, vars) {
|
|
1260
|
+
return authOp(env, AUTH_OPS.resetPassword, vars);
|
|
1223
1261
|
}
|
|
1224
|
-
async function
|
|
1225
|
-
return authOp(env, AUTH_OPS.
|
|
1262
|
+
async function verifyEmail(env, token) {
|
|
1263
|
+
return authOp(env, AUTH_OPS.verifyEmail, { token });
|
|
1226
1264
|
}
|
|
1227
|
-
async function
|
|
1228
|
-
return authOp(env, AUTH_OPS.
|
|
1265
|
+
async function updatePassword(env, vars, options) {
|
|
1266
|
+
return authOp(env, AUTH_OPS.updatePassword, vars, options);
|
|
1229
1267
|
}
|
|
1230
1268
|
async function currentUser(env, options) {
|
|
1231
1269
|
return authOp(env, AUTH_OPS.currentUser, void 0, options);
|
|
@@ -1233,63 +1271,111 @@ async function currentUser(env, options) {
|
|
|
1233
1271
|
async function myProviderToken(env, providerKey, options) {
|
|
1234
1272
|
return authOp(env, AUTH_OPS.myProviderToken, { providerKey }, options);
|
|
1235
1273
|
}
|
|
1236
|
-
async function
|
|
1237
|
-
return authOp(env, AUTH_OPS.
|
|
1274
|
+
async function logout(env, options) {
|
|
1275
|
+
return authOp(env, AUTH_OPS.logout, void 0, options);
|
|
1238
1276
|
}
|
|
1239
1277
|
async function deleteMyAccount(env, vars, options) {
|
|
1240
1278
|
return authOp(env, AUTH_OPS.deleteMyAccount, vars, options);
|
|
1241
1279
|
}
|
|
1280
|
+
async function updateMyProfile(env, change, options) {
|
|
1281
|
+
return authOp(env, AUTH_OPS.updateMyProfile, change, options);
|
|
1282
|
+
}
|
|
1283
|
+
async function myAuthorizedApps(env, options) {
|
|
1284
|
+
return authOp(env, AUTH_OPS.myAuthorizedApps, void 0, options);
|
|
1285
|
+
}
|
|
1286
|
+
async function revokeAuthorizedApp(env, id, options) {
|
|
1287
|
+
return authOp(env, AUTH_OPS.revokeAuthorizedApp, { id }, options);
|
|
1288
|
+
}
|
|
1289
|
+
async function mySessions(env, options) {
|
|
1290
|
+
return authOp(env, AUTH_OPS.mySessions, void 0, options);
|
|
1291
|
+
}
|
|
1292
|
+
async function endMySession(env, id, options) {
|
|
1293
|
+
return authOp(env, AUTH_OPS.endMySession, { id }, options);
|
|
1294
|
+
}
|
|
1295
|
+
async function signOutEverywhere(env, vars = {}, options) {
|
|
1296
|
+
return authOp(env, AUTH_OPS.signOutEverywhere, vars, options);
|
|
1297
|
+
}
|
|
1298
|
+
async function createPersonalAccessToken(env, vars, options) {
|
|
1299
|
+
return authOp(env, AUTH_OPS.createPersonalAccessToken, vars, options);
|
|
1300
|
+
}
|
|
1301
|
+
async function mySignInMethods(env, options) {
|
|
1302
|
+
return authOp(env, AUTH_OPS.mySignInMethods, void 0, options);
|
|
1303
|
+
}
|
|
1304
|
+
async function connectSignInMethod(env, vars, options) {
|
|
1305
|
+
return authOp(env, AUTH_OPS.connectSignInMethod, vars, options);
|
|
1306
|
+
}
|
|
1307
|
+
async function disconnectSignInMethod(env, provider, options) {
|
|
1308
|
+
return authOp(env, AUTH_OPS.disconnectSignInMethod, { provider }, options);
|
|
1309
|
+
}
|
|
1310
|
+
async function myFactors(env, options) {
|
|
1311
|
+
return authOp(env, AUTH_OPS.myFactors, void 0, options);
|
|
1312
|
+
}
|
|
1313
|
+
async function beginStepUp(env, password, options) {
|
|
1314
|
+
return authOp(env, AUTH_OPS.beginStepUp, { password }, options);
|
|
1315
|
+
}
|
|
1316
|
+
async function completeStepUp(env, vars, options) {
|
|
1317
|
+
return authOp(env, AUTH_OPS.completeStepUp, vars, options);
|
|
1318
|
+
}
|
|
1319
|
+
async function beginFactorEnrollment(env, vars, options) {
|
|
1320
|
+
return authOp(env, AUTH_OPS.beginFactorEnrollment, vars, options);
|
|
1321
|
+
}
|
|
1322
|
+
async function completeFactorEnrollment(env, vars, options) {
|
|
1323
|
+
return authOp(env, AUTH_OPS.completeFactorEnrollment, vars, options);
|
|
1324
|
+
}
|
|
1325
|
+
async function removeFactor(env, vars, options) {
|
|
1326
|
+
return authOp(env, AUTH_OPS.removeFactor, vars, options);
|
|
1327
|
+
}
|
|
1328
|
+
async function makeRecoveryCodes(env, elevatedHandle, options) {
|
|
1329
|
+
return authOp(env, AUTH_OPS.makeRecoveryCodes, { elevatedHandle }, options);
|
|
1330
|
+
}
|
|
1242
1331
|
async function myOrganizations(env, vars, options) {
|
|
1243
1332
|
return authOp(env, AUTH_OPS.myOrganizations, vars ?? {}, options);
|
|
1244
1333
|
}
|
|
1245
|
-
async function selectOrganization(env, vars, options) {
|
|
1246
|
-
return authOp(env, AUTH_OPS.selectMyOrganization, vars, options);
|
|
1247
|
-
}
|
|
1248
1334
|
async function registerOrganization(env, vars, options) {
|
|
1249
|
-
return authOp(env, AUTH_OPS.
|
|
1335
|
+
return authOp(env, AUTH_OPS.registerOrganization, vars, options);
|
|
1250
1336
|
}
|
|
1251
1337
|
async function saveSession(adapter, result) {
|
|
1252
1338
|
await adapter.set(TOKEN_KEY, result.token);
|
|
1253
1339
|
await adapter.set(REFRESH_KEY, result.refreshToken);
|
|
1254
|
-
if (!result.
|
|
1255
|
-
return await
|
|
1340
|
+
if (!result.userId) {
|
|
1341
|
+
return await getSessionUser(adapter) ?? { id: "", email: "" };
|
|
1256
1342
|
}
|
|
1257
|
-
await adapter.set(
|
|
1343
|
+
await adapter.set(USER_ID_KEY, result.userId);
|
|
1258
1344
|
await adapter.set(EMAIL_KEY, result.email);
|
|
1259
|
-
return { id: result.
|
|
1345
|
+
return { id: result.userId, email: result.email };
|
|
1260
1346
|
}
|
|
1261
1347
|
async function clearSession(adapter) {
|
|
1262
1348
|
await adapter.unset(TOKEN_KEY);
|
|
1263
1349
|
await adapter.unset(REFRESH_KEY);
|
|
1264
|
-
await adapter.unset(
|
|
1350
|
+
await adapter.unset(USER_ID_KEY);
|
|
1265
1351
|
await adapter.unset(EMAIL_KEY);
|
|
1266
1352
|
}
|
|
1267
1353
|
async function getSessionToken(adapter) {
|
|
1268
1354
|
return await adapter.get(TOKEN_KEY) ?? null;
|
|
1269
1355
|
}
|
|
1270
|
-
async function
|
|
1271
|
-
const id = await adapter.get(
|
|
1356
|
+
async function getSessionUser(adapter) {
|
|
1357
|
+
const id = await adapter.get(USER_ID_KEY) ?? null;
|
|
1272
1358
|
const email = await adapter.get(EMAIL_KEY) ?? null;
|
|
1273
1359
|
if (!id) return null;
|
|
1274
1360
|
return { id, email: email ?? "" };
|
|
1275
1361
|
}
|
|
1276
|
-
async function
|
|
1277
|
-
return saveSession(adapter, await
|
|
1362
|
+
async function signInWithPassword(adapter, env, vars) {
|
|
1363
|
+
return saveSession(adapter, await login(env, vars));
|
|
1278
1364
|
}
|
|
1279
|
-
async function
|
|
1280
|
-
return saveSession(adapter, await
|
|
1365
|
+
async function signUpWithPassword(adapter, env, vars) {
|
|
1366
|
+
return saveSession(adapter, await register(env, vars));
|
|
1281
1367
|
}
|
|
1282
|
-
async function
|
|
1283
|
-
return saveSession(adapter, await
|
|
1368
|
+
async function signInWithOTP(adapter, env, vars) {
|
|
1369
|
+
return saveSession(adapter, await loginWithOTP(env, vars));
|
|
1284
1370
|
}
|
|
1285
1371
|
async function resetPasswordAndSignIn(adapter, env, vars) {
|
|
1286
|
-
return saveSession(adapter, await
|
|
1372
|
+
return saveSession(adapter, await resetPassword(env, vars));
|
|
1287
1373
|
}
|
|
1288
1374
|
async function signOut(adapter, env) {
|
|
1289
1375
|
const token = await getSessionToken(adapter);
|
|
1290
1376
|
if (token) {
|
|
1291
1377
|
try {
|
|
1292
|
-
await
|
|
1378
|
+
await logout(env, { bearerToken: token });
|
|
1293
1379
|
} catch {
|
|
1294
1380
|
}
|
|
1295
1381
|
}
|
|
@@ -1299,7 +1385,7 @@ async function refreshSession(adapter, env) {
|
|
|
1299
1385
|
const refreshToken = await adapter.get(REFRESH_KEY) ?? null;
|
|
1300
1386
|
if (!refreshToken) return null;
|
|
1301
1387
|
try {
|
|
1302
|
-
const result = await
|
|
1388
|
+
const result = await refreshTokens(env, refreshToken);
|
|
1303
1389
|
await saveSession(adapter, result);
|
|
1304
1390
|
return { token: result.token, refreshToken: result.refreshToken };
|
|
1305
1391
|
} catch {
|
|
@@ -1372,20 +1458,20 @@ async function authedOp(adapter, env, op, args) {
|
|
|
1372
1458
|
}
|
|
1373
1459
|
async function requireAuth(adapter, options) {
|
|
1374
1460
|
const token = await getSessionToken(adapter);
|
|
1375
|
-
let
|
|
1376
|
-
if (token && !
|
|
1377
|
-
|
|
1461
|
+
let user = await getSessionUser(adapter);
|
|
1462
|
+
if (token && !user && options.env) {
|
|
1463
|
+
user = await recoverSessionUser(adapter, options.env, token);
|
|
1378
1464
|
}
|
|
1379
|
-
if (!token || !
|
|
1465
|
+
if (!token || !user) {
|
|
1380
1466
|
await options.onUnauthenticated();
|
|
1381
1467
|
throw new Error("[foir] onUnauthenticated must not return");
|
|
1382
1468
|
}
|
|
1383
1469
|
if (options.resolveUser) {
|
|
1384
|
-
return options.resolveUser({ token,
|
|
1470
|
+
return options.resolveUser({ token, user });
|
|
1385
1471
|
}
|
|
1386
|
-
return
|
|
1472
|
+
return user;
|
|
1387
1473
|
}
|
|
1388
|
-
async function
|
|
1474
|
+
async function recoverSessionUser(adapter, env, token) {
|
|
1389
1475
|
let me;
|
|
1390
1476
|
try {
|
|
1391
1477
|
me = await currentUser(env, { bearerToken: token });
|
|
@@ -1393,18 +1479,10 @@ async function recoverSessionCustomer(adapter, env, token) {
|
|
|
1393
1479
|
return null;
|
|
1394
1480
|
}
|
|
1395
1481
|
if (!me?.id) return null;
|
|
1396
|
-
await adapter.set(
|
|
1482
|
+
await adapter.set(USER_ID_KEY, me.id);
|
|
1397
1483
|
await adapter.set(EMAIL_KEY, me.email);
|
|
1398
1484
|
return { id: me.id, email: me.email };
|
|
1399
1485
|
}
|
|
1400
|
-
async function requireAdmin(adapter, options) {
|
|
1401
|
-
const user = await requireAuth(adapter, options);
|
|
1402
|
-
if (!user.isAdmin) {
|
|
1403
|
-
await options.onForbidden();
|
|
1404
|
-
throw new Error("[foir] onForbidden must not return");
|
|
1405
|
-
}
|
|
1406
|
-
return user;
|
|
1407
|
-
}
|
|
1408
1486
|
|
|
1409
1487
|
// src/auth/grant-table.generated.ts
|
|
1410
1488
|
var GRANT_TABLE = [
|
|
@@ -1485,7 +1563,8 @@ var GRANT_TABLE = [
|
|
|
1485
1563
|
["roles:write", false, [], []],
|
|
1486
1564
|
["projects:read", false, [], []],
|
|
1487
1565
|
["projects:write", false, [], []],
|
|
1488
|
-
["project:
|
|
1566
|
+
["project:stand", false, [], []],
|
|
1567
|
+
["project:manage", false, [], ["project:stand", "records:read.all", "records:create", "records:write.all", "records:delete.all", "records:publish.all", "records:attribute", "search:read", "embeddings:read", "embeddings:write", "schemas:read", "drafts:read", "files:read.all", "files:write.all", "files:delete.all", "users:read.all", "identities:read", "users:create", "identities:delete", "users:write.all", "users:setup", "users:delete.all", "notifications:read.all", "notifications:write.all", "notifications:consent", "pushcredentials:read", "pushcredentials:write", "notes:read.all", "notes:write.all", "notes:create", "approvals:read", "approvals:write", "rooms:read", "rooms:write", "presence:read", "operations:read", "operations:execute", "operations:write", "appconfig:read", "schedules:read", "schedules:write", "hooks:read", "hooks:write", "auth:login_with_foir", "relyingparties:read", "relyingparties:write", "domains:read", "domains:write", "secrets:read", "secrets:list", "secrets:put", "secrets:delete", "appsecrets:read", "appsecrets:list", "appsecrets:put", "appsecrets:delete", "usersecrets:read", "usersecrets:list", "usersecrets:put", "usersecrets:delete", "opsecrets:read", "opsecrets:write", "settings:read", "settings:write", "designtokens:read", "designtokens:write", "models:read", "models:write", "configs:read", "configs:write", "signinproviders:read", "signinproviders:write", "apps:read", "apps:write", "events:read", "targeting:debug", "visitors:forward", "apikeys:read", "apikeys:write", "organizations:read", "organizations:create", "organizations:delete", "organizations:write", "organizations:reach", "members:read", "members:write", "roles:read", "roles:write", "projects:read", "projects:write", "audit:read"]],
|
|
1489
1568
|
["projects:create", false, [], []],
|
|
1490
1569
|
["projects:delete", false, [], []],
|
|
1491
1570
|
["tenants:read", false, [], []],
|
|
@@ -1498,12 +1577,14 @@ var GRANT_TABLE = [
|
|
|
1498
1577
|
["usage:read", false, [], []],
|
|
1499
1578
|
["controlkeys:read", false, [], []],
|
|
1500
1579
|
["controlkeys:write", false, [], []],
|
|
1580
|
+
["tenantsigninproviders:read", false, [], []],
|
|
1581
|
+
["tenantsigninproviders:write", false, [], []],
|
|
1501
1582
|
["tenanthooks:read", false, [], []],
|
|
1502
1583
|
["tenanthooks:write", false, [], []],
|
|
1503
1584
|
["apps:install", false, [], []],
|
|
1504
|
-
["tenant:manage", false, [], ["project:manage", "projects:create", "projects:delete", "tenants:read", "tenants:write", "tenants:delete", "export:run", "billing:read", "billing:manage", "usage:read", "controlkeys:read", "controlkeys:write", "tenanthooks:read", "tenanthooks:write", "apps:install"]],
|
|
1585
|
+
["tenant:manage", false, [], ["project:manage", "projects:create", "projects:delete", "tenants:read", "tenants:write", "tenants:delete", "export:run", "billing:read", "billing:manage", "usage:read", "controlkeys:read", "controlkeys:write", "tenanthooks:read", "tenanthooks:write", "tenantsigninproviders:read", "tenantsigninproviders:write", "apps:install"]],
|
|
1505
1586
|
["platform:read", false, [], []],
|
|
1506
|
-
["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace"
|
|
1587
|
+
["platform:manage", false, [], ["tenant:manage", "platform:read", "platform:create_workspace"]],
|
|
1507
1588
|
["platform:create_workspace", false, [], []],
|
|
1508
1589
|
["users:read", false, ["own", "named", "all"], []],
|
|
1509
1590
|
["users:write", false, ["own", "all"], []],
|
|
@@ -1602,15 +1683,15 @@ function holds(held, required) {
|
|
|
1602
1683
|
|
|
1603
1684
|
// src/auth/access.ts
|
|
1604
1685
|
function accessFrom(who) {
|
|
1605
|
-
const
|
|
1606
|
-
if (!
|
|
1686
|
+
const user = who?.credential?.user;
|
|
1687
|
+
if (!user?.id) return null;
|
|
1607
1688
|
return {
|
|
1608
|
-
|
|
1609
|
-
roles: Array.isArray(
|
|
1689
|
+
userId: user.id,
|
|
1690
|
+
roles: Array.isArray(user.roles) ? [...user.roles] : null,
|
|
1610
1691
|
scopes: [...who?.authority?.effective ?? []]
|
|
1611
1692
|
};
|
|
1612
1693
|
}
|
|
1613
|
-
async function
|
|
1694
|
+
async function userAccess(env, options) {
|
|
1614
1695
|
return accessFrom(await authOp(env, AUTH_OPS.whoami, void 0, options));
|
|
1615
1696
|
}
|
|
1616
1697
|
async function getSessionAccess(adapter, env) {
|
|
@@ -1643,11 +1724,11 @@ function denialMessage(reason, required) {
|
|
|
1643
1724
|
case "signed_out":
|
|
1644
1725
|
return "[foir] nobody is signed in";
|
|
1645
1726
|
case "role_not_held":
|
|
1646
|
-
return `[foir] the signed-in
|
|
1727
|
+
return `[foir] the signed-in user does not hold the role "${required.role}"`;
|
|
1647
1728
|
case "roles_unknown":
|
|
1648
|
-
return `[foir] the platform did not say which roles the signed-in
|
|
1729
|
+
return `[foir] the platform did not say which roles the signed-in user holds, so "${required.role}" could not be checked`;
|
|
1649
1730
|
case "scope_not_held":
|
|
1650
|
-
return `[foir] the signed-in
|
|
1731
|
+
return `[foir] the signed-in user's scopes do not cover "${required.scope}"`;
|
|
1651
1732
|
}
|
|
1652
1733
|
}
|
|
1653
1734
|
async function requireRole(adapter, env, key) {
|
|
@@ -1665,7 +1746,7 @@ async function requireScope(adapter, env, scope) {
|
|
|
1665
1746
|
}
|
|
1666
1747
|
|
|
1667
1748
|
// src/auth/hosted.ts
|
|
1668
|
-
var DEFAULT_COOKIE_NAME = "
|
|
1749
|
+
var DEFAULT_COOKIE_NAME = "foir_session";
|
|
1669
1750
|
var DEFAULT_SESSION_PATH = "/session/token";
|
|
1670
1751
|
var DEFAULT_END_SESSION_PATH = "/session/end-session";
|
|
1671
1752
|
function hostedLoginUrl(config, returnTo) {
|
|
@@ -1721,14 +1802,14 @@ async function fetchHostedSession(request, config) {
|
|
|
1721
1802
|
} catch {
|
|
1722
1803
|
return { outcome: "unavailable", reason: "malformed", httpStatus: res.status };
|
|
1723
1804
|
}
|
|
1724
|
-
if (!json.access_token || !json.
|
|
1805
|
+
if (!json.access_token || !json.user_id) {
|
|
1725
1806
|
return { outcome: "unavailable", reason: "malformed", httpStatus: res.status };
|
|
1726
1807
|
}
|
|
1727
1808
|
return {
|
|
1728
1809
|
outcome: "active",
|
|
1729
1810
|
session: {
|
|
1730
1811
|
token: json.access_token,
|
|
1731
|
-
|
|
1812
|
+
userId: json.user_id,
|
|
1732
1813
|
email: json.email ?? "",
|
|
1733
1814
|
expiresIn: typeof json.expires_in === "number" ? json.expires_in : 0
|
|
1734
1815
|
}
|
|
@@ -1804,14 +1885,14 @@ function createFoirSessionClient(config) {
|
|
|
1804
1885
|
} catch {
|
|
1805
1886
|
return cached;
|
|
1806
1887
|
}
|
|
1807
|
-
if (!json.access_token || !json.
|
|
1888
|
+
if (!json.access_token || !json.user_id) return cached;
|
|
1808
1889
|
const expiresIn = typeof json.expires_in === "number" ? json.expires_in : 0;
|
|
1809
1890
|
const next = {
|
|
1810
1891
|
token: json.access_token,
|
|
1811
1892
|
expiresAt: Date.now() + expiresIn * 1e3,
|
|
1812
|
-
user: {
|
|
1893
|
+
user: { userId: json.user_id, email: json.email ?? "" }
|
|
1813
1894
|
};
|
|
1814
|
-
const changed = cached?.user.
|
|
1895
|
+
const changed = cached?.user.userId !== next.user.userId;
|
|
1815
1896
|
cached = next;
|
|
1816
1897
|
scheduleRefresh(next.expiresAt);
|
|
1817
1898
|
if (changed) emit(next.user);
|
|
@@ -1879,51 +1960,69 @@ export {
|
|
|
1879
1960
|
FoirSessionExpiredError,
|
|
1880
1961
|
authedOp,
|
|
1881
1962
|
authedRequest,
|
|
1963
|
+
beginFactorEnrollment,
|
|
1964
|
+
beginStepUp,
|
|
1882
1965
|
clearSession,
|
|
1966
|
+
completeFactorEnrollment,
|
|
1967
|
+
completeStepUp,
|
|
1968
|
+
confirmProviderLink,
|
|
1969
|
+
connectSignInMethod,
|
|
1883
1970
|
createFoirSessionClient,
|
|
1971
|
+
createPersonalAccessToken,
|
|
1884
1972
|
currentUser,
|
|
1885
|
-
customerAccess,
|
|
1886
|
-
customerJoinWaitlist,
|
|
1887
|
-
customerLogin,
|
|
1888
|
-
customerLoginOTP,
|
|
1889
|
-
customerLoginWithProvider,
|
|
1890
|
-
customerLogout,
|
|
1891
|
-
customerProviderCallback,
|
|
1892
|
-
customerProviderVerifyOTP,
|
|
1893
|
-
customerRefreshToken,
|
|
1894
|
-
customerRegister,
|
|
1895
|
-
customerRequestOTP,
|
|
1896
|
-
customerRequestPasswordReset,
|
|
1897
|
-
customerResetPassword,
|
|
1898
|
-
customerSignupContext,
|
|
1899
|
-
customerUpdatePassword,
|
|
1900
|
-
customerVerifyEmail,
|
|
1901
1973
|
deleteMyAccount,
|
|
1974
|
+
disconnectSignInMethod,
|
|
1975
|
+
endMySession,
|
|
1902
1976
|
fetchHostedSession,
|
|
1903
1977
|
getAuthConfig,
|
|
1904
1978
|
getAuthProviders,
|
|
1905
1979
|
getDefaultAuthProvider,
|
|
1906
1980
|
getSessionAccess,
|
|
1907
|
-
getSessionCustomer,
|
|
1908
1981
|
getSessionToken,
|
|
1982
|
+
getSessionUser,
|
|
1909
1983
|
hasRole,
|
|
1910
1984
|
hasScope,
|
|
1911
1985
|
hostedLoginUrl,
|
|
1912
1986
|
hostedLogoutUrl,
|
|
1987
|
+
joinWaitlist,
|
|
1988
|
+
login,
|
|
1913
1989
|
loginWithOTP,
|
|
1914
|
-
|
|
1990
|
+
loginWithProvider,
|
|
1991
|
+
logout,
|
|
1992
|
+
makeRecoveryCodes,
|
|
1993
|
+
myAuthorizedApps,
|
|
1994
|
+
myFactors,
|
|
1915
1995
|
myOrganizations,
|
|
1916
1996
|
myProviderToken,
|
|
1997
|
+
mySessions,
|
|
1998
|
+
mySignInMethods,
|
|
1999
|
+
providerCallback,
|
|
2000
|
+
providerSignInRefusalOf,
|
|
2001
|
+
providerVerifyOTP,
|
|
1917
2002
|
refreshSession,
|
|
1918
2003
|
refreshSessionOnce,
|
|
2004
|
+
refreshTokens,
|
|
2005
|
+
register,
|
|
1919
2006
|
registerOrganization,
|
|
1920
|
-
|
|
1921
|
-
|
|
2007
|
+
removeFactor,
|
|
2008
|
+
requestOTP,
|
|
2009
|
+
requestPasswordReset,
|
|
1922
2010
|
requireAuth,
|
|
1923
2011
|
requireRole,
|
|
1924
2012
|
requireScope,
|
|
2013
|
+
resendProviderLinkCode,
|
|
2014
|
+
resetPassword,
|
|
1925
2015
|
resetPasswordAndSignIn,
|
|
2016
|
+
revokeAuthorizedApp,
|
|
1926
2017
|
saveSession,
|
|
1927
|
-
|
|
1928
|
-
|
|
2018
|
+
signInWithOTP,
|
|
2019
|
+
signInWithPassword,
|
|
2020
|
+
signOut,
|
|
2021
|
+
signOutEverywhere,
|
|
2022
|
+
signUpWithPassword,
|
|
2023
|
+
signupContext,
|
|
2024
|
+
updateMyProfile,
|
|
2025
|
+
updatePassword,
|
|
2026
|
+
userAccess,
|
|
2027
|
+
verifyEmail
|
|
1929
2028
|
};
|
package/dist/client.js
CHANGED
|
@@ -200,8 +200,8 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
|
|
|
200
200
|
downgrade;
|
|
201
201
|
constructor(downgrade) {
|
|
202
202
|
super(
|
|
203
|
-
`[foir] your
|
|
204
|
-
{ graphQLErrors: [{ message: "
|
|
203
|
+
`[foir] your user token was ${downgrade.userToken} (${downgrade.reason}), so the request was served as ${downgrade.servedAs}`,
|
|
204
|
+
{ graphQLErrors: [{ message: "user token rejected", extensions: { code: "AUTH_DOWNGRADED" } }] }
|
|
205
205
|
);
|
|
206
206
|
this.name = "FoirAuthDowngradedError";
|
|
207
207
|
this.downgrade = downgrade;
|
|
@@ -209,7 +209,7 @@ var FoirAuthDowngradedError = class extends FoirRequestError {
|
|
|
209
209
|
};
|
|
210
210
|
var FoirSessionExpiredError = class extends FoirRequestError {
|
|
211
211
|
constructor(options) {
|
|
212
|
-
super("[foir] the
|
|
212
|
+
super("[foir] the user session has expired and could not be refreshed: sign in again", {
|
|
213
213
|
cause: options?.cause,
|
|
214
214
|
graphQLErrors: [{ message: "session expired", extensions: { code: "SESSION_EXPIRED" } }]
|
|
215
215
|
});
|
|
@@ -226,7 +226,7 @@ function reportAuthDowngrade(envelope) {
|
|
|
226
226
|
if (warnedDowngrade === downgrade.reason) return;
|
|
227
227
|
warnedDowngrade = downgrade.reason;
|
|
228
228
|
console.warn(
|
|
229
|
-
`[foir] your
|
|
229
|
+
`[foir] your user token was ${downgrade.userToken} (${downgrade.reason}) \u2014 this request was served as ${downgrade.servedAs}, so auth-targeted content resolved to its anonymous variant. ` + (downgrade.reason === "expired" ? "Re-exchange the token and retry." : "Check which credential you are sending.")
|
|
230
230
|
);
|
|
231
231
|
}
|
|
232
232
|
function refusePrunedDocument(json, options) {
|