@stackframe/stack-shared 2.5.3 → 2.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/crud.d.ts +10 -3
- package/dist/helpers/production-mode.d.ts +6 -0
- package/dist/helpers/production-mode.js +43 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -4
- package/dist/interface/adminInterface.d.ts +28 -67
- package/dist/interface/adminInterface.js +63 -21
- package/dist/interface/clientInterface.d.ts +21 -133
- package/dist/interface/clientInterface.js +92 -118
- package/dist/interface/crud/api-keys.d.ts +134 -0
- package/dist/interface/crud/api-keys.js +61 -0
- package/dist/interface/crud/current-user.d.ts +47 -11
- package/dist/interface/crud/current-user.js +7 -3
- package/dist/interface/crud/email-templates.d.ts +53 -34
- package/dist/interface/crud/email-templates.js +37 -24
- package/dist/interface/crud/oauth.d.ts +8 -9
- package/dist/interface/crud/oauth.js +5 -5
- package/dist/interface/crud/projects.d.ts +446 -0
- package/dist/interface/crud/projects.js +110 -0
- package/dist/interface/crud/team-memberships.d.ts +22 -0
- package/dist/interface/crud/team-memberships.js +22 -0
- package/dist/interface/crud/team-permissions.d.ts +129 -0
- package/dist/interface/crud/team-permissions.js +83 -0
- package/dist/interface/crud/teams.d.ts +148 -0
- package/dist/interface/crud/teams.js +80 -0
- package/dist/interface/crud/users.d.ts +88 -33
- package/dist/interface/crud/users.js +22 -14
- package/dist/interface/crud-deprecated/api-keys.d.ts +134 -0
- package/dist/interface/crud-deprecated/api-keys.js +61 -0
- package/dist/interface/crud-deprecated/current-user.d.ts +127 -0
- package/dist/interface/crud-deprecated/current-user.js +49 -0
- package/dist/interface/crud-deprecated/email-templates.d.ts +75 -0
- package/dist/interface/crud-deprecated/email-templates.js +41 -0
- package/dist/interface/crud-deprecated/oauth.d.ts +24 -0
- package/dist/interface/crud-deprecated/oauth.js +12 -0
- package/dist/interface/crud-deprecated/projects.d.ts +440 -0
- package/dist/interface/crud-deprecated/projects.js +109 -0
- package/dist/interface/crud-deprecated/team-memberships.d.ts +22 -0
- package/dist/interface/crud-deprecated/team-memberships.js +22 -0
- package/dist/interface/crud-deprecated/team-permissions.d.ts +129 -0
- package/dist/interface/crud-deprecated/team-permissions.js +83 -0
- package/dist/interface/crud-deprecated/teams.d.ts +126 -0
- package/dist/interface/crud-deprecated/teams.js +78 -0
- package/dist/interface/crud-deprecated/users.d.ts +201 -0
- package/dist/interface/crud-deprecated/users.js +75 -0
- package/dist/interface/serverInterface.d.ts +33 -60
- package/dist/interface/serverInterface.js +74 -101
- package/dist/known-errors.d.ts +43 -26
- package/dist/known-errors.js +132 -85
- package/dist/schema-fields.d.ts +53 -4
- package/dist/schema-fields.js +156 -25
- package/dist/sessions.d.ts +1 -0
- package/dist/sessions.js +13 -3
- package/dist/utils/compile-time.d.ts +3 -1
- package/dist/utils/compile-time.js +3 -1
- package/dist/utils/errors.d.ts +8 -1
- package/dist/utils/errors.js +17 -4
- package/dist/utils/objects.d.ts +4 -1
- package/dist/utils/objects.js +16 -8
- package/dist/utils/promises.js +6 -1
- package/dist/utils/proxies.d.ts +1 -0
- package/dist/utils/proxies.js +65 -0
- package/dist/utils/react.d.ts +1 -1
- package/dist/utils/react.js +2 -2
- package/dist/utils/strings.js +3 -3
- package/dist/utils/urls.d.ts +1 -0
- package/dist/utils/urls.js +8 -0
- package/package.json +2 -2
- package/dist/utils/yup.d.ts +0 -3
- package/dist/utils/yup.js +0 -13
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as oauth from 'oauth4webapi';
|
|
2
|
-
import { Result } from "../utils/results";
|
|
3
|
-
import { KnownError, KnownErrors } from '../known-errors';
|
|
4
|
-
import { StackAssertionError, captureError, throwErr } from '../utils/errors';
|
|
5
2
|
import { cookies } from '@stackframe/stack-sc';
|
|
6
|
-
import {
|
|
3
|
+
import { KnownError, KnownErrors } from '../known-errors';
|
|
7
4
|
import { AccessToken, InternalSession } from '../sessions';
|
|
5
|
+
import { generateSecureRandomString } from '../utils/crypto';
|
|
6
|
+
import { StackAssertionError, throwErr } from '../utils/errors';
|
|
8
7
|
import { globalVar } from '../utils/globals';
|
|
8
|
+
import { Result } from "../utils/results";
|
|
9
9
|
export const sharedProviders = [
|
|
10
10
|
"shared-github",
|
|
11
11
|
"shared-google",
|
|
@@ -45,12 +45,12 @@ export class StackClientInterface {
|
|
|
45
45
|
const as = {
|
|
46
46
|
issuer: this.options.baseUrl,
|
|
47
47
|
algorithm: 'oauth2',
|
|
48
|
-
token_endpoint: this.getApiUrl() + '/auth/token',
|
|
48
|
+
token_endpoint: this.getApiUrl() + '/auth/oauth/token',
|
|
49
49
|
};
|
|
50
50
|
const client = {
|
|
51
51
|
client_id: this.projectId,
|
|
52
52
|
client_secret: this.options.publishableClientKey,
|
|
53
|
-
token_endpoint_auth_method: '
|
|
53
|
+
token_endpoint_auth_method: 'client_secret_post',
|
|
54
54
|
};
|
|
55
55
|
const rawResponse = await oauth.refreshTokenGrantRequest(as, client, refreshToken.token);
|
|
56
56
|
const response = await this._processResponse(rawResponse);
|
|
@@ -114,7 +114,7 @@ export class StackClientInterface {
|
|
|
114
114
|
const params = {
|
|
115
115
|
/**
|
|
116
116
|
* This fetch may be cross-origin, in which case we don't want to send cookies of the
|
|
117
|
-
* original origin (this is the default
|
|
117
|
+
* original origin (this is the default behavior of `credentials`).
|
|
118
118
|
*
|
|
119
119
|
* To help debugging, also omit cookies on same-origin, so we don't accidentally
|
|
120
120
|
* implement reliance on cookies anywhere.
|
|
@@ -129,10 +129,9 @@ export class StackClientInterface {
|
|
|
129
129
|
headers: {
|
|
130
130
|
"X-Stack-Override-Error-Status": "true",
|
|
131
131
|
"X-Stack-Project-Id": this.projectId,
|
|
132
|
-
"X-Stack-
|
|
132
|
+
"X-Stack-Access-Type": requestType,
|
|
133
133
|
"X-Stack-Client-Version": this.options.clientVersion,
|
|
134
134
|
...(tokenObj ? {
|
|
135
|
-
"Authorization": "StackSession " + tokenObj.accessToken.token,
|
|
136
135
|
"X-Stack-Access-Token": tokenObj.accessToken.token,
|
|
137
136
|
} : {}),
|
|
138
137
|
...(tokenObj?.refreshToken ? {
|
|
@@ -240,15 +239,15 @@ export class StackClientInterface {
|
|
|
240
239
|
}, null);
|
|
241
240
|
throw new StackAssertionError(await res.text());
|
|
242
241
|
}
|
|
243
|
-
async sendForgotPasswordEmail(email,
|
|
244
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/
|
|
242
|
+
async sendForgotPasswordEmail(email, callbackUrl) {
|
|
243
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/send-reset-code", {
|
|
245
244
|
method: "POST",
|
|
246
245
|
headers: {
|
|
247
246
|
"Content-Type": "application/json"
|
|
248
247
|
},
|
|
249
248
|
body: JSON.stringify({
|
|
250
249
|
email,
|
|
251
|
-
|
|
250
|
+
callback_url: callbackUrl,
|
|
252
251
|
}),
|
|
253
252
|
}, null, [KnownErrors.UserNotFound]);
|
|
254
253
|
if (res.status === "error") {
|
|
@@ -256,7 +255,7 @@ export class StackClientInterface {
|
|
|
256
255
|
}
|
|
257
256
|
}
|
|
258
257
|
async sendVerificationEmail(emailVerificationRedirectUrl, session) {
|
|
259
|
-
const res = await this.sendClientRequestAndCatchKnownError("/
|
|
258
|
+
const res = await this.sendClientRequestAndCatchKnownError("/contact-channels/send-verification-code", {
|
|
260
259
|
method: "POST",
|
|
261
260
|
headers: {
|
|
262
261
|
"Content-Type": "application/json"
|
|
@@ -269,15 +268,15 @@ export class StackClientInterface {
|
|
|
269
268
|
return res.error;
|
|
270
269
|
}
|
|
271
270
|
}
|
|
272
|
-
async sendMagicLinkEmail(email,
|
|
273
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/send-
|
|
271
|
+
async sendMagicLinkEmail(email, callbackUrl) {
|
|
272
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/otp/send-sign-in-code", {
|
|
274
273
|
method: "POST",
|
|
275
274
|
headers: {
|
|
276
275
|
"Content-Type": "application/json"
|
|
277
276
|
},
|
|
278
277
|
body: JSON.stringify({
|
|
279
278
|
email,
|
|
280
|
-
|
|
279
|
+
callback_url: callbackUrl,
|
|
281
280
|
}),
|
|
282
281
|
}, null, [KnownErrors.RedirectUrlNotWhitelisted]);
|
|
283
282
|
if (res.status === "error") {
|
|
@@ -285,7 +284,7 @@ export class StackClientInterface {
|
|
|
285
284
|
}
|
|
286
285
|
}
|
|
287
286
|
async resetPassword(options) {
|
|
288
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/password
|
|
287
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/reset", {
|
|
289
288
|
method: "POST",
|
|
290
289
|
headers: {
|
|
291
290
|
"Content-Type": "application/json"
|
|
@@ -297,13 +296,16 @@ export class StackClientInterface {
|
|
|
297
296
|
}
|
|
298
297
|
}
|
|
299
298
|
async updatePassword(options, session) {
|
|
300
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/update
|
|
299
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/update", {
|
|
301
300
|
method: "POST",
|
|
302
301
|
headers: {
|
|
303
302
|
"Content-Type": "application/json"
|
|
304
303
|
},
|
|
305
|
-
body: JSON.stringify(
|
|
306
|
-
|
|
304
|
+
body: JSON.stringify({
|
|
305
|
+
old_password: options.oldPassword,
|
|
306
|
+
new_password: options.newPassword,
|
|
307
|
+
}),
|
|
308
|
+
}, session, [KnownErrors.PasswordConfirmationMismatch, KnownErrors.PasswordRequirementsNotMet]);
|
|
307
309
|
if (res.status === "error") {
|
|
308
310
|
return res.error;
|
|
309
311
|
}
|
|
@@ -316,7 +318,7 @@ export class StackClientInterface {
|
|
|
316
318
|
return res;
|
|
317
319
|
}
|
|
318
320
|
async verifyEmail(code) {
|
|
319
|
-
const res = await this.sendClientRequestAndCatchKnownError("/
|
|
321
|
+
const res = await this.sendClientRequestAndCatchKnownError("/contact-channels/verify", {
|
|
320
322
|
method: "POST",
|
|
321
323
|
headers: {
|
|
322
324
|
"Content-Type": "application/json"
|
|
@@ -330,7 +332,7 @@ export class StackClientInterface {
|
|
|
330
332
|
}
|
|
331
333
|
}
|
|
332
334
|
async signInWithCredential(email, password, session) {
|
|
333
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/
|
|
335
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/sign-in", {
|
|
334
336
|
method: "POST",
|
|
335
337
|
headers: {
|
|
336
338
|
"Content-Type": "application/json"
|
|
@@ -345,12 +347,12 @@ export class StackClientInterface {
|
|
|
345
347
|
}
|
|
346
348
|
const result = await res.data.json();
|
|
347
349
|
return {
|
|
348
|
-
accessToken: result.
|
|
349
|
-
refreshToken: result.
|
|
350
|
+
accessToken: result.access_token,
|
|
351
|
+
refreshToken: result.refresh_token,
|
|
350
352
|
};
|
|
351
353
|
}
|
|
352
354
|
async signUpWithCredential(email, password, emailVerificationRedirectUrl, session) {
|
|
353
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/
|
|
355
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/password/sign-up", {
|
|
354
356
|
headers: {
|
|
355
357
|
"Content-Type": "application/json"
|
|
356
358
|
},
|
|
@@ -358,7 +360,7 @@ export class StackClientInterface {
|
|
|
358
360
|
body: JSON.stringify({
|
|
359
361
|
email,
|
|
360
362
|
password,
|
|
361
|
-
emailVerificationRedirectUrl,
|
|
363
|
+
verification_callback_url: emailVerificationRedirectUrl,
|
|
362
364
|
}),
|
|
363
365
|
}, session, [KnownErrors.UserEmailAlreadyExists, KnownErrors.PasswordRequirementsNotMet]);
|
|
364
366
|
if (res.status === "error") {
|
|
@@ -366,12 +368,12 @@ export class StackClientInterface {
|
|
|
366
368
|
}
|
|
367
369
|
const result = await res.data.json();
|
|
368
370
|
return {
|
|
369
|
-
accessToken: result.
|
|
370
|
-
refreshToken: result.
|
|
371
|
+
accessToken: result.access_token,
|
|
372
|
+
refreshToken: result.refresh_token,
|
|
371
373
|
};
|
|
372
374
|
}
|
|
373
|
-
async signInWithMagicLink(code
|
|
374
|
-
const res = await this.sendClientRequestAndCatchKnownError("/auth/
|
|
375
|
+
async signInWithMagicLink(code) {
|
|
376
|
+
const res = await this.sendClientRequestAndCatchKnownError("/auth/otp/sign-in", {
|
|
375
377
|
method: "POST",
|
|
376
378
|
headers: {
|
|
377
379
|
"Content-Type": "application/json"
|
|
@@ -385,9 +387,9 @@ export class StackClientInterface {
|
|
|
385
387
|
}
|
|
386
388
|
const result = await res.data.json();
|
|
387
389
|
return {
|
|
388
|
-
accessToken: result.
|
|
389
|
-
refreshToken: result.
|
|
390
|
-
newUser: result.
|
|
390
|
+
accessToken: result.access_token,
|
|
391
|
+
refreshToken: result.refresh_token,
|
|
392
|
+
newUser: result.new_user,
|
|
391
393
|
};
|
|
392
394
|
}
|
|
393
395
|
async getOAuthUrl(options) {
|
|
@@ -402,26 +404,26 @@ export class StackClientInterface {
|
|
|
402
404
|
// TODO fix
|
|
403
405
|
throw new Error("Admin session token is currently not supported for OAuth");
|
|
404
406
|
}
|
|
405
|
-
const url = new URL(this.getApiUrl() + "/auth/authorize/" + options.provider.toLowerCase());
|
|
407
|
+
const url = new URL(this.getApiUrl() + "/auth/oauth/authorize/" + options.provider.toLowerCase());
|
|
406
408
|
url.searchParams.set("client_id", this.projectId);
|
|
407
409
|
url.searchParams.set("client_secret", this.options.publishableClientKey);
|
|
408
410
|
url.searchParams.set("redirect_uri", updatedRedirectUrl.toString());
|
|
409
|
-
url.searchParams.set("scope", "
|
|
411
|
+
url.searchParams.set("scope", "legacy");
|
|
410
412
|
url.searchParams.set("state", options.state);
|
|
411
413
|
url.searchParams.set("grant_type", "authorization_code");
|
|
412
414
|
url.searchParams.set("code_challenge", options.codeChallenge);
|
|
413
415
|
url.searchParams.set("code_challenge_method", "S256");
|
|
414
416
|
url.searchParams.set("response_type", "code");
|
|
415
417
|
url.searchParams.set("type", options.type);
|
|
416
|
-
url.searchParams.set("
|
|
418
|
+
url.searchParams.set("error_redirect_url", options.errorRedirectUrl);
|
|
417
419
|
if (options.afterCallbackRedirectUrl) {
|
|
418
|
-
url.searchParams.set("
|
|
420
|
+
url.searchParams.set("after_callback_redirect_rrl", options.afterCallbackRedirectUrl);
|
|
419
421
|
}
|
|
420
422
|
if (options.type === "link") {
|
|
421
423
|
const tokens = await options.session.getPotentiallyExpiredTokens();
|
|
422
424
|
url.searchParams.set("token", tokens?.accessToken.token || "");
|
|
423
425
|
if (options.providerScope) {
|
|
424
|
-
url.searchParams.set("
|
|
426
|
+
url.searchParams.set("provider_scope", options.providerScope);
|
|
425
427
|
}
|
|
426
428
|
}
|
|
427
429
|
return url.toString();
|
|
@@ -434,12 +436,12 @@ export class StackClientInterface {
|
|
|
434
436
|
const as = {
|
|
435
437
|
issuer: this.options.baseUrl,
|
|
436
438
|
algorithm: 'oauth2',
|
|
437
|
-
token_endpoint: this.getApiUrl() + '/auth/token',
|
|
439
|
+
token_endpoint: this.getApiUrl() + '/auth/oauth/token',
|
|
438
440
|
};
|
|
439
441
|
const client = {
|
|
440
442
|
client_id: this.projectId,
|
|
441
443
|
client_secret: this.options.publishableClientKey,
|
|
442
|
-
token_endpoint_auth_method: '
|
|
444
|
+
token_endpoint_auth_method: 'client_secret_post',
|
|
443
445
|
};
|
|
444
446
|
const params = oauth.validateAuthResponse(as, client, options.oauthParams, options.state);
|
|
445
447
|
if (oauth.isOAuth2Error(params)) {
|
|
@@ -461,52 +463,66 @@ export class StackClientInterface {
|
|
|
461
463
|
async signOut(session) {
|
|
462
464
|
const tokenObj = await session.getPotentiallyExpiredTokens();
|
|
463
465
|
if (tokenObj) {
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
466
|
+
const resOrError = await this.sendClientRequestAndCatchKnownError("/auth/sessions/current", {
|
|
467
|
+
method: "DELETE",
|
|
468
|
+
headers: {
|
|
469
|
+
"Content-Type": "application/json"
|
|
470
|
+
},
|
|
471
|
+
body: JSON.stringify({}),
|
|
472
|
+
}, session, [KnownErrors.RefreshTokenError]);
|
|
473
|
+
if (resOrError.status === "error") {
|
|
474
|
+
if (resOrError.error instanceof KnownErrors.RefreshTokenError) {
|
|
475
|
+
// refresh token was already invalid, just continue like nothing happened
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
// this should never happen
|
|
479
|
+
throw new StackAssertionError("Unexpected error", { error: resOrError.error });
|
|
480
|
+
}
|
|
467
481
|
}
|
|
468
482
|
else {
|
|
469
|
-
|
|
470
|
-
method: "POST",
|
|
471
|
-
headers: {
|
|
472
|
-
"Content-Type": "application/json"
|
|
473
|
-
},
|
|
474
|
-
body: JSON.stringify({
|
|
475
|
-
refreshToken: tokenObj.refreshToken.token,
|
|
476
|
-
}),
|
|
477
|
-
}, session);
|
|
478
|
-
await res.json();
|
|
483
|
+
// user was signed out successfully, all good
|
|
479
484
|
}
|
|
480
485
|
}
|
|
481
486
|
session.markInvalid();
|
|
482
487
|
}
|
|
483
|
-
async getClientUserByToken(
|
|
484
|
-
const
|
|
488
|
+
async getClientUserByToken(session) {
|
|
489
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError("/users/me", {}, session, [KnownErrors.CannotGetOwnUserWithoutUser]);
|
|
490
|
+
if (responseOrError.status === "error") {
|
|
491
|
+
if (responseOrError.error instanceof KnownErrors.CannotGetOwnUserWithoutUser) {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
else {
|
|
495
|
+
throw new StackAssertionError("Unexpected uncaught error", { cause: responseOrError.error });
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
const response = responseOrError.data;
|
|
485
499
|
const user = await response.json();
|
|
486
500
|
if (!user)
|
|
487
|
-
|
|
488
|
-
return
|
|
501
|
+
throw new StackAssertionError("User endpoint returned null; this should never happen");
|
|
502
|
+
return user;
|
|
489
503
|
}
|
|
490
|
-
async
|
|
491
|
-
const response = await this.sendClientRequest(`/
|
|
492
|
-
const
|
|
493
|
-
return
|
|
504
|
+
async listCurrentUserTeamPermissions(options, session) {
|
|
505
|
+
const response = await this.sendClientRequest(`/team-permissions?team_id=${options.teamId}?user_id=me&recursive=${options.recursive}`, {}, session);
|
|
506
|
+
const result = await response.json();
|
|
507
|
+
return result.items;
|
|
494
508
|
}
|
|
495
|
-
async
|
|
496
|
-
const response = await this.sendClientRequest("/
|
|
497
|
-
const
|
|
498
|
-
return
|
|
509
|
+
async listCurrentUserTeams(session) {
|
|
510
|
+
const response = await this.sendClientRequest("/teams?user_id=me", {}, session);
|
|
511
|
+
const result = await response.json();
|
|
512
|
+
return result.items;
|
|
499
513
|
}
|
|
500
514
|
async getClientProject() {
|
|
501
|
-
const
|
|
515
|
+
const responseOrError = await this.sendClientRequestAndCatchKnownError("/projects/current", {}, null, [KnownErrors.ProjectNotFound]);
|
|
516
|
+
if (responseOrError.status === "error") {
|
|
517
|
+
return Result.error(responseOrError.error);
|
|
518
|
+
}
|
|
519
|
+
const response = responseOrError.data;
|
|
502
520
|
const project = await response.json();
|
|
503
|
-
if (!project)
|
|
504
|
-
return Result.error(new Error("Failed to get project"));
|
|
505
521
|
return Result.ok(project);
|
|
506
522
|
}
|
|
507
|
-
async
|
|
508
|
-
await this.sendClientRequest("/
|
|
509
|
-
method: "
|
|
523
|
+
async updateClientUser(update, session) {
|
|
524
|
+
await this.sendClientRequest("/users/me", {
|
|
525
|
+
method: "PATCH",
|
|
510
526
|
headers: {
|
|
511
527
|
"content-type": "application/json",
|
|
512
528
|
},
|
|
@@ -514,15 +530,15 @@ export class StackClientInterface {
|
|
|
514
530
|
}, session);
|
|
515
531
|
}
|
|
516
532
|
async listProjects(session) {
|
|
517
|
-
const response = await this.sendClientRequest("/projects", {}, session);
|
|
533
|
+
const response = await this.sendClientRequest("/internal/projects", {}, session);
|
|
518
534
|
if (!response.ok) {
|
|
519
535
|
throw new Error("Failed to list projects: " + response.status + " " + (await response.text()));
|
|
520
536
|
}
|
|
521
537
|
const json = await response.json();
|
|
522
|
-
return json;
|
|
538
|
+
return json.items;
|
|
523
539
|
}
|
|
524
540
|
async createProject(project, session) {
|
|
525
|
-
const fetchResponse = await this.sendClientRequest("/projects", {
|
|
541
|
+
const fetchResponse = await this.sendClientRequest("/internal/projects", {
|
|
526
542
|
method: "POST",
|
|
527
543
|
headers: {
|
|
528
544
|
"content-type": "application/json",
|
|
@@ -536,7 +552,7 @@ export class StackClientInterface {
|
|
|
536
552
|
return json;
|
|
537
553
|
}
|
|
538
554
|
async getAccessToken(provider, scope, session) {
|
|
539
|
-
const response = await this.sendClientRequest(`/auth/
|
|
555
|
+
const response = await this.sendClientRequest(`/auth/oauth/connected-account/${provider}/access-token`, {
|
|
540
556
|
method: "POST",
|
|
541
557
|
headers: {
|
|
542
558
|
"content-type": "application/json",
|
|
@@ -549,7 +565,7 @@ export class StackClientInterface {
|
|
|
549
565
|
};
|
|
550
566
|
}
|
|
551
567
|
async createTeamForCurrentUser(data, session) {
|
|
552
|
-
const response = await this.sendClientRequest("/
|
|
568
|
+
const response = await this.sendClientRequest("/teams?add_current_user=true", {
|
|
553
569
|
method: "POST",
|
|
554
570
|
headers: {
|
|
555
571
|
"content-type": "application/json",
|
|
@@ -559,45 +575,3 @@ export class StackClientInterface {
|
|
|
559
575
|
return await response.json();
|
|
560
576
|
}
|
|
561
577
|
}
|
|
562
|
-
export function getProductionModeErrors(project) {
|
|
563
|
-
const errors = [];
|
|
564
|
-
const fixUrlRelative = `/projects/${project.id}/domains`;
|
|
565
|
-
if (project.evaluatedConfig.allowLocalhost) {
|
|
566
|
-
errors.push({
|
|
567
|
-
errorMessage: "Localhost is not allowed in production mode, turn off 'Allow localhost' in project settings",
|
|
568
|
-
fixUrlRelative,
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
for (const { domain } of project.evaluatedConfig.domains) {
|
|
572
|
-
let url;
|
|
573
|
-
try {
|
|
574
|
-
url = new URL(domain);
|
|
575
|
-
}
|
|
576
|
-
catch (e) {
|
|
577
|
-
errors.push({
|
|
578
|
-
errorMessage: "Domain should be a valid URL: " + domain,
|
|
579
|
-
fixUrlRelative,
|
|
580
|
-
});
|
|
581
|
-
continue;
|
|
582
|
-
}
|
|
583
|
-
if (url.hostname === "localhost") {
|
|
584
|
-
errors.push({
|
|
585
|
-
errorMessage: "Domain should not be localhost: " + domain,
|
|
586
|
-
fixUrlRelative,
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
else if (!url.hostname.includes(".") || url.hostname.match(/\d+(\.\d+)*/)) {
|
|
590
|
-
errors.push({
|
|
591
|
-
errorMessage: "Not a valid domain" + domain,
|
|
592
|
-
fixUrlRelative,
|
|
593
|
-
});
|
|
594
|
-
}
|
|
595
|
-
else if (url.protocol !== "https:") {
|
|
596
|
-
errors.push({
|
|
597
|
-
errorMessage: "Domain should be HTTPS: " + domain,
|
|
598
|
-
fixUrlRelative,
|
|
599
|
-
});
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
return errors;
|
|
603
|
-
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { CrudTypeOf } from "../../crud";
|
|
2
|
+
export declare const apiKeysCreateInputSchema: import("yup").ObjectSchema<{
|
|
3
|
+
description: string;
|
|
4
|
+
expires_at_millis: number;
|
|
5
|
+
has_publishable_client_key: NonNullable<boolean | undefined>;
|
|
6
|
+
has_secret_server_key: NonNullable<boolean | undefined>;
|
|
7
|
+
has_super_secret_admin_key: NonNullable<boolean | undefined>;
|
|
8
|
+
}, import("yup").AnyObject, {
|
|
9
|
+
description: undefined;
|
|
10
|
+
expires_at_millis: undefined;
|
|
11
|
+
has_publishable_client_key: undefined;
|
|
12
|
+
has_secret_server_key: undefined;
|
|
13
|
+
has_super_secret_admin_key: undefined;
|
|
14
|
+
}, "">;
|
|
15
|
+
export declare const apiKeysCreateOutputSchema: import("yup").ObjectSchema<{
|
|
16
|
+
id: string;
|
|
17
|
+
description: string;
|
|
18
|
+
expires_at_millis: number;
|
|
19
|
+
manually_revoked_at_millis: number | undefined;
|
|
20
|
+
created_at_millis: number;
|
|
21
|
+
} & {
|
|
22
|
+
publishable_client_key: string | undefined;
|
|
23
|
+
secret_server_key: string | undefined;
|
|
24
|
+
super_secret_admin_key: string | undefined;
|
|
25
|
+
}, import("yup").AnyObject, {
|
|
26
|
+
id: undefined;
|
|
27
|
+
description: undefined;
|
|
28
|
+
expires_at_millis: undefined;
|
|
29
|
+
manually_revoked_at_millis: undefined;
|
|
30
|
+
created_at_millis: undefined;
|
|
31
|
+
publishable_client_key: undefined;
|
|
32
|
+
secret_server_key: undefined;
|
|
33
|
+
super_secret_admin_key: undefined;
|
|
34
|
+
}, "">;
|
|
35
|
+
export declare const apiKeysCrudAdminObfuscatedReadSchema: import("yup").ObjectSchema<{
|
|
36
|
+
id: string;
|
|
37
|
+
description: string;
|
|
38
|
+
expires_at_millis: number;
|
|
39
|
+
manually_revoked_at_millis: number | undefined;
|
|
40
|
+
created_at_millis: number;
|
|
41
|
+
} & {
|
|
42
|
+
publishable_client_key: {
|
|
43
|
+
last_four: string;
|
|
44
|
+
} | undefined;
|
|
45
|
+
secret_server_key: {
|
|
46
|
+
last_four: string;
|
|
47
|
+
} | undefined;
|
|
48
|
+
super_secret_admin_key: {
|
|
49
|
+
last_four: string;
|
|
50
|
+
} | undefined;
|
|
51
|
+
}, import("yup").AnyObject, {
|
|
52
|
+
id: undefined;
|
|
53
|
+
description: undefined;
|
|
54
|
+
expires_at_millis: undefined;
|
|
55
|
+
manually_revoked_at_millis: undefined;
|
|
56
|
+
created_at_millis: undefined;
|
|
57
|
+
publishable_client_key: {
|
|
58
|
+
last_four: undefined;
|
|
59
|
+
};
|
|
60
|
+
secret_server_key: {
|
|
61
|
+
last_four: undefined;
|
|
62
|
+
};
|
|
63
|
+
super_secret_admin_key: {
|
|
64
|
+
last_four: undefined;
|
|
65
|
+
};
|
|
66
|
+
}, "">;
|
|
67
|
+
export declare const apiKeysCrudAdminUpdateSchema: import("yup").ObjectSchema<{
|
|
68
|
+
description: string | undefined;
|
|
69
|
+
revoked: boolean | undefined;
|
|
70
|
+
}, import("yup").AnyObject, {
|
|
71
|
+
description: undefined;
|
|
72
|
+
revoked: undefined;
|
|
73
|
+
}, "">;
|
|
74
|
+
export declare const apiKeysCrudAdminDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
|
|
75
|
+
export declare const apiKeysCrud: import("../../crud").CrudSchemaFromOptions<{
|
|
76
|
+
adminReadSchema: import("yup").ObjectSchema<{
|
|
77
|
+
id: string;
|
|
78
|
+
description: string;
|
|
79
|
+
expires_at_millis: number;
|
|
80
|
+
manually_revoked_at_millis: number | undefined;
|
|
81
|
+
created_at_millis: number;
|
|
82
|
+
} & {
|
|
83
|
+
publishable_client_key: {
|
|
84
|
+
last_four: string;
|
|
85
|
+
} | undefined;
|
|
86
|
+
secret_server_key: {
|
|
87
|
+
last_four: string;
|
|
88
|
+
} | undefined;
|
|
89
|
+
super_secret_admin_key: {
|
|
90
|
+
last_four: string;
|
|
91
|
+
} | undefined;
|
|
92
|
+
}, import("yup").AnyObject, {
|
|
93
|
+
id: undefined;
|
|
94
|
+
description: undefined;
|
|
95
|
+
expires_at_millis: undefined;
|
|
96
|
+
manually_revoked_at_millis: undefined;
|
|
97
|
+
created_at_millis: undefined;
|
|
98
|
+
publishable_client_key: {
|
|
99
|
+
last_four: undefined;
|
|
100
|
+
};
|
|
101
|
+
secret_server_key: {
|
|
102
|
+
last_four: undefined;
|
|
103
|
+
};
|
|
104
|
+
super_secret_admin_key: {
|
|
105
|
+
last_four: undefined;
|
|
106
|
+
};
|
|
107
|
+
}, "">;
|
|
108
|
+
adminUpdateSchema: import("yup").ObjectSchema<{
|
|
109
|
+
description: string | undefined;
|
|
110
|
+
revoked: boolean | undefined;
|
|
111
|
+
}, import("yup").AnyObject, {
|
|
112
|
+
description: undefined;
|
|
113
|
+
revoked: undefined;
|
|
114
|
+
}, "">;
|
|
115
|
+
adminDeleteSchema: import("yup").MixedSchema<{} | undefined, import("yup").AnyObject, undefined, "">;
|
|
116
|
+
docs: {
|
|
117
|
+
adminList: {
|
|
118
|
+
hidden: true;
|
|
119
|
+
};
|
|
120
|
+
adminRead: {
|
|
121
|
+
hidden: true;
|
|
122
|
+
};
|
|
123
|
+
adminCreate: {
|
|
124
|
+
hidden: true;
|
|
125
|
+
};
|
|
126
|
+
adminUpdate: {
|
|
127
|
+
hidden: true;
|
|
128
|
+
};
|
|
129
|
+
adminDelete: {
|
|
130
|
+
hidden: true;
|
|
131
|
+
};
|
|
132
|
+
};
|
|
133
|
+
}>;
|
|
134
|
+
export type ApiKeysCrud = CrudTypeOf<typeof apiKeysCrud>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createCrud } from "../../crud";
|
|
2
|
+
import { yupBoolean, yupMixed, yupNumber, yupObject, yupString } from "../../schema-fields";
|
|
3
|
+
const baseApiKeysReadSchema = yupObject({
|
|
4
|
+
id: yupString().required(),
|
|
5
|
+
description: yupString().required(),
|
|
6
|
+
expires_at_millis: yupNumber().required(),
|
|
7
|
+
manually_revoked_at_millis: yupNumber().optional(),
|
|
8
|
+
created_at_millis: yupNumber().required(),
|
|
9
|
+
});
|
|
10
|
+
// Used for the result of the create endpoint
|
|
11
|
+
export const apiKeysCreateInputSchema = yupObject({
|
|
12
|
+
description: yupString().required(),
|
|
13
|
+
expires_at_millis: yupNumber().required(),
|
|
14
|
+
has_publishable_client_key: yupBoolean().required(),
|
|
15
|
+
has_secret_server_key: yupBoolean().required(),
|
|
16
|
+
has_super_secret_admin_key: yupBoolean().required(),
|
|
17
|
+
});
|
|
18
|
+
export const apiKeysCreateOutputSchema = baseApiKeysReadSchema.concat(yupObject({
|
|
19
|
+
publishable_client_key: yupString().optional(),
|
|
20
|
+
secret_server_key: yupString().optional(),
|
|
21
|
+
super_secret_admin_key: yupString().optional(),
|
|
22
|
+
}).required());
|
|
23
|
+
// Used for list, read and update endpoints after the initial creation
|
|
24
|
+
export const apiKeysCrudAdminObfuscatedReadSchema = baseApiKeysReadSchema.concat(yupObject({
|
|
25
|
+
publishable_client_key: yupObject({
|
|
26
|
+
last_four: yupString().required(),
|
|
27
|
+
}).optional(),
|
|
28
|
+
secret_server_key: yupObject({
|
|
29
|
+
last_four: yupString().required(),
|
|
30
|
+
}).optional(),
|
|
31
|
+
super_secret_admin_key: yupObject({
|
|
32
|
+
last_four: yupString().required(),
|
|
33
|
+
}).optional(),
|
|
34
|
+
}));
|
|
35
|
+
export const apiKeysCrudAdminUpdateSchema = yupObject({
|
|
36
|
+
description: yupString().optional(),
|
|
37
|
+
revoked: yupBoolean().oneOf([true]).optional(),
|
|
38
|
+
}).required();
|
|
39
|
+
export const apiKeysCrudAdminDeleteSchema = yupMixed();
|
|
40
|
+
export const apiKeysCrud = createCrud({
|
|
41
|
+
adminReadSchema: apiKeysCrudAdminObfuscatedReadSchema,
|
|
42
|
+
adminUpdateSchema: apiKeysCrudAdminUpdateSchema,
|
|
43
|
+
adminDeleteSchema: apiKeysCrudAdminDeleteSchema,
|
|
44
|
+
docs: {
|
|
45
|
+
adminList: {
|
|
46
|
+
hidden: true,
|
|
47
|
+
},
|
|
48
|
+
adminRead: {
|
|
49
|
+
hidden: true,
|
|
50
|
+
},
|
|
51
|
+
adminCreate: {
|
|
52
|
+
hidden: true,
|
|
53
|
+
},
|
|
54
|
+
adminUpdate: {
|
|
55
|
+
hidden: true,
|
|
56
|
+
},
|
|
57
|
+
adminDelete: {
|
|
58
|
+
hidden: true,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
});
|