faire-auth 1.0.3 → 1.1.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/dist/{adapter-factory-lKIOf2OR.mjs → adapter-factory-qPVW8x9-.mjs} +34 -36
- package/dist/{adapter-factory-D1I7joki.cjs → adapter-factory-u8r3oTez.cjs} +66 -68
- package/dist/adapters/drizzle-adapter/index.cjs +34 -40
- package/dist/adapters/drizzle-adapter/index.d.cts +4 -9
- package/dist/adapters/drizzle-adapter/index.d.mts +4 -9
- package/dist/adapters/drizzle-adapter/index.mjs +20 -26
- package/dist/adapters/index.cjs +11 -16
- package/dist/adapters/index.d.cts +11 -37
- package/dist/adapters/index.d.mts +11 -37
- package/dist/adapters/index.mjs +4 -13
- package/dist/adapters/kysely-adapter/index.cjs +270 -11
- package/dist/adapters/kysely-adapter/index.d.cts +9 -19
- package/dist/adapters/kysely-adapter/index.d.mts +9 -19
- package/dist/adapters/kysely-adapter/index.mjs +267 -9
- package/dist/adapters/memory-adapter/index.cjs +146 -9
- package/dist/adapters/memory-adapter/index.d.cts +4 -10
- package/dist/adapters/memory-adapter/index.d.mts +4 -10
- package/dist/adapters/memory-adapter/index.mjs +145 -9
- package/dist/adapters/mongodb-adapter/index.cjs +13 -21
- package/dist/adapters/mongodb-adapter/index.d.cts +3 -8
- package/dist/adapters/mongodb-adapter/index.d.mts +4 -9
- package/dist/adapters/mongodb-adapter/index.mjs +12 -20
- package/dist/adapters/prisma-adapter/index.cjs +12 -20
- package/dist/adapters/prisma-adapter/index.d.cts +4 -8
- package/dist/adapters/prisma-adapter/index.d.mts +4 -8
- package/dist/adapters/prisma-adapter/index.mjs +5 -13
- package/dist/adapters/test.cjs +86 -69
- package/dist/adapters/test.d.cts +7 -11
- package/dist/adapters/test.d.mts +7 -11
- package/dist/adapters/test.mjs +83 -66
- package/dist/api/index.cjs +3 -20
- package/dist/api/index.d.cts +2 -3
- package/dist/api/index.d.mts +2 -3
- package/dist/api/index.mjs +1 -20
- package/dist/api/middleware/index.cjs +4 -11
- package/dist/api/middleware/index.d.cts +3 -9
- package/dist/api/middleware/index.d.mts +3 -9
- package/dist/api/middleware/index.mjs +3 -11
- package/dist/{api-B4RDwBty.mjs → api-0f-F-Fi2.mjs} +292 -189
- package/dist/{api-CaRC1Gio.cjs → api-LjfH6hQi.cjs} +557 -452
- package/dist/{test-utils/bun-sqlite-dialect-BZBvHchL.cjs → bun-sqlite-dialect-BHkarnxN.cjs} +5 -9
- package/dist/{test-utils/bun-sqlite-dialect-BSWhhKNs.mjs → bun-sqlite-dialect-BiZBuEF6.mjs} +6 -9
- package/dist/client/index.cjs +8 -15
- package/dist/client/index.d.cts +9 -14
- package/dist/client/index.d.mts +9 -14
- package/dist/client/index.mjs +7 -15
- package/dist/client/lynx/index.cjs +10 -18
- package/dist/client/lynx/index.d.cts +402 -71
- package/dist/client/lynx/index.d.mts +402 -71
- package/dist/client/lynx/index.mjs +5 -13
- package/dist/client/plugins/index.cjs +3 -5
- package/dist/client/plugins/index.d.cts +5 -10
- package/dist/client/plugins/index.d.mts +5 -10
- package/dist/client/plugins/index.mjs +2 -4
- package/dist/client/react/index.cjs +6 -14
- package/dist/client/react/index.d.cts +402 -71
- package/dist/client/react/index.d.mts +402 -71
- package/dist/client/react/index.mjs +5 -13
- package/dist/client/solid/index.cjs +6 -14
- package/dist/client/solid/index.d.cts +393 -57
- package/dist/client/solid/index.d.mts +393 -57
- package/dist/client/solid/index.mjs +5 -13
- package/dist/client/svelte/index.cjs +5 -10
- package/dist/client/svelte/index.d.cts +400 -67
- package/dist/client/svelte/index.d.mts +400 -67
- package/dist/client/svelte/index.mjs +4 -10
- package/dist/client/vue/index.cjs +6 -14
- package/dist/client/vue/index.d.cts +401 -68
- package/dist/client/vue/index.d.mts +401 -68
- package/dist/client/vue/index.mjs +5 -13
- package/dist/{cookies-BTs1o992.mjs → cookies-D9aY_gJh.mjs} +25 -21
- package/dist/{cookies-BTl72THv.cjs → cookies-DQ52rcOy.cjs} +119 -115
- package/dist/crypto/index.cjs +10 -8
- package/dist/crypto/index.d.cts +5 -13
- package/dist/crypto/index.d.mts +5 -13
- package/dist/crypto/index.mjs +2 -5
- package/dist/{crypto-DH2Aa7jN.mjs → crypto-BH-hD0lJ.mjs} +7 -10
- package/dist/{crypto-DpSCnrTp.cjs → crypto-BITfWVwD.cjs} +24 -27
- package/dist/db/index.cjs +1135 -29
- package/dist/db/index.d.cts +1 -2
- package/dist/db/index.d.mts +1 -2
- package/dist/db/index.mjs +1115 -16
- package/dist/defu-D2h4S3X-.mjs +87 -0
- package/dist/defu-DWS5RPWt.cjs +134 -0
- package/dist/{email-verification-DI_0H4JC.cjs → email-verification-DOPnSgbI.cjs} +65 -71
- package/dist/{email-verification-C_lBu_JY.mjs → email-verification-YSR5n5lb.mjs} +23 -29
- package/dist/{hono-CO-zsqI-.mjs → hono-BAV2wQkK.mjs} +16 -33
- package/dist/hono-SVQuc5Ru.mjs +4 -0
- package/dist/hono-pgK4H_U1.cjs +9 -0
- package/dist/{hono-DnW5crl1.cjs → hono-tyFFJFdS.cjs} +42 -60
- package/dist/index-B86Cy0dE.d.cts +2 -0
- package/dist/index-B86Cy0dE.d.mts +2 -0
- package/dist/index.cjs +115 -150
- package/dist/index.d.cts +4 -5
- package/dist/index.d.mts +4 -5
- package/dist/index.mjs +46 -81
- package/dist/integrations/next-js.cjs +5 -9
- package/dist/integrations/next-js.d.cts +6 -14
- package/dist/integrations/next-js.d.mts +6 -14
- package/dist/integrations/next-js.mjs +4 -9
- package/dist/integrations/node.cjs +16 -14
- package/dist/integrations/node.d.cts +6 -14
- package/dist/integrations/node.d.mts +6 -14
- package/dist/integrations/node.mjs +15 -13
- package/dist/integrations/react-start.cjs +7 -11
- package/dist/integrations/react-start.d.cts +5 -13
- package/dist/integrations/react-start.d.mts +5 -13
- package/dist/integrations/react-start.mjs +6 -11
- package/dist/integrations/solid-start.cjs +3 -5
- package/dist/integrations/solid-start.d.cts +2 -5
- package/dist/integrations/solid-start.d.mts +2 -5
- package/dist/integrations/solid-start.mjs +2 -4
- package/dist/integrations/svelte-kit.cjs +6 -10
- package/dist/integrations/svelte-kit.d.cts +11 -23
- package/dist/integrations/svelte-kit.d.mts +11 -23
- package/dist/integrations/svelte-kit.mjs +5 -10
- package/dist/{ip-BjNYspCH.mjs → ip-6Lv2o42m.mjs} +4 -9
- package/dist/{ip-C17Qdq-G.cjs → ip-DPydExzV.cjs} +21 -27
- package/dist/{json--tl7Grvs.cjs → json-D3aq-nH2.cjs} +9 -13
- package/dist/{json-B1v2qRTQ.mjs → json-DooGMtnJ.mjs} +2 -5
- package/dist/{logged-CyGfp8_H.mjs → logged-B83SzMnJ.mjs} +6 -10
- package/dist/{logged-Dv3st5qc.cjs → logged-BIpCpnVY.cjs} +13 -18
- package/dist/{middleware-CE6OhDkq.mjs → middleware-Cakg4e1D.mjs} +2 -4
- package/dist/{middleware-CWvRH4EW.cjs → middleware-Cd-VkNxB.cjs} +17 -20
- package/dist/{node-sqlite-dialect-w4DAg0PH.mjs → node-sqlite-dialect-BMVOjEMh.mjs} +6 -9
- package/dist/{test-utils/node-sqlite-dialect-BgJqjBOu.cjs → node-sqlite-dialect-D3QPFROH.cjs} +5 -9
- package/dist/oauth2/index.cjs +166 -22
- package/dist/oauth2/index.d.cts +5 -17
- package/dist/oauth2/index.d.mts +5 -17
- package/dist/oauth2/index.mjs +156 -16
- package/dist/{origin-check-DjLTuZQ8.cjs → origin-check-BflGhEEN.cjs} +34 -38
- package/dist/{origin-check-8Gajklvh.mjs → origin-check-CRgs1M7k.mjs} +13 -16
- package/dist/{parser-B25ylT5u.mjs → parser-CqwvpF6l.cjs} +12 -10
- package/dist/{parser-B_wxvaAr.cjs → parser-DcKDjjHO.mjs} +7 -22
- package/dist/plugins/access/index.cjs +38 -4
- package/dist/plugins/access/index.d.cts +36 -2
- package/dist/plugins/access/index.d.mts +36 -2
- package/dist/plugins/access/index.mjs +36 -3
- package/dist/plugins/bearer/index.cjs +52 -7
- package/dist/plugins/bearer/index.d.cts +27 -4
- package/dist/plugins/bearer/index.d.mts +27 -4
- package/dist/plugins/bearer/index.mjs +51 -7
- package/dist/plugins/index.cjs +1385 -842
- package/dist/plugins/index.d.cts +489 -7566
- package/dist/plugins/index.d.mts +489 -7566
- package/dist/plugins/index.mjs +1118 -576
- package/dist/plugins/passkey/index.cjs +551 -15
- package/dist/plugins/passkey/index.d.cts +123 -4
- package/dist/plugins/passkey/index.d.mts +123 -4
- package/dist/plugins/passkey/index.mjs +547 -15
- package/dist/{chunk-BFnQceUY.mjs → rolldown-runtime-BKpuH2hG.mjs} +6 -7
- package/dist/{chunk-fPmz2rbM.cjs → rolldown-runtime-C_Pgydhf.cjs} +22 -24
- package/dist/{schema-DTIwLLmf.mjs → schema-CFCpv0tK.mjs} +3 -6
- package/dist/{schema-CirKflVs.cjs → schema-b-lKhMkG.cjs} +51 -55
- package/dist/{session-CM3rmOYF.mjs → session-BGjJgihS.mjs} +51 -74
- package/dist/{session-Cwrj4GfV.cjs → session-CzZSMmQC.cjs} +197 -219
- package/dist/shared.d.cts +1581 -0
- package/dist/shared.d.mts +1581 -0
- package/dist/social-providers/index.cjs +9 -9
- package/dist/social-providers/index.d.cts +1 -1
- package/dist/social-providers/index.d.mts +1 -1
- package/dist/social-providers/index.mjs +3 -5
- package/dist/social-providers-CjPww-qf.mjs +6 -0
- package/dist/social-providers-D7w_7Ym8.cjs +10 -0
- package/dist/{state-CvSihlVT.cjs → state-2OrNjOO-.cjs} +24 -24
- package/dist/{state-CQghgH9I.mjs → state-Dooeisfq.mjs} +17 -17
- package/dist/{bun-sqlite-dialect-DPgTzc0w.cjs → test-utils/bun-sqlite-dialect-BHkarnxN.cjs} +5 -9
- package/dist/{bun-sqlite-dialect-6NqeV3px.mjs → test-utils/bun-sqlite-dialect-BiZBuEF6.mjs} +6 -9
- package/dist/test-utils/index.cjs +8831 -7941
- package/dist/test-utils/index.d.cts +310 -12440
- package/dist/test-utils/index.d.mts +313 -12440
- package/dist/test-utils/index.mjs +8591 -7701
- package/dist/test-utils/{node-sqlite-dialect-DAQXiobH.mjs → node-sqlite-dialect-BMVOjEMh.mjs} +6 -9
- package/dist/{node-sqlite-dialect-DP11CB0y.cjs → test-utils/node-sqlite-dialect-D3QPFROH.cjs} +5 -9
- package/dist/types/index.d.cts +2 -3
- package/dist/types/index.d.mts +2 -3
- package/dist/types/index.mjs +1 -1
- package/dist/{url-BoUuoIwZ.mjs → url-CJtdrrUu.mjs} +12 -13
- package/dist/{url-Ce7CVaQD.cjs → url-DjCmCUHS.cjs} +42 -44
- package/dist/utils/cookies.cjs +29 -30
- package/dist/utils/cookies.d.cts +21 -25
- package/dist/utils/cookies.d.mts +20 -24
- package/dist/utils/cookies.mjs +2 -7
- package/dist/utils-C7OHyfHa.mjs +4 -0
- package/dist/utils-iX0Vy_UL.cjs +3 -0
- package/package.json +40 -30
- package/dist/access-BZ7-AbTM.cjs +0 -51
- package/dist/access-D0DRqUKC.mjs +0 -39
- package/dist/bearer-DDzrp5M7.cjs +0 -60
- package/dist/bearer-WZcs7gxL.mjs +0 -54
- package/dist/db-4tUsQJXd.mjs +0 -1119
- package/dist/db-ChMbb_U-.cjs +0 -1180
- package/dist/defu-BmOYq4PU.cjs +0 -34
- package/dist/defu-D9ZTXqlo.mjs +0 -28
- package/dist/hono-C14rpOEa.cjs +0 -13
- package/dist/hono-CoKYWnXA.mjs +0 -7
- package/dist/hono-D0VqxVy1.d.mts +0 -18
- package/dist/hono-DOM31WQz.d.cts +0 -18
- package/dist/index-BCTFWP_o.d.mts +0 -992
- package/dist/index-BDhhaE6Y.d.cts +0 -3
- package/dist/index-BVRfQy6L.d.mts +0 -992
- package/dist/index-Baarsq5J.d.mts +0 -33
- package/dist/index-By364WbF.d.cts +0 -992
- package/dist/index-BzWwMgxr.d.cts +0 -992
- package/dist/index-CF9iq55a.d.mts +0 -3
- package/dist/index-CJD2yB-W.d.cts +0 -33
- package/dist/index-CRt_fppq.d.mts +0 -41
- package/dist/index-CdLyn7qP.d.cts +0 -41
- package/dist/index-CsWF3f7U.d.cts +0 -13350
- package/dist/index-CzidsAyA.d.mts +0 -13350
- package/dist/index-DvW-GCcI.d.cts +0 -33
- package/dist/index-f-5OJ9yV.d.cts +0 -13350
- package/dist/index-rFv8Hxld.d.mts +0 -13350
- package/dist/index-ztVZPQdV.d.mts +0 -33
- package/dist/kysely-adapter-CtIdoHa8.mjs +0 -270
- package/dist/kysely-adapter-QZTx077T.cjs +0 -288
- package/dist/memory-adapter-17RZd5df.cjs +0 -154
- package/dist/memory-adapter-Dp4XdCZK.mjs +0 -148
- package/dist/oauth2-5RL4cVNS.cjs +0 -177
- package/dist/oauth2-C56wz-n9.mjs +0 -159
- package/dist/passkey-BTT-v5c-.cjs +0 -512
- package/dist/passkey-CzY_W2us.mjs +0 -505
- package/dist/request-1NL_1lyJ.mjs +0 -58
- package/dist/request-CPNlp-DK.cjs +0 -100
- package/dist/social-providers-B8RK5yqI.mjs +0 -9
- package/dist/social-providers-BmFOIIPk.cjs +0 -13
- package/dist/utils-44aDDP8f.cjs +0 -2
- package/dist/utils-D4vZd1-9.mjs +0 -4
package/dist/plugins/index.cjs
CHANGED
|
@@ -1,57 +1,49 @@
|
|
|
1
|
-
|
|
2
|
-
require(
|
|
3
|
-
require(
|
|
4
|
-
const
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
require(
|
|
8
|
-
const
|
|
9
|
-
const require_middleware = require(
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
require(
|
|
14
|
-
require(
|
|
15
|
-
require(
|
|
16
|
-
const
|
|
17
|
-
require(
|
|
18
|
-
require(
|
|
19
|
-
|
|
20
|
-
require(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const require_passkey = require('../passkey-BTT-v5c-.cjs');
|
|
25
|
-
let __faire_auth_core_env = require("@faire-auth/core/env");
|
|
26
|
-
let __faire_auth_core_error = require("@faire-auth/core/error");
|
|
27
|
-
let __faire_auth_core_factory = require("@faire-auth/core/factory");
|
|
28
|
-
let __faire_auth_core_static = require("@faire-auth/core/static");
|
|
29
|
-
let __faire_auth_core_utils = require("@faire-auth/core/utils");
|
|
30
|
-
let __faire_auth_core_datatypes = require("@faire-auth/core/datatypes");
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_rolldown_runtime = require("../rolldown-runtime-C_Pgydhf.cjs");
|
|
3
|
+
const require_plugins_access_index = require("./access/index.cjs");
|
|
4
|
+
const require_plugins_bearer_index = require("./bearer/index.cjs");
|
|
5
|
+
const require_session = require("../session-CzZSMmQC.cjs");
|
|
6
|
+
const require_origin_check = require("../origin-check-BflGhEEN.cjs");
|
|
7
|
+
const require_crypto = require("../crypto-BITfWVwD.cjs");
|
|
8
|
+
const require_cookies = require("../cookies-DQ52rcOy.cjs");
|
|
9
|
+
const require_middleware = require("../middleware-Cd-VkNxB.cjs");
|
|
10
|
+
const require_url = require("../url-DjCmCUHS.cjs");
|
|
11
|
+
const require_parser = require("../parser-CqwvpF6l.cjs");
|
|
12
|
+
const require_db_index = require("../db/index.cjs");
|
|
13
|
+
require("../utils-iX0Vy_UL.cjs");
|
|
14
|
+
const require_plugins_passkey_index = require("./passkey/index.cjs");
|
|
15
|
+
const require_schema = require("../schema-b-lKhMkG.cjs");
|
|
16
|
+
const require_json = require("../json-D3aq-nH2.cjs");
|
|
17
|
+
const require_email_verification = require("../email-verification-DOPnSgbI.cjs");
|
|
18
|
+
let _faire_auth_core_env = require("@faire-auth/core/env");
|
|
19
|
+
let _faire_auth_core_error = require("@faire-auth/core/error");
|
|
20
|
+
let _faire_auth_core_factory = require("@faire-auth/core/factory");
|
|
21
|
+
let _faire_auth_core_static = require("@faire-auth/core/static");
|
|
22
|
+
let _faire_auth_core_utils = require("@faire-auth/core/utils");
|
|
23
|
+
let _faire_auth_core_datatypes = require("@faire-auth/core/datatypes");
|
|
31
24
|
let zod = require("zod");
|
|
32
|
-
zod =
|
|
33
|
-
let
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
//#region src/plugins/magic-link/index.ts
|
|
25
|
+
zod = require_rolldown_runtime.__toESM(zod, 1);
|
|
26
|
+
let _faire_auth_core_db = require("@faire-auth/core/db");
|
|
27
|
+
let _faire_auth_core_crypto = require("@faire-auth/core/crypto");
|
|
28
|
+
// src/plugins/magic-link/index.ts
|
|
37
29
|
const magicLink = (options) => ({
|
|
38
30
|
id: "magic-link",
|
|
39
31
|
routes: {
|
|
40
|
-
signInMagicLink: require_session.createEndpoint((0,
|
|
32
|
+
signInMagicLink: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
41
33
|
operationId: "signInMagicLink",
|
|
42
34
|
method: "post",
|
|
43
35
|
path: "/sign-in/magic-link",
|
|
44
36
|
description: "Sign in with magic link",
|
|
45
|
-
request: (0,
|
|
46
|
-
email:
|
|
47
|
-
name:
|
|
48
|
-
callbackURL: (0,
|
|
37
|
+
request: (0, _faire_auth_core_factory.req)().bdy(zod.object({
|
|
38
|
+
email: _faire_auth_core_factory.emailSchema.openapi({ description: "Email address to send the magic link" }),
|
|
39
|
+
name: _faire_auth_core_factory.nameSchema,
|
|
40
|
+
callbackURL: (0, _faire_auth_core_factory.callbackURLSchema)(true).openapi({ description: "URL to redirect after magic link verification" })
|
|
49
41
|
})).bld(),
|
|
50
|
-
responses: (0,
|
|
42
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default).bld()
|
|
51
43
|
}), (_authOptions) => async (ctx) => {
|
|
52
44
|
const { email, name, callbackURL } = ctx.req.valid("json");
|
|
53
45
|
if (options.disableSignUp === true) {
|
|
54
|
-
if (!await ctx.get("context").internalAdapter.findUserByEmail(email)) throw new
|
|
46
|
+
if (!await ctx.get("context").internalAdapter.findUserByEmail(email)) throw new _faire_auth_core_error.APIError("BAD_REQUEST", { message: _faire_auth_core_error.BASE_ERROR_CODES.USER_NOT_FOUND });
|
|
55
47
|
}
|
|
56
48
|
const verificationToken = options.generateToken ? await options.generateToken(email) : (0, require_crypto.crypto_exports.generateRandomString)(32, "a-z", "A-Z");
|
|
57
49
|
await ctx.get("context").internalAdapter.createVerificationValue({
|
|
@@ -68,15 +60,15 @@ const magicLink = (options) => ({
|
|
|
68
60
|
url,
|
|
69
61
|
token: verificationToken
|
|
70
62
|
}, ctx.req);
|
|
71
|
-
return ctx.render({ success:
|
|
63
|
+
return ctx.render({ success: _faire_auth_core_static.True }, 200);
|
|
72
64
|
}),
|
|
73
|
-
verifyMagicLink: require_session.createEndpoint((0,
|
|
65
|
+
verifyMagicLink: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
74
66
|
operationId: "verifyMagicLink",
|
|
75
67
|
method: "get",
|
|
76
68
|
path: "/magic-link/verify",
|
|
77
69
|
description: "Verify magic link",
|
|
78
70
|
middleware: [require_origin_check.originCheck((ctx) => ctx.req.query("callbackURL"))],
|
|
79
|
-
request: (0,
|
|
71
|
+
request: (0, _faire_auth_core_factory.req)().qry(zod.object({
|
|
80
72
|
token: zod.string().openapi({
|
|
81
73
|
param: {
|
|
82
74
|
in: "query",
|
|
@@ -84,7 +76,7 @@ const magicLink = (options) => ({
|
|
|
84
76
|
},
|
|
85
77
|
description: "Verification token"
|
|
86
78
|
}),
|
|
87
|
-
callbackURL: (0,
|
|
79
|
+
callbackURL: (0, _faire_auth_core_factory.callbackURLSchema)(true).openapi({
|
|
88
80
|
param: {
|
|
89
81
|
in: "query",
|
|
90
82
|
name: "callbackURL"
|
|
@@ -92,7 +84,7 @@ const magicLink = (options) => ({
|
|
|
92
84
|
description: "URL to redirect after magic link verification, if not provided will return session"
|
|
93
85
|
})
|
|
94
86
|
})).bld(),
|
|
95
|
-
responses: (0,
|
|
87
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SESSION_USER].default).rdr("Redirect if provided callbackURL").bld()
|
|
96
88
|
}), (authOptions) => async (ctx) => {
|
|
97
89
|
const { token, callbackURL } = ctx.req.valid("query");
|
|
98
90
|
const toRedirectTo = callbackURL?.startsWith("http") === true ? `${authOptions.baseURL}${callbackURL}` : authOptions.baseURL;
|
|
@@ -104,15 +96,17 @@ const magicLink = (options) => ({
|
|
|
104
96
|
}
|
|
105
97
|
await ctx.get("context").internalAdapter.deleteVerificationValue(tokenValue.id);
|
|
106
98
|
const { email, name } = JSON.parse(tokenValue.value);
|
|
107
|
-
let user = await ctx.get("context").internalAdapter.findUserByEmail(email).then((res
|
|
108
|
-
if (!user)
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
99
|
+
let user = await ctx.get("context").internalAdapter.findUserByEmail(email).then((res) => res?.user);
|
|
100
|
+
if (!user) {
|
|
101
|
+
if (!(options.disableSignUp ?? false)) {
|
|
102
|
+
user = await ctx.get("context").internalAdapter.createUser({
|
|
103
|
+
email,
|
|
104
|
+
emailVerified: true,
|
|
105
|
+
...name != null && { name }
|
|
106
|
+
});
|
|
107
|
+
if (user == null) return ctx.redirect(`${toRedirectTo}?error=failed_to_create_user`, 302);
|
|
108
|
+
} else return ctx.redirect(`${toRedirectTo}?error=failed_to_create_user`, 302);
|
|
109
|
+
}
|
|
116
110
|
if (!user.emailVerified) await ctx.get("context").internalAdapter.updateUser(user.id, { emailVerified: true });
|
|
117
111
|
const session = await ctx.get("context").internalAdapter.createSession(user.id);
|
|
118
112
|
if (session == null) return ctx.redirect(`${toRedirectTo}?error=failed_to_create_session`, 302);
|
|
@@ -133,9 +127,7 @@ const magicLink = (options) => ({
|
|
|
133
127
|
max: options.rateLimit?.max ?? 5
|
|
134
128
|
}]
|
|
135
129
|
});
|
|
136
|
-
|
|
137
|
-
//#endregion
|
|
138
|
-
//#region src/plugins/oauth-proxy/index.ts
|
|
130
|
+
// src/plugins/oauth-proxy/index.ts
|
|
139
131
|
/**
|
|
140
132
|
* A proxy plugin, that allows you to proxy OAuth requests.
|
|
141
133
|
* Useful for development and preview deployments where
|
|
@@ -150,24 +142,24 @@ const oAuthProxy = (opts) => {
|
|
|
150
142
|
if (ctx.req.header("x-skip-oauth-proxy")) return;
|
|
151
143
|
const { origin: baseURL, pathname: basePath } = new URL(ctx.get("context").baseURL);
|
|
152
144
|
const url = resolveCurrentURL(ctx);
|
|
153
|
-
const productionURL = opts?.productionURL ??
|
|
145
|
+
const productionURL = opts?.productionURL ?? _faire_auth_core_env.env["FAIRE_AUTH_URL"];
|
|
154
146
|
console.log(productionURL, baseURL);
|
|
155
147
|
if (productionURL === baseURL) return;
|
|
156
148
|
input.data.callbackURL = `${url.origin}${basePath}/oauth-proxy-callback?callbackURL=${encodeURIComponent(input.data.callbackURL ?? ctx.get("context").baseURL)}`;
|
|
157
149
|
};
|
|
158
150
|
return {
|
|
159
151
|
id: "oauth-proxy",
|
|
160
|
-
routes: { oAuthProxy: require_session.createEndpoint((0,
|
|
152
|
+
routes: { oAuthProxy: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
161
153
|
operationId: "oAuthProxy",
|
|
162
154
|
method: "get",
|
|
163
155
|
path: "/oauth-proxy-callback",
|
|
164
156
|
isAction: false,
|
|
165
157
|
middleware: [require_origin_check.originCheck((ctx) => ctx.req.query("callbackURL"))],
|
|
166
|
-
request: (0,
|
|
167
|
-
callbackURL: (0,
|
|
158
|
+
request: (0, _faire_auth_core_factory.req)().qry(zod.object({
|
|
159
|
+
callbackURL: (0, _faire_auth_core_factory.callbackURLSchema)().openapi({ description: "The URL to redirect to after the proxy" }),
|
|
168
160
|
cookies: zod.string().openapi({ description: "The cookies to set after the proxy" })
|
|
169
161
|
})).bld(),
|
|
170
|
-
responses: (0,
|
|
162
|
+
responses: (0, _faire_auth_core_factory.res)().rdr().bld()
|
|
171
163
|
}), (options) => async (ctx) => {
|
|
172
164
|
const { callbackURL, cookies } = ctx.req.valid("query");
|
|
173
165
|
const context = ctx.get("context");
|
|
@@ -223,10 +215,7 @@ const oAuthProxy = (opts) => {
|
|
|
223
215
|
}] }
|
|
224
216
|
};
|
|
225
217
|
};
|
|
226
|
-
|
|
227
|
-
//#endregion
|
|
228
|
-
//#region src/plugins/organization/access/statement.ts
|
|
229
|
-
const defaultStatements = {
|
|
218
|
+
const defaultAc = require_plugins_access_index.createAccessControl({
|
|
230
219
|
organization: ["update", "delete"],
|
|
231
220
|
member: [
|
|
232
221
|
"create",
|
|
@@ -245,63 +234,57 @@ const defaultStatements = {
|
|
|
245
234
|
"update",
|
|
246
235
|
"delete"
|
|
247
236
|
]
|
|
248
|
-
};
|
|
249
|
-
const defaultAc = require_access.createAccessControl(defaultStatements);
|
|
250
|
-
const adminAc = defaultAc.newRole({
|
|
251
|
-
organization: ["update"],
|
|
252
|
-
invitation: ["create", "cancel"],
|
|
253
|
-
member: [
|
|
254
|
-
"create",
|
|
255
|
-
"update",
|
|
256
|
-
"delete"
|
|
257
|
-
],
|
|
258
|
-
team: [
|
|
259
|
-
"create",
|
|
260
|
-
"update",
|
|
261
|
-
"delete"
|
|
262
|
-
],
|
|
263
|
-
ac: [
|
|
264
|
-
"create",
|
|
265
|
-
"read",
|
|
266
|
-
"update",
|
|
267
|
-
"delete"
|
|
268
|
-
]
|
|
269
|
-
});
|
|
270
|
-
const ownerAc = defaultAc.newRole({
|
|
271
|
-
organization: ["update", "delete"],
|
|
272
|
-
member: [
|
|
273
|
-
"create",
|
|
274
|
-
"update",
|
|
275
|
-
"delete"
|
|
276
|
-
],
|
|
277
|
-
invitation: ["create", "cancel"],
|
|
278
|
-
team: [
|
|
279
|
-
"create",
|
|
280
|
-
"update",
|
|
281
|
-
"delete"
|
|
282
|
-
],
|
|
283
|
-
ac: [
|
|
284
|
-
"create",
|
|
285
|
-
"read",
|
|
286
|
-
"update",
|
|
287
|
-
"delete"
|
|
288
|
-
]
|
|
289
|
-
});
|
|
290
|
-
const memberAc = defaultAc.newRole({
|
|
291
|
-
organization: [],
|
|
292
|
-
member: [],
|
|
293
|
-
invitation: [],
|
|
294
|
-
team: [],
|
|
295
|
-
ac: ["read"]
|
|
296
237
|
});
|
|
297
238
|
const defaultRoles$1 = {
|
|
298
|
-
admin:
|
|
299
|
-
|
|
300
|
-
|
|
239
|
+
admin: defaultAc.newRole({
|
|
240
|
+
organization: ["update"],
|
|
241
|
+
invitation: ["create", "cancel"],
|
|
242
|
+
member: [
|
|
243
|
+
"create",
|
|
244
|
+
"update",
|
|
245
|
+
"delete"
|
|
246
|
+
],
|
|
247
|
+
team: [
|
|
248
|
+
"create",
|
|
249
|
+
"update",
|
|
250
|
+
"delete"
|
|
251
|
+
],
|
|
252
|
+
ac: [
|
|
253
|
+
"create",
|
|
254
|
+
"read",
|
|
255
|
+
"update",
|
|
256
|
+
"delete"
|
|
257
|
+
]
|
|
258
|
+
}),
|
|
259
|
+
owner: defaultAc.newRole({
|
|
260
|
+
organization: ["update", "delete"],
|
|
261
|
+
member: [
|
|
262
|
+
"create",
|
|
263
|
+
"update",
|
|
264
|
+
"delete"
|
|
265
|
+
],
|
|
266
|
+
invitation: ["create", "cancel"],
|
|
267
|
+
team: [
|
|
268
|
+
"create",
|
|
269
|
+
"update",
|
|
270
|
+
"delete"
|
|
271
|
+
],
|
|
272
|
+
ac: [
|
|
273
|
+
"create",
|
|
274
|
+
"read",
|
|
275
|
+
"update",
|
|
276
|
+
"delete"
|
|
277
|
+
]
|
|
278
|
+
}),
|
|
279
|
+
member: defaultAc.newRole({
|
|
280
|
+
organization: [],
|
|
281
|
+
member: [],
|
|
282
|
+
invitation: [],
|
|
283
|
+
team: [],
|
|
284
|
+
ac: ["read"]
|
|
285
|
+
})
|
|
301
286
|
};
|
|
302
|
-
|
|
303
|
-
//#endregion
|
|
304
|
-
//#region src/plugins/organization/adapter.ts
|
|
287
|
+
// src/plugins/organization/adapter.ts
|
|
305
288
|
const getOrgAdapter = (context, options) => {
|
|
306
289
|
const adapter = context.adapter;
|
|
307
290
|
return {
|
|
@@ -315,7 +298,7 @@ const getOrgAdapter = (context, options) => {
|
|
|
315
298
|
});
|
|
316
299
|
},
|
|
317
300
|
createOrganization: async (data) => {
|
|
318
|
-
const organization
|
|
301
|
+
const organization = await adapter.create({
|
|
319
302
|
model: "organization",
|
|
320
303
|
data: {
|
|
321
304
|
...data.organization,
|
|
@@ -323,8 +306,8 @@ const getOrgAdapter = (context, options) => {
|
|
|
323
306
|
}
|
|
324
307
|
});
|
|
325
308
|
return {
|
|
326
|
-
...organization
|
|
327
|
-
...organization
|
|
309
|
+
...organization,
|
|
310
|
+
...organization["metadata"] && typeof organization["metadata"] === "string" && { metadata: JSON.parse(organization["metadata"]) }
|
|
328
311
|
};
|
|
329
312
|
},
|
|
330
313
|
findMemberByEmail: async (data) => {
|
|
@@ -393,8 +376,8 @@ const getOrgAdapter = (context, options) => {
|
|
|
393
376
|
});
|
|
394
377
|
return {
|
|
395
378
|
members: members[0].map((member) => {
|
|
396
|
-
const user = users.find((user
|
|
397
|
-
if (!user) throw new
|
|
379
|
+
const user = users.find((user) => user.id === member.userId);
|
|
380
|
+
if (!user) throw new _faire_auth_core_error.FaireAuthError("Unexpected error: User not found for member");
|
|
398
381
|
return {
|
|
399
382
|
...member,
|
|
400
383
|
user: {
|
|
@@ -472,14 +455,14 @@ const getOrgAdapter = (context, options) => {
|
|
|
472
455
|
}
|
|
473
456
|
});
|
|
474
457
|
},
|
|
475
|
-
updateMember: async (memberId, role
|
|
458
|
+
updateMember: async (memberId, role) => {
|
|
476
459
|
return await adapter.update({
|
|
477
460
|
model: "member",
|
|
478
461
|
where: [{
|
|
479
462
|
field: "id",
|
|
480
463
|
value: memberId
|
|
481
464
|
}],
|
|
482
|
-
update: { role
|
|
465
|
+
update: { role }
|
|
483
466
|
});
|
|
484
467
|
},
|
|
485
468
|
deleteMember: async (memberId) => {
|
|
@@ -492,7 +475,7 @@ const getOrgAdapter = (context, options) => {
|
|
|
492
475
|
});
|
|
493
476
|
},
|
|
494
477
|
updateOrganization: async (organizationId, data) => {
|
|
495
|
-
const organization
|
|
478
|
+
const organization = await adapter.update({
|
|
496
479
|
model: "organization",
|
|
497
480
|
where: [{
|
|
498
481
|
field: "id",
|
|
@@ -503,10 +486,10 @@ const getOrgAdapter = (context, options) => {
|
|
|
503
486
|
metadata: typeof data["metadata"] === "object" ? JSON.stringify(data["metadata"]) : data["metadata"]
|
|
504
487
|
}
|
|
505
488
|
});
|
|
506
|
-
if (!organization
|
|
489
|
+
if (!organization) return null;
|
|
507
490
|
return {
|
|
508
|
-
...organization
|
|
509
|
-
metadata: organization
|
|
491
|
+
...organization,
|
|
492
|
+
metadata: organization["metadata"] ? require_parser.parseJSON(organization["metadata"]) : void 0
|
|
510
493
|
};
|
|
511
494
|
},
|
|
512
495
|
deleteOrganization: async (organizationId) => {
|
|
@@ -557,6 +540,9 @@ const getOrgAdapter = (context, options) => {
|
|
|
557
540
|
}]
|
|
558
541
|
});
|
|
559
542
|
},
|
|
543
|
+
/**
|
|
544
|
+
* @requires db
|
|
545
|
+
*/
|
|
560
546
|
findFullOrganization: async ({ organizationId, isSlug, includeTeams, membersLimit }) => {
|
|
561
547
|
const org = await adapter.findOne({
|
|
562
548
|
model: "organization",
|
|
@@ -604,7 +590,7 @@ const getOrgAdapter = (context, options) => {
|
|
|
604
590
|
const userMap = new Map(users.map((user) => [user.id, user]));
|
|
605
591
|
const membersWithUsers = members.map((member) => {
|
|
606
592
|
const user = userMap.get(member.userId);
|
|
607
|
-
if (!user) throw new
|
|
593
|
+
if (!user) throw new _faire_auth_core_error.FaireAuthError("Unexpected error: User not found for member");
|
|
608
594
|
return {
|
|
609
595
|
...member,
|
|
610
596
|
user: {
|
|
@@ -712,13 +698,13 @@ const getOrgAdapter = (context, options) => {
|
|
|
712
698
|
}]
|
|
713
699
|
});
|
|
714
700
|
},
|
|
715
|
-
createTeamInvitation: async ({ email, role
|
|
716
|
-
const expiresAt = (0,
|
|
701
|
+
createTeamInvitation: async ({ email, role, teamId, organizationId, inviterId, expiresIn = 1728e5 }) => {
|
|
702
|
+
const expiresAt = (0, _faire_auth_core_utils.getDate)(expiresIn);
|
|
717
703
|
return await adapter.create({
|
|
718
704
|
model: "invitation",
|
|
719
705
|
data: {
|
|
720
706
|
email,
|
|
721
|
-
role
|
|
707
|
+
role,
|
|
722
708
|
organizationId,
|
|
723
709
|
teamId,
|
|
724
710
|
inviterId,
|
|
@@ -838,7 +824,7 @@ const getOrgAdapter = (context, options) => {
|
|
|
838
824
|
});
|
|
839
825
|
},
|
|
840
826
|
createInvitation: async ({ invitation, user }) => {
|
|
841
|
-
const expiresAt = (0,
|
|
827
|
+
const expiresAt = (0, _faire_auth_core_utils.getDate)(options?.invitationExpiresIn || 172800, "sec");
|
|
842
828
|
return await adapter.create({
|
|
843
829
|
model: "invitation",
|
|
844
830
|
data: {
|
|
@@ -911,9 +897,7 @@ const getOrgAdapter = (context, options) => {
|
|
|
911
897
|
}
|
|
912
898
|
};
|
|
913
899
|
};
|
|
914
|
-
|
|
915
|
-
//#endregion
|
|
916
|
-
//#region src/plugins/organization/call.ts
|
|
900
|
+
// src/plugins/organization/call.ts
|
|
917
901
|
/**
|
|
918
902
|
* the orgMiddleware type-asserts and adds org options, roles, and a getSession function.
|
|
919
903
|
*/
|
|
@@ -923,16 +907,14 @@ const orgMiddleware = (orgOptions) => require_middleware.createMiddleware()(asyn
|
|
|
923
907
|
...defaultRoles$1,
|
|
924
908
|
...orgOptions?.roles
|
|
925
909
|
});
|
|
926
|
-
ctx.set("getSession", async (ctx
|
|
910
|
+
ctx.set("getSession", async (ctx) => await require_session.getSessionFromCtx(ctx).then((s) => {
|
|
927
911
|
if (s instanceof Response) return null;
|
|
928
912
|
return s;
|
|
929
913
|
}));
|
|
930
914
|
return await next();
|
|
931
915
|
});
|
|
932
916
|
const orgSessionMiddleware = require_session.sessionMiddleware();
|
|
933
|
-
|
|
934
|
-
//#endregion
|
|
935
|
-
//#region src/plugins/organization/error-codes.ts
|
|
917
|
+
// src/plugins/organization/error-codes.ts
|
|
936
918
|
const ORGANIZATION_ERROR_CODES = {
|
|
937
919
|
YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION: "You are not allowed to create a new organization",
|
|
938
920
|
YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS: "You have reached the maximum number of organizations",
|
|
@@ -990,9 +972,7 @@ const ORGANIZATION_ERROR_CODES = {
|
|
|
990
972
|
ROLE_NAME_IS_ALREADY_TAKEN: "That role name is already taken",
|
|
991
973
|
CANNOT_DELETE_A_PRE_DEFINED_ROLE: "Cannot delete a pre-defined role"
|
|
992
974
|
};
|
|
993
|
-
|
|
994
|
-
//#endregion
|
|
995
|
-
//#region src/plugins/organization/permission.ts
|
|
975
|
+
// src/plugins/organization/permission.ts
|
|
996
976
|
const hasPermissionFn = (input, acRoles) => {
|
|
997
977
|
if (!input.permissions && !input.permission) return false;
|
|
998
978
|
const roles = input.role.split(",");
|
|
@@ -1000,13 +980,11 @@ const hasPermissionFn = (input, acRoles) => {
|
|
|
1000
980
|
const isCreator = roles.includes(creatorRole);
|
|
1001
981
|
const allowCreatorsAllPermissions = input.allowCreatorAllPermissions || false;
|
|
1002
982
|
if (isCreator && allowCreatorsAllPermissions) return true;
|
|
1003
|
-
for (const role
|
|
983
|
+
for (const role of roles) if ((acRoles[role]?.authorize(input.permissions ?? input.permission))?.success) return true;
|
|
1004
984
|
return false;
|
|
1005
985
|
};
|
|
1006
986
|
let cacheAllRoles = /* @__PURE__ */ new Map();
|
|
1007
|
-
|
|
1008
|
-
//#endregion
|
|
1009
|
-
//#region src/plugins/organization/has-permission.ts
|
|
987
|
+
// src/plugins/organization/has-permission.ts
|
|
1010
988
|
const hasPermission = async (input, ctx) => {
|
|
1011
989
|
let acRoles = { ...input.options.roles || defaultRoles$1 };
|
|
1012
990
|
if (ctx && input.organizationId && input.options.dynamicAccessControl?.enabled && input.options.ac && !input.useMemoryCache) {
|
|
@@ -1017,23 +995,21 @@ const hasPermission = async (input, ctx) => {
|
|
|
1017
995
|
value: input.organizationId
|
|
1018
996
|
}]
|
|
1019
997
|
});
|
|
1020
|
-
for (const { role
|
|
1021
|
-
if (role
|
|
998
|
+
for (const { role, permission: permissionsString } of roles) {
|
|
999
|
+
if (role in acRoles) continue;
|
|
1022
1000
|
const result = zod.record(zod.string(), zod.array(zod.string())).safeParse(JSON.parse(permissionsString));
|
|
1023
1001
|
if (!result.success) {
|
|
1024
|
-
ctx.get("context").logger.error("[hasPermission] Invalid permissions for role " + role
|
|
1025
|
-
throw new
|
|
1002
|
+
ctx.get("context").logger.error("[hasPermission] Invalid permissions for role " + role, { permissions: JSON.parse(permissionsString) });
|
|
1003
|
+
throw new _faire_auth_core_error.APIError("INTERNAL_SERVER_ERROR", { message: "Invalid permissions for role " + role });
|
|
1026
1004
|
}
|
|
1027
|
-
acRoles[role
|
|
1005
|
+
acRoles[role] = input.options.ac.newRole(result.data);
|
|
1028
1006
|
}
|
|
1029
1007
|
}
|
|
1030
1008
|
if (input.useMemoryCache) acRoles = cacheAllRoles.get(input.organizationId) || acRoles;
|
|
1031
1009
|
cacheAllRoles.set(input.organizationId, acRoles);
|
|
1032
1010
|
return hasPermissionFn(input, acRoles);
|
|
1033
1011
|
};
|
|
1034
|
-
|
|
1035
|
-
//#endregion
|
|
1036
|
-
//#region src/plugins/organization/schema/base.ts
|
|
1012
|
+
// src/plugins/organization/schema/base.ts
|
|
1037
1013
|
const role$1 = zod.string().openapi({ description: "Role identifier for organization members (e.g., admin, member, owner)" });
|
|
1038
1014
|
const invitationStatus = zod.enum([
|
|
1039
1015
|
"pending",
|
|
@@ -1046,63 +1022,61 @@ const defaultRoles = [
|
|
|
1046
1022
|
"member",
|
|
1047
1023
|
"owner"
|
|
1048
1024
|
];
|
|
1049
|
-
|
|
1025
|
+
zod.union([zod.enum(defaultRoles), zod.array(zod.enum(defaultRoles))]).openapi({ description: "Default role options for organization members" });
|
|
1050
1026
|
const organizationSchema = zod.looseObject({
|
|
1051
|
-
id: zod.string().default(
|
|
1027
|
+
id: zod.string().default(_faire_auth_core_crypto.generateId).openapi({ description: "Unique identifier for the organization" }),
|
|
1052
1028
|
name: zod.string().openapi({ description: "Display name of the organization" }),
|
|
1053
1029
|
slug: zod.string().openapi({ description: "URL-friendly slug for the organization" }),
|
|
1054
1030
|
logo: zod.string().nullish().openapi({ description: "URL or path to the organization logo image" }),
|
|
1055
1031
|
metadata: zod.record(zod.string(), zod.unknown()).or(zod.string().transform((v) => JSON.parse(v))).nullish().openapi({ description: "Additional metadata for the organization as key-value pairs" }),
|
|
1056
|
-
createdAt:
|
|
1032
|
+
createdAt: _faire_auth_core_factory.dateOrIsoStringSchema.openapi({ description: "Timestamp when the organization was created" })
|
|
1057
1033
|
});
|
|
1058
1034
|
const organizationRoleSchema = zod.looseObject({
|
|
1059
|
-
id: zod.string().default(
|
|
1035
|
+
id: zod.string().default(_faire_auth_core_crypto.generateId),
|
|
1060
1036
|
organizationId: zod.string(),
|
|
1061
1037
|
role: zod.string(),
|
|
1062
1038
|
permission: zod.record(zod.string(), zod.array(zod.string())),
|
|
1063
|
-
createdAt:
|
|
1064
|
-
updatedAt:
|
|
1039
|
+
createdAt: _faire_auth_core_factory.dateOrIsoStringSchema.default(() => /* @__PURE__ */ new Date()),
|
|
1040
|
+
updatedAt: _faire_auth_core_factory.dateOrIsoStringSchema.optional()
|
|
1065
1041
|
});
|
|
1066
1042
|
const memberSchema = zod.looseObject({
|
|
1067
|
-
id: zod.string().default(
|
|
1043
|
+
id: zod.string().default(_faire_auth_core_crypto.generateId).openapi({ description: "Unique identifier for the organization member" }),
|
|
1068
1044
|
organizationId: zod.string().openapi({ description: "ID of the organization this member belongs to" }),
|
|
1069
1045
|
userId: zod.coerce.string().openapi({ description: "ID of the user who is a member of the organization" }),
|
|
1070
1046
|
role: role$1,
|
|
1071
|
-
createdAt:
|
|
1047
|
+
createdAt: _faire_auth_core_factory.dateOrIsoStringSchema.default(() => /* @__PURE__ */ new Date()).openapi({ description: "Timestamp when the member was added to the organization" })
|
|
1072
1048
|
});
|
|
1073
1049
|
const invitationSchema = zod.looseObject({
|
|
1074
|
-
id: zod.string().default(
|
|
1050
|
+
id: zod.string().default(_faire_auth_core_crypto.generateId).openapi({ description: "Unique identifier for the invitation" }),
|
|
1075
1051
|
organizationId: zod.string().openapi({ description: "The organization ID to invite the user to" }),
|
|
1076
|
-
email:
|
|
1052
|
+
email: _faire_auth_core_factory.emailSchema.openapi({ description: "The email address of the user to invite" }),
|
|
1077
1053
|
role: role$1.openapi({ description: "The role(s) to assign to the user. It can be `admin`, `member`, or `guest`. Eg: \"member\"" }),
|
|
1078
1054
|
status: invitationStatus,
|
|
1079
1055
|
teamId: zod.string().optional().openapi({ description: "The team ID to invite the user to" }),
|
|
1080
1056
|
inviterId: zod.string().openapi({ description: "ID of the user who sent the invitation" }),
|
|
1081
|
-
expiresAt:
|
|
1057
|
+
expiresAt: _faire_auth_core_factory.dateOrIsoStringSchema.openapi({ description: "Timestamp when the invitation expires" })
|
|
1082
1058
|
});
|
|
1083
1059
|
const teamSchema = zod.looseObject({
|
|
1084
|
-
id: zod.string().default(
|
|
1060
|
+
id: zod.string().default(_faire_auth_core_crypto.generateId).openapi({ description: "Unique identifier of the team" }),
|
|
1085
1061
|
name: zod.string().min(1).openapi({ description: "Name of the team" }),
|
|
1086
1062
|
organizationId: zod.string().openapi({ description: "ID of the organization the team belongs to" }),
|
|
1087
|
-
createdAt:
|
|
1088
|
-
updatedAt:
|
|
1063
|
+
createdAt: _faire_auth_core_factory.dateOrIsoStringSchema.openapi({ description: "Timestamp when the team was created" }),
|
|
1064
|
+
updatedAt: _faire_auth_core_factory.dateOrIsoStringSchema.optional().openapi({ description: "Timestamp when the team was last updated" })
|
|
1089
1065
|
});
|
|
1090
1066
|
const teamMemberSchema = zod.looseObject({
|
|
1091
|
-
id: zod.string().default(
|
|
1067
|
+
id: zod.string().default(_faire_auth_core_crypto.generateId).openapi({ description: "Unique identifier for the team member" }),
|
|
1092
1068
|
teamId: zod.string().openapi({ description: "ID of the team this member belongs to" }),
|
|
1093
1069
|
userId: zod.string().openapi({ description: "ID of the user who is a member of the team" }),
|
|
1094
|
-
createdAt:
|
|
1070
|
+
createdAt: _faire_auth_core_factory.dateOrIsoStringSchema.default(() => /* @__PURE__ */ new Date()).openapi({ description: "Timestamp when the member was added to the team" })
|
|
1095
1071
|
});
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
//#region src/plugins/organization/routes/crud-access-control.ts
|
|
1099
|
-
const normalizeRoleName = (role$2) => role$2.toLowerCase();
|
|
1072
|
+
// src/plugins/organization/routes/crud-access-control.ts
|
|
1073
|
+
const normalizeRoleName = (role) => role.toLowerCase();
|
|
1100
1074
|
const DEFAULT_MAXIMUM_ROLES_PER_ORGANIZATION = Number.POSITIVE_INFINITY;
|
|
1101
1075
|
const getAdditionalFields = (options, shouldBePartial = false) => {
|
|
1102
1076
|
let additionalFields = options?.schema?.organizationRole?.additionalFields || {};
|
|
1103
1077
|
if (shouldBePartial) for (const key in additionalFields) additionalFields[key].required = false;
|
|
1104
1078
|
return {
|
|
1105
|
-
additionalFieldsSchema:
|
|
1079
|
+
additionalFieldsSchema: require_db_index.toZodSchema({
|
|
1106
1080
|
fields: additionalFields,
|
|
1107
1081
|
isClientSide: true
|
|
1108
1082
|
}),
|
|
@@ -1121,33 +1095,33 @@ const createOrgRole = (options) => {
|
|
|
1121
1095
|
const createOrgRoleResponseSchema = zod.object({
|
|
1122
1096
|
roleData: organizationRoleSchema.extend(additionalFieldsSchema.shape),
|
|
1123
1097
|
statements: zod.record(zod.string(), zod.array(zod.string()))
|
|
1124
|
-
}).transform(
|
|
1125
|
-
return require_session.createEndpoint((0,
|
|
1098
|
+
}).transform(_faire_auth_core_utils.toSuccess);
|
|
1099
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
1126
1100
|
operationId: "createOrgRole",
|
|
1127
1101
|
method: "post",
|
|
1128
1102
|
path: "/organization/create-role",
|
|
1129
1103
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
1130
|
-
request: (0,
|
|
1131
|
-
responses: (0,
|
|
1104
|
+
request: (0, _faire_auth_core_factory.req)().bdy(createOrgRoleRequestSchema).bld(),
|
|
1105
|
+
responses: (0, _faire_auth_core_factory.res)(createOrgRoleResponseSchema).err(400).err(403, "Not a member or not allowed to create a role", _faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.ERROR].default.extend({ missingPermissions: zod.array(zod.custom((v) => typeof v === "string" && v.includes(":"))).optional() })).err(501).bld()
|
|
1132
1106
|
}), (_authOptions) => async (ctx) => {
|
|
1133
1107
|
const { session, user } = ctx.get("session");
|
|
1134
|
-
const { organizationId = session.activeOrganizationId, role
|
|
1108
|
+
const { organizationId = session.activeOrganizationId, role, permission, additionalFields } = ctx.req.valid("json");
|
|
1135
1109
|
const ac = options.ac;
|
|
1136
1110
|
if (!ac) {
|
|
1137
1111
|
ctx.get("context").logger.error(`[Dynamic Access Control] The organization plugin is missing a pre-defined ac instance.`, `\nPlease refer to the documentation here: https://faire-auth.com/docs/plugins/organization#dynamic-access-control`);
|
|
1138
1112
|
return ctx.render({
|
|
1139
|
-
success:
|
|
1113
|
+
success: _faire_auth_core_static.False,
|
|
1140
1114
|
message: ORGANIZATION_ERROR_CODES.MISSING_AC_INSTANCE
|
|
1141
1115
|
}, 501);
|
|
1142
1116
|
}
|
|
1143
1117
|
if (!organizationId) {
|
|
1144
1118
|
ctx.get("context").logger.error(`[Dynamic Access Control] The session is missing an active organization id to create a role. Either set an active org id, or pass an organizationId in the request body.`);
|
|
1145
1119
|
return ctx.render({
|
|
1146
|
-
success:
|
|
1120
|
+
success: _faire_auth_core_static.False,
|
|
1147
1121
|
message: ORGANIZATION_ERROR_CODES.YOU_MUST_BE_IN_AN_ORGANIZATION_TO_CREATE_A_ROLE
|
|
1148
1122
|
}, 400);
|
|
1149
1123
|
}
|
|
1150
|
-
const roleName = normalizeRoleName(role
|
|
1124
|
+
const roleName = normalizeRoleName(role);
|
|
1151
1125
|
const takenRes = await checkIfRoleNameIsTakenByPreDefinedRole({
|
|
1152
1126
|
role: roleName,
|
|
1153
1127
|
organizationId,
|
|
@@ -1175,7 +1149,7 @@ const createOrgRole = (options) => {
|
|
|
1175
1149
|
organizationId
|
|
1176
1150
|
});
|
|
1177
1151
|
return ctx.render({
|
|
1178
|
-
success:
|
|
1152
|
+
success: _faire_auth_core_static.False,
|
|
1179
1153
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
1180
1154
|
}, 403);
|
|
1181
1155
|
}
|
|
@@ -1191,7 +1165,7 @@ const createOrgRole = (options) => {
|
|
|
1191
1165
|
role: member.role
|
|
1192
1166
|
});
|
|
1193
1167
|
return ctx.render({
|
|
1194
|
-
success:
|
|
1168
|
+
success: _faire_auth_core_static.False,
|
|
1195
1169
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_CREATE_A_ROLE
|
|
1196
1170
|
}, 403);
|
|
1197
1171
|
}
|
|
@@ -1212,7 +1186,7 @@ const createOrgRole = (options) => {
|
|
|
1212
1186
|
rolesInDB
|
|
1213
1187
|
});
|
|
1214
1188
|
return ctx.render({
|
|
1215
|
-
success:
|
|
1189
|
+
success: _faire_auth_core_static.False,
|
|
1216
1190
|
message: ORGANIZATION_ERROR_CODES.TOO_MANY_ROLES
|
|
1217
1191
|
}, 400);
|
|
1218
1192
|
}
|
|
@@ -1262,13 +1236,13 @@ const createOrgRole = (options) => {
|
|
|
1262
1236
|
const deleteOrgRole = (options) => {
|
|
1263
1237
|
const deleteOrgRoleRequestSchema = zod.object({ organizationId: zod.string().optional().openapi({ description: "The id of the organization to create the role in. If not provided, the user's active organization will be used." }) }).and(zod.union([zod.object({ roleName: zod.string().openapi({ description: "The name of the role to delete" }) }), zod.object({ roleId: zod.string().openapi({ description: "The id of the role to delete" }) })]));
|
|
1264
1238
|
const deleteOrgRoleResponseSchema = zod.object({ success: zod.literal(true) });
|
|
1265
|
-
return require_session.createEndpoint((0,
|
|
1239
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
1266
1240
|
operationId: "deleteOrgRole",
|
|
1267
1241
|
method: "post",
|
|
1268
1242
|
path: "/organization/delete-role",
|
|
1269
1243
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
1270
|
-
request: (0,
|
|
1271
|
-
responses: (0,
|
|
1244
|
+
request: (0, _faire_auth_core_factory.req)().bdy(deleteOrgRoleRequestSchema).bld(),
|
|
1245
|
+
responses: (0, _faire_auth_core_factory.res)(deleteOrgRoleResponseSchema).err(400).err(403).bld()
|
|
1272
1246
|
}), (_authOptions) => async (ctx) => {
|
|
1273
1247
|
const { session, user } = ctx.get("session");
|
|
1274
1248
|
const validData = ctx.req.valid("json");
|
|
@@ -1278,7 +1252,7 @@ const deleteOrgRole = (options) => {
|
|
|
1278
1252
|
if (!organizationId) {
|
|
1279
1253
|
ctx.get("context").logger.error(`[Dynamic Access Control] The session is missing an active organization id to delete a role. Either set an active org id, or pass an organizationId in the request body.`);
|
|
1280
1254
|
return ctx.render({
|
|
1281
|
-
success:
|
|
1255
|
+
success: _faire_auth_core_static.False,
|
|
1282
1256
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
1283
1257
|
}, 400);
|
|
1284
1258
|
}
|
|
@@ -1302,7 +1276,7 @@ const deleteOrgRole = (options) => {
|
|
|
1302
1276
|
organizationId
|
|
1303
1277
|
});
|
|
1304
1278
|
return ctx.render({
|
|
1305
|
-
success:
|
|
1279
|
+
success: _faire_auth_core_static.False,
|
|
1306
1280
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
1307
1281
|
}, 403);
|
|
1308
1282
|
}
|
|
@@ -1318,24 +1292,24 @@ const deleteOrgRole = (options) => {
|
|
|
1318
1292
|
role: member.role
|
|
1319
1293
|
});
|
|
1320
1294
|
return ctx.render({
|
|
1321
|
-
success:
|
|
1295
|
+
success: _faire_auth_core_static.False,
|
|
1322
1296
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_A_ROLE
|
|
1323
1297
|
}, 403);
|
|
1324
1298
|
}
|
|
1325
1299
|
if (roleName) {
|
|
1326
|
-
const defaultRoles
|
|
1300
|
+
const defaultRoles = options.roles ? Object.keys(options.roles) : [
|
|
1327
1301
|
"owner",
|
|
1328
1302
|
"admin",
|
|
1329
1303
|
"member"
|
|
1330
1304
|
];
|
|
1331
|
-
if (defaultRoles
|
|
1305
|
+
if (defaultRoles.includes(roleName)) {
|
|
1332
1306
|
ctx.get("context").logger.error(`[Dynamic Access Control] Cannot delete a pre-defined role.`, {
|
|
1333
1307
|
roleName,
|
|
1334
1308
|
organizationId,
|
|
1335
|
-
defaultRoles
|
|
1309
|
+
defaultRoles
|
|
1336
1310
|
});
|
|
1337
1311
|
return ctx.render({
|
|
1338
|
-
success:
|
|
1312
|
+
success: _faire_auth_core_static.False,
|
|
1339
1313
|
message: ORGANIZATION_ERROR_CODES.CANNOT_DELETE_A_PRE_DEFINED_ROLE
|
|
1340
1314
|
}, 400);
|
|
1341
1315
|
}
|
|
@@ -1368,7 +1342,7 @@ const deleteOrgRole = (options) => {
|
|
|
1368
1342
|
organizationId
|
|
1369
1343
|
});
|
|
1370
1344
|
return ctx.render({
|
|
1371
|
-
success:
|
|
1345
|
+
success: _faire_auth_core_static.False,
|
|
1372
1346
|
message: ORGANIZATION_ERROR_CODES.ROLE_NOT_FOUND
|
|
1373
1347
|
}, 400);
|
|
1374
1348
|
}
|
|
@@ -1382,28 +1356,28 @@ const deleteOrgRole = (options) => {
|
|
|
1382
1356
|
connector: "AND"
|
|
1383
1357
|
}, condition]
|
|
1384
1358
|
});
|
|
1385
|
-
return ctx.render({ success:
|
|
1359
|
+
return ctx.render({ success: _faire_auth_core_static.True }, 200);
|
|
1386
1360
|
});
|
|
1387
1361
|
};
|
|
1388
1362
|
const listOrgRoles = (options) => {
|
|
1389
1363
|
const { $ReturnAdditionalFields } = getAdditionalFields(options, false);
|
|
1390
1364
|
const listOrgRolesRequestSchema = zod.object({ organizationId: zod.string().optional().openapi({ description: "The id of the organization to list roles for. If not provided, the user's active organization will be used." }) });
|
|
1391
1365
|
const { additionalFieldsSchema } = getAdditionalFields(options, false);
|
|
1392
|
-
const listOrgRolesResponseSchema = zod.array(organizationRoleSchema.extend(additionalFieldsSchema.shape)).transform(
|
|
1393
|
-
return require_session.createEndpoint((0,
|
|
1366
|
+
const listOrgRolesResponseSchema = zod.array(organizationRoleSchema.extend(additionalFieldsSchema.shape)).transform(_faire_auth_core_utils.toSuccess);
|
|
1367
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
1394
1368
|
operationId: "listOrgRoles",
|
|
1395
1369
|
method: "get",
|
|
1396
1370
|
path: "/organization/list-roles",
|
|
1397
1371
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
1398
|
-
request: (0,
|
|
1399
|
-
responses: (0,
|
|
1372
|
+
request: (0, _faire_auth_core_factory.req)().qry(listOrgRolesRequestSchema).bld(),
|
|
1373
|
+
responses: (0, _faire_auth_core_factory.res)(listOrgRolesResponseSchema).err(400).err(403).bld()
|
|
1400
1374
|
}), (_authOptions) => async (ctx) => {
|
|
1401
1375
|
const { session, user } = ctx.get("session");
|
|
1402
1376
|
const { organizationId = session.activeOrganizationId } = ctx.req.valid("query");
|
|
1403
1377
|
if (!organizationId) {
|
|
1404
1378
|
ctx.get("context").logger.error(`[Dynamic Access Control] The session is missing an active organization id to list roles. Either set an active org id, or pass an organizationId in the request query.`);
|
|
1405
1379
|
return ctx.render({
|
|
1406
|
-
success:
|
|
1380
|
+
success: _faire_auth_core_static.False,
|
|
1407
1381
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
1408
1382
|
}, 400);
|
|
1409
1383
|
}
|
|
@@ -1427,7 +1401,7 @@ const listOrgRoles = (options) => {
|
|
|
1427
1401
|
organizationId
|
|
1428
1402
|
});
|
|
1429
1403
|
return ctx.render({
|
|
1430
|
-
success:
|
|
1404
|
+
success: _faire_auth_core_static.False,
|
|
1431
1405
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
1432
1406
|
}, 403);
|
|
1433
1407
|
}
|
|
@@ -1443,7 +1417,7 @@ const listOrgRoles = (options) => {
|
|
|
1443
1417
|
role: member.role
|
|
1444
1418
|
});
|
|
1445
1419
|
return ctx.render({
|
|
1446
|
-
success:
|
|
1420
|
+
success: _faire_auth_core_static.False,
|
|
1447
1421
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_LIST_A_ROLE
|
|
1448
1422
|
}, 403);
|
|
1449
1423
|
}
|
|
@@ -1471,21 +1445,21 @@ const getOrgRole = (options) => {
|
|
|
1471
1445
|
roleId: zod.string().optional().openapi({ description: "The id of the role to read" })
|
|
1472
1446
|
});
|
|
1473
1447
|
const { additionalFieldsSchema } = getAdditionalFields(options, false);
|
|
1474
|
-
const getOrgRoleResponseSchema = organizationRoleSchema.extend(additionalFieldsSchema.shape).transform(
|
|
1475
|
-
return require_session.createEndpoint((0,
|
|
1448
|
+
const getOrgRoleResponseSchema = organizationRoleSchema.extend(additionalFieldsSchema.shape).transform(_faire_auth_core_utils.toSuccess);
|
|
1449
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
1476
1450
|
operationId: "getOrgRole",
|
|
1477
1451
|
method: "get",
|
|
1478
1452
|
path: "/organization/get-role",
|
|
1479
1453
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
1480
|
-
request: (0,
|
|
1481
|
-
responses: (0,
|
|
1454
|
+
request: (0, _faire_auth_core_factory.req)().qry(getOrgRoleRequestSchema).bld(),
|
|
1455
|
+
responses: (0, _faire_auth_core_factory.res)(getOrgRoleResponseSchema).err(400).err(403).bld()
|
|
1482
1456
|
}), (_authOptions) => async (ctx) => {
|
|
1483
1457
|
const { session, user } = ctx.get("session");
|
|
1484
1458
|
const { organizationId = session.activeOrganizationId, roleName, roleId } = ctx.req.valid("query");
|
|
1485
1459
|
if (!organizationId) {
|
|
1486
1460
|
ctx.get("context").logger.error(`[Dynamic Access Control] The session is missing an active organization id to read a role. Either set an active org id, or pass an organizationId in the request query.`);
|
|
1487
1461
|
return ctx.render({
|
|
1488
|
-
success:
|
|
1462
|
+
success: _faire_auth_core_static.False,
|
|
1489
1463
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
1490
1464
|
}, 400);
|
|
1491
1465
|
}
|
|
@@ -1509,7 +1483,7 @@ const getOrgRole = (options) => {
|
|
|
1509
1483
|
organizationId
|
|
1510
1484
|
});
|
|
1511
1485
|
return ctx.render({
|
|
1512
|
-
success:
|
|
1486
|
+
success: _faire_auth_core_static.False,
|
|
1513
1487
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
1514
1488
|
}, 403);
|
|
1515
1489
|
}
|
|
@@ -1525,7 +1499,7 @@ const getOrgRole = (options) => {
|
|
|
1525
1499
|
role: member.role
|
|
1526
1500
|
});
|
|
1527
1501
|
return ctx.render({
|
|
1528
|
-
success:
|
|
1502
|
+
success: _faire_auth_core_static.False,
|
|
1529
1503
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_READ_A_ROLE
|
|
1530
1504
|
}, 403);
|
|
1531
1505
|
}
|
|
@@ -1542,7 +1516,7 @@ const getOrgRole = (options) => {
|
|
|
1542
1516
|
operator: "eq",
|
|
1543
1517
|
connector: "AND"
|
|
1544
1518
|
};
|
|
1545
|
-
let role
|
|
1519
|
+
let role = await ctx.get("context").adapter.findOne({
|
|
1546
1520
|
model: "organizationRole",
|
|
1547
1521
|
where: [{
|
|
1548
1522
|
field: "organizationId",
|
|
@@ -1551,18 +1525,18 @@ const getOrgRole = (options) => {
|
|
|
1551
1525
|
connector: "AND"
|
|
1552
1526
|
}, condition]
|
|
1553
1527
|
});
|
|
1554
|
-
if (!role
|
|
1528
|
+
if (!role) {
|
|
1555
1529
|
ctx.get("context").logger.error(`[Dynamic Access Control] The role name/id does not exist in the database.`, {
|
|
1556
1530
|
...roleName ? { roleName } : { roleId },
|
|
1557
1531
|
organizationId
|
|
1558
1532
|
});
|
|
1559
1533
|
return ctx.render({
|
|
1560
|
-
success:
|
|
1534
|
+
success: _faire_auth_core_static.False,
|
|
1561
1535
|
message: ORGANIZATION_ERROR_CODES.ROLE_NOT_FOUND
|
|
1562
1536
|
}, 400);
|
|
1563
1537
|
}
|
|
1564
|
-
role
|
|
1565
|
-
return ctx.render(role
|
|
1538
|
+
role.permission = JSON.parse(role.permission);
|
|
1539
|
+
return ctx.render(role, 200);
|
|
1566
1540
|
});
|
|
1567
1541
|
};
|
|
1568
1542
|
const updateOrgRole = (options) => {
|
|
@@ -1574,14 +1548,14 @@ const updateOrgRole = (options) => {
|
|
|
1574
1548
|
roleName: zod.string().optional().openapi({ description: "The name of the role to update" })
|
|
1575
1549
|
}).extend(additionalFieldsSchema.shape)
|
|
1576
1550
|
}).and(zod.union([zod.object({ roleName: zod.string().openapi({ description: "The name of the role to update" }) }), zod.object({ roleId: zod.string().openapi({ description: "The id of the role to update" }) })]));
|
|
1577
|
-
const updateOrgRoleResponseSchema = organizationRoleSchema.extend(additionalFieldsSchema.shape).transform(
|
|
1578
|
-
return require_session.createEndpoint((0,
|
|
1551
|
+
const updateOrgRoleResponseSchema = organizationRoleSchema.extend(additionalFieldsSchema.shape).transform(_faire_auth_core_utils.toSuccess);
|
|
1552
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
1579
1553
|
operationId: "updateOrgRole",
|
|
1580
1554
|
method: "post",
|
|
1581
1555
|
path: "/organization/update-role",
|
|
1582
1556
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
1583
|
-
request: (0,
|
|
1584
|
-
responses: (0,
|
|
1557
|
+
request: (0, _faire_auth_core_factory.req)().bdy(updateOrgRoleRequestSchema).bld(),
|
|
1558
|
+
responses: (0, _faire_auth_core_factory.res)(updateOrgRoleResponseSchema).err(400).err(403).err(501).bld()
|
|
1585
1559
|
}), (_authOptions) => async (ctx) => {
|
|
1586
1560
|
const { session, user } = ctx.get("session");
|
|
1587
1561
|
const validData = ctx.req.valid("json");
|
|
@@ -1592,14 +1566,14 @@ const updateOrgRole = (options) => {
|
|
|
1592
1566
|
if (!ac) {
|
|
1593
1567
|
ctx.get("context").logger.error(`[Dynamic Access Control] The organization plugin is missing a pre-defined ac instance.`, `\nPlease refer to the documentation here: https://faire-auth.com/docs/plugins/organization#dynamic-access-control`);
|
|
1594
1568
|
return ctx.render({
|
|
1595
|
-
success:
|
|
1569
|
+
success: _faire_auth_core_static.False,
|
|
1596
1570
|
message: ORGANIZATION_ERROR_CODES.MISSING_AC_INSTANCE
|
|
1597
1571
|
}, 501);
|
|
1598
1572
|
}
|
|
1599
1573
|
if (!organizationId) {
|
|
1600
1574
|
ctx.get("context").logger.error(`[Dynamic Access Control] The session is missing an active organization id to update a role. Either set an active org id, or pass an organizationId in the request body.`);
|
|
1601
1575
|
return ctx.render({
|
|
1602
|
-
success:
|
|
1576
|
+
success: _faire_auth_core_static.False,
|
|
1603
1577
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
1604
1578
|
}, 400);
|
|
1605
1579
|
}
|
|
@@ -1623,7 +1597,7 @@ const updateOrgRole = (options) => {
|
|
|
1623
1597
|
organizationId
|
|
1624
1598
|
});
|
|
1625
1599
|
return ctx.render({
|
|
1626
|
-
success:
|
|
1600
|
+
success: _faire_auth_core_static.False,
|
|
1627
1601
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
1628
1602
|
}, 403);
|
|
1629
1603
|
}
|
|
@@ -1635,7 +1609,7 @@ const updateOrgRole = (options) => {
|
|
|
1635
1609
|
}, ctx)) {
|
|
1636
1610
|
ctx.get("context").logger.error(`[Dynamic Access Control] The user is not permitted to update a role.`);
|
|
1637
1611
|
return ctx.render({
|
|
1638
|
-
success:
|
|
1612
|
+
success: _faire_auth_core_static.False,
|
|
1639
1613
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_A_ROLE
|
|
1640
1614
|
}, 403);
|
|
1641
1615
|
}
|
|
@@ -1652,7 +1626,7 @@ const updateOrgRole = (options) => {
|
|
|
1652
1626
|
operator: "eq",
|
|
1653
1627
|
connector: "AND"
|
|
1654
1628
|
};
|
|
1655
|
-
let role
|
|
1629
|
+
let role = await ctx.get("context").adapter.findOne({
|
|
1656
1630
|
model: "organizationRole",
|
|
1657
1631
|
where: [{
|
|
1658
1632
|
field: "organizationId",
|
|
@@ -1661,18 +1635,18 @@ const updateOrgRole = (options) => {
|
|
|
1661
1635
|
connector: "AND"
|
|
1662
1636
|
}, condition]
|
|
1663
1637
|
});
|
|
1664
|
-
if (!role
|
|
1638
|
+
if (!role) {
|
|
1665
1639
|
ctx.get("context").logger.error(`[Dynamic Access Control] The role name/id does not exist in the database.`, {
|
|
1666
1640
|
...roleName ? { roleName } : { roleId },
|
|
1667
1641
|
organizationId
|
|
1668
1642
|
});
|
|
1669
1643
|
return ctx.render({
|
|
1670
|
-
success:
|
|
1644
|
+
success: _faire_auth_core_static.False,
|
|
1671
1645
|
message: ORGANIZATION_ERROR_CODES.ROLE_NOT_FOUND
|
|
1672
1646
|
}, 400);
|
|
1673
1647
|
}
|
|
1674
|
-
role
|
|
1675
|
-
const { permission: _, roleName: __
|
|
1648
|
+
role.permission = role.permission ? JSON.parse(role.permission) : void 0;
|
|
1649
|
+
const { permission: _, roleName: __, ...additionalFields } = data;
|
|
1676
1650
|
let updateData = { ...additionalFields };
|
|
1677
1651
|
if (data.permission) {
|
|
1678
1652
|
let newPermission = data.permission;
|
|
@@ -1727,9 +1701,9 @@ const updateOrgRole = (options) => {
|
|
|
1727
1701
|
update
|
|
1728
1702
|
});
|
|
1729
1703
|
return ctx.render({
|
|
1730
|
-
...role
|
|
1704
|
+
...role,
|
|
1731
1705
|
...update,
|
|
1732
|
-
permission: updateData.permission || role
|
|
1706
|
+
permission: updateData.permission || role.permission || null
|
|
1733
1707
|
}, 200);
|
|
1734
1708
|
});
|
|
1735
1709
|
};
|
|
@@ -1742,7 +1716,7 @@ async function checkForInvalidResources({ ac, ctx, permission }) {
|
|
|
1742
1716
|
validResources
|
|
1743
1717
|
});
|
|
1744
1718
|
return ctx.render({
|
|
1745
|
-
success:
|
|
1719
|
+
success: _faire_auth_core_static.False,
|
|
1746
1720
|
message: ORGANIZATION_ERROR_CODES.INVALID_RESOURCE
|
|
1747
1721
|
}, 400);
|
|
1748
1722
|
}
|
|
@@ -1779,31 +1753,31 @@ async function checkIfMemberHasPermission({ ctx, permissionRequired: permission,
|
|
|
1779
1753
|
else if (action === "list") errorMessage = ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_LIST_A_ROLE;
|
|
1780
1754
|
else errorMessage = ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_GET_A_ROLE;
|
|
1781
1755
|
return ctx.render({
|
|
1782
|
-
success:
|
|
1756
|
+
success: _faire_auth_core_static.False,
|
|
1783
1757
|
message: errorMessage,
|
|
1784
1758
|
missingPermissions
|
|
1785
1759
|
}, 403);
|
|
1786
1760
|
}
|
|
1787
1761
|
}
|
|
1788
|
-
async function checkIfRoleNameIsTakenByPreDefinedRole({ options, organizationId, role
|
|
1789
|
-
const defaultRoles
|
|
1762
|
+
async function checkIfRoleNameIsTakenByPreDefinedRole({ options, organizationId, role, ctx }) {
|
|
1763
|
+
const defaultRoles = options.roles ? Object.keys(options.roles) : [
|
|
1790
1764
|
"owner",
|
|
1791
1765
|
"admin",
|
|
1792
1766
|
"member"
|
|
1793
1767
|
];
|
|
1794
|
-
if (defaultRoles
|
|
1795
|
-
ctx.get("context").logger.error(`[Dynamic Access Control] The role name "${role
|
|
1796
|
-
role
|
|
1768
|
+
if (defaultRoles.includes(role)) {
|
|
1769
|
+
ctx.get("context").logger.error(`[Dynamic Access Control] The role name "${role}" is already taken by a pre-defined role.`, {
|
|
1770
|
+
role,
|
|
1797
1771
|
organizationId,
|
|
1798
|
-
defaultRoles
|
|
1772
|
+
defaultRoles
|
|
1799
1773
|
});
|
|
1800
1774
|
return ctx.render({
|
|
1801
|
-
success:
|
|
1775
|
+
success: _faire_auth_core_static.False,
|
|
1802
1776
|
message: ORGANIZATION_ERROR_CODES.ROLE_NAME_IS_ALREADY_TAKEN
|
|
1803
1777
|
}, 400);
|
|
1804
1778
|
}
|
|
1805
1779
|
}
|
|
1806
|
-
async function checkIfRoleNameIsTakenByRoleInDB({ organizationId, role
|
|
1780
|
+
async function checkIfRoleNameIsTakenByRoleInDB({ organizationId, role, ctx }) {
|
|
1807
1781
|
if (await ctx.get("context").adapter.findOne({
|
|
1808
1782
|
model: "organizationRole",
|
|
1809
1783
|
where: [{
|
|
@@ -1813,24 +1787,22 @@ async function checkIfRoleNameIsTakenByRoleInDB({ organizationId, role: role$2,
|
|
|
1813
1787
|
connector: "AND"
|
|
1814
1788
|
}, {
|
|
1815
1789
|
field: "role",
|
|
1816
|
-
value: role
|
|
1790
|
+
value: role,
|
|
1817
1791
|
operator: "eq",
|
|
1818
1792
|
connector: "AND"
|
|
1819
1793
|
}]
|
|
1820
1794
|
})) {
|
|
1821
|
-
ctx.get("context").logger.error(`[Dynamic Access Control] The role name "${role
|
|
1822
|
-
role
|
|
1795
|
+
ctx.get("context").logger.error(`[Dynamic Access Control] The role name "${role}" is already taken by a role in the database.`, {
|
|
1796
|
+
role,
|
|
1823
1797
|
organizationId
|
|
1824
1798
|
});
|
|
1825
1799
|
return ctx.render({
|
|
1826
|
-
success:
|
|
1800
|
+
success: _faire_auth_core_static.False,
|
|
1827
1801
|
message: ORGANIZATION_ERROR_CODES.ROLE_NAME_IS_ALREADY_TAKEN
|
|
1828
1802
|
}, 400);
|
|
1829
1803
|
}
|
|
1830
1804
|
}
|
|
1831
|
-
|
|
1832
|
-
//#endregion
|
|
1833
|
-
//#region src/plugins/organization/schema/invitation.ts
|
|
1805
|
+
// src/plugins/organization/schema/invitation.ts
|
|
1834
1806
|
/**
|
|
1835
1807
|
* Schema for creating an invitation
|
|
1836
1808
|
*/
|
|
@@ -1857,7 +1829,7 @@ const getInvitationQuerySchema = zod.object({ id: zod.string().openapi({ descrip
|
|
|
1857
1829
|
const getInvitationResponseSchema = invitationSchema.extend({
|
|
1858
1830
|
organizationName: zod.string().openapi({ description: "Name of the organization" }),
|
|
1859
1831
|
organizationSlug: zod.string().openapi({ description: "URL-friendly slug of the organization" }),
|
|
1860
|
-
inviterEmail:
|
|
1832
|
+
inviterEmail: _faire_auth_core_factory.emailSchema.openapi({ description: "Email address of the user who sent the invitation" })
|
|
1861
1833
|
});
|
|
1862
1834
|
/**
|
|
1863
1835
|
* Schema for listing invitations query
|
|
@@ -1870,11 +1842,9 @@ const listInvitationsResponseSchema = zod.array(invitationSchema).openapi({ desc
|
|
|
1870
1842
|
/**
|
|
1871
1843
|
* Schema for listing user invitations query
|
|
1872
1844
|
*/
|
|
1873
|
-
const listUserInvitationsQuerySchema = zod.object({ email:
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
//#region src/plugins/organization/schema/member.ts
|
|
1877
|
-
const memberWithUserSchema = memberSchema.extend({ user: __faire_auth_core_db.looseUserSchema.extend({ email: zod.string() }) });
|
|
1845
|
+
const listUserInvitationsQuerySchema = zod.object({ email: _faire_auth_core_factory.emailSchema.openapi({ description: "The email of the user to list invitations for. This only works for server side API calls." }).optional() });
|
|
1846
|
+
// src/plugins/organization/schema/member.ts
|
|
1847
|
+
const memberWithUserSchema = memberSchema.extend({ user: _faire_auth_core_db.looseUserSchema.extend({ email: zod.string() }) });
|
|
1878
1848
|
/**
|
|
1879
1849
|
* Schema for adding a member
|
|
1880
1850
|
*/
|
|
@@ -1931,9 +1901,7 @@ const listMembersQuerySchema = zod.object({
|
|
|
1931
1901
|
* Schema for leave organization
|
|
1932
1902
|
*/
|
|
1933
1903
|
const leaveOrganizationSchema = zod.object({ organizationId: memberSchema.shape.organizationId.openapi({ description: "The organization ID to leave" }) });
|
|
1934
|
-
|
|
1935
|
-
//#endregion
|
|
1936
|
-
//#region src/plugins/organization/schema/organization.ts
|
|
1904
|
+
// src/plugins/organization/schema/organization.ts
|
|
1937
1905
|
/**
|
|
1938
1906
|
* Base schema for creating an organization
|
|
1939
1907
|
*/
|
|
@@ -2000,9 +1968,7 @@ const deleteOrganizationSchema = zod.object({ organizationId: zod.string().opena
|
|
|
2000
1968
|
* Response schema for deleted organization
|
|
2001
1969
|
*/
|
|
2002
1970
|
const deleteOrganizationResponseSchema = zod.string().openapi({ description: "ID of the organization that was successfully deleted" });
|
|
2003
|
-
|
|
2004
|
-
//#endregion
|
|
2005
|
-
//#region src/plugins/organization/schema/team.ts
|
|
1971
|
+
// src/plugins/organization/schema/team.ts
|
|
2006
1972
|
/**
|
|
2007
1973
|
* Base schema for creating a team
|
|
2008
1974
|
*/
|
|
@@ -2065,34 +2031,32 @@ const teamMemberResponseSchema = zod.object({
|
|
|
2065
2031
|
id: zod.string().openapi({ description: "Unique identifier for the team member" }),
|
|
2066
2032
|
userId: zod.string().openapi({ description: "ID of the user who is a member of the team" }),
|
|
2067
2033
|
teamId: zod.string().openapi({ description: "ID of the team this member belongs to" }),
|
|
2068
|
-
createdAt:
|
|
2034
|
+
createdAt: _faire_auth_core_factory.dateOrIsoStringSchema.openapi({ description: "Timestamp when the member was added to the team" })
|
|
2069
2035
|
});
|
|
2070
2036
|
/**
|
|
2071
2037
|
* Schema for team member list response
|
|
2072
2038
|
*/
|
|
2073
2039
|
const teamMemberListResponseSchema = zod.array(teamMemberResponseSchema).openapi({ description: "List of team members" });
|
|
2074
|
-
|
|
2075
|
-
//#endregion
|
|
2076
|
-
//#region src/plugins/organization/routes/crud-invites.ts
|
|
2040
|
+
// src/plugins/organization/routes/crud-invites.ts
|
|
2077
2041
|
const createInvitation = (option) => {
|
|
2078
|
-
const additionalFieldsSchema =
|
|
2042
|
+
const additionalFieldsSchema = require_db_index.toZodSchema({
|
|
2079
2043
|
fields: option?.schema?.invitation?.additionalFields ?? {},
|
|
2080
2044
|
isClientSide: true
|
|
2081
2045
|
});
|
|
2082
|
-
return require_session.createEndpoint((0,
|
|
2046
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2083
2047
|
operationId: "createInvitation",
|
|
2084
2048
|
method: "post",
|
|
2085
2049
|
path: "/organization/invite-member",
|
|
2086
2050
|
description: "Invite a user to an organization",
|
|
2087
2051
|
middleware: [orgSessionMiddleware, orgMiddleware(option)],
|
|
2088
|
-
request: (0,
|
|
2089
|
-
responses: (0,
|
|
2052
|
+
request: (0, _faire_auth_core_factory.req)().bdy(createInvitationSchema.extend(additionalFieldsSchema.shape)).bld(),
|
|
2053
|
+
responses: (0, _faire_auth_core_factory.res)(invitationResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").err(401, "Not allowed to perform action").err(403, "Not allowed to perform action or invitation or member limit reached").bld()
|
|
2090
2054
|
}), (_authOptions) => async (ctx) => {
|
|
2091
2055
|
const session = ctx.get("session");
|
|
2092
|
-
const { organizationId: requestOrganizationId, role
|
|
2056
|
+
const { organizationId: requestOrganizationId, role, email, resend, teamId, ...additionalFields } = ctx.req.valid("json");
|
|
2093
2057
|
const organizationId = requestOrganizationId ?? session.session.activeOrganizationId;
|
|
2094
2058
|
if (!organizationId) return ctx.render({
|
|
2095
|
-
success:
|
|
2059
|
+
success: _faire_auth_core_static.False,
|
|
2096
2060
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2097
2061
|
}, 400);
|
|
2098
2062
|
const adapter = getOrgAdapter(ctx.get("context"), option);
|
|
@@ -2101,7 +2065,7 @@ const createInvitation = (option) => {
|
|
|
2101
2065
|
organizationId
|
|
2102
2066
|
});
|
|
2103
2067
|
if (!member) return ctx.render({
|
|
2104
|
-
success:
|
|
2068
|
+
success: _faire_auth_core_static.False,
|
|
2105
2069
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2106
2070
|
}, 400);
|
|
2107
2071
|
if (!await hasPermission({
|
|
@@ -2110,20 +2074,20 @@ const createInvitation = (option) => {
|
|
|
2110
2074
|
permissions: { invitation: ["create"] },
|
|
2111
2075
|
organizationId
|
|
2112
2076
|
}, ctx)) return ctx.render({
|
|
2113
|
-
success:
|
|
2077
|
+
success: _faire_auth_core_static.False,
|
|
2114
2078
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_INVITE_USERS_TO_THIS_ORGANIZATION
|
|
2115
2079
|
}, 403);
|
|
2116
2080
|
const creatorRole = ctx.get("orgOptions").creatorRole || "owner";
|
|
2117
|
-
const roles = parseRoles(role
|
|
2081
|
+
const roles = parseRoles(role);
|
|
2118
2082
|
if (member.role !== creatorRole && roles.split(",").includes(creatorRole)) return ctx.render({
|
|
2119
|
-
success:
|
|
2083
|
+
success: _faire_auth_core_static.False,
|
|
2120
2084
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_INVITE_USER_WITH_THIS_ROLE
|
|
2121
2085
|
}, 403);
|
|
2122
2086
|
if (await adapter.findMemberByEmail({
|
|
2123
2087
|
email,
|
|
2124
2088
|
organizationId
|
|
2125
2089
|
})) return ctx.render({
|
|
2126
|
-
success:
|
|
2090
|
+
success: _faire_auth_core_static.False,
|
|
2127
2091
|
message: ORGANIZATION_ERROR_CODES.USER_IS_ALREADY_A_MEMBER_OF_THIS_ORGANIZATION
|
|
2128
2092
|
}, 400);
|
|
2129
2093
|
const alreadyInvited = await adapter.findPendingInvitation({
|
|
@@ -2131,17 +2095,17 @@ const createInvitation = (option) => {
|
|
|
2131
2095
|
organizationId
|
|
2132
2096
|
});
|
|
2133
2097
|
if (alreadyInvited.length && !resend) return ctx.render({
|
|
2134
|
-
success:
|
|
2098
|
+
success: _faire_auth_core_static.False,
|
|
2135
2099
|
message: ORGANIZATION_ERROR_CODES.USER_IS_ALREADY_INVITED_TO_THIS_ORGANIZATION
|
|
2136
2100
|
}, 400);
|
|
2137
|
-
const organization
|
|
2138
|
-
if (!organization
|
|
2139
|
-
success:
|
|
2101
|
+
const organization = await adapter.findOrganizationById(organizationId);
|
|
2102
|
+
if (!organization) return ctx.render({
|
|
2103
|
+
success: _faire_auth_core_static.False,
|
|
2140
2104
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2141
2105
|
}, 400);
|
|
2142
2106
|
if (alreadyInvited.length && resend) {
|
|
2143
2107
|
const existingInvitation = alreadyInvited[0];
|
|
2144
|
-
const newExpiresAt = (0,
|
|
2108
|
+
const newExpiresAt = (0, _faire_auth_core_utils.getDate)(ctx.get("orgOptions").invitationExpiresIn ?? 172800, "sec");
|
|
2145
2109
|
await ctx.get("context").adapter.update({
|
|
2146
2110
|
model: "invitation",
|
|
2147
2111
|
where: [{
|
|
@@ -2158,7 +2122,7 @@ const createInvitation = (option) => {
|
|
|
2158
2122
|
id: updatedInvitation.id,
|
|
2159
2123
|
role: updatedInvitation.role,
|
|
2160
2124
|
email: updatedInvitation.email.toLowerCase(),
|
|
2161
|
-
organization
|
|
2125
|
+
organization,
|
|
2162
2126
|
inviter: {
|
|
2163
2127
|
...member,
|
|
2164
2128
|
user: session.user
|
|
@@ -2174,34 +2138,34 @@ const createInvitation = (option) => {
|
|
|
2174
2138
|
const optionInvitationLimit = ctx.get("orgOptions").invitationLimit;
|
|
2175
2139
|
const invitationLimit = typeof optionInvitationLimit === "function" ? await optionInvitationLimit({
|
|
2176
2140
|
user: session.user,
|
|
2177
|
-
organization
|
|
2141
|
+
organization,
|
|
2178
2142
|
member
|
|
2179
2143
|
}, ctx.get("context")) : optionInvitationLimit ?? 100;
|
|
2180
2144
|
if ((await adapter.findPendingInvitations({ organizationId })).length >= invitationLimit) return ctx.render({
|
|
2181
|
-
success:
|
|
2145
|
+
success: _faire_auth_core_static.False,
|
|
2182
2146
|
message: ORGANIZATION_ERROR_CODES.INVITATION_LIMIT_REACHED
|
|
2183
2147
|
}, 403);
|
|
2184
2148
|
const orgOptions = ctx.get("orgOptions");
|
|
2185
2149
|
if (orgOptions.teams && orgOptions.teams.enabled && orgOptions.teams.maximumMembersPerTeam !== void 0 && teamId) {
|
|
2186
|
-
const teamIds
|
|
2187
|
-
for (const teamId
|
|
2150
|
+
const teamIds = typeof teamId === "string" ? [teamId] : teamId;
|
|
2151
|
+
for (const teamId of teamIds) {
|
|
2188
2152
|
const team = await adapter.findTeamById({
|
|
2189
|
-
teamId
|
|
2153
|
+
teamId,
|
|
2190
2154
|
organizationId,
|
|
2191
2155
|
includeTeamMembers: true
|
|
2192
2156
|
});
|
|
2193
2157
|
if (!team) return ctx.render({
|
|
2194
|
-
success:
|
|
2158
|
+
success: _faire_auth_core_static.False,
|
|
2195
2159
|
message: ORGANIZATION_ERROR_CODES.TEAM_NOT_FOUND
|
|
2196
2160
|
}, 400);
|
|
2197
2161
|
if (!!orgOptions.teams?.enabled) {
|
|
2198
2162
|
const maximumMembersPerTeam = typeof orgOptions.teams.maximumMembersPerTeam === "function" ? await orgOptions.teams.maximumMembersPerTeam({
|
|
2199
|
-
teamId
|
|
2163
|
+
teamId,
|
|
2200
2164
|
session,
|
|
2201
2165
|
organizationId
|
|
2202
2166
|
}) : orgOptions.teams.maximumMembersPerTeam ?? Infinity;
|
|
2203
2167
|
if (team.members.length >= maximumMembersPerTeam) return ctx.render({
|
|
2204
|
-
success:
|
|
2168
|
+
success: _faire_auth_core_static.False,
|
|
2205
2169
|
message: ORGANIZATION_ERROR_CODES.TEAM_MEMBER_LIMIT_REACHED
|
|
2206
2170
|
}, 403);
|
|
2207
2171
|
}
|
|
@@ -2223,7 +2187,7 @@ const createInvitation = (option) => {
|
|
|
2223
2187
|
...teamIds.length > 0 && { teamId: teamIds[0] }
|
|
2224
2188
|
},
|
|
2225
2189
|
inviter: session.user,
|
|
2226
|
-
organization
|
|
2190
|
+
organization
|
|
2227
2191
|
});
|
|
2228
2192
|
if (response && typeof response === "object" && "data" in response) invitationData = {
|
|
2229
2193
|
...invitationData,
|
|
@@ -2238,7 +2202,7 @@ const createInvitation = (option) => {
|
|
|
2238
2202
|
id: invitation.id,
|
|
2239
2203
|
role: invitation.role,
|
|
2240
2204
|
email: invitation.email.toLowerCase(),
|
|
2241
|
-
organization
|
|
2205
|
+
organization,
|
|
2242
2206
|
inviter: {
|
|
2243
2207
|
...member,
|
|
2244
2208
|
user: session.user
|
|
@@ -2248,57 +2212,57 @@ const createInvitation = (option) => {
|
|
|
2248
2212
|
if (option?.organizationHooks?.afterCreateInvitation) await option?.organizationHooks.afterCreateInvitation({
|
|
2249
2213
|
invitation,
|
|
2250
2214
|
inviter: session.user,
|
|
2251
|
-
organization
|
|
2215
|
+
organization
|
|
2252
2216
|
});
|
|
2253
2217
|
return ctx.render({ invitation }, 200);
|
|
2254
2218
|
});
|
|
2255
2219
|
};
|
|
2256
|
-
const acceptInvitation = (options) => require_session.createEndpoint((0,
|
|
2220
|
+
const acceptInvitation = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2257
2221
|
operationId: "acceptInvitation",
|
|
2258
2222
|
method: "post",
|
|
2259
2223
|
path: "/organization/accept-invitation",
|
|
2260
2224
|
description: "Accept an invitation to an organization",
|
|
2261
2225
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
2262
|
-
request: (0,
|
|
2263
|
-
responses: (0,
|
|
2226
|
+
request: (0, _faire_auth_core_factory.req)().bdy(invitationRequestSchema).bld(),
|
|
2227
|
+
responses: (0, _faire_auth_core_factory.res)(invitationResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").err(401, "Not allowed to perform action or limit reached").err(403, "Not recipient of invitation").bld()
|
|
2264
2228
|
}), (authOptions) => async (ctx) => {
|
|
2265
2229
|
const { invitationId } = ctx.req.valid("json");
|
|
2266
2230
|
const session = ctx.get("session");
|
|
2267
2231
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
2268
2232
|
const invitation = await adapter.findInvitationById(invitationId);
|
|
2269
2233
|
if (!invitation || invitation.expiresAt < /* @__PURE__ */ new Date() || invitation.status !== "pending") return ctx.render({
|
|
2270
|
-
success:
|
|
2234
|
+
success: _faire_auth_core_static.False,
|
|
2271
2235
|
message: ORGANIZATION_ERROR_CODES.INVITATION_NOT_FOUND
|
|
2272
2236
|
}, 400);
|
|
2273
2237
|
if (invitation.email.toLowerCase() !== session.user.email.toLowerCase()) return ctx.render({
|
|
2274
|
-
success:
|
|
2238
|
+
success: _faire_auth_core_static.False,
|
|
2275
2239
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION
|
|
2276
2240
|
}, 403);
|
|
2277
2241
|
if (ctx.get("orgOptions").requireEmailVerificationOnInvitation && !session.user.emailVerified) return ctx.render({
|
|
2278
|
-
success:
|
|
2242
|
+
success: _faire_auth_core_static.False,
|
|
2279
2243
|
message: ORGANIZATION_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION
|
|
2280
2244
|
}, 403);
|
|
2281
2245
|
const membershipLimit = ctx.get("orgOptions")?.membershipLimit || 100;
|
|
2282
2246
|
if (await adapter.countMembers({ organizationId: invitation.organizationId }) >= membershipLimit) return ctx.render({
|
|
2283
|
-
success:
|
|
2247
|
+
success: _faire_auth_core_static.False,
|
|
2284
2248
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_MEMBERSHIP_LIMIT_REACHED
|
|
2285
2249
|
}, 401);
|
|
2286
|
-
const organization
|
|
2287
|
-
if (!organization
|
|
2288
|
-
success:
|
|
2250
|
+
const organization = await adapter.findOrganizationById(invitation.organizationId);
|
|
2251
|
+
if (!organization) return ctx.render({
|
|
2252
|
+
success: _faire_auth_core_static.False,
|
|
2289
2253
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2290
2254
|
}, 400);
|
|
2291
2255
|
if (options?.organizationHooks?.beforeAcceptInvitation) await options?.organizationHooks.beforeAcceptInvitation({
|
|
2292
2256
|
invitation,
|
|
2293
2257
|
user: session.user,
|
|
2294
|
-
organization
|
|
2258
|
+
organization
|
|
2295
2259
|
});
|
|
2296
2260
|
const acceptedI = await adapter.updateInvitation({
|
|
2297
2261
|
invitationId,
|
|
2298
2262
|
status: "accepted"
|
|
2299
2263
|
});
|
|
2300
2264
|
if (!acceptedI) return ctx.render({
|
|
2301
|
-
success:
|
|
2265
|
+
success: _faire_auth_core_static.False,
|
|
2302
2266
|
message: ORGANIZATION_ERROR_CODES.FAILED_TO_RETRIEVE_INVITATION
|
|
2303
2267
|
}, 400);
|
|
2304
2268
|
if (ctx.get("orgOptions").teams && ctx.get("orgOptions").teams.enabled && "teamId" in acceptedI && acceptedI.teamId) {
|
|
@@ -2317,15 +2281,16 @@ const acceptInvitation = (options) => require_session.createEndpoint((0, __faire
|
|
|
2317
2281
|
session,
|
|
2318
2282
|
organizationId: invitation.organizationId
|
|
2319
2283
|
}) : optionMaximumMembersPerTeam ?? Infinity)) return ctx.render({
|
|
2320
|
-
success:
|
|
2284
|
+
success: _faire_auth_core_static.False,
|
|
2321
2285
|
message: ORGANIZATION_ERROR_CODES.TEAM_MEMBER_LIMIT_REACHED
|
|
2322
2286
|
}, 403);
|
|
2323
2287
|
}
|
|
2324
2288
|
}
|
|
2325
2289
|
if (onlyOne) {
|
|
2326
2290
|
const teamId = teamIds[0];
|
|
2291
|
+
const updatedSession = await adapter.setActiveTeam(session.session.token, teamId);
|
|
2327
2292
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
2328
|
-
session:
|
|
2293
|
+
session: updatedSession,
|
|
2329
2294
|
user: session.user
|
|
2330
2295
|
});
|
|
2331
2296
|
}
|
|
@@ -2338,54 +2303,54 @@ const acceptInvitation = (options) => require_session.createEndpoint((0, __faire
|
|
|
2338
2303
|
});
|
|
2339
2304
|
await adapter.setActiveOrganization(session.session.token, invitation.organizationId);
|
|
2340
2305
|
if (!acceptedI) return ctx.render({
|
|
2341
|
-
success:
|
|
2306
|
+
success: _faire_auth_core_static.False,
|
|
2342
2307
|
message: ORGANIZATION_ERROR_CODES.INVITATION_NOT_FOUND
|
|
2343
2308
|
}, 400);
|
|
2344
2309
|
if (options?.organizationHooks?.afterAcceptInvitation) await options?.organizationHooks.afterAcceptInvitation({
|
|
2345
2310
|
invitation: acceptedI,
|
|
2346
2311
|
member,
|
|
2347
2312
|
user: session.user,
|
|
2348
|
-
organization
|
|
2313
|
+
organization
|
|
2349
2314
|
});
|
|
2350
2315
|
return ctx.render({
|
|
2351
2316
|
invitation: acceptedI,
|
|
2352
2317
|
member
|
|
2353
2318
|
}, 200);
|
|
2354
2319
|
});
|
|
2355
|
-
const rejectInvitation = (options) => require_session.createEndpoint((0,
|
|
2320
|
+
const rejectInvitation = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2356
2321
|
operationId: "rejectInvitation",
|
|
2357
2322
|
method: "post",
|
|
2358
2323
|
path: "/organization/reject-invitation",
|
|
2359
2324
|
description: "Reject an invitation to an organization",
|
|
2360
2325
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
2361
|
-
request: (0,
|
|
2362
|
-
responses: (0,
|
|
2326
|
+
request: (0, _faire_auth_core_factory.req)().bdy(invitationRequestSchema).bld(),
|
|
2327
|
+
responses: (0, _faire_auth_core_factory.res)(invitationResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").err(401, "Not allowed to perform action or limit reached").bld()
|
|
2363
2328
|
}), (_authOptions) => async (ctx) => {
|
|
2364
2329
|
const { invitationId } = ctx.req.valid("json");
|
|
2365
2330
|
const session = ctx.get("session");
|
|
2366
2331
|
const adapter = getOrgAdapter(ctx.get("context"), ctx.get("orgOptions"));
|
|
2367
2332
|
const invitation = await adapter.findInvitationById(invitationId);
|
|
2368
2333
|
if (!invitation || invitation.expiresAt < /* @__PURE__ */ new Date() || invitation.status !== "pending") return ctx.render({
|
|
2369
|
-
success:
|
|
2334
|
+
success: _faire_auth_core_static.False,
|
|
2370
2335
|
message: "Invitation not found!"
|
|
2371
2336
|
}, 400);
|
|
2372
2337
|
if (invitation.email.toLowerCase() !== session.user.email.toLowerCase()) return ctx.render({
|
|
2373
|
-
success:
|
|
2338
|
+
success: _faire_auth_core_static.False,
|
|
2374
2339
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION
|
|
2375
2340
|
}, 401);
|
|
2376
2341
|
if (ctx.get("orgOptions").requireEmailVerificationOnInvitation && !session.user.emailVerified) return ctx.render({
|
|
2377
|
-
success:
|
|
2342
|
+
success: _faire_auth_core_static.False,
|
|
2378
2343
|
message: ORGANIZATION_ERROR_CODES.EMAIL_VERIFICATION_REQUIRED_BEFORE_ACCEPTING_OR_REJECTING_INVITATION
|
|
2379
2344
|
}, 403);
|
|
2380
|
-
const organization
|
|
2381
|
-
if (!organization
|
|
2382
|
-
success:
|
|
2345
|
+
const organization = await adapter.findOrganizationById(invitation.organizationId);
|
|
2346
|
+
if (!organization) return ctx.render({
|
|
2347
|
+
success: _faire_auth_core_static.False,
|
|
2383
2348
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2384
2349
|
}, 400);
|
|
2385
2350
|
if (options?.organizationHooks?.beforeRejectInvitation) await options?.organizationHooks.beforeRejectInvitation({
|
|
2386
2351
|
invitation,
|
|
2387
2352
|
user: session.user,
|
|
2388
|
-
organization
|
|
2353
|
+
organization
|
|
2389
2354
|
});
|
|
2390
2355
|
const rejectedI = await adapter.updateInvitation({
|
|
2391
2356
|
invitationId,
|
|
@@ -2394,25 +2359,25 @@ const rejectInvitation = (options) => require_session.createEndpoint((0, __faire
|
|
|
2394
2359
|
if (options?.organizationHooks?.afterRejectInvitation) await options?.organizationHooks.afterRejectInvitation({
|
|
2395
2360
|
invitation: rejectedI ?? invitation,
|
|
2396
2361
|
user: session.user,
|
|
2397
|
-
organization
|
|
2362
|
+
organization
|
|
2398
2363
|
});
|
|
2399
2364
|
return ctx.render({ invitation: rejectedI }, 200);
|
|
2400
2365
|
});
|
|
2401
|
-
const cancelInvitation = (options) => require_session.createEndpoint((0,
|
|
2366
|
+
const cancelInvitation = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2402
2367
|
operationId: "cancelInvitation",
|
|
2403
2368
|
method: "post",
|
|
2404
2369
|
path: "/organization/cancel-invitation",
|
|
2405
2370
|
description: "Cancel an invitation to an organization",
|
|
2406
2371
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
2407
|
-
request: (0,
|
|
2408
|
-
responses: (0,
|
|
2372
|
+
request: (0, _faire_auth_core_factory.req)().bdy(invitationRequestSchema).bld(),
|
|
2373
|
+
responses: (0, _faire_auth_core_factory.res)(invitationSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").err(401, "Not allowed to perform action or limit reached").bld()
|
|
2409
2374
|
}), (_authOptions) => async (ctx) => {
|
|
2410
2375
|
const { invitationId } = ctx.req.valid("json");
|
|
2411
2376
|
const session = ctx.get("session");
|
|
2412
2377
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
2413
2378
|
const invitation = await adapter.findInvitationById(invitationId);
|
|
2414
2379
|
if (!invitation) return ctx.render({
|
|
2415
|
-
success:
|
|
2380
|
+
success: _faire_auth_core_static.False,
|
|
2416
2381
|
message: ORGANIZATION_ERROR_CODES.INVITATION_NOT_FOUND
|
|
2417
2382
|
}, 400);
|
|
2418
2383
|
const member = await adapter.findMemberByOrgId({
|
|
@@ -2420,7 +2385,7 @@ const cancelInvitation = (options) => require_session.createEndpoint((0, __faire
|
|
|
2420
2385
|
organizationId: invitation.organizationId
|
|
2421
2386
|
});
|
|
2422
2387
|
if (!member) return ctx.render({
|
|
2423
|
-
success:
|
|
2388
|
+
success: _faire_auth_core_static.False,
|
|
2424
2389
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2425
2390
|
}, 400);
|
|
2426
2391
|
if (!await hasPermission({
|
|
@@ -2429,18 +2394,18 @@ const cancelInvitation = (options) => require_session.createEndpoint((0, __faire
|
|
|
2429
2394
|
permissions: { invitation: ["cancel"] },
|
|
2430
2395
|
organizationId: invitation.organizationId
|
|
2431
2396
|
}, ctx)) return ctx.render({
|
|
2432
|
-
success:
|
|
2397
|
+
success: _faire_auth_core_static.False,
|
|
2433
2398
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_CANCEL_THIS_INVITATION
|
|
2434
2399
|
}, 401);
|
|
2435
|
-
const organization
|
|
2436
|
-
if (!organization
|
|
2437
|
-
success:
|
|
2400
|
+
const organization = await adapter.findOrganizationById(invitation.organizationId);
|
|
2401
|
+
if (!organization) return ctx.render({
|
|
2402
|
+
success: _faire_auth_core_static.False,
|
|
2438
2403
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2439
2404
|
}, 400);
|
|
2440
2405
|
if (options?.organizationHooks?.beforeCancelInvitation) await options?.organizationHooks.beforeCancelInvitation({
|
|
2441
2406
|
invitation,
|
|
2442
2407
|
cancelledBy: session.user,
|
|
2443
|
-
organization
|
|
2408
|
+
organization
|
|
2444
2409
|
});
|
|
2445
2410
|
const canceledI = await adapter.updateInvitation({
|
|
2446
2411
|
invitationId,
|
|
@@ -2449,34 +2414,34 @@ const cancelInvitation = (options) => require_session.createEndpoint((0, __faire
|
|
|
2449
2414
|
if (options?.organizationHooks?.afterCancelInvitation) await options?.organizationHooks.afterCancelInvitation({
|
|
2450
2415
|
invitation: canceledI ?? invitation,
|
|
2451
2416
|
cancelledBy: session.user,
|
|
2452
|
-
organization
|
|
2417
|
+
organization
|
|
2453
2418
|
});
|
|
2454
2419
|
return ctx.render(canceledI, 200);
|
|
2455
2420
|
});
|
|
2456
|
-
const getInvitation = (options) => require_session.createEndpoint((0,
|
|
2421
|
+
const getInvitation = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2457
2422
|
operationId: "getInvitation",
|
|
2458
2423
|
method: "get",
|
|
2459
2424
|
path: "/organization/get-invitation",
|
|
2460
2425
|
description: "Get an invitation by ID",
|
|
2461
2426
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
2462
|
-
request: (0,
|
|
2463
|
-
responses: (0,
|
|
2427
|
+
request: (0, _faire_auth_core_factory.req)().qry(getInvitationQuerySchema).bld(),
|
|
2428
|
+
responses: (0, _faire_auth_core_factory.res)(getInvitationResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").err(401, "Not allowed to perform action or limit reached").bld()
|
|
2464
2429
|
}), (_authOptions) => async (ctx) => {
|
|
2465
2430
|
const { id } = ctx.req.valid("query");
|
|
2466
2431
|
const session = ctx.get("session");
|
|
2467
2432
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
2468
2433
|
const invitation = await adapter.findInvitationById(id);
|
|
2469
2434
|
if (!invitation || invitation.status !== "pending" || invitation.expiresAt < /* @__PURE__ */ new Date()) return ctx.render({
|
|
2470
|
-
success:
|
|
2435
|
+
success: _faire_auth_core_static.False,
|
|
2471
2436
|
message: "Invitation not found!"
|
|
2472
2437
|
}, 400);
|
|
2473
2438
|
if (invitation.email.toLowerCase() !== session.user.email.toLowerCase()) return ctx.render({
|
|
2474
|
-
success:
|
|
2439
|
+
success: _faire_auth_core_static.False,
|
|
2475
2440
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_THE_RECIPIENT_OF_THE_INVITATION
|
|
2476
2441
|
}, 403);
|
|
2477
|
-
const organization
|
|
2478
|
-
if (!organization
|
|
2479
|
-
success:
|
|
2442
|
+
const organization = await adapter.findOrganizationById(invitation.organizationId);
|
|
2443
|
+
if (!organization) return ctx.render({
|
|
2444
|
+
success: _faire_auth_core_static.False,
|
|
2480
2445
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2481
2446
|
}, 400);
|
|
2482
2447
|
const member = await adapter.findMemberByOrgId({
|
|
@@ -2484,29 +2449,29 @@ const getInvitation = (options) => require_session.createEndpoint((0, __faire_au
|
|
|
2484
2449
|
organizationId: invitation.organizationId
|
|
2485
2450
|
});
|
|
2486
2451
|
if (!member) return ctx.render({
|
|
2487
|
-
success:
|
|
2452
|
+
success: _faire_auth_core_static.False,
|
|
2488
2453
|
message: ORGANIZATION_ERROR_CODES.INVITER_IS_NO_LONGER_A_MEMBER_OF_THE_ORGANIZATION
|
|
2489
2454
|
}, 400);
|
|
2490
2455
|
return ctx.render({
|
|
2491
2456
|
...invitation,
|
|
2492
|
-
organizationName: organization
|
|
2493
|
-
organizationSlug: organization
|
|
2457
|
+
organizationName: organization["name"],
|
|
2458
|
+
organizationSlug: organization["slug"],
|
|
2494
2459
|
inviterEmail: member.user.email
|
|
2495
2460
|
}, 200);
|
|
2496
2461
|
});
|
|
2497
|
-
const listInvitations = (options) => require_session.createEndpoint((0,
|
|
2462
|
+
const listInvitations = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2498
2463
|
operationId: "listInvitations",
|
|
2499
2464
|
method: "get",
|
|
2500
2465
|
path: "/organization/list-invitations",
|
|
2501
2466
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
2502
|
-
request: (0,
|
|
2503
|
-
responses: (0,
|
|
2467
|
+
request: (0, _faire_auth_core_factory.req)().qry(listInvitationsQuerySchema).bld(),
|
|
2468
|
+
responses: (0, _faire_auth_core_factory.res)(listInvitationsResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").err(401, "Not allowed to perform action or limit reached").bld()
|
|
2504
2469
|
}), (_authOptions) => async (ctx) => {
|
|
2505
2470
|
const session = ctx.get("session");
|
|
2506
2471
|
const { organizationId } = ctx.req.valid("query");
|
|
2507
2472
|
const orgId = organizationId ?? session.session.activeOrganizationId;
|
|
2508
2473
|
if (!orgId) return ctx.render({
|
|
2509
|
-
success:
|
|
2474
|
+
success: _faire_auth_core_static.False,
|
|
2510
2475
|
message: "Organization ID is required"
|
|
2511
2476
|
}, 400);
|
|
2512
2477
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -2514,7 +2479,7 @@ const listInvitations = (options) => require_session.createEndpoint((0, __faire_
|
|
|
2514
2479
|
userId: session.user.id,
|
|
2515
2480
|
organizationId: orgId
|
|
2516
2481
|
})) return ctx.render({
|
|
2517
|
-
success:
|
|
2482
|
+
success: _faire_auth_core_static.False,
|
|
2518
2483
|
message: "You are not a member of this organization"
|
|
2519
2484
|
}, 401);
|
|
2520
2485
|
const invitations = await adapter.listInvitations({ organizationId: orgId });
|
|
@@ -2523,72 +2488,70 @@ const listInvitations = (options) => require_session.createEndpoint((0, __faire_
|
|
|
2523
2488
|
/**
|
|
2524
2489
|
* List all invitations a user has received
|
|
2525
2490
|
*/
|
|
2526
|
-
const listUserInvitations = (options) => require_session.createEndpoint((0,
|
|
2491
|
+
const listUserInvitations = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2527
2492
|
operationId: "listUserInvitations",
|
|
2528
2493
|
method: "get",
|
|
2529
2494
|
path: "/organization/list-user-invitations",
|
|
2530
2495
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(options)],
|
|
2531
|
-
request: (0,
|
|
2532
|
-
responses: (0,
|
|
2496
|
+
request: (0, _faire_auth_core_factory.req)().qry(listUserInvitationsQuerySchema).bld(),
|
|
2497
|
+
responses: (0, _faire_auth_core_factory.res)(listInvitationsResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Not found or already invited").bld()
|
|
2533
2498
|
}), (_authOptions) => async (ctx) => {
|
|
2534
2499
|
const session = ctx.get("session");
|
|
2535
2500
|
const { email } = ctx.req.valid("query");
|
|
2536
2501
|
if (!ctx.get("isServer") && email) return ctx.render({
|
|
2537
|
-
success:
|
|
2502
|
+
success: _faire_auth_core_static.False,
|
|
2538
2503
|
message: "User email cannot be passed for client side API calls."
|
|
2539
2504
|
}, 400);
|
|
2540
2505
|
const userEmail = session?.user.email ?? email;
|
|
2541
2506
|
if (!userEmail) return ctx.render({
|
|
2542
|
-
success:
|
|
2507
|
+
success: _faire_auth_core_static.False,
|
|
2543
2508
|
message: "Missing session headers, or email query parameter."
|
|
2544
2509
|
}, 400);
|
|
2545
2510
|
const invitations = await getOrgAdapter(ctx.get("context"), options).listUserInvitations(userEmail);
|
|
2546
2511
|
return ctx.render(invitations, 200);
|
|
2547
2512
|
});
|
|
2548
|
-
|
|
2549
|
-
//#endregion
|
|
2550
|
-
//#region src/plugins/organization/routes/crud-members.ts
|
|
2513
|
+
// src/plugins/organization/routes/crud-members.ts
|
|
2551
2514
|
const addMember = (option) => {
|
|
2552
|
-
const additionalFieldsSchema =
|
|
2515
|
+
const additionalFieldsSchema = require_db_index.toZodSchema({
|
|
2553
2516
|
fields: option?.schema?.member?.additionalFields ?? {},
|
|
2554
2517
|
isClientSide: true
|
|
2555
2518
|
});
|
|
2556
|
-
return require_session.createEndpoint((0,
|
|
2519
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2557
2520
|
operationId: "addMember",
|
|
2558
2521
|
method: "post",
|
|
2559
2522
|
path: "/organization/add-member",
|
|
2560
2523
|
SERVER_ONLY: true,
|
|
2561
2524
|
description: "Add a user as a member to an organization",
|
|
2562
2525
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(option)],
|
|
2563
|
-
request: (0,
|
|
2564
|
-
responses: (0,
|
|
2526
|
+
request: (0, _faire_auth_core_factory.req)().bdy(addMemberSchema.extend(additionalFieldsSchema.shape)).bld(),
|
|
2527
|
+
responses: (0, _faire_auth_core_factory.res)(memberSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "User not found or already a member").err(401, "Not allowed to perform action").err(403, "Membership limit reached").bld()
|
|
2565
2528
|
}), (_authOptions) => async (ctx) => {
|
|
2566
|
-
let { organizationId, role
|
|
2529
|
+
let { organizationId, role, userId, teamId, ...additionalFields } = ctx.req.valid("json");
|
|
2567
2530
|
const session = userId == null || organizationId == null ? ctx.get("session") ?? null : null;
|
|
2568
2531
|
userId ??= session?.user.id;
|
|
2569
2532
|
organizationId ??= session?.session.activeOrganizationId;
|
|
2570
2533
|
if (!organizationId) return ctx.render({
|
|
2571
|
-
success:
|
|
2534
|
+
success: _faire_auth_core_static.False,
|
|
2572
2535
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
2573
2536
|
}, 400);
|
|
2574
2537
|
if (teamId && !option.teams?.enabled) {
|
|
2575
2538
|
ctx.get("context").logger.error("Teams are not enabled");
|
|
2576
2539
|
return ctx.render({
|
|
2577
|
-
success:
|
|
2540
|
+
success: _faire_auth_core_static.False,
|
|
2578
2541
|
message: "Teams are not enabled"
|
|
2579
2542
|
}, 400);
|
|
2580
2543
|
}
|
|
2581
2544
|
const adapter = getOrgAdapter(ctx.get("context"), option);
|
|
2582
2545
|
const user = session?.user ?? await ctx.get("context").internalAdapter.findUserById(userId);
|
|
2583
2546
|
if (!user) return ctx.render({
|
|
2584
|
-
success:
|
|
2585
|
-
message:
|
|
2547
|
+
success: _faire_auth_core_static.False,
|
|
2548
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.USER_NOT_FOUND
|
|
2586
2549
|
}, 400);
|
|
2587
2550
|
if (await adapter.findMemberByEmail({
|
|
2588
2551
|
email: user.email,
|
|
2589
2552
|
organizationId
|
|
2590
2553
|
})) return ctx.render({
|
|
2591
|
-
success:
|
|
2554
|
+
success: _faire_auth_core_static.False,
|
|
2592
2555
|
message: ORGANIZATION_ERROR_CODES.USER_IS_ALREADY_A_MEMBER_OF_THIS_ORGANIZATION
|
|
2593
2556
|
}, 400);
|
|
2594
2557
|
if (teamId) {
|
|
@@ -2597,24 +2560,24 @@ const addMember = (option) => {
|
|
|
2597
2560
|
organizationId
|
|
2598
2561
|
});
|
|
2599
2562
|
if (!team || team.organizationId !== organizationId) return ctx.render({
|
|
2600
|
-
success:
|
|
2563
|
+
success: _faire_auth_core_static.False,
|
|
2601
2564
|
message: ORGANIZATION_ERROR_CODES.TEAM_NOT_FOUND
|
|
2602
2565
|
}, 400);
|
|
2603
2566
|
}
|
|
2604
2567
|
const membershipLimit = ctx.get("orgOptions").membershipLimit ?? 100;
|
|
2605
2568
|
if (await adapter.countMembers({ organizationId }) >= membershipLimit) return ctx.render({
|
|
2606
|
-
success:
|
|
2569
|
+
success: _faire_auth_core_static.False,
|
|
2607
2570
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_MEMBERSHIP_LIMIT_REACHED
|
|
2608
2571
|
}, 403);
|
|
2609
|
-
const organization
|
|
2610
|
-
if (!organization
|
|
2611
|
-
success:
|
|
2572
|
+
const organization = await adapter.findOrganizationById(organizationId);
|
|
2573
|
+
if (!organization) return ctx.render({
|
|
2574
|
+
success: _faire_auth_core_static.False,
|
|
2612
2575
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2613
2576
|
}, 400);
|
|
2614
2577
|
let memberData = {
|
|
2615
2578
|
organizationId,
|
|
2616
2579
|
userId: user.id,
|
|
2617
|
-
role: parseRoles(role
|
|
2580
|
+
role: parseRoles(role),
|
|
2618
2581
|
createdAt: /* @__PURE__ */ new Date(),
|
|
2619
2582
|
...additionalFields ? additionalFields : {}
|
|
2620
2583
|
};
|
|
@@ -2623,11 +2586,11 @@ const addMember = (option) => {
|
|
|
2623
2586
|
member: {
|
|
2624
2587
|
userId: user.id,
|
|
2625
2588
|
organizationId,
|
|
2626
|
-
role: parseRoles(role
|
|
2589
|
+
role: parseRoles(role),
|
|
2627
2590
|
...additionalFields
|
|
2628
2591
|
},
|
|
2629
2592
|
user,
|
|
2630
|
-
organization
|
|
2593
|
+
organization
|
|
2631
2594
|
});
|
|
2632
2595
|
if (response && typeof response === "object" && "data" in response) memberData = {
|
|
2633
2596
|
...memberData,
|
|
@@ -2642,25 +2605,25 @@ const addMember = (option) => {
|
|
|
2642
2605
|
if (option?.organizationHooks?.afterAddMember) await option?.organizationHooks.afterAddMember({
|
|
2643
2606
|
member: createdMember,
|
|
2644
2607
|
user,
|
|
2645
|
-
organization
|
|
2608
|
+
organization
|
|
2646
2609
|
});
|
|
2647
2610
|
return ctx.render(createdMember, 200);
|
|
2648
2611
|
});
|
|
2649
2612
|
};
|
|
2650
|
-
const removeMember = (option) => require_session.createEndpoint((0,
|
|
2613
|
+
const removeMember = (option) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2651
2614
|
operationId: "removeMember",
|
|
2652
2615
|
method: "post",
|
|
2653
2616
|
path: "/organization/remove-member",
|
|
2654
2617
|
description: "Remove a member from an organization",
|
|
2655
2618
|
middleware: [orgSessionMiddleware, orgMiddleware(option)],
|
|
2656
|
-
request: (0,
|
|
2657
|
-
responses: (0,
|
|
2619
|
+
request: (0, _faire_auth_core_factory.req)().bdy(removeMemberSchema).bld(),
|
|
2620
|
+
responses: (0, _faire_auth_core_factory.res)(memberSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Member not found").err(401, "Not allowed to perform action or limit reached").bld()
|
|
2658
2621
|
}), (_authOptions) => async (ctx) => {
|
|
2659
2622
|
const session = ctx.get("session");
|
|
2660
2623
|
let { memberIdOrEmail, organizationId } = ctx.req.valid("json");
|
|
2661
2624
|
organizationId ??= session.session.activeOrganizationId;
|
|
2662
2625
|
if (!organizationId) return ctx.render({
|
|
2663
|
-
success:
|
|
2626
|
+
success: _faire_auth_core_static.False,
|
|
2664
2627
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
2665
2628
|
}, 400);
|
|
2666
2629
|
const adapter = getOrgAdapter(ctx.get("context"), option);
|
|
@@ -2669,7 +2632,7 @@ const removeMember = (option) => require_session.createEndpoint((0, __faire_auth
|
|
|
2669
2632
|
organizationId
|
|
2670
2633
|
});
|
|
2671
2634
|
if (!member) return ctx.render({
|
|
2672
|
-
success:
|
|
2635
|
+
success: _faire_auth_core_static.False,
|
|
2673
2636
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2674
2637
|
}, 400);
|
|
2675
2638
|
let toBeRemovedMember = null;
|
|
@@ -2679,19 +2642,19 @@ const removeMember = (option) => require_session.createEndpoint((0, __faire_auth
|
|
|
2679
2642
|
});
|
|
2680
2643
|
else toBeRemovedMember = await adapter.findMemberById(memberIdOrEmail);
|
|
2681
2644
|
if (!toBeRemovedMember) return ctx.render({
|
|
2682
|
-
success:
|
|
2645
|
+
success: _faire_auth_core_static.False,
|
|
2683
2646
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2684
2647
|
}, 400);
|
|
2685
2648
|
const roles = toBeRemovedMember.role.split(",");
|
|
2686
2649
|
const creatorRole = ctx.get("orgOptions").creatorRole || "owner";
|
|
2687
2650
|
if (roles.includes(creatorRole)) {
|
|
2688
2651
|
if (member.role !== creatorRole) return ctx.render({
|
|
2689
|
-
success:
|
|
2652
|
+
success: _faire_auth_core_static.False,
|
|
2690
2653
|
message: ORGANIZATION_ERROR_CODES.YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER
|
|
2691
2654
|
}, 400);
|
|
2692
2655
|
const { members } = await adapter.listMembers({ organizationId });
|
|
2693
2656
|
if (members.filter((m) => m.role.split(",").includes(creatorRole)).length <= 1) return ctx.render({
|
|
2694
|
-
success:
|
|
2657
|
+
success: _faire_auth_core_static.False,
|
|
2695
2658
|
message: ORGANIZATION_ERROR_CODES.YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER
|
|
2696
2659
|
}, 400);
|
|
2697
2660
|
}
|
|
@@ -2701,51 +2664,51 @@ const removeMember = (option) => require_session.createEndpoint((0, __faire_auth
|
|
|
2701
2664
|
permissions: { member: ["delete"] },
|
|
2702
2665
|
organizationId
|
|
2703
2666
|
}, ctx)) return ctx.render({
|
|
2704
|
-
success:
|
|
2667
|
+
success: _faire_auth_core_static.False,
|
|
2705
2668
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_MEMBER
|
|
2706
2669
|
}, 401);
|
|
2707
2670
|
if (toBeRemovedMember?.organizationId !== organizationId) return ctx.render({
|
|
2708
|
-
success:
|
|
2671
|
+
success: _faire_auth_core_static.False,
|
|
2709
2672
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2710
2673
|
}, 400);
|
|
2711
|
-
const organization
|
|
2712
|
-
if (!organization
|
|
2713
|
-
status:
|
|
2674
|
+
const organization = await adapter.findOrganizationById(organizationId);
|
|
2675
|
+
if (!organization) return ctx.render({
|
|
2676
|
+
status: _faire_auth_core_static.False,
|
|
2714
2677
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2715
2678
|
}, 400);
|
|
2716
2679
|
const userBeingRemoved = await ctx.get("context").internalAdapter.findUserById(toBeRemovedMember.userId);
|
|
2717
2680
|
if (!userBeingRemoved) return ctx.render({
|
|
2718
|
-
status:
|
|
2681
|
+
status: _faire_auth_core_static.False,
|
|
2719
2682
|
message: "User not found"
|
|
2720
2683
|
}, 400);
|
|
2721
2684
|
if (option?.organizationHooks?.beforeRemoveMember) await option?.organizationHooks.beforeRemoveMember({
|
|
2722
2685
|
member: toBeRemovedMember,
|
|
2723
2686
|
user: userBeingRemoved,
|
|
2724
|
-
organization
|
|
2687
|
+
organization
|
|
2725
2688
|
});
|
|
2726
2689
|
await adapter.deleteMember(toBeRemovedMember.id);
|
|
2727
2690
|
if (session.user.id === toBeRemovedMember.userId && session.session.activeOrganizationId === toBeRemovedMember.organizationId) await adapter.setActiveOrganization(session.session.token, null);
|
|
2728
2691
|
if (option?.organizationHooks?.afterRemoveMember) await option?.organizationHooks.afterRemoveMember({
|
|
2729
2692
|
member: toBeRemovedMember,
|
|
2730
2693
|
user: userBeingRemoved,
|
|
2731
|
-
organization
|
|
2694
|
+
organization
|
|
2732
2695
|
});
|
|
2733
2696
|
return ctx.render(toBeRemovedMember, 200);
|
|
2734
2697
|
});
|
|
2735
|
-
const updateMemberRole = (option) => require_session.createEndpoint((0,
|
|
2698
|
+
const updateMemberRole = (option) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2736
2699
|
operationId: "updateMemberRole",
|
|
2737
2700
|
method: "post",
|
|
2738
2701
|
path: "/organization/update-member-role",
|
|
2739
2702
|
description: "Update the role of a member in an organization",
|
|
2740
2703
|
middleware: [orgSessionMiddleware, orgMiddleware(option)],
|
|
2741
|
-
request: (0,
|
|
2742
|
-
responses: (0,
|
|
2704
|
+
request: (0, _faire_auth_core_factory.req)().bdy(updateMemberRoleSchema).bld(),
|
|
2705
|
+
responses: (0, _faire_auth_core_factory.res)(memberSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Member not found").err(401, "Member limit reached").err(403, "Not allowed to perform this action").bld()
|
|
2743
2706
|
}), (_authOptions) => async (ctx) => {
|
|
2744
2707
|
const session = ctx.get("session");
|
|
2745
|
-
const { role
|
|
2708
|
+
const { role, memberId, organizationId: requestOrganizationId } = ctx.req.valid("json");
|
|
2746
2709
|
const organizationId = requestOrganizationId ?? session.session.activeOrganizationId;
|
|
2747
2710
|
if (!organizationId) return ctx.render({
|
|
2748
|
-
success:
|
|
2711
|
+
success: _faire_auth_core_static.False,
|
|
2749
2712
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
2750
2713
|
}, 400);
|
|
2751
2714
|
const adapter = getOrgAdapter(ctx.get("context"), option);
|
|
@@ -2754,28 +2717,28 @@ const updateMemberRole = (option) => require_session.createEndpoint((0, __faire_
|
|
|
2754
2717
|
organizationId
|
|
2755
2718
|
});
|
|
2756
2719
|
if (!member) return ctx.render({
|
|
2757
|
-
success:
|
|
2720
|
+
success: _faire_auth_core_static.False,
|
|
2758
2721
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2759
2722
|
}, 400);
|
|
2760
2723
|
const toBeUpdatedMember = member.id !== memberId ? await adapter.findMemberById(memberId) : member;
|
|
2761
2724
|
if (!toBeUpdatedMember) return ctx.render({
|
|
2762
|
-
success:
|
|
2725
|
+
success: _faire_auth_core_static.False,
|
|
2763
2726
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2764
2727
|
}, 400);
|
|
2765
2728
|
if (toBeUpdatedMember.organizationId !== organizationId) return ctx.render({
|
|
2766
|
-
success:
|
|
2729
|
+
success: _faire_auth_core_static.False,
|
|
2767
2730
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER
|
|
2768
2731
|
}, 403);
|
|
2769
2732
|
const creatorRole = ctx.get("orgOptions").creatorRole ?? "owner";
|
|
2770
2733
|
const updatingMemberRoles = member.role.split(",");
|
|
2771
2734
|
const toBeUpdatedMemberRoles = toBeUpdatedMember.role.split(",");
|
|
2772
|
-
const roleToSet = Array.isArray(role
|
|
2735
|
+
const roleToSet = Array.isArray(role) ? role : [role];
|
|
2773
2736
|
const isUpdatingCreator = toBeUpdatedMemberRoles.includes(creatorRole);
|
|
2774
2737
|
const updaterIsCreator = updatingMemberRoles.includes(creatorRole);
|
|
2775
2738
|
const isSettingCreatorRole = roleToSet.includes(creatorRole);
|
|
2776
2739
|
const memberIsUpdatingThemselves = member.id === toBeUpdatedMember.id;
|
|
2777
2740
|
if (isUpdatingCreator && !updaterIsCreator || isSettingCreatorRole && !updaterIsCreator) return ctx.render({
|
|
2778
|
-
success:
|
|
2741
|
+
success: _faire_auth_core_static.False,
|
|
2779
2742
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER
|
|
2780
2743
|
}, 403);
|
|
2781
2744
|
if (updaterIsCreator && memberIsUpdatingThemselves) {
|
|
@@ -2785,10 +2748,10 @@ const updateMemberRole = (option) => require_session.createEndpoint((0, __faire_
|
|
|
2785
2748
|
field: "organizationId",
|
|
2786
2749
|
value: organizationId
|
|
2787
2750
|
}]
|
|
2788
|
-
})).filter((member
|
|
2789
|
-
return member
|
|
2751
|
+
})).filter((member) => {
|
|
2752
|
+
return member.role.split(",").includes(creatorRole);
|
|
2790
2753
|
}).length <= 1 && !isSettingCreatorRole) return ctx.render({
|
|
2791
|
-
success:
|
|
2754
|
+
success: _faire_auth_core_static.False,
|
|
2792
2755
|
message: ORGANIZATION_ERROR_CODES.YOU_CANNOT_LEAVE_THE_ORGANIZATION_WITHOUT_AN_OWNER
|
|
2793
2756
|
}, 400);
|
|
2794
2757
|
}
|
|
@@ -2799,68 +2762,68 @@ const updateMemberRole = (option) => require_session.createEndpoint((0, __faire_
|
|
|
2799
2762
|
allowCreatorAllPermissions: true,
|
|
2800
2763
|
organizationId
|
|
2801
2764
|
}, ctx)) return ctx.render({
|
|
2802
|
-
success:
|
|
2765
|
+
success: _faire_auth_core_static.False,
|
|
2803
2766
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_MEMBER
|
|
2804
2767
|
}, 403);
|
|
2805
|
-
const organization
|
|
2806
|
-
if (!organization
|
|
2807
|
-
success:
|
|
2768
|
+
const organization = await adapter.findOrganizationById(organizationId);
|
|
2769
|
+
if (!organization) return ctx.render({
|
|
2770
|
+
success: _faire_auth_core_static.False,
|
|
2808
2771
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
2809
2772
|
}, 400);
|
|
2810
2773
|
const userBeingUpdated = await ctx.get("context").internalAdapter.findUserById(toBeUpdatedMember.userId);
|
|
2811
2774
|
if (!userBeingUpdated) return ctx.render({
|
|
2812
|
-
success:
|
|
2775
|
+
success: _faire_auth_core_static.False,
|
|
2813
2776
|
message: "User not found"
|
|
2814
2777
|
}, 400);
|
|
2815
2778
|
const previousRole = toBeUpdatedMember.role;
|
|
2816
|
-
const newRole = parseRoles(role
|
|
2779
|
+
const newRole = parseRoles(role);
|
|
2817
2780
|
if (option?.organizationHooks?.beforeUpdateMemberRole) {
|
|
2818
2781
|
const response = await option?.organizationHooks.beforeUpdateMemberRole({
|
|
2819
2782
|
member: toBeUpdatedMember,
|
|
2820
2783
|
newRole,
|
|
2821
2784
|
user: userBeingUpdated,
|
|
2822
|
-
organization
|
|
2785
|
+
organization
|
|
2823
2786
|
});
|
|
2824
2787
|
if (response && typeof response === "object" && "data" in response) {
|
|
2825
|
-
const updatedMember
|
|
2826
|
-
if (!updatedMember
|
|
2827
|
-
success:
|
|
2788
|
+
const updatedMember = await adapter.updateMember(memberId, response.data.role ?? newRole);
|
|
2789
|
+
if (!updatedMember) return ctx.render({
|
|
2790
|
+
success: _faire_auth_core_static.False,
|
|
2828
2791
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2829
2792
|
}, 400);
|
|
2830
2793
|
if (option?.organizationHooks?.afterUpdateMemberRole) await option?.organizationHooks.afterUpdateMemberRole({
|
|
2831
|
-
member: updatedMember
|
|
2794
|
+
member: updatedMember,
|
|
2832
2795
|
previousRole,
|
|
2833
2796
|
user: userBeingUpdated,
|
|
2834
|
-
organization
|
|
2797
|
+
organization
|
|
2835
2798
|
});
|
|
2836
|
-
return ctx.render(updatedMember
|
|
2799
|
+
return ctx.render(updatedMember, 200);
|
|
2837
2800
|
}
|
|
2838
2801
|
}
|
|
2839
2802
|
const updatedMember = await adapter.updateMember(memberId, newRole);
|
|
2840
2803
|
if (!updatedMember) return ctx.render({
|
|
2841
|
-
success:
|
|
2804
|
+
success: _faire_auth_core_static.False,
|
|
2842
2805
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2843
2806
|
}, 400);
|
|
2844
2807
|
if (option?.organizationHooks?.afterUpdateMemberRole) await option?.organizationHooks.afterUpdateMemberRole({
|
|
2845
2808
|
member: updatedMember,
|
|
2846
2809
|
previousRole,
|
|
2847
2810
|
user: userBeingUpdated,
|
|
2848
|
-
organization
|
|
2811
|
+
organization
|
|
2849
2812
|
});
|
|
2850
2813
|
return ctx.render(updatedMember, 200);
|
|
2851
2814
|
});
|
|
2852
|
-
const getActiveMember = (option) => require_session.createEndpoint((0,
|
|
2815
|
+
const getActiveMember = (option) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2853
2816
|
operationId: "getActiveMember",
|
|
2854
2817
|
method: "get",
|
|
2855
2818
|
path: "/organization/get-active-member",
|
|
2856
2819
|
description: "Get the member details of the active organization",
|
|
2857
2820
|
middleware: [orgSessionMiddleware, orgMiddleware(option)],
|
|
2858
|
-
responses: (0,
|
|
2821
|
+
responses: (0, _faire_auth_core_factory.res)(memberSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "No active organization").bld()
|
|
2859
2822
|
}), (_authOptions) => async (ctx) => {
|
|
2860
2823
|
const session = ctx.get("session");
|
|
2861
2824
|
const organizationId = session.session.activeOrganizationId;
|
|
2862
2825
|
if (!organizationId) return ctx.render({
|
|
2863
|
-
success:
|
|
2826
|
+
success: _faire_auth_core_static.False,
|
|
2864
2827
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
2865
2828
|
}, 400);
|
|
2866
2829
|
const member = await getOrgAdapter(ctx.get("context"), option).findMemberByOrgId({
|
|
@@ -2868,19 +2831,19 @@ const getActiveMember = (option) => require_session.createEndpoint((0, __faire_a
|
|
|
2868
2831
|
organizationId
|
|
2869
2832
|
});
|
|
2870
2833
|
if (!member) return ctx.render({
|
|
2871
|
-
success:
|
|
2834
|
+
success: _faire_auth_core_static.False,
|
|
2872
2835
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2873
2836
|
}, 400);
|
|
2874
2837
|
return ctx.render(member, 200);
|
|
2875
2838
|
});
|
|
2876
|
-
const leaveOrganization = (option) => require_session.createEndpoint((0,
|
|
2839
|
+
const leaveOrganization = (option) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2877
2840
|
operationId: "leaveOrganization",
|
|
2878
2841
|
method: "post",
|
|
2879
2842
|
path: "/organization/leave",
|
|
2880
2843
|
description: "Leave an organization",
|
|
2881
2844
|
middleware: [orgSessionMiddleware, orgMiddleware(option)],
|
|
2882
|
-
request: (0,
|
|
2883
|
-
responses: (0,
|
|
2845
|
+
request: (0, _faire_auth_core_factory.req)().bdy(leaveOrganizationSchema).bld(),
|
|
2846
|
+
responses: (0, _faire_auth_core_factory.res)(memberSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Cannot leave as the only owner").bld()
|
|
2884
2847
|
}), (_authOptions) => async (ctx) => {
|
|
2885
2848
|
const session = ctx.get("session");
|
|
2886
2849
|
const { organizationId } = ctx.req.valid("json");
|
|
@@ -2890,7 +2853,7 @@ const leaveOrganization = (option) => require_session.createEndpoint((0, __faire
|
|
|
2890
2853
|
organizationId
|
|
2891
2854
|
});
|
|
2892
2855
|
if (!member) return ctx.render({
|
|
2893
|
-
success:
|
|
2856
|
+
success: _faire_auth_core_static.False,
|
|
2894
2857
|
message: ORGANIZATION_ERROR_CODES.MEMBER_NOT_FOUND
|
|
2895
2858
|
}, 400);
|
|
2896
2859
|
const creatorRole = ctx.get("orgOptions").creatorRole ?? "owner";
|
|
@@ -2905,7 +2868,7 @@ const leaveOrganization = (option) => require_session.createEndpoint((0, __faire
|
|
|
2905
2868
|
})).filter((m) => {
|
|
2906
2869
|
return m.role.split(",").includes(creatorRole);
|
|
2907
2870
|
}).length <= 1) return ctx.render({
|
|
2908
|
-
success:
|
|
2871
|
+
success: _faire_auth_core_static.False,
|
|
2909
2872
|
message: ORGANIZATION_ERROR_CODES.YOU_CANNOT_LEAVE_THE_ORGANIZATION_AS_THE_ONLY_OWNER
|
|
2910
2873
|
}, 400);
|
|
2911
2874
|
}
|
|
@@ -2913,20 +2876,20 @@ const leaveOrganization = (option) => require_session.createEndpoint((0, __faire
|
|
|
2913
2876
|
if (session.session.activeOrganizationId === organizationId) await adapter.setActiveOrganization(session.session.token, null);
|
|
2914
2877
|
return ctx.render(member, 200);
|
|
2915
2878
|
});
|
|
2916
|
-
const listMembers = (option) => require_session.createEndpoint((0,
|
|
2879
|
+
const listMembers = (option) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2917
2880
|
operationId: "listMembers",
|
|
2918
2881
|
method: "get",
|
|
2919
2882
|
path: "/organization/list-members",
|
|
2920
2883
|
description: "List all members of an organization",
|
|
2921
2884
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(option)],
|
|
2922
|
-
request: (0,
|
|
2923
|
-
responses: (0,
|
|
2885
|
+
request: (0, _faire_auth_core_factory.req)().qry(listMembersQuerySchema).bld(),
|
|
2886
|
+
responses: (0, _faire_auth_core_factory.res)(memberListResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "No active organization").err(403, "Not allowed to perform action or limit reached").bld()
|
|
2924
2887
|
}), (_authOptions) => async (ctx) => {
|
|
2925
2888
|
const session = ctx.get("session");
|
|
2926
2889
|
let { limit, offset, sortBy, sortDirection, filterField, filterValue, filterOperator, organizationId } = ctx.req.valid("query");
|
|
2927
2890
|
organizationId ??= session?.session.activeOrganizationId;
|
|
2928
2891
|
if (!organizationId) return ctx.render({
|
|
2929
|
-
success:
|
|
2892
|
+
success: _faire_auth_core_static.False,
|
|
2930
2893
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
2931
2894
|
}, 400);
|
|
2932
2895
|
const adapter = getOrgAdapter(ctx.get("context"), option);
|
|
@@ -2934,7 +2897,7 @@ const listMembers = (option) => require_session.createEndpoint((0, __faire_auth_
|
|
|
2934
2897
|
userId: session.user.id,
|
|
2935
2898
|
organizationId
|
|
2936
2899
|
}) : null) && !ctx.get("isServer")) return ctx.render({
|
|
2937
|
-
success:
|
|
2900
|
+
success: _faire_auth_core_static.False,
|
|
2938
2901
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
2939
2902
|
}, 403);
|
|
2940
2903
|
const { members, total } = await adapter.listMembers({
|
|
@@ -2954,23 +2917,23 @@ const listMembers = (option) => require_session.createEndpoint((0, __faire_auth_
|
|
|
2954
2917
|
total
|
|
2955
2918
|
}, 200);
|
|
2956
2919
|
});
|
|
2957
|
-
const getActiveMemberRole = (option) => require_session.createEndpoint((0,
|
|
2920
|
+
const getActiveMemberRole = (option) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2958
2921
|
operationId: "getActiveMemberRole",
|
|
2959
2922
|
method: "get",
|
|
2960
2923
|
path: "/organization/get-active-member-role",
|
|
2961
2924
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(option)],
|
|
2962
|
-
request: (0,
|
|
2925
|
+
request: (0, _faire_auth_core_factory.req)().qry(zod.object({
|
|
2963
2926
|
userId: zod.string().openapi({ description: "The user ID to get the role for. If not provided, will default to the current user's" }).optional(),
|
|
2964
2927
|
organizationId: zod.string().openapi({ description: "The organization ID to list members for. If not provided, will default to the user's active organization. Eg: \"organization-id\"" }).optional()
|
|
2965
2928
|
})).bld(),
|
|
2966
|
-
responses: (0,
|
|
2929
|
+
responses: (0, _faire_auth_core_factory.res)(zod.string().transform(_faire_auth_core_utils.toSuccess)).err(400, "No active organization").err(403, "Not member of organization").bld()
|
|
2967
2930
|
}), (_authOptions) => async (ctx) => {
|
|
2968
2931
|
let { userId, organizationId } = ctx.req.valid("query");
|
|
2969
2932
|
const session = userId == null || organizationId == null ? ctx.get("session") ?? null : null;
|
|
2970
2933
|
userId ??= session?.user.id;
|
|
2971
2934
|
organizationId ??= session?.session.activeOrganizationId;
|
|
2972
2935
|
if (!organizationId || !userId) return ctx.render({
|
|
2973
|
-
success:
|
|
2936
|
+
success: _faire_auth_core_static.False,
|
|
2974
2937
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
2975
2938
|
}, 400);
|
|
2976
2939
|
const member = await getOrgAdapter(ctx.get("context"), option).findMemberByOrgId({
|
|
@@ -2978,58 +2941,56 @@ const getActiveMemberRole = (option) => require_session.createEndpoint((0, __fai
|
|
|
2978
2941
|
organizationId
|
|
2979
2942
|
});
|
|
2980
2943
|
if (!member) return ctx.render({
|
|
2981
|
-
success:
|
|
2944
|
+
success: _faire_auth_core_static.False,
|
|
2982
2945
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION
|
|
2983
2946
|
}, 403);
|
|
2984
2947
|
return ctx.render(member.role, 200);
|
|
2985
2948
|
});
|
|
2986
|
-
|
|
2987
|
-
//#endregion
|
|
2988
|
-
//#region src/plugins/organization/routes/crud-org.ts
|
|
2949
|
+
// src/plugins/organization/routes/crud-org.ts
|
|
2989
2950
|
const createOrganization = (options) => {
|
|
2990
|
-
const additionalFieldsSchema =
|
|
2951
|
+
const additionalFieldsSchema = require_db_index.toZodSchema({
|
|
2991
2952
|
fields: options?.schema?.organization?.additionalFields ?? {},
|
|
2992
2953
|
isClientSide: true
|
|
2993
2954
|
});
|
|
2994
2955
|
const baseSchema = createOrganizationBaseSchema;
|
|
2995
|
-
return require_session.createEndpoint((0,
|
|
2956
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
2996
2957
|
operationId: "createOrganization",
|
|
2997
2958
|
method: "post",
|
|
2998
2959
|
path: "/organization/create",
|
|
2999
2960
|
description: "Create a new organization",
|
|
3000
2961
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(options)],
|
|
3001
|
-
request: (0,
|
|
3002
|
-
responses: (0,
|
|
2962
|
+
request: (0, _faire_auth_core_factory.req)().bdy(baseSchema.extend(additionalFieldsSchema.shape)).bld(),
|
|
2963
|
+
responses: (0, _faire_auth_core_factory.res)(organizationWithMembersSchema.transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(403).bld()
|
|
3003
2964
|
}), (_authOptions) => async (ctx) => {
|
|
3004
2965
|
const session = ctx.get("session");
|
|
3005
|
-
let { name, slug, userId, logo, metadata, keepCurrentActiveOrganization
|
|
2966
|
+
let { name, slug, userId, logo, metadata, keepCurrentActiveOrganization, ...additionalFields } = ctx.req.valid("json");
|
|
3006
2967
|
if (userId && !ctx.get("isServer")) return ctx.render({
|
|
3007
|
-
success:
|
|
2968
|
+
success: _faire_auth_core_static.False,
|
|
3008
2969
|
message: "userId is a server-only field"
|
|
3009
2970
|
}, 401);
|
|
3010
2971
|
userId ??= session?.user.id;
|
|
3011
2972
|
if (!userId) return ctx.render({
|
|
3012
|
-
success:
|
|
2973
|
+
success: _faire_auth_core_static.False,
|
|
3013
2974
|
message: "Could not find userId"
|
|
3014
2975
|
}, 401);
|
|
3015
2976
|
let user = session?.user ?? await ctx.get("context").internalAdapter.findUserById(userId);
|
|
3016
2977
|
if (!user) return ctx.render({
|
|
3017
|
-
success:
|
|
2978
|
+
success: _faire_auth_core_static.False,
|
|
3018
2979
|
message: "Could not find user for userId"
|
|
3019
2980
|
}, 401);
|
|
3020
2981
|
const orgOptions = ctx.get("orgOptions");
|
|
3021
2982
|
if (!(typeof orgOptions?.allowUserToCreateOrganization === "function" ? await orgOptions.allowUserToCreateOrganization(user) : orgOptions?.allowUserToCreateOrganization === void 0 ? true : orgOptions.allowUserToCreateOrganization)) return ctx.render({
|
|
3022
|
-
success:
|
|
2983
|
+
success: _faire_auth_core_static.False,
|
|
3023
2984
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_ORGANIZATION
|
|
3024
2985
|
}, 403);
|
|
3025
2986
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
3026
2987
|
const userOrganizations = await adapter.listOrganizations(user.id);
|
|
3027
2988
|
if (typeof orgOptions.organizationLimit === "number" ? userOrganizations.length >= orgOptions.organizationLimit : typeof orgOptions.organizationLimit === "function" ? await orgOptions.organizationLimit(user) : false) return ctx.render({
|
|
3028
|
-
success:
|
|
2989
|
+
success: _faire_auth_core_static.False,
|
|
3029
2990
|
message: ORGANIZATION_ERROR_CODES.YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_ORGANIZATIONS
|
|
3030
2991
|
}, 403);
|
|
3031
2992
|
if (await adapter.findOrganizationBySlug(slug)) return ctx.render({
|
|
3032
|
-
success:
|
|
2993
|
+
success: _faire_auth_core_static.False,
|
|
3033
2994
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_ALREADY_EXISTS
|
|
3034
2995
|
}, 400);
|
|
3035
2996
|
const orgData = {
|
|
@@ -3050,7 +3011,7 @@ const createOrganization = (options) => {
|
|
|
3050
3011
|
});
|
|
3051
3012
|
if (response && typeof response === "object" && "data" in response) hookResponse = response;
|
|
3052
3013
|
}
|
|
3053
|
-
const organization
|
|
3014
|
+
const organization = await adapter.createOrganization({ organization: {
|
|
3054
3015
|
...orgData,
|
|
3055
3016
|
createdAt: /* @__PURE__ */ new Date(),
|
|
3056
3017
|
...hookResponse?.data || {}
|
|
@@ -3058,15 +3019,15 @@ const createOrganization = (options) => {
|
|
|
3058
3019
|
let member;
|
|
3059
3020
|
let teamMember = null;
|
|
3060
3021
|
if (orgOptions?.teams?.enabled === true && orgOptions.teams.defaultTeam?.enabled !== false) {
|
|
3061
|
-
const defaultTeam = await orgOptions.teams.defaultTeam?.customCreateDefaultTeam?.(organization
|
|
3062
|
-
organizationId: organization
|
|
3063
|
-
name: `${organization
|
|
3022
|
+
const defaultTeam = await orgOptions.teams.defaultTeam?.customCreateDefaultTeam?.(organization, ctx.req) ?? await adapter.createTeam({
|
|
3023
|
+
organizationId: organization.id,
|
|
3024
|
+
name: `${organization.name}`,
|
|
3064
3025
|
createdAt: /* @__PURE__ */ new Date(),
|
|
3065
3026
|
updatedAt: /* @__PURE__ */ new Date()
|
|
3066
3027
|
});
|
|
3067
3028
|
member = await adapter.createMember({
|
|
3068
3029
|
userId: user.id,
|
|
3069
|
-
organizationId: organization
|
|
3030
|
+
organizationId: organization.id,
|
|
3070
3031
|
role: orgOptions.creatorRole ?? "owner"
|
|
3071
3032
|
});
|
|
3072
3033
|
teamMember = await adapter.findOrCreateTeamMember({
|
|
@@ -3075,61 +3036,61 @@ const createOrganization = (options) => {
|
|
|
3075
3036
|
});
|
|
3076
3037
|
} else member = await adapter.createMember({
|
|
3077
3038
|
userId: user.id,
|
|
3078
|
-
organizationId: organization
|
|
3039
|
+
organizationId: organization.id,
|
|
3079
3040
|
role: orgOptions.creatorRole ?? "owner"
|
|
3080
3041
|
});
|
|
3081
3042
|
if (orgOptions.organizationHooks?.afterCreateOrganization) await orgOptions.organizationHooks.afterCreateOrganization({
|
|
3082
|
-
organization
|
|
3043
|
+
organization,
|
|
3083
3044
|
user,
|
|
3084
3045
|
member
|
|
3085
3046
|
});
|
|
3086
|
-
if (session && !keepCurrentActiveOrganization) await adapter.setActiveOrganization(session.session.token, organization
|
|
3047
|
+
if (session && !keepCurrentActiveOrganization) await adapter.setActiveOrganization(session.session.token, organization.id);
|
|
3087
3048
|
if (teamMember && session && !keepCurrentActiveOrganization) await adapter.setActiveTeam(session.session.token, teamMember.teamId);
|
|
3088
3049
|
return ctx.render({
|
|
3089
|
-
...organization
|
|
3090
|
-
metadata: organization
|
|
3050
|
+
...organization,
|
|
3051
|
+
metadata: organization.metadata && typeof organization.metadata === "string" ? JSON.parse(organization.metadata) : organization.metadata,
|
|
3091
3052
|
members: [member]
|
|
3092
3053
|
}, 200);
|
|
3093
3054
|
});
|
|
3094
3055
|
};
|
|
3095
|
-
const checkOrganizationSlug = (options) => require_session.createEndpoint((0,
|
|
3056
|
+
const checkOrganizationSlug = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3096
3057
|
operationId: "checkOrganizationSlug",
|
|
3097
3058
|
method: "post",
|
|
3098
3059
|
path: "/organization/check-slug",
|
|
3099
3060
|
description: "Check if an organization slug is available",
|
|
3100
3061
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(options)],
|
|
3101
|
-
request: (0,
|
|
3102
|
-
responses: (0,
|
|
3062
|
+
request: (0, _faire_auth_core_factory.req)().bdy(checkOrganizationSlugSchema).bld(),
|
|
3063
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default, "Success - Slug is available").err(400, "Slug is taken").zod().bld()
|
|
3103
3064
|
}), (_authOptions) => async (ctx) => {
|
|
3104
3065
|
const { slug } = ctx.req.valid("json");
|
|
3105
3066
|
if (!await getOrgAdapter(ctx.get("context"), options).findOrganizationBySlug(slug)) return ctx.render({
|
|
3106
|
-
success:
|
|
3067
|
+
success: _faire_auth_core_static.True,
|
|
3107
3068
|
message: "Slug is available"
|
|
3108
3069
|
}, 200);
|
|
3109
3070
|
return ctx.render({
|
|
3110
|
-
success:
|
|
3071
|
+
success: _faire_auth_core_static.False,
|
|
3111
3072
|
message: "Slug is taken"
|
|
3112
3073
|
}, 400);
|
|
3113
3074
|
});
|
|
3114
3075
|
const updateOrganization = (options) => {
|
|
3115
|
-
const additionalFieldsSchema =
|
|
3076
|
+
const additionalFieldsSchema = require_db_index.toZodSchema({
|
|
3116
3077
|
fields: options?.schema?.organization?.additionalFields ?? {},
|
|
3117
3078
|
isClientSide: true
|
|
3118
3079
|
});
|
|
3119
|
-
return require_session.createEndpoint((0,
|
|
3080
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3120
3081
|
operationId: "updateOrganization",
|
|
3121
3082
|
method: "post",
|
|
3122
3083
|
path: "/organization/update",
|
|
3123
3084
|
description: "Update an organization",
|
|
3124
3085
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3125
|
-
request: (0,
|
|
3126
|
-
responses: (0,
|
|
3086
|
+
request: (0, _faire_auth_core_factory.req)().bdy(updateOrganizationSchema.extend({ data: updateOrganizationSchema.shape.data.extend(additionalFieldsSchema.shape).partial() })).bld(),
|
|
3087
|
+
responses: (0, _faire_auth_core_factory.res)(organizationSchema.transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(403).bld()
|
|
3127
3088
|
}), (_authOptions) => async (ctx) => {
|
|
3128
3089
|
const session = ctx.get("session");
|
|
3129
3090
|
const { data, organizationId } = ctx.req.valid("json");
|
|
3130
3091
|
const orgId = organizationId ?? session.session.activeOrganizationId;
|
|
3131
3092
|
if (!orgId) return ctx.render({
|
|
3132
|
-
success:
|
|
3093
|
+
success: _faire_auth_core_static.False,
|
|
3133
3094
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3134
3095
|
}, 400);
|
|
3135
3096
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -3138,7 +3099,7 @@ const updateOrganization = (options) => {
|
|
|
3138
3099
|
organizationId: orgId
|
|
3139
3100
|
});
|
|
3140
3101
|
if (!member) return ctx.render({
|
|
3141
|
-
success:
|
|
3102
|
+
success: _faire_auth_core_static.False,
|
|
3142
3103
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3143
3104
|
}, 400);
|
|
3144
3105
|
if (!hasPermission({
|
|
@@ -3147,26 +3108,26 @@ const updateOrganization = (options) => {
|
|
|
3147
3108
|
options: ctx.get("orgOptions"),
|
|
3148
3109
|
organizationId: orgId
|
|
3149
3110
|
}, ctx)) return ctx.render({
|
|
3150
|
-
success:
|
|
3111
|
+
success: _faire_auth_core_static.False,
|
|
3151
3112
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_ORGANIZATION
|
|
3152
3113
|
}, 403);
|
|
3153
3114
|
const updatedOrg = await adapter.updateOrganization(orgId, data);
|
|
3154
3115
|
return ctx.render(updatedOrg, 200);
|
|
3155
3116
|
});
|
|
3156
3117
|
};
|
|
3157
|
-
const deleteOrganization = (options) => require_session.createEndpoint((0,
|
|
3118
|
+
const deleteOrganization = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3158
3119
|
operationId: "deleteOrganization",
|
|
3159
3120
|
method: "post",
|
|
3160
3121
|
path: "/organization/delete",
|
|
3161
3122
|
description: "Delete an organization",
|
|
3162
3123
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3163
|
-
request: (0,
|
|
3164
|
-
responses: (0,
|
|
3124
|
+
request: (0, _faire_auth_core_factory.req)().bdy(deleteOrganizationSchema).bld(),
|
|
3125
|
+
responses: (0, _faire_auth_core_factory.res)(deleteOrganizationResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(403).zod().bld()
|
|
3165
3126
|
}), (_authOptions) => async (ctx) => {
|
|
3166
3127
|
const session = ctx.get("session");
|
|
3167
3128
|
const { organizationId } = ctx.req.valid("json");
|
|
3168
3129
|
if (!organizationId) return ctx.render({
|
|
3169
|
-
success:
|
|
3130
|
+
success: _faire_auth_core_static.False,
|
|
3170
3131
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3171
3132
|
}, 400);
|
|
3172
3133
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -3175,7 +3136,7 @@ const deleteOrganization = (options) => require_session.createEndpoint((0, __fai
|
|
|
3175
3136
|
organizationId
|
|
3176
3137
|
});
|
|
3177
3138
|
if (!member) return ctx.render({
|
|
3178
|
-
success:
|
|
3139
|
+
success: _faire_auth_core_static.False,
|
|
3179
3140
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3180
3141
|
}, 400);
|
|
3181
3142
|
if (!hasPermission({
|
|
@@ -3184,18 +3145,18 @@ const deleteOrganization = (options) => require_session.createEndpoint((0, __fai
|
|
|
3184
3145
|
options: ctx.get("orgOptions"),
|
|
3185
3146
|
organizationId
|
|
3186
3147
|
}, ctx)) return ctx.render({
|
|
3187
|
-
success:
|
|
3148
|
+
success: _faire_auth_core_static.False,
|
|
3188
3149
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_ORGANIZATION
|
|
3189
3150
|
}, 403);
|
|
3190
3151
|
if (organizationId === session.session.activeOrganizationId) await adapter.setActiveOrganization(session.session.token, null);
|
|
3191
3152
|
const orgOptions = ctx.get("orgOptions");
|
|
3192
3153
|
if (orgOptions.disableOrganizationDeletion === true) return ctx.render({
|
|
3193
|
-
success:
|
|
3154
|
+
success: _faire_auth_core_static.False,
|
|
3194
3155
|
message: "Organization deletion is disabled"
|
|
3195
3156
|
}, 403);
|
|
3196
3157
|
const org = await adapter.findOrganizationById(organizationId);
|
|
3197
3158
|
if (!org) return ctx.render({
|
|
3198
|
-
success:
|
|
3159
|
+
success: _faire_auth_core_static.False,
|
|
3199
3160
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3200
3161
|
}, 400);
|
|
3201
3162
|
if (orgOptions.organizationHooks?.beforeDeleteOrganization) await orgOptions.organizationHooks.beforeDeleteOrganization({
|
|
@@ -3210,59 +3171,60 @@ const deleteOrganization = (options) => require_session.createEndpoint((0, __fai
|
|
|
3210
3171
|
return ctx.render(org.id, 200);
|
|
3211
3172
|
});
|
|
3212
3173
|
const getFullOrganization = (options) => {
|
|
3213
|
-
return require_session.createEndpoint((0,
|
|
3174
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3214
3175
|
operationId: "getFullOrganization",
|
|
3215
3176
|
method: "get",
|
|
3216
3177
|
path: "/organization/get-full-organization",
|
|
3217
3178
|
description: "Get the full organization with members and teams",
|
|
3218
3179
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3219
|
-
request: (0,
|
|
3220
|
-
responses: (0,
|
|
3180
|
+
request: (0, _faire_auth_core_factory.req)().qry(getFullOrganizationQuerySchema).bld(),
|
|
3181
|
+
responses: (0, _faire_auth_core_factory.res)(fullOrganizationSchema.transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(403).zod().bld()
|
|
3221
3182
|
}), (_authOptions) => async (ctx) => {
|
|
3222
3183
|
const session = ctx.get("session");
|
|
3223
3184
|
const { organizationId, organizationSlug, membersLimit } = ctx.req.valid("query");
|
|
3224
3185
|
const orgId = organizationSlug ?? organizationId ?? session.session.activeOrganizationId;
|
|
3225
3186
|
if (!orgId) return ctx.render({
|
|
3226
|
-
success:
|
|
3187
|
+
success: _faire_auth_core_static.False,
|
|
3227
3188
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3228
3189
|
}, 400);
|
|
3229
3190
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
3230
|
-
const organization
|
|
3191
|
+
const organization = await adapter.findFullOrganization({
|
|
3231
3192
|
organizationId: orgId,
|
|
3232
3193
|
isSlug: !!organizationSlug,
|
|
3233
3194
|
...membersLimit && { membersLimit },
|
|
3234
3195
|
...ctx.get("orgOptions").teams?.enabled === true && { includeTeams: ctx.get("orgOptions").teams.enabled }
|
|
3235
3196
|
});
|
|
3236
|
-
if (!organization
|
|
3237
|
-
success:
|
|
3197
|
+
if (!organization) return ctx.render({
|
|
3198
|
+
success: _faire_auth_core_static.False,
|
|
3238
3199
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3239
3200
|
}, 400);
|
|
3240
|
-
if (!organization
|
|
3201
|
+
if (!organization.members.find((member) => member.userId === session.user.id)) {
|
|
3241
3202
|
await adapter.setActiveOrganization(session.session.token, null);
|
|
3242
3203
|
return ctx.render({
|
|
3243
|
-
success:
|
|
3204
|
+
success: _faire_auth_core_static.False,
|
|
3244
3205
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3245
3206
|
}, 403);
|
|
3246
3207
|
}
|
|
3247
|
-
return ctx.render(organization
|
|
3208
|
+
return ctx.render(organization, 200);
|
|
3248
3209
|
});
|
|
3249
3210
|
};
|
|
3250
|
-
const setActiveOrganization = (options) => require_session.createEndpoint((0,
|
|
3211
|
+
const setActiveOrganization = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3251
3212
|
operationId: "setActiveOrganization",
|
|
3252
3213
|
method: "post",
|
|
3253
3214
|
path: "/organization/set-active",
|
|
3254
3215
|
description: "Set the active organization",
|
|
3255
3216
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3256
|
-
request: (0,
|
|
3257
|
-
responses: (0,
|
|
3217
|
+
request: (0, _faire_auth_core_factory.req)().bdy(setActiveOrganizationSchema).bld(),
|
|
3218
|
+
responses: (0, _faire_auth_core_factory.res)(organizationSchema.nullable().transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(403).zod().bld()
|
|
3258
3219
|
}), (authOptions) => async (ctx) => {
|
|
3259
3220
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
3260
3221
|
const session = ctx.get("session");
|
|
3261
3222
|
let { organizationId, organizationSlug } = ctx.req.valid("json");
|
|
3262
3223
|
if (organizationId === null) {
|
|
3263
3224
|
if (!session.session.activeOrganizationId) return ctx.render(null, 200);
|
|
3225
|
+
const updatedSession = await adapter.setActiveOrganization(session.session.token, null);
|
|
3264
3226
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
3265
|
-
session:
|
|
3227
|
+
session: updatedSession,
|
|
3266
3228
|
user: session.user
|
|
3267
3229
|
});
|
|
3268
3230
|
return ctx.render(null, 200);
|
|
@@ -3270,21 +3232,21 @@ const setActiveOrganization = (options) => require_session.createEndpoint((0, __
|
|
|
3270
3232
|
if (organizationId === void 0 && organizationSlug === void 0) {
|
|
3271
3233
|
const sessionOrgId = session.session.activeOrganizationId;
|
|
3272
3234
|
if (!sessionOrgId) return ctx.render({
|
|
3273
|
-
success:
|
|
3235
|
+
success: _faire_auth_core_static.False,
|
|
3274
3236
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3275
3237
|
}, 400);
|
|
3276
3238
|
organizationId = sessionOrgId;
|
|
3277
3239
|
}
|
|
3278
3240
|
if (organizationSlug !== void 0 && organizationId === void 0) {
|
|
3279
|
-
const organization
|
|
3280
|
-
if (!organization
|
|
3281
|
-
success:
|
|
3241
|
+
const organization = await adapter.findOrganizationBySlug(organizationSlug);
|
|
3242
|
+
if (!organization) return ctx.render({
|
|
3243
|
+
success: _faire_auth_core_static.False,
|
|
3282
3244
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3283
3245
|
}, 400);
|
|
3284
|
-
organizationId = organization
|
|
3246
|
+
organizationId = organization.id;
|
|
3285
3247
|
}
|
|
3286
3248
|
if (organizationId === void 0) return ctx.render({
|
|
3287
|
-
success:
|
|
3249
|
+
success: _faire_auth_core_static.False,
|
|
3288
3250
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3289
3251
|
}, 400);
|
|
3290
3252
|
if (!await adapter.checkMembership({
|
|
@@ -3293,56 +3255,55 @@ const setActiveOrganization = (options) => require_session.createEndpoint((0, __
|
|
|
3293
3255
|
})) {
|
|
3294
3256
|
await adapter.setActiveOrganization(session.session.token, null);
|
|
3295
3257
|
return ctx.render({
|
|
3296
|
-
success:
|
|
3258
|
+
success: _faire_auth_core_static.False,
|
|
3297
3259
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3298
3260
|
}, 403);
|
|
3299
3261
|
}
|
|
3300
|
-
let organization
|
|
3301
|
-
if (!organization
|
|
3302
|
-
success:
|
|
3262
|
+
let organization = await adapter.findOrganizationById(organizationId);
|
|
3263
|
+
if (!organization) return ctx.render({
|
|
3264
|
+
success: _faire_auth_core_static.False,
|
|
3303
3265
|
message: ORGANIZATION_ERROR_CODES.ORGANIZATION_NOT_FOUND
|
|
3304
3266
|
}, 400);
|
|
3267
|
+
const updatedSession = await adapter.setActiveOrganization(session.session.token, organization.id);
|
|
3305
3268
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
3306
|
-
session:
|
|
3269
|
+
session: updatedSession,
|
|
3307
3270
|
user: session.user
|
|
3308
3271
|
});
|
|
3309
|
-
return ctx.render(organization
|
|
3272
|
+
return ctx.render(organization, 200);
|
|
3310
3273
|
});
|
|
3311
|
-
const listOrganizations = (options) => require_session.createEndpoint((0,
|
|
3274
|
+
const listOrganizations = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3312
3275
|
operationId: "listOrganizations",
|
|
3313
3276
|
method: "get",
|
|
3314
3277
|
path: "/organization/list",
|
|
3315
3278
|
description: "List all organizations for the current user",
|
|
3316
3279
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3317
|
-
responses: (0,
|
|
3280
|
+
responses: (0, _faire_auth_core_factory.res)(organizationListResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(401).bld()
|
|
3318
3281
|
}), (_authOptions) => async (ctx) => {
|
|
3319
3282
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
3320
3283
|
const session = ctx.get("session");
|
|
3321
3284
|
const organizations = await adapter.listOrganizations(session.user.id);
|
|
3322
3285
|
return ctx.render(organizations, 200);
|
|
3323
3286
|
});
|
|
3324
|
-
|
|
3325
|
-
//#endregion
|
|
3326
|
-
//#region src/plugins/organization/routes/crud-team.ts
|
|
3287
|
+
// src/plugins/organization/routes/crud-team.ts
|
|
3327
3288
|
const createTeam = (options) => {
|
|
3328
|
-
const additionalFieldsSchema =
|
|
3289
|
+
const additionalFieldsSchema = require_db_index.toZodSchema({
|
|
3329
3290
|
fields: options?.schema?.team?.additionalFields ?? {},
|
|
3330
3291
|
isClientSide: true
|
|
3331
3292
|
});
|
|
3332
3293
|
const baseSchema = createTeamBaseSchema;
|
|
3333
|
-
return require_session.createEndpoint((0,
|
|
3294
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3334
3295
|
operationId: "createTeam",
|
|
3335
3296
|
method: "post",
|
|
3336
3297
|
path: "/organization/create-team",
|
|
3337
3298
|
description: "Create a new team within an organization",
|
|
3338
3299
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(options)],
|
|
3339
|
-
request: (0,
|
|
3340
|
-
responses: (0,
|
|
3300
|
+
request: (0, _faire_auth_core_factory.req)().bdy(baseSchema.extend(additionalFieldsSchema.shape)).bld(),
|
|
3301
|
+
responses: (0, _faire_auth_core_factory.res)(teamSchema.transform(_faire_auth_core_utils.toSuccess), "Team created successfully").err(400).err(401).err(403).bld()
|
|
3341
3302
|
}), (_authOptions) => async (ctx) => {
|
|
3342
3303
|
const session = ctx.get("session") ?? null;
|
|
3343
|
-
const { name, organizationId = session?.session.activeOrganizationId
|
|
3304
|
+
const { name, organizationId = session?.session.activeOrganizationId, ...additionalFields } = ctx.req.valid("json");
|
|
3344
3305
|
if (!organizationId) return ctx.render({
|
|
3345
|
-
success:
|
|
3306
|
+
success: _faire_auth_core_static.False,
|
|
3346
3307
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3347
3308
|
}, 400);
|
|
3348
3309
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -3352,7 +3313,7 @@ const createTeam = (options) => {
|
|
|
3352
3313
|
organizationId
|
|
3353
3314
|
});
|
|
3354
3315
|
if (!member) return ctx.render({
|
|
3355
|
-
success:
|
|
3316
|
+
success: _faire_auth_core_static.False,
|
|
3356
3317
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_INVITE_USERS_TO_THIS_ORGANIZATION
|
|
3357
3318
|
}, 403);
|
|
3358
3319
|
if (!hasPermission({
|
|
@@ -3361,7 +3322,7 @@ const createTeam = (options) => {
|
|
|
3361
3322
|
permissions: { team: ["create"] },
|
|
3362
3323
|
organizationId
|
|
3363
3324
|
}, ctx)) return ctx.render({
|
|
3364
|
-
success:
|
|
3325
|
+
success: _faire_auth_core_static.False,
|
|
3365
3326
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_CREATE_TEAMS_IN_THIS_ORGANIZATION
|
|
3366
3327
|
}, 403);
|
|
3367
3328
|
}
|
|
@@ -3372,7 +3333,7 @@ const createTeam = (options) => {
|
|
|
3372
3333
|
session
|
|
3373
3334
|
}, ctx.req) : maximumTeams;
|
|
3374
3335
|
if (maximum ? existingTeams.length >= maximum : false) return ctx.render({
|
|
3375
|
-
success:
|
|
3336
|
+
success: _faire_auth_core_static.False,
|
|
3376
3337
|
message: ORGANIZATION_ERROR_CODES.YOU_HAVE_REACHED_THE_MAXIMUM_NUMBER_OF_TEAMS
|
|
3377
3338
|
}, 400);
|
|
3378
3339
|
const createdTeam = await adapter.createTeam({
|
|
@@ -3385,19 +3346,19 @@ const createTeam = (options) => {
|
|
|
3385
3346
|
return ctx.render(createdTeam, 200);
|
|
3386
3347
|
});
|
|
3387
3348
|
};
|
|
3388
|
-
const removeTeam = (options) => require_session.createEndpoint((0,
|
|
3349
|
+
const removeTeam = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3389
3350
|
operationId: "removeTeam",
|
|
3390
3351
|
method: "post",
|
|
3391
3352
|
path: "/organization/remove-team",
|
|
3392
3353
|
description: "Remove a team from an organization",
|
|
3393
3354
|
middleware: [require_session.requestOnlySessionMiddleware, orgMiddleware(options)],
|
|
3394
|
-
request: (0,
|
|
3395
|
-
responses: (0,
|
|
3355
|
+
request: (0, _faire_auth_core_factory.req)().bdy(removeTeamSchema).bld(),
|
|
3356
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default, "Team removed successfully").err(400).err(401).err(403).zod().bld()
|
|
3396
3357
|
}), (_authOptions) => async (ctx) => {
|
|
3397
3358
|
const session = ctx.get("session");
|
|
3398
3359
|
const { teamId, organizationId = session?.session.activeOrganizationId } = ctx.req.valid("json");
|
|
3399
3360
|
if (!organizationId) return ctx.render({
|
|
3400
|
-
success:
|
|
3361
|
+
success: _faire_auth_core_static.False,
|
|
3401
3362
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3402
3363
|
}, 400);
|
|
3403
3364
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -3407,7 +3368,7 @@ const removeTeam = (options) => require_session.createEndpoint((0, __faire_auth_
|
|
|
3407
3368
|
organizationId
|
|
3408
3369
|
});
|
|
3409
3370
|
if (!member || session.session?.activeTeamId === teamId) return ctx.render({
|
|
3410
|
-
success:
|
|
3371
|
+
success: _faire_auth_core_static.False,
|
|
3411
3372
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_THIS_TEAM
|
|
3412
3373
|
}, 403);
|
|
3413
3374
|
if (!hasPermission({
|
|
@@ -3416,7 +3377,7 @@ const removeTeam = (options) => require_session.createEndpoint((0, __faire_auth_
|
|
|
3416
3377
|
permissions: { team: ["delete"] },
|
|
3417
3378
|
organizationId
|
|
3418
3379
|
}, ctx)) return ctx.render({
|
|
3419
|
-
success:
|
|
3380
|
+
success: _faire_auth_core_static.False,
|
|
3420
3381
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_DELETE_TEAMS_IN_THIS_ORGANIZATION
|
|
3421
3382
|
}, 403);
|
|
3422
3383
|
}
|
|
@@ -3425,39 +3386,39 @@ const removeTeam = (options) => require_session.createEndpoint((0, __faire_auth_
|
|
|
3425
3386
|
organizationId
|
|
3426
3387
|
});
|
|
3427
3388
|
if (!team || team.organizationId !== organizationId) return ctx.render({
|
|
3428
|
-
success:
|
|
3389
|
+
success: _faire_auth_core_static.False,
|
|
3429
3390
|
message: ORGANIZATION_ERROR_CODES.TEAM_NOT_FOUND
|
|
3430
3391
|
}, 400);
|
|
3431
3392
|
if (!ctx.get("orgOptions").teams?.allowRemovingAllTeams) {
|
|
3432
3393
|
if ((await adapter.listTeams(organizationId)).length <= 1) return ctx.render({
|
|
3433
|
-
success:
|
|
3394
|
+
success: _faire_auth_core_static.False,
|
|
3434
3395
|
message: ORGANIZATION_ERROR_CODES.UNABLE_TO_REMOVE_LAST_TEAM
|
|
3435
3396
|
}, 400);
|
|
3436
3397
|
}
|
|
3437
3398
|
await adapter.deleteTeam(team.id);
|
|
3438
3399
|
return ctx.render({
|
|
3439
|
-
success:
|
|
3400
|
+
success: _faire_auth_core_static.True,
|
|
3440
3401
|
message: "Team removed successfully."
|
|
3441
3402
|
}, 200);
|
|
3442
3403
|
});
|
|
3443
3404
|
const updateTeam = (options) => {
|
|
3444
|
-
const additionalFieldsSchema =
|
|
3405
|
+
const additionalFieldsSchema = require_db_index.toZodSchema({
|
|
3445
3406
|
fields: options?.schema?.team?.additionalFields ?? {},
|
|
3446
3407
|
isClientSide: true
|
|
3447
3408
|
});
|
|
3448
|
-
return require_session.createEndpoint((0,
|
|
3409
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3449
3410
|
operationId: "updateTeam",
|
|
3450
3411
|
method: "post",
|
|
3451
3412
|
path: "/organization/update-team",
|
|
3452
3413
|
description: "Update an existing team in an organization",
|
|
3453
3414
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3454
|
-
request: (0,
|
|
3455
|
-
responses: (0,
|
|
3415
|
+
request: (0, _faire_auth_core_factory.req)().bdy(updateTeamSchema.extend({ data: updateTeamSchema.shape.data.extend(additionalFieldsSchema.shape).partial() })).bld(),
|
|
3416
|
+
responses: (0, _faire_auth_core_factory.res)(teamSchema.transform(_faire_auth_core_utils.toSuccess), "Team updated successfully").err(400).err(401).err(403).bld()
|
|
3456
3417
|
}), (_authOptions) => async (ctx) => {
|
|
3457
3418
|
const session = ctx.get("session");
|
|
3458
|
-
const { teamId, data: { name, organizationId = session.session.activeOrganizationId
|
|
3419
|
+
const { teamId, data: { name, organizationId = session.session.activeOrganizationId, ...additionalFields } } = ctx.req.valid("json");
|
|
3459
3420
|
if (!organizationId) return ctx.render({
|
|
3460
|
-
success:
|
|
3421
|
+
success: _faire_auth_core_static.False,
|
|
3461
3422
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3462
3423
|
}, 400);
|
|
3463
3424
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -3466,7 +3427,7 @@ const updateTeam = (options) => {
|
|
|
3466
3427
|
organizationId
|
|
3467
3428
|
});
|
|
3468
3429
|
if (!member) return ctx.render({
|
|
3469
|
-
success:
|
|
3430
|
+
success: _faire_auth_core_static.False,
|
|
3470
3431
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_TEAM
|
|
3471
3432
|
}, 403);
|
|
3472
3433
|
if (!hasPermission({
|
|
@@ -3475,7 +3436,7 @@ const updateTeam = (options) => {
|
|
|
3475
3436
|
permissions: { team: ["update"] },
|
|
3476
3437
|
organizationId
|
|
3477
3438
|
}, ctx)) return ctx.render({
|
|
3478
|
-
success:
|
|
3439
|
+
success: _faire_auth_core_static.False,
|
|
3479
3440
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_UPDATE_THIS_TEAM
|
|
3480
3441
|
}, 403);
|
|
3481
3442
|
const team = await adapter.findTeamById({
|
|
@@ -3483,7 +3444,7 @@ const updateTeam = (options) => {
|
|
|
3483
3444
|
organizationId
|
|
3484
3445
|
});
|
|
3485
3446
|
if (!team || team.organizationId !== organizationId) return ctx.render({
|
|
3486
|
-
success:
|
|
3447
|
+
success: _faire_auth_core_static.False,
|
|
3487
3448
|
message: ORGANIZATION_ERROR_CODES.TEAM_NOT_FOUND
|
|
3488
3449
|
}, 400);
|
|
3489
3450
|
const updatedTeam = await adapter.updateTeam(team.id, {
|
|
@@ -3493,20 +3454,20 @@ const updateTeam = (options) => {
|
|
|
3493
3454
|
return ctx.render(updatedTeam, 200);
|
|
3494
3455
|
});
|
|
3495
3456
|
};
|
|
3496
|
-
const listOrganizationTeams = (options) => require_session.createEndpoint((0,
|
|
3457
|
+
const listOrganizationTeams = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3497
3458
|
operationId: "listOrganizationTeams",
|
|
3498
3459
|
method: "get",
|
|
3499
3460
|
path: "/organization/list-teams",
|
|
3500
3461
|
description: "List all teams in an organization",
|
|
3501
3462
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3502
|
-
request: (0,
|
|
3503
|
-
responses: (0,
|
|
3463
|
+
request: (0, _faire_auth_core_factory.req)().qry(listTeamsQuerySchema).bld(),
|
|
3464
|
+
responses: (0, _faire_auth_core_factory.res)(teamListResponseSchema.transform(_faire_auth_core_utils.toSuccess), "Teams retrieved successfully").err(400).err(401).err(403).zod().bld()
|
|
3504
3465
|
}), (_authOptions) => async (ctx) => {
|
|
3505
3466
|
const session = ctx.get("session");
|
|
3506
3467
|
const { organizationId } = ctx.req.valid("query");
|
|
3507
3468
|
const orgId = organizationId ?? session.session.activeOrganizationId;
|
|
3508
3469
|
if (!orgId) return ctx.render({
|
|
3509
|
-
success:
|
|
3470
|
+
success: _faire_auth_core_static.False,
|
|
3510
3471
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3511
3472
|
}, 400);
|
|
3512
3473
|
const adapter = getOrgAdapter(ctx.get("context"), options);
|
|
@@ -3514,28 +3475,29 @@ const listOrganizationTeams = (options) => require_session.createEndpoint((0, __
|
|
|
3514
3475
|
userId: session.user.id,
|
|
3515
3476
|
organizationId: orgId
|
|
3516
3477
|
})) return ctx.render({
|
|
3517
|
-
success:
|
|
3478
|
+
success: _faire_auth_core_static.False,
|
|
3518
3479
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_ACCESS_THIS_ORGANIZATION
|
|
3519
3480
|
}, 403);
|
|
3520
3481
|
const teams = await adapter.listTeams(orgId);
|
|
3521
3482
|
return ctx.render(teams, 200);
|
|
3522
3483
|
});
|
|
3523
|
-
const setActiveTeam = (options) => require_session.createEndpoint((0,
|
|
3484
|
+
const setActiveTeam = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3524
3485
|
operationId: "setActiveTeam",
|
|
3525
3486
|
method: "post",
|
|
3526
3487
|
path: "/organization/set-active-team",
|
|
3527
3488
|
description: "Set the active team",
|
|
3528
3489
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3529
|
-
request: (0,
|
|
3530
|
-
responses: (0,
|
|
3490
|
+
request: (0, _faire_auth_core_factory.req)().bdy(setActiveTeamSchema).bld(),
|
|
3491
|
+
responses: (0, _faire_auth_core_factory.res)(teamSchema.nullable().transform(_faire_auth_core_utils.toSuccess)).err(400).err(401).err(403).zod().bld()
|
|
3531
3492
|
}), (authOptions) => async (ctx) => {
|
|
3532
3493
|
const adapter = getOrgAdapter(ctx.get("context"), ctx.get("orgOptions"));
|
|
3533
3494
|
const session = ctx.get("session");
|
|
3534
3495
|
let { teamId } = ctx.req.valid("json");
|
|
3535
3496
|
if (teamId === null) {
|
|
3536
3497
|
if (!session.session.activeTeamId) return ctx.render(null, 200);
|
|
3498
|
+
const updatedSession = await adapter.setActiveTeam(session.session.token, null);
|
|
3537
3499
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
3538
|
-
session:
|
|
3500
|
+
session: updatedSession,
|
|
3539
3501
|
user: session.user
|
|
3540
3502
|
});
|
|
3541
3503
|
return ctx.render(null, 200);
|
|
@@ -3543,83 +3505,84 @@ const setActiveTeam = (options) => require_session.createEndpoint((0, __faire_au
|
|
|
3543
3505
|
if (teamId === void 0) {
|
|
3544
3506
|
const sessionTeamId = session.session.activeTeamId;
|
|
3545
3507
|
if (!sessionTeamId) return ctx.render({
|
|
3546
|
-
success:
|
|
3508
|
+
success: _faire_auth_core_static.False,
|
|
3547
3509
|
message: ORGANIZATION_ERROR_CODES.TEAM_NOT_FOUND
|
|
3548
3510
|
}, 400);
|
|
3549
3511
|
teamId = sessionTeamId;
|
|
3550
3512
|
} else teamId = teamId;
|
|
3551
3513
|
const team = await adapter.findTeamById({ teamId });
|
|
3552
3514
|
if (!team) return ctx.render({
|
|
3553
|
-
success:
|
|
3515
|
+
success: _faire_auth_core_static.False,
|
|
3554
3516
|
message: ORGANIZATION_ERROR_CODES.TEAM_NOT_FOUND
|
|
3555
3517
|
}, 400);
|
|
3556
3518
|
if (!await adapter.findTeamMember({
|
|
3557
3519
|
teamId,
|
|
3558
3520
|
userId: session.user.id
|
|
3559
3521
|
})) return ctx.render({
|
|
3560
|
-
success:
|
|
3522
|
+
success: _faire_auth_core_static.False,
|
|
3561
3523
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_TEAM
|
|
3562
3524
|
}, 403);
|
|
3525
|
+
const updatedSession = await adapter.setActiveTeam(session.session.token, team.id);
|
|
3563
3526
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
3564
|
-
session:
|
|
3527
|
+
session: updatedSession,
|
|
3565
3528
|
user: session.user
|
|
3566
3529
|
});
|
|
3567
3530
|
return ctx.render(team, 200);
|
|
3568
3531
|
});
|
|
3569
|
-
const listUserTeams = (options) => require_session.createEndpoint((0,
|
|
3532
|
+
const listUserTeams = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3570
3533
|
operationId: "listUserTeams",
|
|
3571
3534
|
method: "get",
|
|
3572
3535
|
path: "/organization/list-user-teams",
|
|
3573
3536
|
description: "List all teams that the current user is a part of",
|
|
3574
3537
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3575
|
-
request: (0,
|
|
3576
|
-
responses: (0,
|
|
3538
|
+
request: (0, _faire_auth_core_factory.req)().bld(),
|
|
3539
|
+
responses: (0, _faire_auth_core_factory.res)(teamListResponseSchema.transform(_faire_auth_core_utils.toSuccess), "Teams retrieved successfully").err(401).bld()
|
|
3577
3540
|
}), (_authOptions) => async (ctx) => {
|
|
3578
3541
|
const session = ctx.get("session");
|
|
3579
3542
|
const teams = await getOrgAdapter(ctx.get("context"), ctx.get("orgOptions")).listTeamsByUser({ userId: session.user.id });
|
|
3580
3543
|
return ctx.render(teams, 200);
|
|
3581
3544
|
});
|
|
3582
|
-
const listTeamMembers = (options) => require_session.createEndpoint((0,
|
|
3545
|
+
const listTeamMembers = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3583
3546
|
operationId: "listTeamMembers",
|
|
3584
3547
|
method: "get",
|
|
3585
3548
|
path: "/organization/list-team-members",
|
|
3586
3549
|
description: "List the members of the given team",
|
|
3587
3550
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3588
|
-
request: (0,
|
|
3589
|
-
responses: (0,
|
|
3551
|
+
request: (0, _faire_auth_core_factory.req)().qry(listTeamMembersQuerySchema).bld(),
|
|
3552
|
+
responses: (0, _faire_auth_core_factory.res)(teamMemberListResponseSchema.transform(_faire_auth_core_utils.toSuccess), "Teams retrieved successfully").err(400).err(401).err(403).zod().bld()
|
|
3590
3553
|
}), (_authOptions) => async (ctx) => {
|
|
3591
3554
|
const session = ctx.get("session");
|
|
3592
3555
|
const adapter = getOrgAdapter(ctx.get("context"), ctx.get("orgOptions"));
|
|
3593
3556
|
let { teamId } = ctx.req.valid("query");
|
|
3594
3557
|
teamId ??= session.session.activeTeamId;
|
|
3595
3558
|
if (!teamId) return ctx.render({
|
|
3596
|
-
success:
|
|
3559
|
+
success: _faire_auth_core_static.False,
|
|
3597
3560
|
message: ORGANIZATION_ERROR_CODES.YOU_DO_NOT_HAVE_AN_ACTIVE_TEAM
|
|
3598
3561
|
}, 400);
|
|
3599
3562
|
if (!await adapter.findTeamMember({
|
|
3600
3563
|
userId: session.user.id,
|
|
3601
3564
|
teamId
|
|
3602
3565
|
})) return ctx.render({
|
|
3603
|
-
success:
|
|
3566
|
+
success: _faire_auth_core_static.False,
|
|
3604
3567
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_TEAM
|
|
3605
3568
|
}, 403);
|
|
3606
3569
|
const members = await adapter.listTeamMembers({ teamId });
|
|
3607
3570
|
return ctx.render(members, 200);
|
|
3608
3571
|
});
|
|
3609
|
-
const addTeamMember = (options) => require_session.createEndpoint((0,
|
|
3572
|
+
const addTeamMember = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3610
3573
|
operationId: "addTeamMember",
|
|
3611
3574
|
method: "post",
|
|
3612
3575
|
path: "/organization/add-team-member",
|
|
3613
3576
|
description: "Add a user as a member of a team",
|
|
3614
3577
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3615
|
-
request: (0,
|
|
3616
|
-
responses: (0,
|
|
3578
|
+
request: (0, _faire_auth_core_factory.req)().bdy(addTeamMemberSchema).bld(),
|
|
3579
|
+
responses: (0, _faire_auth_core_factory.res)(teamMemberResponseSchema.transform(_faire_auth_core_utils.toSuccess), "Team member created successfully").err(400).err(401).err(403).zod().bld()
|
|
3617
3580
|
}), (_authOptions) => async (ctx) => {
|
|
3618
3581
|
const session = ctx.get("session");
|
|
3619
3582
|
const adapter = getOrgAdapter(ctx.get("context"), ctx.get("orgOptions"));
|
|
3620
3583
|
const { teamId, userId } = ctx.req.valid("json");
|
|
3621
3584
|
if (!session.session.activeOrganizationId) return ctx.render({
|
|
3622
|
-
success:
|
|
3585
|
+
success: _faire_auth_core_static.False,
|
|
3623
3586
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3624
3587
|
}, 400);
|
|
3625
3588
|
const currentMember = await adapter.findMemberByOrgId({
|
|
@@ -3627,7 +3590,7 @@ const addTeamMember = (options) => require_session.createEndpoint((0, __faire_au
|
|
|
3627
3590
|
organizationId: session.session.activeOrganizationId
|
|
3628
3591
|
});
|
|
3629
3592
|
if (!currentMember) return ctx.render({
|
|
3630
|
-
success:
|
|
3593
|
+
success: _faire_auth_core_static.False,
|
|
3631
3594
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3632
3595
|
}, 400);
|
|
3633
3596
|
if (!hasPermission({
|
|
@@ -3636,14 +3599,14 @@ const addTeamMember = (options) => require_session.createEndpoint((0, __faire_au
|
|
|
3636
3599
|
permissions: { member: ["update"] },
|
|
3637
3600
|
organizationId: session.session.activeOrganizationId
|
|
3638
3601
|
}, ctx)) return ctx.render({
|
|
3639
|
-
success:
|
|
3602
|
+
success: _faire_auth_core_static.False,
|
|
3640
3603
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_CREATE_A_NEW_TEAM_MEMBER
|
|
3641
3604
|
}, 403);
|
|
3642
3605
|
if (!await adapter.findMemberByOrgId({
|
|
3643
3606
|
userId,
|
|
3644
3607
|
organizationId: session.session.activeOrganizationId
|
|
3645
3608
|
})) return ctx.render({
|
|
3646
|
-
success:
|
|
3609
|
+
success: _faire_auth_core_static.False,
|
|
3647
3610
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3648
3611
|
}, 400);
|
|
3649
3612
|
const teamMember = await adapter.findOrCreateTeamMember({
|
|
@@ -3652,20 +3615,20 @@ const addTeamMember = (options) => require_session.createEndpoint((0, __faire_au
|
|
|
3652
3615
|
});
|
|
3653
3616
|
return ctx.render(teamMember, 200);
|
|
3654
3617
|
});
|
|
3655
|
-
const removeTeamMember = (options) => require_session.createEndpoint((0,
|
|
3618
|
+
const removeTeamMember = (options) => require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3656
3619
|
operationId: "removeTeamMember",
|
|
3657
3620
|
method: "post",
|
|
3658
3621
|
path: "/organization/remove-team-member",
|
|
3659
3622
|
description: "Remove a member from a team",
|
|
3660
3623
|
middleware: [orgSessionMiddleware, orgMiddleware(options)],
|
|
3661
|
-
request: (0,
|
|
3662
|
-
responses: (0,
|
|
3624
|
+
request: (0, _faire_auth_core_factory.req)().bdy(removeTeamMemberSchema).bld(),
|
|
3625
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default, "Team member removed successfully").err(400).err(401).err(403).zod().bld()
|
|
3663
3626
|
}), (_authOptions) => async (ctx) => {
|
|
3664
3627
|
const session = ctx.get("session");
|
|
3665
3628
|
const adapter = getOrgAdapter(ctx.get("context"), ctx.get("orgOptions"));
|
|
3666
3629
|
const { teamId, userId } = ctx.req.valid("json");
|
|
3667
3630
|
if (!session.session.activeOrganizationId) return ctx.render({
|
|
3668
|
-
success:
|
|
3631
|
+
success: _faire_auth_core_static.False,
|
|
3669
3632
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3670
3633
|
}, 400);
|
|
3671
3634
|
const currentMember = await adapter.findMemberByOrgId({
|
|
@@ -3673,7 +3636,7 @@ const removeTeamMember = (options) => require_session.createEndpoint((0, __faire
|
|
|
3673
3636
|
organizationId: session.session.activeOrganizationId
|
|
3674
3637
|
});
|
|
3675
3638
|
if (!currentMember) return ctx.render({
|
|
3676
|
-
success:
|
|
3639
|
+
success: _faire_auth_core_static.False,
|
|
3677
3640
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3678
3641
|
}, 400);
|
|
3679
3642
|
if (!hasPermission({
|
|
@@ -3682,14 +3645,14 @@ const removeTeamMember = (options) => require_session.createEndpoint((0, __faire
|
|
|
3682
3645
|
permissions: { member: ["delete"] },
|
|
3683
3646
|
organizationId: session.session.activeOrganizationId
|
|
3684
3647
|
}, ctx)) return ctx.render({
|
|
3685
|
-
success:
|
|
3648
|
+
success: _faire_auth_core_static.False,
|
|
3686
3649
|
message: ORGANIZATION_ERROR_CODES.YOU_ARE_NOT_ALLOWED_TO_REMOVE_A_TEAM_MEMBER
|
|
3687
3650
|
}, 403);
|
|
3688
3651
|
if (!await adapter.findMemberByOrgId({
|
|
3689
3652
|
userId,
|
|
3690
3653
|
organizationId: session.session.activeOrganizationId
|
|
3691
3654
|
})) return ctx.render({
|
|
3692
|
-
success:
|
|
3655
|
+
success: _faire_auth_core_static.False,
|
|
3693
3656
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3694
3657
|
}, 400);
|
|
3695
3658
|
await adapter.removeTeamMember({
|
|
@@ -3697,34 +3660,32 @@ const removeTeamMember = (options) => require_session.createEndpoint((0, __faire
|
|
|
3697
3660
|
userId
|
|
3698
3661
|
});
|
|
3699
3662
|
return ctx.render({
|
|
3700
|
-
success:
|
|
3663
|
+
success: _faire_auth_core_static.True,
|
|
3701
3664
|
message: "Team member removed successfully."
|
|
3702
3665
|
}, 200);
|
|
3703
3666
|
});
|
|
3704
|
-
|
|
3705
|
-
//#endregion
|
|
3706
|
-
//#region src/plugins/organization/organization.ts
|
|
3667
|
+
// src/plugins/organization/organization.ts
|
|
3707
3668
|
function parseRoles(roles) {
|
|
3708
3669
|
return Array.isArray(roles) ? roles.join(",") : roles;
|
|
3709
3670
|
}
|
|
3710
3671
|
const createHasPermission = (options) => {
|
|
3711
|
-
return require_session.createEndpoint((0,
|
|
3672
|
+
return require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
3712
3673
|
operationId: "hasPermission",
|
|
3713
3674
|
method: "post",
|
|
3714
3675
|
path: "/organization/has-permission",
|
|
3715
3676
|
description: "Check if the user has permission",
|
|
3716
3677
|
middleware: [orgSessionMiddleware],
|
|
3717
|
-
request: (0,
|
|
3678
|
+
request: (0, _faire_auth_core_factory.req)().bdy(zod.object({ organizationId: zod.string().optional() }).and(zod.union([zod.object({
|
|
3718
3679
|
permission: zod.record(zod.string(), zod.array(zod.string())).openapi({
|
|
3719
3680
|
description: "The permission to check",
|
|
3720
3681
|
deprecated: true
|
|
3721
3682
|
}),
|
|
3722
|
-
permissions: zod.undefined()
|
|
3683
|
+
permissions: zod.undefined().optional()
|
|
3723
3684
|
}), zod.object({
|
|
3724
|
-
permission: zod.undefined(),
|
|
3685
|
+
permission: zod.undefined().optional(),
|
|
3725
3686
|
permissions: zod.record(zod.string(), zod.array(zod.string())).openapi({ description: "The permission to check" })
|
|
3726
3687
|
})]))).bld(),
|
|
3727
|
-
responses: (0,
|
|
3688
|
+
responses: (0, _faire_auth_core_factory.res)(zod.object({
|
|
3728
3689
|
success: zod.literal(true),
|
|
3729
3690
|
data: zod.boolean()
|
|
3730
3691
|
})).err(400, "No permissions were provided").err(401, "User not member of organization").bld()
|
|
@@ -3732,7 +3693,7 @@ const createHasPermission = (options) => {
|
|
|
3732
3693
|
const { organizationId, permission, permissions } = ctx.req.valid("json");
|
|
3733
3694
|
const activeOrganizationId = organizationId ?? ctx.get("session").session.activeOrganizationId;
|
|
3734
3695
|
if (!activeOrganizationId) return ctx.render({
|
|
3735
|
-
success:
|
|
3696
|
+
success: _faire_auth_core_static.False,
|
|
3736
3697
|
message: ORGANIZATION_ERROR_CODES.NO_ACTIVE_ORGANIZATION
|
|
3737
3698
|
}, 400);
|
|
3738
3699
|
const member = await getOrgAdapter(ctx.get("context"), options).findMemberByOrgId({
|
|
@@ -3740,7 +3701,7 @@ const createHasPermission = (options) => {
|
|
|
3740
3701
|
organizationId: activeOrganizationId
|
|
3741
3702
|
});
|
|
3742
3703
|
if (!member) return ctx.render({
|
|
3743
|
-
success:
|
|
3704
|
+
success: _faire_auth_core_static.False,
|
|
3744
3705
|
message: ORGANIZATION_ERROR_CODES.USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION
|
|
3745
3706
|
}, 401);
|
|
3746
3707
|
const result = await hasPermission({
|
|
@@ -3750,45 +3711,493 @@ const createHasPermission = (options) => {
|
|
|
3750
3711
|
organizationId: activeOrganizationId
|
|
3751
3712
|
}, ctx);
|
|
3752
3713
|
return ctx.render({
|
|
3753
|
-
success:
|
|
3714
|
+
success: _faire_auth_core_static.True,
|
|
3754
3715
|
data: result
|
|
3755
3716
|
}, 200);
|
|
3756
3717
|
});
|
|
3757
3718
|
};
|
|
3758
3719
|
function organization(options) {
|
|
3759
3720
|
let endpoints = {
|
|
3721
|
+
/**
|
|
3722
|
+
* ### Endpoint
|
|
3723
|
+
*
|
|
3724
|
+
* POST `/organization/create`
|
|
3725
|
+
*
|
|
3726
|
+
* ### API Methods
|
|
3727
|
+
*
|
|
3728
|
+
* **server:**
|
|
3729
|
+
* `auth.api.createOrganization`
|
|
3730
|
+
*
|
|
3731
|
+
* **client:**
|
|
3732
|
+
* `authClient.organization.create`
|
|
3733
|
+
*
|
|
3734
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-create)
|
|
3735
|
+
*/
|
|
3760
3736
|
createOrganization: createOrganization(options),
|
|
3737
|
+
/**
|
|
3738
|
+
* ### Endpoint
|
|
3739
|
+
*
|
|
3740
|
+
* POST `/organization/update`
|
|
3741
|
+
*
|
|
3742
|
+
* ### API Methods
|
|
3743
|
+
*
|
|
3744
|
+
* **server:**
|
|
3745
|
+
* `auth.api.updateOrganization`
|
|
3746
|
+
*
|
|
3747
|
+
* **client:**
|
|
3748
|
+
* `authClient.organization.update`
|
|
3749
|
+
*
|
|
3750
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-update)
|
|
3751
|
+
*/
|
|
3761
3752
|
updateOrganization: updateOrganization(options),
|
|
3753
|
+
/**
|
|
3754
|
+
* ### Endpoint
|
|
3755
|
+
*
|
|
3756
|
+
* POST `/organization/delete`
|
|
3757
|
+
*
|
|
3758
|
+
* ### API Methods
|
|
3759
|
+
*
|
|
3760
|
+
* **server:**
|
|
3761
|
+
* `auth.api.deleteOrganization`
|
|
3762
|
+
*
|
|
3763
|
+
* **client:**
|
|
3764
|
+
* `authClient.organization.delete`
|
|
3765
|
+
*
|
|
3766
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-delete)
|
|
3767
|
+
*/
|
|
3762
3768
|
deleteOrganization: deleteOrganization(options),
|
|
3769
|
+
/**
|
|
3770
|
+
* ### Endpoint
|
|
3771
|
+
*
|
|
3772
|
+
* POST `/organization/set-active`
|
|
3773
|
+
*
|
|
3774
|
+
* ### API Methods
|
|
3775
|
+
*
|
|
3776
|
+
* **server:**
|
|
3777
|
+
* `auth.api.setActiveOrganization`
|
|
3778
|
+
*
|
|
3779
|
+
* **client:**
|
|
3780
|
+
* `authClient.organization.setActive`
|
|
3781
|
+
*
|
|
3782
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-set-active)
|
|
3783
|
+
*/
|
|
3763
3784
|
setActiveOrganization: setActiveOrganization(options),
|
|
3785
|
+
/**
|
|
3786
|
+
* ### Endpoint
|
|
3787
|
+
*
|
|
3788
|
+
* GET `/organization/get-full-organization`
|
|
3789
|
+
*
|
|
3790
|
+
* ### API Methods
|
|
3791
|
+
*
|
|
3792
|
+
* **server:**
|
|
3793
|
+
* `auth.api.getFullOrganization`
|
|
3794
|
+
*
|
|
3795
|
+
* **client:**
|
|
3796
|
+
* `authClient.organization.getFullOrganization`
|
|
3797
|
+
*
|
|
3798
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-get-full-organization)
|
|
3799
|
+
*/
|
|
3764
3800
|
getFullOrganization: getFullOrganization(options),
|
|
3801
|
+
/**
|
|
3802
|
+
* ### Endpoint
|
|
3803
|
+
*
|
|
3804
|
+
* GET `/organization/list`
|
|
3805
|
+
*
|
|
3806
|
+
* ### API Methods
|
|
3807
|
+
*
|
|
3808
|
+
* **server:**
|
|
3809
|
+
* `auth.api.listOrganizations`
|
|
3810
|
+
*
|
|
3811
|
+
* **client:**
|
|
3812
|
+
* `authClient.organization.list`
|
|
3813
|
+
*
|
|
3814
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-list)
|
|
3815
|
+
*/
|
|
3765
3816
|
listOrganizations: listOrganizations(options),
|
|
3817
|
+
/**
|
|
3818
|
+
* ### Endpoint
|
|
3819
|
+
*
|
|
3820
|
+
* POST `/organization/invite-member`
|
|
3821
|
+
*
|
|
3822
|
+
* ### API Methods
|
|
3823
|
+
*
|
|
3824
|
+
* **server:**
|
|
3825
|
+
* `auth.api.createInvitation`
|
|
3826
|
+
*
|
|
3827
|
+
* **client:**
|
|
3828
|
+
* `authClient.organization.inviteMember`
|
|
3829
|
+
*
|
|
3830
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-invite-member)
|
|
3831
|
+
*/
|
|
3766
3832
|
createInvitation: createInvitation(options),
|
|
3833
|
+
/**
|
|
3834
|
+
* ### Endpoint
|
|
3835
|
+
*
|
|
3836
|
+
* POST `/organization/cancel-invitation`
|
|
3837
|
+
*
|
|
3838
|
+
* ### API Methods
|
|
3839
|
+
*
|
|
3840
|
+
* **server:**
|
|
3841
|
+
* `auth.api.cancelInvitation`
|
|
3842
|
+
*
|
|
3843
|
+
* **client:**
|
|
3844
|
+
* `authClient.organization.cancelInvitation`
|
|
3845
|
+
*
|
|
3846
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-cancel-invitation)
|
|
3847
|
+
*/
|
|
3767
3848
|
cancelInvitation: cancelInvitation(options),
|
|
3849
|
+
/**
|
|
3850
|
+
* ### Endpoint
|
|
3851
|
+
*
|
|
3852
|
+
* POST `/organization/accept-invitation`
|
|
3853
|
+
*
|
|
3854
|
+
* ### API Methods
|
|
3855
|
+
*
|
|
3856
|
+
* **server:**
|
|
3857
|
+
* `auth.api.acceptInvitation`
|
|
3858
|
+
*
|
|
3859
|
+
* **client:**
|
|
3860
|
+
* `authClient.organization.acceptInvitation`
|
|
3861
|
+
*
|
|
3862
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-accept-invitation)
|
|
3863
|
+
*/
|
|
3768
3864
|
acceptInvitation: acceptInvitation(options),
|
|
3865
|
+
/**
|
|
3866
|
+
* ### Endpoint
|
|
3867
|
+
*
|
|
3868
|
+
* GET `/organization/get-invitation`
|
|
3869
|
+
*
|
|
3870
|
+
* ### API Methods
|
|
3871
|
+
*
|
|
3872
|
+
* **server:**
|
|
3873
|
+
* `auth.api.getInvitation`
|
|
3874
|
+
*
|
|
3875
|
+
* **client:**
|
|
3876
|
+
* `authClient.organization.getInvitation`
|
|
3877
|
+
*
|
|
3878
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-get-invitation)
|
|
3879
|
+
*/
|
|
3769
3880
|
getInvitation: getInvitation(options),
|
|
3881
|
+
/**
|
|
3882
|
+
* ### Endpoint
|
|
3883
|
+
*
|
|
3884
|
+
* POST `/organization/reject-invitation`
|
|
3885
|
+
*
|
|
3886
|
+
* ### API Methods
|
|
3887
|
+
*
|
|
3888
|
+
* **server:**
|
|
3889
|
+
* `auth.api.rejectInvitation`
|
|
3890
|
+
*
|
|
3891
|
+
* **client:**
|
|
3892
|
+
* `authClient.organization.rejectInvitation`
|
|
3893
|
+
*
|
|
3894
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-reject-invitation)
|
|
3895
|
+
*/
|
|
3770
3896
|
rejectInvitation: rejectInvitation(options),
|
|
3897
|
+
/**
|
|
3898
|
+
* ### Endpoint
|
|
3899
|
+
*
|
|
3900
|
+
* GET `/organization/list-invitations`
|
|
3901
|
+
*
|
|
3902
|
+
* ### API Methods
|
|
3903
|
+
*
|
|
3904
|
+
* **server:**
|
|
3905
|
+
* `auth.api.listInvitations`
|
|
3906
|
+
*
|
|
3907
|
+
* **client:**
|
|
3908
|
+
* `authClient.organization.listInvitations`
|
|
3909
|
+
*
|
|
3910
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-list-invitations)
|
|
3911
|
+
*/
|
|
3771
3912
|
listInvitations: listInvitations(options),
|
|
3913
|
+
/**
|
|
3914
|
+
* ### Endpoint
|
|
3915
|
+
*
|
|
3916
|
+
* GET `/organization/get-active-member`
|
|
3917
|
+
*
|
|
3918
|
+
* ### API Methods
|
|
3919
|
+
*
|
|
3920
|
+
* **server:**
|
|
3921
|
+
* `auth.api.getActiveMember`
|
|
3922
|
+
*
|
|
3923
|
+
* **client:**
|
|
3924
|
+
* `authClient.organization.getActiveMember`
|
|
3925
|
+
*
|
|
3926
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-get-active-member)
|
|
3927
|
+
*/
|
|
3772
3928
|
getActiveMember: getActiveMember(options),
|
|
3929
|
+
/**
|
|
3930
|
+
* ### Endpoint
|
|
3931
|
+
*
|
|
3932
|
+
* POST `/organization/check-slug`
|
|
3933
|
+
*
|
|
3934
|
+
* ### API Methods
|
|
3935
|
+
*
|
|
3936
|
+
* **server:**
|
|
3937
|
+
* `auth.api.checkOrganizationSlug`
|
|
3938
|
+
*
|
|
3939
|
+
* **client:**
|
|
3940
|
+
* `authClient.organization.checkSlug`
|
|
3941
|
+
*
|
|
3942
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-check-slug)
|
|
3943
|
+
*/
|
|
3773
3944
|
checkOrganizationSlug: checkOrganizationSlug(options),
|
|
3945
|
+
/**
|
|
3946
|
+
* ### Endpoint
|
|
3947
|
+
*
|
|
3948
|
+
* POST `/organization/add-member`
|
|
3949
|
+
*
|
|
3950
|
+
* ### API Methods
|
|
3951
|
+
*
|
|
3952
|
+
* **server:**
|
|
3953
|
+
* `auth.api.addMember`
|
|
3954
|
+
*
|
|
3955
|
+
* **client:**
|
|
3956
|
+
* `authClient.organization.addMember`
|
|
3957
|
+
*
|
|
3958
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-add-member)
|
|
3959
|
+
*/
|
|
3774
3960
|
addMember: addMember(options),
|
|
3961
|
+
/**
|
|
3962
|
+
* ### Endpoint
|
|
3963
|
+
*
|
|
3964
|
+
* POST `/organization/remove-member`
|
|
3965
|
+
*
|
|
3966
|
+
* ### API Methods
|
|
3967
|
+
*
|
|
3968
|
+
* **server:**
|
|
3969
|
+
* `auth.api.removeMember`
|
|
3970
|
+
*
|
|
3971
|
+
* **client:**
|
|
3972
|
+
* `authClient.organization.removeMember`
|
|
3973
|
+
*
|
|
3974
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-remove-member)
|
|
3975
|
+
*/
|
|
3775
3976
|
removeMember: removeMember(options),
|
|
3977
|
+
/**
|
|
3978
|
+
* ### Endpoint
|
|
3979
|
+
*
|
|
3980
|
+
* POST `/organization/update-member-role`
|
|
3981
|
+
*
|
|
3982
|
+
* ### API Methods
|
|
3983
|
+
*
|
|
3984
|
+
* **server:**
|
|
3985
|
+
* `auth.api.updateMemberRole`
|
|
3986
|
+
*
|
|
3987
|
+
* **client:**
|
|
3988
|
+
* `authClient.organization.updateMemberRole`
|
|
3989
|
+
*
|
|
3990
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-update-member-role)
|
|
3991
|
+
*/
|
|
3776
3992
|
updateMemberRole: updateMemberRole(options),
|
|
3993
|
+
/**
|
|
3994
|
+
* ### Endpoint
|
|
3995
|
+
*
|
|
3996
|
+
* POST `/organization/leave`
|
|
3997
|
+
*
|
|
3998
|
+
* ### API Methods
|
|
3999
|
+
*
|
|
4000
|
+
* **server:**
|
|
4001
|
+
* `auth.api.leaveOrganization`
|
|
4002
|
+
*
|
|
4003
|
+
* **client:**
|
|
4004
|
+
* `authClient.organization.leave`
|
|
4005
|
+
*
|
|
4006
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-leave)
|
|
4007
|
+
*/
|
|
3777
4008
|
leaveOrganization: leaveOrganization(options),
|
|
4009
|
+
/**
|
|
4010
|
+
* ### Endpoint
|
|
4011
|
+
*
|
|
4012
|
+
* GET `/organization/list-members`
|
|
4013
|
+
*
|
|
4014
|
+
* ### API Methods
|
|
4015
|
+
*
|
|
4016
|
+
* **server:**
|
|
4017
|
+
* `auth.api.listMembers`
|
|
4018
|
+
*
|
|
4019
|
+
* **client:**
|
|
4020
|
+
* `authClient.organization.listMembers`
|
|
4021
|
+
*
|
|
4022
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-list-members)
|
|
4023
|
+
*/
|
|
3778
4024
|
listUserInvitations: listUserInvitations(options),
|
|
4025
|
+
/**
|
|
4026
|
+
* ### Endpoint
|
|
4027
|
+
*
|
|
4028
|
+
* GET `/organization/list-members`
|
|
4029
|
+
*
|
|
4030
|
+
* ### API Methods
|
|
4031
|
+
*
|
|
4032
|
+
* **server:**
|
|
4033
|
+
* `auth.api.listMembers`
|
|
4034
|
+
*
|
|
4035
|
+
* **client:**
|
|
4036
|
+
* `authClient.organization.listMembers`
|
|
4037
|
+
*/
|
|
3779
4038
|
listMembers: listMembers(options),
|
|
4039
|
+
/**
|
|
4040
|
+
* ### Endpoint
|
|
4041
|
+
*
|
|
4042
|
+
* GET `/organization/get-active-member-role`
|
|
4043
|
+
*
|
|
4044
|
+
* ### API Methods
|
|
4045
|
+
*
|
|
4046
|
+
* **server:**
|
|
4047
|
+
* `auth.api.getActiveMemberRole`
|
|
4048
|
+
*
|
|
4049
|
+
* **client:**
|
|
4050
|
+
* `authClient.organization.getActiveMemberRole`
|
|
4051
|
+
*
|
|
4052
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-get-active-member-role)
|
|
4053
|
+
*/
|
|
3780
4054
|
getActiveMemberRole: getActiveMemberRole(options)
|
|
3781
4055
|
};
|
|
3782
4056
|
const teamSupport = options?.teams?.enabled === true;
|
|
3783
4057
|
const teamEndpoints = {
|
|
4058
|
+
/**
|
|
4059
|
+
* ### Endpoint
|
|
4060
|
+
*
|
|
4061
|
+
* POST `/organization/create-team`
|
|
4062
|
+
*
|
|
4063
|
+
* ### API Methods
|
|
4064
|
+
*
|
|
4065
|
+
* **server:**
|
|
4066
|
+
* `auth.api.createTeam`
|
|
4067
|
+
*
|
|
4068
|
+
* **client:**
|
|
4069
|
+
* `authClient.organization.createTeam`
|
|
4070
|
+
*
|
|
4071
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-create-team)
|
|
4072
|
+
*/
|
|
3784
4073
|
createTeam: createTeam(options),
|
|
4074
|
+
/**
|
|
4075
|
+
* ### Endpoint
|
|
4076
|
+
*
|
|
4077
|
+
* GET `/organization/list-teams`
|
|
4078
|
+
*
|
|
4079
|
+
* ### API Methods
|
|
4080
|
+
*
|
|
4081
|
+
* **server:**
|
|
4082
|
+
* `auth.api.listOrganizationTeams`
|
|
4083
|
+
*
|
|
4084
|
+
* **client:**
|
|
4085
|
+
* `authClient.organization.listTeams`
|
|
4086
|
+
*
|
|
4087
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-list-teams)
|
|
4088
|
+
*/
|
|
3785
4089
|
listOrganizationTeams: listOrganizationTeams(options),
|
|
4090
|
+
/**
|
|
4091
|
+
* ### Endpoint
|
|
4092
|
+
*
|
|
4093
|
+
* POST `/organization/remove-team`
|
|
4094
|
+
*
|
|
4095
|
+
* ### API Methods
|
|
4096
|
+
*
|
|
4097
|
+
* **server:**
|
|
4098
|
+
* `auth.api.removeTeam`
|
|
4099
|
+
*
|
|
4100
|
+
* **client:**
|
|
4101
|
+
* `authClient.organization.removeTeam`
|
|
4102
|
+
*
|
|
4103
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-remove-team)
|
|
4104
|
+
*/
|
|
3786
4105
|
removeTeam: removeTeam(options),
|
|
4106
|
+
/**
|
|
4107
|
+
* ### Endpoint
|
|
4108
|
+
*
|
|
4109
|
+
* POST `/organization/update-team`
|
|
4110
|
+
*
|
|
4111
|
+
* ### API Methods
|
|
4112
|
+
*
|
|
4113
|
+
* **server:**
|
|
4114
|
+
* `auth.api.updateTeam`
|
|
4115
|
+
*
|
|
4116
|
+
* **client:**
|
|
4117
|
+
* `authClient.organization.updateTeam`
|
|
4118
|
+
*
|
|
4119
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-method-organization-update-team)
|
|
4120
|
+
*/
|
|
3787
4121
|
updateTeam: updateTeam(options),
|
|
4122
|
+
/**
|
|
4123
|
+
* ### Endpoint
|
|
4124
|
+
*
|
|
4125
|
+
* POST `/organization/set-active-team`
|
|
4126
|
+
*
|
|
4127
|
+
* ### API Methods
|
|
4128
|
+
*
|
|
4129
|
+
* **server:**
|
|
4130
|
+
* `auth.api.setActiveTeam`
|
|
4131
|
+
*
|
|
4132
|
+
* **client:**
|
|
4133
|
+
* `authClient.organization.setActiveTeam`
|
|
4134
|
+
*
|
|
4135
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-set-active-team)
|
|
4136
|
+
*/
|
|
3788
4137
|
setActiveTeam: setActiveTeam(options),
|
|
4138
|
+
/**
|
|
4139
|
+
* ### Endpoint
|
|
4140
|
+
*
|
|
4141
|
+
* GET `/organization/list-user-teams`
|
|
4142
|
+
*
|
|
4143
|
+
* ### API Methods
|
|
4144
|
+
*
|
|
4145
|
+
* **server:**
|
|
4146
|
+
* `auth.api.listUserTeams`
|
|
4147
|
+
*
|
|
4148
|
+
* **client:**
|
|
4149
|
+
* `authClient.organization.listUserTeams`
|
|
4150
|
+
*
|
|
4151
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-set-active-team)
|
|
4152
|
+
*/
|
|
3789
4153
|
listUserTeams: listUserTeams(options),
|
|
4154
|
+
/**
|
|
4155
|
+
* ### Endpoint
|
|
4156
|
+
*
|
|
4157
|
+
* POST `/organization/list-team-members`
|
|
4158
|
+
*
|
|
4159
|
+
* ### API Methods
|
|
4160
|
+
*
|
|
4161
|
+
* **server:**
|
|
4162
|
+
* `auth.api.listTeamMembers`
|
|
4163
|
+
*
|
|
4164
|
+
* **client:**
|
|
4165
|
+
* `authClient.organization.listTeamMembers`
|
|
4166
|
+
*
|
|
4167
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-set-active-team)
|
|
4168
|
+
*/
|
|
3790
4169
|
listTeamMembers: listTeamMembers(options),
|
|
4170
|
+
/**
|
|
4171
|
+
* ### Endpoint
|
|
4172
|
+
*
|
|
4173
|
+
* POST `/organization/add-team-member`
|
|
4174
|
+
*
|
|
4175
|
+
* ### API Methods
|
|
4176
|
+
*
|
|
4177
|
+
* **server:**
|
|
4178
|
+
* `auth.api.addTeamMember`
|
|
4179
|
+
*
|
|
4180
|
+
* **client:**
|
|
4181
|
+
* `authClient.organization.addTeamMember`
|
|
4182
|
+
*
|
|
4183
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-add-team-member)
|
|
4184
|
+
*/
|
|
3791
4185
|
addTeamMember: addTeamMember(options),
|
|
4186
|
+
/**
|
|
4187
|
+
* ### Endpoint
|
|
4188
|
+
*
|
|
4189
|
+
* POST `/organization/remove-team-member`
|
|
4190
|
+
*
|
|
4191
|
+
* ### API Methods
|
|
4192
|
+
*
|
|
4193
|
+
* **server:**
|
|
4194
|
+
* `auth.api.removeTeamMember`
|
|
4195
|
+
*
|
|
4196
|
+
* **client:**
|
|
4197
|
+
* `authClient.organization.removeTeamMember`
|
|
4198
|
+
*
|
|
4199
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/organization#api-remove-team-member)
|
|
4200
|
+
*/
|
|
3792
4201
|
removeTeamMember: removeTeamMember(options)
|
|
3793
4202
|
};
|
|
3794
4203
|
if (teamSupport) endpoints = {
|
|
@@ -3807,7 +4216,7 @@ function organization(options) {
|
|
|
3807
4216
|
...endpoints,
|
|
3808
4217
|
...dynamicAccessControlEndpoints
|
|
3809
4218
|
};
|
|
3810
|
-
const teamSchema
|
|
4219
|
+
const teamSchema = teamSupport ? {
|
|
3811
4220
|
team: {
|
|
3812
4221
|
modelName: options?.schema?.team?.modelName,
|
|
3813
4222
|
fields: {
|
|
@@ -3868,7 +4277,7 @@ function organization(options) {
|
|
|
3868
4277
|
}
|
|
3869
4278
|
}
|
|
3870
4279
|
} : {};
|
|
3871
|
-
const organizationRoleSchema
|
|
4280
|
+
const organizationRoleSchema = options?.dynamicAccessControl?.enabled ? { organizationRole: {
|
|
3872
4281
|
fields: {
|
|
3873
4282
|
organizationId: {
|
|
3874
4283
|
type: "string",
|
|
@@ -3905,7 +4314,7 @@ function organization(options) {
|
|
|
3905
4314
|
},
|
|
3906
4315
|
modelName: options?.schema?.organizationRole?.modelName
|
|
3907
4316
|
} } : {};
|
|
3908
|
-
const schema
|
|
4317
|
+
const schema = {
|
|
3909
4318
|
organization: {
|
|
3910
4319
|
modelName: options?.schema?.organization?.modelName,
|
|
3911
4320
|
fields: {
|
|
@@ -3940,8 +4349,8 @@ function organization(options) {
|
|
|
3940
4349
|
...options?.schema?.organization?.additionalFields || {}
|
|
3941
4350
|
}
|
|
3942
4351
|
},
|
|
3943
|
-
...organizationRoleSchema
|
|
3944
|
-
...teamSchema
|
|
4352
|
+
...organizationRoleSchema,
|
|
4353
|
+
...teamSchema,
|
|
3945
4354
|
member: {
|
|
3946
4355
|
modelName: options?.schema?.member?.modelName,
|
|
3947
4356
|
fields: {
|
|
@@ -4046,7 +4455,7 @@ function organization(options) {
|
|
|
4046
4455
|
hasPermission: createHasPermission(options)
|
|
4047
4456
|
},
|
|
4048
4457
|
schema: {
|
|
4049
|
-
...schema
|
|
4458
|
+
...schema,
|
|
4050
4459
|
session: { fields: {
|
|
4051
4460
|
activeOrganizationId: {
|
|
4052
4461
|
type: "string",
|
|
@@ -4072,9 +4481,7 @@ function organization(options) {
|
|
|
4072
4481
|
options
|
|
4073
4482
|
};
|
|
4074
4483
|
}
|
|
4075
|
-
|
|
4076
|
-
//#endregion
|
|
4077
|
-
//#region src/plugins/two-factor/error-code.ts
|
|
4484
|
+
// src/plugins/two-factor/error-code.ts
|
|
4078
4485
|
const TWO_FACTOR_ERROR_CODES = {
|
|
4079
4486
|
OTP_NOT_ENABLED: "OTP not enabled",
|
|
4080
4487
|
OTP_HAS_EXPIRED: "OTP has expired",
|
|
@@ -4086,39 +4493,55 @@ const TWO_FACTOR_ERROR_CODES = {
|
|
|
4086
4493
|
TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE: "Too many attempts. Please request a new code.",
|
|
4087
4494
|
INVALID_TWO_FACTOR_COOKIE: "Invalid two factor cookie"
|
|
4088
4495
|
};
|
|
4089
|
-
|
|
4090
|
-
//#endregion
|
|
4091
|
-
//#region src/plugins/two-factor/schema/totp.ts
|
|
4496
|
+
// src/plugins/two-factor/schema/totp.ts
|
|
4092
4497
|
const generateTOTPSchema = zod.object({ secret: zod.string().openapi({ description: "The secret to generate the TOTP code" }) });
|
|
4093
4498
|
const generateTOTPResponseSchema = zod.string();
|
|
4094
4499
|
const getTOTPURISchema = zod.object({ password: zod.string().openapi({ description: "User password" }) });
|
|
4095
4500
|
const getTOTPURIResponseSchema = zod.url();
|
|
4096
4501
|
const verifyTOTPSchema = zod.object({
|
|
4097
4502
|
code: zod.string().openapi({ description: "The otp code to verify. Eg: \"012345\"" }),
|
|
4503
|
+
/**
|
|
4504
|
+
* if true, the device will be trusted
|
|
4505
|
+
* for 30 days. It'll be refreshed on
|
|
4506
|
+
* every sign in request within this time.
|
|
4507
|
+
*/
|
|
4098
4508
|
trustDevice: zod.boolean().openapi({ description: "If true, the device will be trusted for 30 days. It'll be refreshed on every sign in request within this time. Eg: true" }).optional()
|
|
4099
4509
|
});
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4510
|
+
// src/plugins/two-factor/schema/otp.ts
|
|
4511
|
+
const sendTwoFactorOTPSchema = zod.object({
|
|
4512
|
+
/**
|
|
4513
|
+
* if true, the device will be trusted
|
|
4514
|
+
* for 30 days. It'll be refreshed on
|
|
4515
|
+
* every sign in request within this time.
|
|
4516
|
+
*/
|
|
4517
|
+
trustDevice: zod.boolean().optional().openapi({ description: "If true, the device will be trusted for 30 days. It'll be refreshed on every sign in request within this time. Eg: true" }) });
|
|
4104
4518
|
const verifyTwoFactorOTPSchema = zod.object({
|
|
4105
4519
|
code: zod.string().openapi({ description: "The otp code to verify. Eg: \"012345\"" }),
|
|
4520
|
+
/**
|
|
4521
|
+
* if true, the device will be trusted
|
|
4522
|
+
* for 30 days. It'll be refreshed on
|
|
4523
|
+
* every sign in request within this time.
|
|
4524
|
+
*/
|
|
4106
4525
|
trustDevice: zod.boolean().optional().openapi({ description: "If true, the device will be trusted for 30 days. It'll be refreshed on every sign in request within this time. Eg: true" })
|
|
4107
4526
|
});
|
|
4108
|
-
|
|
4109
|
-
//#endregion
|
|
4110
|
-
//#region src/plugins/two-factor/schema/backup-codes.ts
|
|
4527
|
+
// src/plugins/two-factor/schema/backup-codes.ts
|
|
4111
4528
|
const verifyBackupCodeSchema = zod.object({
|
|
4112
4529
|
code: zod.string().openapi({ description: `A backup code to verify. Eg: "123456"` }),
|
|
4530
|
+
/**
|
|
4531
|
+
* Disable setting the session cookie
|
|
4532
|
+
*/
|
|
4113
4533
|
disableSession: zod.boolean().openapi({ description: "If true, the session cookie will not be set." }).optional(),
|
|
4534
|
+
/**
|
|
4535
|
+
* if true, the device will be trusted
|
|
4536
|
+
* for 30 days. It'll be refreshed on
|
|
4537
|
+
* every sign in request within this time.
|
|
4538
|
+
*/
|
|
4114
4539
|
trustDevice: zod.boolean().openapi({ description: "If true, the device will be trusted for 30 days. It'll be refreshed on every sign in request within this time. Eg: true" }).optional()
|
|
4115
4540
|
});
|
|
4116
4541
|
const generateBackupCodesSchema = zod.object({ password: zod.string().openapi({ description: "The users password." }) });
|
|
4117
4542
|
const viewBackupCodesSchema = zod.object({ userId: zod.coerce.string().openapi({ description: `The user ID to view all backup codes. Eg: "user-id"` }) });
|
|
4118
4543
|
const backupCodesResponseSchema = zod.array(zod.string()).openapi({ description: "Array of generated backup codes in plain text" });
|
|
4119
|
-
|
|
4120
|
-
//#endregion
|
|
4121
|
-
//#region src/plugins/two-factor/schema/index.ts
|
|
4544
|
+
// src/plugins/two-factor/schema/index.ts
|
|
4122
4545
|
const schema = {
|
|
4123
4546
|
user: { fields: { twoFactorEnabled: {
|
|
4124
4547
|
type: "boolean",
|
|
@@ -4157,18 +4580,14 @@ const totpURISchema = zod.object({
|
|
|
4157
4580
|
totpURI: zod.url().openapi({ description: "TOTP URI" }),
|
|
4158
4581
|
backupCodes: zod.array(zod.string()).openapi({ description: "Backup codes" })
|
|
4159
4582
|
});
|
|
4160
|
-
|
|
4161
|
-
//#endregion
|
|
4162
|
-
//#region src/plugins/two-factor/constant.ts
|
|
4583
|
+
// src/plugins/two-factor/constant.ts
|
|
4163
4584
|
const TWO_FACTOR_COOKIE_NAME = "two_factor";
|
|
4164
4585
|
const TRUST_DEVICE_COOKIE_NAME = "trust_device";
|
|
4165
|
-
const TRUST_DEVICE_COOKIE_MAX_AGE =
|
|
4166
|
-
|
|
4167
|
-
//#endregion
|
|
4168
|
-
//#region src/plugins/two-factor/verify-two-factor.ts
|
|
4586
|
+
const TRUST_DEVICE_COOKIE_MAX_AGE = 2592e3;
|
|
4587
|
+
// src/plugins/two-factor/verify-two-factor.ts
|
|
4169
4588
|
async function verifyTwoFactor(ctx, options) {
|
|
4170
4589
|
const invalid = (errorKey) => ctx.render({
|
|
4171
|
-
success:
|
|
4590
|
+
success: _faire_auth_core_static.False,
|
|
4172
4591
|
message: TWO_FACTOR_ERROR_CODES[errorKey]
|
|
4173
4592
|
}, 401);
|
|
4174
4593
|
const session = await require_session.getSessionFromCtx(ctx);
|
|
@@ -4177,45 +4596,45 @@ async function verifyTwoFactor(ctx, options) {
|
|
|
4177
4596
|
const cookieName = context.createAuthCookie(TWO_FACTOR_COOKIE_NAME);
|
|
4178
4597
|
const twoFactorCookie = await (0, require_cookies.cookies_exports.getSignedCookie)(ctx, context.secret, cookieName.name);
|
|
4179
4598
|
if (!twoFactorCookie) return ctx.render({
|
|
4180
|
-
success:
|
|
4599
|
+
success: _faire_auth_core_static.False,
|
|
4181
4600
|
message: TWO_FACTOR_ERROR_CODES.INVALID_TWO_FACTOR_COOKIE
|
|
4182
4601
|
}, 401);
|
|
4183
4602
|
const verificationToken = await context.internalAdapter.findVerificationValue(twoFactorCookie);
|
|
4184
4603
|
if (!verificationToken) return ctx.render({
|
|
4185
|
-
success:
|
|
4604
|
+
success: _faire_auth_core_static.False,
|
|
4186
4605
|
message: TWO_FACTOR_ERROR_CODES.INVALID_TWO_FACTOR_COOKIE
|
|
4187
4606
|
}, 401);
|
|
4188
4607
|
const user = await context.internalAdapter.findUserById(verificationToken.value);
|
|
4189
4608
|
if (!user) return ctx.render({
|
|
4190
|
-
success:
|
|
4609
|
+
success: _faire_auth_core_static.False,
|
|
4191
4610
|
message: TWO_FACTOR_ERROR_CODES.INVALID_TWO_FACTOR_COOKIE
|
|
4192
4611
|
}, 401);
|
|
4193
4612
|
const dontRememberMe = await (0, require_cookies.cookies_exports.getSignedCookie)(ctx, context.secret, context.authCookies.dontRememberToken.name);
|
|
4194
4613
|
return {
|
|
4195
|
-
valid: async (ctx
|
|
4196
|
-
const session
|
|
4197
|
-
if (!session
|
|
4198
|
-
success:
|
|
4614
|
+
valid: async (ctx) => {
|
|
4615
|
+
const session = await context.internalAdapter.createSession(verificationToken.value, !!dontRememberMe);
|
|
4616
|
+
if (!session) return ctx.render({
|
|
4617
|
+
success: _faire_auth_core_static.False,
|
|
4199
4618
|
message: "Failed to create session"
|
|
4200
4619
|
}, 500);
|
|
4201
|
-
await require_cookies.setSessionCookie(ctx
|
|
4202
|
-
session
|
|
4620
|
+
await require_cookies.setSessionCookie(ctx, options, {
|
|
4621
|
+
session,
|
|
4203
4622
|
user
|
|
4204
4623
|
});
|
|
4205
|
-
if (ctx
|
|
4206
|
-
const trustDeviceCookie = context.createAuthCookie(TRUST_DEVICE_COOKIE_NAME, { maxAge:
|
|
4624
|
+
if (ctx.req.valid("json").trustDevice === true) {
|
|
4625
|
+
const trustDeviceCookie = context.createAuthCookie(TRUST_DEVICE_COOKIE_NAME, { maxAge: 2592e3 });
|
|
4207
4626
|
/**
|
|
4208
4627
|
* create a token that will be used to
|
|
4209
4628
|
* verify the device
|
|
4210
4629
|
*/
|
|
4211
|
-
const token = await (0,
|
|
4212
|
-
await (0, require_cookies.cookies_exports.setSignedCookie)(ctx
|
|
4213
|
-
(0, require_cookies.cookies_exports.deleteCookie)(ctx
|
|
4214
|
-
(0, require_cookies.cookies_exports.deleteCookie)(ctx
|
|
4630
|
+
const token = await (0, _faire_auth_core_datatypes.createHMAC)("SHA-256", "base64urlnopad").sign(context.secret, `${user.id}!${session.token}`);
|
|
4631
|
+
await (0, require_cookies.cookies_exports.setSignedCookie)(ctx, trustDeviceCookie.name, `${token}!${session.token}`, context.secret, trustDeviceCookie.attributes);
|
|
4632
|
+
(0, require_cookies.cookies_exports.deleteCookie)(ctx, context.authCookies.dontRememberToken.name, context.authCookies.dontRememberToken.options);
|
|
4633
|
+
(0, require_cookies.cookies_exports.deleteCookie)(ctx, cookieName.name, cookieName.attributes);
|
|
4215
4634
|
}
|
|
4216
|
-
return ctx
|
|
4217
|
-
success:
|
|
4218
|
-
token: session
|
|
4635
|
+
return ctx.render({
|
|
4636
|
+
success: _faire_auth_core_static.True,
|
|
4637
|
+
token: session.token,
|
|
4219
4638
|
user: {
|
|
4220
4639
|
id: user.id,
|
|
4221
4640
|
email: user.email,
|
|
@@ -4236,8 +4655,8 @@ async function verifyTwoFactor(ctx, options) {
|
|
|
4236
4655
|
};
|
|
4237
4656
|
}
|
|
4238
4657
|
return {
|
|
4239
|
-
valid: (ctx
|
|
4240
|
-
success:
|
|
4658
|
+
valid: (ctx) => ctx.render({
|
|
4659
|
+
success: _faire_auth_core_static.True,
|
|
4241
4660
|
token: session.session.token,
|
|
4242
4661
|
user: {
|
|
4243
4662
|
id: session.user.id,
|
|
@@ -4254,11 +4673,9 @@ async function verifyTwoFactor(ctx, options) {
|
|
|
4254
4673
|
key: `${session.user.id}!${session.session.id}`
|
|
4255
4674
|
};
|
|
4256
4675
|
}
|
|
4257
|
-
|
|
4258
|
-
//#endregion
|
|
4259
|
-
//#region src/plugins/two-factor/backup-codes/index.ts
|
|
4676
|
+
// src/plugins/two-factor/backup-codes/index.ts
|
|
4260
4677
|
function generateBackupCodesFn(options) {
|
|
4261
|
-
return Array.from({ length: options?.amount ?? 10 }).fill(null).map(() => (0,
|
|
4678
|
+
return Array.from({ length: options?.amount ?? 10 }).fill(null).map(() => (0, _faire_auth_core_crypto.generateRandomString)(options?.length ?? 10, "a-z", "0-9", "A-Z")).map((code) => `${code.slice(0, 5)}-${code.slice(5)}`);
|
|
4262
4679
|
}
|
|
4263
4680
|
async function generateBackupCodes(secret, options) {
|
|
4264
4681
|
const backupCodes = options?.customBackupCodesGenerate ? options.customBackupCodesGenerate() : generateBackupCodesFn(options);
|
|
@@ -4290,11 +4707,17 @@ async function verifyBackupCode(data, key, options) {
|
|
|
4290
4707
|
};
|
|
4291
4708
|
}
|
|
4292
4709
|
async function getBackupCodes(backupCodes, key, options) {
|
|
4293
|
-
if (options?.storeBackupCodes === "encrypted")
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
|
|
4710
|
+
if (options?.storeBackupCodes === "encrypted") {
|
|
4711
|
+
const decrypted = await (0, require_crypto.crypto_exports.symmetricDecrypt)({
|
|
4712
|
+
key,
|
|
4713
|
+
data: backupCodes
|
|
4714
|
+
});
|
|
4715
|
+
return require_json.safeJSONParse(decrypted);
|
|
4716
|
+
}
|
|
4717
|
+
if (typeof options?.storeBackupCodes === "object" && "decrypt" in options?.storeBackupCodes) {
|
|
4718
|
+
const decrypted = await options?.storeBackupCodes.decrypt(backupCodes);
|
|
4719
|
+
return require_json.safeJSONParse(decrypted);
|
|
4720
|
+
}
|
|
4298
4721
|
return require_json.safeJSONParse(backupCodes);
|
|
4299
4722
|
}
|
|
4300
4723
|
const backupCode2fa = (options) => {
|
|
@@ -4302,36 +4725,51 @@ const backupCode2fa = (options) => {
|
|
|
4302
4725
|
return {
|
|
4303
4726
|
id: "backup_code",
|
|
4304
4727
|
routes: {
|
|
4305
|
-
|
|
4728
|
+
/**
|
|
4729
|
+
* ### Endpoint
|
|
4730
|
+
*
|
|
4731
|
+
* POST `/two-factor/verify-backup-code`
|
|
4732
|
+
*
|
|
4733
|
+
* ### API Methods
|
|
4734
|
+
*
|
|
4735
|
+
* **server:**
|
|
4736
|
+
* `auth.api.verifyBackupCode`
|
|
4737
|
+
*
|
|
4738
|
+
* **client:**
|
|
4739
|
+
* `authClient.twoFactor.verifyBackupCode`
|
|
4740
|
+
*
|
|
4741
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-verify-backup-code)
|
|
4742
|
+
*/
|
|
4743
|
+
verifyBackupCode: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4306
4744
|
operationId: "verifyBackupCode",
|
|
4307
4745
|
method: "post",
|
|
4308
4746
|
path: "/two-factor/verify-backup-code",
|
|
4309
4747
|
description: "Verify a backup code for two-factor authentication",
|
|
4310
|
-
request: (0,
|
|
4311
|
-
responses: (0,
|
|
4748
|
+
request: (0, _faire_auth_core_factory.req)().bdy(verifyBackupCodeSchema).bld(),
|
|
4749
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.TOKEN_USER].default, "Backup code verified successfully").err(400, "Backup Codes not configured").err(401, "Invalid backup code").err(500, "Failed to create session").zod().bld()
|
|
4312
4750
|
}), (authOptions) => async (ctx) => {
|
|
4313
4751
|
const context = ctx.get("context");
|
|
4314
4752
|
const response = await verifyTwoFactor(ctx, authOptions);
|
|
4315
4753
|
if (response instanceof Response) return response;
|
|
4316
4754
|
const { session, valid } = response;
|
|
4317
|
-
const twoFactor
|
|
4755
|
+
const twoFactor = await context.adapter.findOne({
|
|
4318
4756
|
model: twoFactorTable,
|
|
4319
4757
|
where: [{
|
|
4320
4758
|
field: "userId",
|
|
4321
4759
|
value: session.user.id
|
|
4322
4760
|
}]
|
|
4323
4761
|
});
|
|
4324
|
-
if (!twoFactor
|
|
4325
|
-
success:
|
|
4762
|
+
if (!twoFactor) return ctx.render({
|
|
4763
|
+
success: _faire_auth_core_static.False,
|
|
4326
4764
|
message: TWO_FACTOR_ERROR_CODES.BACKUP_CODES_NOT_ENABLED
|
|
4327
4765
|
}, 400);
|
|
4328
4766
|
const { code, disableSession } = ctx.req.valid("json");
|
|
4329
4767
|
const validate = await verifyBackupCode({
|
|
4330
|
-
backupCodes: twoFactor
|
|
4768
|
+
backupCodes: twoFactor.backupCodes,
|
|
4331
4769
|
code
|
|
4332
4770
|
}, context.secret, options);
|
|
4333
4771
|
if (!validate.status) return ctx.render({
|
|
4334
|
-
success:
|
|
4772
|
+
success: _faire_auth_core_static.False,
|
|
4335
4773
|
message: TWO_FACTOR_ERROR_CODES.INVALID_BACKUP_CODE
|
|
4336
4774
|
}, 401);
|
|
4337
4775
|
const updatedBackupCodes = await (0, require_crypto.crypto_exports.symmetricEncrypt)({
|
|
@@ -4348,28 +4786,43 @@ const backupCode2fa = (options) => {
|
|
|
4348
4786
|
});
|
|
4349
4787
|
if (!disableSession) return await valid(ctx);
|
|
4350
4788
|
return ctx.render({
|
|
4351
|
-
success:
|
|
4789
|
+
success: _faire_auth_core_static.True,
|
|
4352
4790
|
token: session.session?.token ?? null,
|
|
4353
4791
|
user: session.user
|
|
4354
4792
|
}, 200);
|
|
4355
4793
|
}),
|
|
4356
|
-
|
|
4794
|
+
/**
|
|
4795
|
+
* ### Endpoint
|
|
4796
|
+
*
|
|
4797
|
+
* POST `/two-factor/generate-backup-codes`
|
|
4798
|
+
*
|
|
4799
|
+
* ### API Methods
|
|
4800
|
+
*
|
|
4801
|
+
* **server:**
|
|
4802
|
+
* `auth.api.generateBackupCodes`
|
|
4803
|
+
*
|
|
4804
|
+
* **client:**
|
|
4805
|
+
* `authClient.twoFactor.generateBackupCodes`
|
|
4806
|
+
*
|
|
4807
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-generate-backup-codes)
|
|
4808
|
+
*/
|
|
4809
|
+
generateBackupCodes: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4357
4810
|
operationId: "generateBackupCodes",
|
|
4358
4811
|
method: "post",
|
|
4359
4812
|
path: "/two-factor/generate-backup-codes",
|
|
4360
4813
|
description: "Generate new backup codes for two-factor authentication",
|
|
4361
4814
|
middleware: [require_session.sessionMiddleware()],
|
|
4362
|
-
request: (0,
|
|
4363
|
-
responses: (0,
|
|
4815
|
+
request: (0, _faire_auth_core_factory.req)().bdy(generateBackupCodesSchema).bld(),
|
|
4816
|
+
responses: (0, _faire_auth_core_factory.res)(backupCodesResponseSchema.transform(_faire_auth_core_utils.toSuccess), "Backup codes generated successfully").err(400, "Backup Codes not configured").zod().bld()
|
|
4364
4817
|
}), (_authOptions) => async (ctx) => {
|
|
4365
4818
|
const { user } = ctx.get("session");
|
|
4366
4819
|
const context = ctx.get("context");
|
|
4367
4820
|
if (!user.twoFactorEnabled) return ctx.render({
|
|
4368
|
-
success:
|
|
4821
|
+
success: _faire_auth_core_static.False,
|
|
4369
4822
|
message: TWO_FACTOR_ERROR_CODES.TWO_FACTOR_NOT_ENABLED
|
|
4370
4823
|
}, 400);
|
|
4371
|
-
const res
|
|
4372
|
-
if (res
|
|
4824
|
+
const res = await context.password.checkPassword(user.id, ctx);
|
|
4825
|
+
if (res instanceof Response) return res;
|
|
4373
4826
|
const backupCodes = await generateBackupCodes(context.secret, options);
|
|
4374
4827
|
await context.adapter.updateMany({
|
|
4375
4828
|
model: twoFactorTable,
|
|
@@ -4381,34 +4834,49 @@ const backupCode2fa = (options) => {
|
|
|
4381
4834
|
});
|
|
4382
4835
|
return ctx.render(backupCodes.backupCodes, 200);
|
|
4383
4836
|
}),
|
|
4384
|
-
|
|
4837
|
+
/**
|
|
4838
|
+
* ### Endpoint
|
|
4839
|
+
*
|
|
4840
|
+
* GET `/two-factor/view-backup-codes`
|
|
4841
|
+
*
|
|
4842
|
+
* ### API Methods
|
|
4843
|
+
*
|
|
4844
|
+
* **server:**
|
|
4845
|
+
* `auth.api.viewBackupCodes`
|
|
4846
|
+
*
|
|
4847
|
+
* **client:**
|
|
4848
|
+
* `authClient.twoFactor.viewBackupCodes`
|
|
4849
|
+
*
|
|
4850
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-view-backup-codes)
|
|
4851
|
+
*/
|
|
4852
|
+
viewBackupCodes: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4385
4853
|
operationId: "viewBackupCodes",
|
|
4386
4854
|
method: "post",
|
|
4387
4855
|
path: "/two-factor/view-backup-codes",
|
|
4388
4856
|
SERVER_ONLY: true,
|
|
4389
|
-
request: (0,
|
|
4390
|
-
responses: (0,
|
|
4857
|
+
request: (0, _faire_auth_core_factory.req)().bdy(viewBackupCodesSchema).bld(),
|
|
4858
|
+
responses: (0, _faire_auth_core_factory.res)(backupCodesResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Backup Codes not configured").err(401, "Server only endpoint").zod().bld()
|
|
4391
4859
|
}), (_authOptions) => async (ctx) => {
|
|
4392
4860
|
const context = ctx.get("context");
|
|
4393
4861
|
if (!ctx.get("isServer")) return ctx.render({
|
|
4394
|
-
success:
|
|
4862
|
+
success: _faire_auth_core_static.False,
|
|
4395
4863
|
message: "Unauthorized"
|
|
4396
4864
|
}, 401);
|
|
4397
4865
|
const { userId } = ctx.req.valid("json");
|
|
4398
|
-
const twoFactor
|
|
4866
|
+
const twoFactor = await context.adapter.findOne({
|
|
4399
4867
|
model: twoFactorTable,
|
|
4400
4868
|
where: [{
|
|
4401
4869
|
field: "userId",
|
|
4402
4870
|
value: userId
|
|
4403
4871
|
}]
|
|
4404
4872
|
});
|
|
4405
|
-
if (!twoFactor
|
|
4406
|
-
success:
|
|
4873
|
+
if (!twoFactor) return ctx.render({
|
|
4874
|
+
success: _faire_auth_core_static.False,
|
|
4407
4875
|
message: TWO_FACTOR_ERROR_CODES.BACKUP_CODES_NOT_ENABLED
|
|
4408
4876
|
}, 400);
|
|
4409
|
-
const decryptedBackupCodes = await getBackupCodes(twoFactor
|
|
4877
|
+
const decryptedBackupCodes = await getBackupCodes(twoFactor.backupCodes, context.secret, options);
|
|
4410
4878
|
if (!decryptedBackupCodes) return ctx.render({
|
|
4411
|
-
success:
|
|
4879
|
+
success: _faire_auth_core_static.False,
|
|
4412
4880
|
message: TWO_FACTOR_ERROR_CODES.BACKUP_CODES_NOT_ENABLED
|
|
4413
4881
|
}, 400);
|
|
4414
4882
|
return ctx.render(decryptedBackupCodes, 200);
|
|
@@ -4416,16 +4884,12 @@ const backupCode2fa = (options) => {
|
|
|
4416
4884
|
}
|
|
4417
4885
|
};
|
|
4418
4886
|
};
|
|
4419
|
-
|
|
4420
|
-
//#endregion
|
|
4421
|
-
//#region src/plugins/two-factor/utils.ts
|
|
4887
|
+
// src/plugins/two-factor/utils.ts
|
|
4422
4888
|
const defaultKeyHasher = async (token) => {
|
|
4423
|
-
const hash = await (0,
|
|
4424
|
-
return
|
|
4889
|
+
const hash = await (0, _faire_auth_core_datatypes.createHash)("SHA-256").digest(new TextEncoder().encode(token));
|
|
4890
|
+
return _faire_auth_core_datatypes.base64Url.encode(new Uint8Array(hash), { padding: false });
|
|
4425
4891
|
};
|
|
4426
|
-
|
|
4427
|
-
//#endregion
|
|
4428
|
-
//#region src/plugins/two-factor/otp/index.ts
|
|
4892
|
+
// src/plugins/two-factor/otp/index.ts
|
|
4429
4893
|
/**
|
|
4430
4894
|
* The otp adapter is created from the totp adapter.
|
|
4431
4895
|
*/
|
|
@@ -4459,20 +4923,35 @@ const otp2fa = (options) => {
|
|
|
4459
4923
|
return {
|
|
4460
4924
|
id: "otp",
|
|
4461
4925
|
routes: {
|
|
4462
|
-
|
|
4926
|
+
/**
|
|
4927
|
+
* ### Endpoint
|
|
4928
|
+
*
|
|
4929
|
+
* POST `/two-factor/send-otp`
|
|
4930
|
+
*
|
|
4931
|
+
* ### API Methods
|
|
4932
|
+
*
|
|
4933
|
+
* **server:**
|
|
4934
|
+
* `auth.api.send2FaOTP`
|
|
4935
|
+
*
|
|
4936
|
+
* **client:**
|
|
4937
|
+
* `authClient.twoFactor.sendOtp`
|
|
4938
|
+
*
|
|
4939
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-send-otp)
|
|
4940
|
+
*/
|
|
4941
|
+
sendTwoFactorOTP: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4463
4942
|
operationId: "sendTwoFactorOTP",
|
|
4464
4943
|
method: "post",
|
|
4465
4944
|
path: "/two-factor/send-otp",
|
|
4466
4945
|
summary: "Send two factor OTP",
|
|
4467
4946
|
description: "Send two factor OTP to the user",
|
|
4468
|
-
request: (0,
|
|
4469
|
-
responses: (0,
|
|
4947
|
+
request: (0, _faire_auth_core_factory.req)().bdy(sendTwoFactorOTPSchema).bld(),
|
|
4948
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default).err(400, "OTP isn't configured").err(401, "OTP error").zod().bld()
|
|
4470
4949
|
}), (authOptions) => async (ctx) => {
|
|
4471
4950
|
const context = ctx.get("context");
|
|
4472
4951
|
if (!options || !options.sendOTP) {
|
|
4473
4952
|
context.logger.error("send otp isn't configured. Please configure the send otp function on otp options.");
|
|
4474
4953
|
return ctx.render({
|
|
4475
|
-
success:
|
|
4954
|
+
success: _faire_auth_core_static.False,
|
|
4476
4955
|
message: "OTP isn't configured"
|
|
4477
4956
|
}, 400);
|
|
4478
4957
|
}
|
|
@@ -4480,7 +4959,7 @@ const otp2fa = (options) => {
|
|
|
4480
4959
|
if (response instanceof Response) return response;
|
|
4481
4960
|
const { session, key } = response;
|
|
4482
4961
|
if (!session.user.twoFactorEnabled) return ctx.render({
|
|
4483
|
-
success:
|
|
4962
|
+
success: _faire_auth_core_static.False,
|
|
4484
4963
|
message: TWO_FACTOR_ERROR_CODES.OTP_NOT_ENABLED
|
|
4485
4964
|
}, 400);
|
|
4486
4965
|
const code = (0, require_crypto.crypto_exports.generateRandomString)(opts.digits, "0-9");
|
|
@@ -4494,16 +4973,31 @@ const otp2fa = (options) => {
|
|
|
4494
4973
|
user: session.user,
|
|
4495
4974
|
otp: code
|
|
4496
4975
|
}, ctx.req);
|
|
4497
|
-
return ctx.render({ success:
|
|
4976
|
+
return ctx.render({ success: _faire_auth_core_static.True }, 200);
|
|
4498
4977
|
}),
|
|
4499
|
-
|
|
4978
|
+
/**
|
|
4979
|
+
* ### Endpoint
|
|
4980
|
+
*
|
|
4981
|
+
* POST `/two-factor/verify-otp`
|
|
4982
|
+
*
|
|
4983
|
+
* ### API Methods
|
|
4984
|
+
*
|
|
4985
|
+
* **server:**
|
|
4986
|
+
* `auth.api.verifyOTP`
|
|
4987
|
+
*
|
|
4988
|
+
* **client:**
|
|
4989
|
+
* `authClient.twoFactor.verifyOtp`
|
|
4990
|
+
*
|
|
4991
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-verify-otp)
|
|
4992
|
+
*/
|
|
4993
|
+
verifyTwoFactorOTP: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4500
4994
|
operationId: "verifyTwoFactorOTP",
|
|
4501
4995
|
method: "post",
|
|
4502
4996
|
path: "/two-factor/verify-otp",
|
|
4503
4997
|
summary: "Verify two factor OTP",
|
|
4504
4998
|
description: "Verify two factor OTP",
|
|
4505
|
-
request: (0,
|
|
4506
|
-
responses: (0,
|
|
4999
|
+
request: (0, _faire_auth_core_factory.req)().bdy(verifyTwoFactorOTPSchema).bld(),
|
|
5000
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.TOKEN_USER].default, "Two-factor OTP verified successfully").err(400, "OTP isn't enabled or failed to create session").err(401, "OTP Error").err(500, "Failed to update user").zod().bld()
|
|
4507
5001
|
}), (authOptions) => async (ctx) => {
|
|
4508
5002
|
const context = ctx.get("context");
|
|
4509
5003
|
const response = await verifyTwoFactor(ctx, authOptions);
|
|
@@ -4512,14 +5006,14 @@ const otp2fa = (options) => {
|
|
|
4512
5006
|
const toCheckOtp = await context.internalAdapter.findVerificationValue(`2fa-otp-${key}`);
|
|
4513
5007
|
const [otp, counter] = toCheckOtp?.value?.split(":") || [];
|
|
4514
5008
|
if (!counter || !otp) return ctx.render({
|
|
4515
|
-
success:
|
|
5009
|
+
success: _faire_auth_core_static.False,
|
|
4516
5010
|
message: TWO_FACTOR_ERROR_CODES.INVALID_CODE
|
|
4517
5011
|
}, 400);
|
|
4518
5012
|
const decryptedOtp = await decryptOTP(ctx, otp);
|
|
4519
5013
|
if (!toCheckOtp || toCheckOtp.expiresAt < /* @__PURE__ */ new Date()) {
|
|
4520
5014
|
if (toCheckOtp) await context.internalAdapter.deleteVerificationValue(toCheckOtp.id);
|
|
4521
5015
|
return ctx.render({
|
|
4522
|
-
success:
|
|
5016
|
+
success: _faire_auth_core_static.False,
|
|
4523
5017
|
message: TWO_FACTOR_ERROR_CODES.OTP_HAS_EXPIRED
|
|
4524
5018
|
}, 400);
|
|
4525
5019
|
}
|
|
@@ -4527,20 +5021,20 @@ const otp2fa = (options) => {
|
|
|
4527
5021
|
if (parseInt(counter) >= allowedAttempts) {
|
|
4528
5022
|
await context.internalAdapter.deleteVerificationValue(toCheckOtp.id);
|
|
4529
5023
|
return ctx.render({
|
|
4530
|
-
success:
|
|
5024
|
+
success: _faire_auth_core_static.False,
|
|
4531
5025
|
message: TWO_FACTOR_ERROR_CODES.TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE
|
|
4532
5026
|
}, 400);
|
|
4533
5027
|
}
|
|
4534
5028
|
if (decryptedOtp === ctx.req.valid("json").code) {
|
|
4535
5029
|
if (!session.user.twoFactorEnabled) {
|
|
4536
5030
|
if (!session.session) return ctx.render({
|
|
4537
|
-
success:
|
|
4538
|
-
message:
|
|
5031
|
+
success: _faire_auth_core_static.False,
|
|
5032
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION
|
|
4539
5033
|
}, 400);
|
|
4540
5034
|
const updatedUser = await context.internalAdapter.updateUser(session.user.id, { twoFactorEnabled: true });
|
|
4541
5035
|
if (updatedUser == null) return ctx.render({
|
|
4542
|
-
success:
|
|
4543
|
-
message:
|
|
5036
|
+
success: _faire_auth_core_static.False,
|
|
5037
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_UPDATE_USER
|
|
4544
5038
|
}, 500);
|
|
4545
5039
|
const newSession = await context.internalAdapter.createSession(session.user.id, false, session.session);
|
|
4546
5040
|
await context.internalAdapter.deleteSession(session.session.token);
|
|
@@ -4549,7 +5043,7 @@ const otp2fa = (options) => {
|
|
|
4549
5043
|
user: updatedUser
|
|
4550
5044
|
});
|
|
4551
5045
|
return ctx.render({
|
|
4552
|
-
success:
|
|
5046
|
+
success: _faire_auth_core_static.True,
|
|
4553
5047
|
token: newSession.token,
|
|
4554
5048
|
user: updatedUser
|
|
4555
5049
|
}, 200);
|
|
@@ -4563,9 +5057,7 @@ const otp2fa = (options) => {
|
|
|
4563
5057
|
}
|
|
4564
5058
|
};
|
|
4565
5059
|
};
|
|
4566
|
-
|
|
4567
|
-
//#endregion
|
|
4568
|
-
//#region src/plugins/two-factor/totp/index.ts
|
|
5060
|
+
// src/plugins/two-factor/totp/index.ts
|
|
4569
5061
|
const totp2fa = (options) => {
|
|
4570
5062
|
const opts = {
|
|
4571
5063
|
...options,
|
|
@@ -4576,118 +5068,149 @@ const totp2fa = (options) => {
|
|
|
4576
5068
|
return {
|
|
4577
5069
|
id: "totp",
|
|
4578
5070
|
routes: {
|
|
4579
|
-
|
|
5071
|
+
/**
|
|
5072
|
+
* ### Endpoint
|
|
5073
|
+
*
|
|
5074
|
+
* POST `/totp/generate`
|
|
5075
|
+
*
|
|
5076
|
+
* ### API Methods
|
|
5077
|
+
*
|
|
5078
|
+
* **server:**
|
|
5079
|
+
* `auth.api.generateTOTP`
|
|
5080
|
+
*
|
|
5081
|
+
* **client:**
|
|
5082
|
+
* `authClient.totp.generate`
|
|
5083
|
+
*
|
|
5084
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/totp#api-method-totp-generate)
|
|
5085
|
+
*/
|
|
5086
|
+
generateTOTP: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4580
5087
|
operationId: "generateTOTP",
|
|
4581
5088
|
method: "post",
|
|
4582
5089
|
path: "/totp/generate",
|
|
4583
5090
|
SERVER_ONLY: true,
|
|
4584
5091
|
summary: "Generate TOTP code",
|
|
4585
5092
|
description: "Use this endpoint to generate a TOTP code",
|
|
4586
|
-
request: (0,
|
|
4587
|
-
responses: (0,
|
|
5093
|
+
request: (0, _faire_auth_core_factory.req)().bdy(generateTOTPSchema).bld(),
|
|
5094
|
+
responses: (0, _faire_auth_core_factory.res)(generateTOTPResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "TOTP isn't configured").zod().bld()
|
|
4588
5095
|
}), (_authOptions) => async (ctx) => {
|
|
4589
5096
|
if (options?.disable === true) {
|
|
4590
5097
|
ctx.get("context").logger.error("TOTP isn't configured. Please pass totp option on two factor plugin to enable totp");
|
|
4591
5098
|
return ctx.render({
|
|
4592
|
-
success:
|
|
5099
|
+
success: _faire_auth_core_static.False,
|
|
4593
5100
|
message: "TOTP isn't configured"
|
|
4594
5101
|
}, 400);
|
|
4595
5102
|
}
|
|
4596
|
-
const code = await (0,
|
|
5103
|
+
const code = await (0, _faire_auth_core_datatypes.createOTP)(ctx.req.valid("json").secret, {
|
|
4597
5104
|
period: opts.period,
|
|
4598
5105
|
digits: opts.digits
|
|
4599
5106
|
}).totp();
|
|
4600
5107
|
return ctx.json(code, 200);
|
|
4601
5108
|
}),
|
|
4602
|
-
|
|
5109
|
+
/**
|
|
5110
|
+
* ### Endpoint
|
|
5111
|
+
*
|
|
5112
|
+
* POST `/two-factor/get-totp-uri`
|
|
5113
|
+
*
|
|
5114
|
+
* ### API Methods
|
|
5115
|
+
*
|
|
5116
|
+
* **server:**
|
|
5117
|
+
* `auth.api.getTOTPURI`
|
|
5118
|
+
*
|
|
5119
|
+
* **client:**
|
|
5120
|
+
* `authClient.twoFactor.getTotpUri`
|
|
5121
|
+
*
|
|
5122
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/two-factor#api-method-two-factor-get-totp-uri)
|
|
5123
|
+
*/
|
|
5124
|
+
getTOTPURI: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4603
5125
|
operationId: "getTOTPURI",
|
|
4604
5126
|
method: "post",
|
|
4605
5127
|
path: "/two-factor/get-totp-uri",
|
|
4606
5128
|
summary: "Get TOTP URI",
|
|
4607
5129
|
description: "Use this endpoint to get the TOTP URI",
|
|
4608
5130
|
middleware: [require_session.sessionMiddleware()],
|
|
4609
|
-
request: (0,
|
|
4610
|
-
responses: (0,
|
|
5131
|
+
request: (0, _faire_auth_core_factory.req)().bdy(getTOTPURISchema).bld(),
|
|
5132
|
+
responses: (0, _faire_auth_core_factory.res)(getTOTPURIResponseSchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "TOTP isn't enabled").zod().bld()
|
|
4611
5133
|
}), (_authOptions) => async (ctx) => {
|
|
4612
5134
|
const context = ctx.get("context");
|
|
4613
5135
|
if (options?.disable) {
|
|
4614
5136
|
context.logger.error("TOTP isn't configured. Please pass totp option on two factor plugin to enable totp");
|
|
4615
5137
|
return ctx.render({
|
|
4616
|
-
success:
|
|
5138
|
+
success: _faire_auth_core_static.False,
|
|
4617
5139
|
message: "TOTP isn't configured"
|
|
4618
5140
|
}, 400);
|
|
4619
5141
|
}
|
|
4620
5142
|
const session = ctx.get("session");
|
|
4621
|
-
const twoFactor
|
|
5143
|
+
const twoFactor = await context.adapter.findOne({
|
|
4622
5144
|
model: twoFactorTable,
|
|
4623
5145
|
where: [{
|
|
4624
5146
|
field: "userId",
|
|
4625
5147
|
value: session.user.id
|
|
4626
5148
|
}]
|
|
4627
5149
|
});
|
|
4628
|
-
if (!twoFactor
|
|
4629
|
-
success:
|
|
5150
|
+
if (!twoFactor) return ctx.render({
|
|
5151
|
+
success: _faire_auth_core_static.False,
|
|
4630
5152
|
message: TWO_FACTOR_ERROR_CODES.TOTP_NOT_ENABLED
|
|
4631
5153
|
}, 400);
|
|
4632
5154
|
const secret = await (0, require_crypto.crypto_exports.symmetricDecrypt)({
|
|
4633
5155
|
key: context.secret,
|
|
4634
|
-
data: twoFactor
|
|
5156
|
+
data: twoFactor.secret
|
|
4635
5157
|
});
|
|
4636
|
-
const res
|
|
4637
|
-
if (res
|
|
4638
|
-
const totpURI = (0,
|
|
5158
|
+
const res = await context.password.checkPassword(session.user.id, ctx);
|
|
5159
|
+
if (res instanceof Response) return res;
|
|
5160
|
+
const totpURI = (0, _faire_auth_core_datatypes.createOTP)(secret, {
|
|
4639
5161
|
digits: opts.digits,
|
|
4640
5162
|
period: opts.period
|
|
4641
5163
|
}).url(options?.issuer ?? context.appName, session.user.email);
|
|
4642
5164
|
return ctx.render(totpURI, 200);
|
|
4643
5165
|
}),
|
|
4644
|
-
verifyTOTP: require_session.createEndpoint((0,
|
|
5166
|
+
verifyTOTP: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4645
5167
|
operationId: "verifyTOTP",
|
|
4646
5168
|
method: "post",
|
|
4647
5169
|
path: "/two-factor/verify-totp",
|
|
4648
5170
|
summary: "Verify two factor TOTP",
|
|
4649
5171
|
description: "Verify two factor TOTP",
|
|
4650
|
-
request: (0,
|
|
4651
|
-
responses: (0,
|
|
5172
|
+
request: (0, _faire_auth_core_factory.req)().bdy(verifyTOTPSchema).bld(),
|
|
5173
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.TOKEN_USER].default).err(400, "TOTP isn't enabled or failed to create session").err(401, "TOTP Error").err(500, "Failed to update user").zod().bld()
|
|
4652
5174
|
}), (authOptions) => async (ctx) => {
|
|
4653
5175
|
const context = ctx.get("context");
|
|
4654
5176
|
if (options?.disable === true) {
|
|
4655
5177
|
context.logger.error("totp isn't configured. please pass totp option on two factor plugin to enable totp");
|
|
4656
5178
|
return ctx.render({
|
|
4657
|
-
success:
|
|
5179
|
+
success: _faire_auth_core_static.False,
|
|
4658
5180
|
message: "TOTP isn't configured"
|
|
4659
5181
|
}, 400);
|
|
4660
5182
|
}
|
|
4661
5183
|
const result = await verifyTwoFactor(ctx, authOptions);
|
|
4662
5184
|
if (result instanceof Response) return result;
|
|
4663
5185
|
const { session, valid, invalid } = result;
|
|
4664
|
-
const twoFactor
|
|
5186
|
+
const twoFactor = await context.adapter.findOne({
|
|
4665
5187
|
model: twoFactorTable,
|
|
4666
5188
|
where: [{
|
|
4667
5189
|
field: "userId",
|
|
4668
5190
|
value: session.user.id
|
|
4669
5191
|
}]
|
|
4670
5192
|
});
|
|
4671
|
-
if (!twoFactor
|
|
4672
|
-
success:
|
|
5193
|
+
if (!twoFactor) return ctx.render({
|
|
5194
|
+
success: _faire_auth_core_static.False,
|
|
4673
5195
|
message: TWO_FACTOR_ERROR_CODES.TOTP_NOT_ENABLED
|
|
4674
5196
|
}, 400);
|
|
4675
|
-
|
|
5197
|
+
const decrypted = await (0, require_crypto.crypto_exports.symmetricDecrypt)({
|
|
4676
5198
|
key: context.secret,
|
|
4677
|
-
data: twoFactor
|
|
4678
|
-
})
|
|
5199
|
+
data: twoFactor.secret
|
|
5200
|
+
});
|
|
5201
|
+
if (!await (0, _faire_auth_core_datatypes.createOTP)(decrypted, {
|
|
4679
5202
|
period: opts.period,
|
|
4680
5203
|
digits: opts.digits
|
|
4681
5204
|
}).verify(ctx.req.valid("json").code)) return await invalid("INVALID_CODE");
|
|
4682
5205
|
if (!session.user.twoFactorEnabled) {
|
|
4683
5206
|
if (!session.session) return ctx.render({
|
|
4684
|
-
success:
|
|
4685
|
-
message:
|
|
5207
|
+
success: _faire_auth_core_static.False,
|
|
5208
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION
|
|
4686
5209
|
}, 400);
|
|
4687
5210
|
const updatedUser = await context.internalAdapter.updateUser(session.user.id, { twoFactorEnabled: true });
|
|
4688
5211
|
if (updatedUser == null) return ctx.render({
|
|
4689
|
-
success:
|
|
4690
|
-
message:
|
|
5212
|
+
success: _faire_auth_core_static.False,
|
|
5213
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_UPDATE_USER
|
|
4691
5214
|
}, 500);
|
|
4692
5215
|
const newSession = await context.internalAdapter.createSession(session.user.id, false, session.session);
|
|
4693
5216
|
await context.internalAdapter.deleteSession(session.session.token);
|
|
@@ -4701,9 +5224,7 @@ const totp2fa = (options) => {
|
|
|
4701
5224
|
}
|
|
4702
5225
|
};
|
|
4703
5226
|
};
|
|
4704
|
-
|
|
4705
|
-
//#endregion
|
|
4706
|
-
//#region src/plugins/two-factor/client.ts
|
|
5227
|
+
// src/plugins/two-factor/client.ts
|
|
4707
5228
|
const twoFactorClient = (options) => {
|
|
4708
5229
|
return {
|
|
4709
5230
|
id: "two-factor",
|
|
@@ -4729,9 +5250,7 @@ const twoFactorClient = (options) => {
|
|
|
4729
5250
|
}]
|
|
4730
5251
|
};
|
|
4731
5252
|
};
|
|
4732
|
-
|
|
4733
|
-
//#endregion
|
|
4734
|
-
//#region src/plugins/two-factor/index.ts
|
|
5253
|
+
// src/plugins/two-factor/index.ts
|
|
4735
5254
|
const twoFactor = (options) => {
|
|
4736
5255
|
const opts = { twoFactorTable: "twoFactor" };
|
|
4737
5256
|
const backupCodeOptions = {
|
|
@@ -4747,15 +5266,30 @@ const twoFactor = (options) => {
|
|
|
4747
5266
|
...totp.routes,
|
|
4748
5267
|
...otp.routes,
|
|
4749
5268
|
...backupCode.routes,
|
|
4750
|
-
|
|
5269
|
+
/**
|
|
5270
|
+
* ### Endpoint
|
|
5271
|
+
*
|
|
5272
|
+
* POST `/two-factor/enable`
|
|
5273
|
+
*
|
|
5274
|
+
* ### API Methods
|
|
5275
|
+
*
|
|
5276
|
+
* **server:**
|
|
5277
|
+
* `auth.api.enableTwoFactor`
|
|
5278
|
+
*
|
|
5279
|
+
* **client:**
|
|
5280
|
+
* `authClient.twoFactor.enable`
|
|
5281
|
+
*
|
|
5282
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-enable)
|
|
5283
|
+
*/
|
|
5284
|
+
enableTwoFactor: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4751
5285
|
operationId: "enableTwoFactor",
|
|
4752
5286
|
method: "post",
|
|
4753
5287
|
path: "/two-factor/enable",
|
|
4754
5288
|
summary: "Enable two factor authentication",
|
|
4755
5289
|
description: "Use this endpoint to enable two factor authentication. This will generate a TOTP URI and backup codes. Once the user verifies the TOTP URI, the two factor authentication will be enabled.",
|
|
4756
5290
|
middleware: [require_session.sessionMiddleware()],
|
|
4757
|
-
request: (0,
|
|
4758
|
-
responses: (0,
|
|
5291
|
+
request: (0, _faire_auth_core_factory.req)().bdy(enableTwoFactorSchema).bld(),
|
|
5292
|
+
responses: (0, _faire_auth_core_factory.res)(totpURISchema.transform(_faire_auth_core_utils.toSuccess)).err(400, "Invalid password").err(500, "Failed to update user").zod().bld()
|
|
4759
5293
|
}), (authOptions) => async (ctx) => {
|
|
4760
5294
|
const session = ctx.get("session");
|
|
4761
5295
|
const context = ctx.get("context");
|
|
@@ -4765,10 +5299,10 @@ const twoFactor = (options) => {
|
|
|
4765
5299
|
password,
|
|
4766
5300
|
userId: user.id
|
|
4767
5301
|
})) return ctx.render({
|
|
4768
|
-
success:
|
|
4769
|
-
message:
|
|
5302
|
+
success: _faire_auth_core_static.False,
|
|
5303
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.INVALID_PASSWORD
|
|
4770
5304
|
}, 400);
|
|
4771
|
-
const secret = (0,
|
|
5305
|
+
const secret = (0, _faire_auth_core_crypto.generateRandomString)(32);
|
|
4772
5306
|
const encryptedSecret = await (0, require_crypto.crypto_exports.symmetricEncrypt)({
|
|
4773
5307
|
key: context.secret,
|
|
4774
5308
|
data: secret
|
|
@@ -4777,14 +5311,15 @@ const twoFactor = (options) => {
|
|
|
4777
5311
|
if (options?.skipVerificationOnEnable === true) {
|
|
4778
5312
|
const updatedUser = await context.internalAdapter.updateUser(user.id, { twoFactorEnabled: true });
|
|
4779
5313
|
if (updatedUser == null) return ctx.render({
|
|
4780
|
-
success:
|
|
4781
|
-
message:
|
|
5314
|
+
success: _faire_auth_core_static.False,
|
|
5315
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_UPDATE_USER
|
|
4782
5316
|
}, 500);
|
|
5317
|
+
const newSession = await context.internalAdapter.createSession(updatedUser.id, false, session.session);
|
|
4783
5318
|
/**
|
|
4784
5319
|
* Update the session cookie with the new user data
|
|
4785
5320
|
*/
|
|
4786
5321
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
4787
|
-
session:
|
|
5322
|
+
session: newSession,
|
|
4788
5323
|
user: updatedUser
|
|
4789
5324
|
});
|
|
4790
5325
|
await context.internalAdapter.deleteSession(session.session.token);
|
|
@@ -4804,7 +5339,7 @@ const twoFactor = (options) => {
|
|
|
4804
5339
|
userId: user.id
|
|
4805
5340
|
}
|
|
4806
5341
|
});
|
|
4807
|
-
const totpURI = (0,
|
|
5342
|
+
const totpURI = (0, _faire_auth_core_datatypes.createOTP)(secret, {
|
|
4808
5343
|
digits: options?.totpOptions?.digits ?? 6,
|
|
4809
5344
|
period: options?.totpOptions?.period
|
|
4810
5345
|
}).url(issuer ?? options?.issuer ?? context.appName, user.email);
|
|
@@ -4813,15 +5348,30 @@ const twoFactor = (options) => {
|
|
|
4813
5348
|
backupCodes: backupCodes.backupCodes
|
|
4814
5349
|
}, 200);
|
|
4815
5350
|
}),
|
|
4816
|
-
|
|
5351
|
+
/**
|
|
5352
|
+
* ### Endpoint
|
|
5353
|
+
*
|
|
5354
|
+
* POST `/two-factor/disable`
|
|
5355
|
+
*
|
|
5356
|
+
* ### API Methods
|
|
5357
|
+
*
|
|
5358
|
+
* **server:**
|
|
5359
|
+
* `auth.api.disableTwoFactor`
|
|
5360
|
+
*
|
|
5361
|
+
* **client:**
|
|
5362
|
+
* `authClient.twoFactor.disable`
|
|
5363
|
+
*
|
|
5364
|
+
* @see [Read our docs to learn more.](https://faire-auth.com/docs/plugins/2fa#api-method-two-factor-disable)
|
|
5365
|
+
*/
|
|
5366
|
+
disableTwoFactor: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
4817
5367
|
operationId: "disableTwoFactor",
|
|
4818
5368
|
method: "post",
|
|
4819
5369
|
path: "/two-factor/disable",
|
|
4820
5370
|
summary: "Disable two factor authentication",
|
|
4821
5371
|
description: "Use this endpoint to disable two factor authentication.",
|
|
4822
5372
|
middleware: [require_session.sessionMiddleware()],
|
|
4823
|
-
request: (0,
|
|
4824
|
-
responses: (0,
|
|
5373
|
+
request: (0, _faire_auth_core_factory.req)().bdy(disableTwoFactorSchema).bld(),
|
|
5374
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.SUCCESS].default).err(400, "Invalid password").err(500, "Failed to update user").zod().bld()
|
|
4825
5375
|
}), (authOptions) => async (ctx) => {
|
|
4826
5376
|
const context = ctx.get("context");
|
|
4827
5377
|
const session = ctx.get("session");
|
|
@@ -4831,13 +5381,13 @@ const twoFactor = (options) => {
|
|
|
4831
5381
|
password,
|
|
4832
5382
|
userId: user.id
|
|
4833
5383
|
})) return ctx.render({
|
|
4834
|
-
success:
|
|
5384
|
+
success: _faire_auth_core_static.False,
|
|
4835
5385
|
message: "Invalid password"
|
|
4836
5386
|
}, 400);
|
|
4837
5387
|
const updatedUser = await context.internalAdapter.updateUser(user.id, { twoFactorEnabled: false });
|
|
4838
5388
|
if (updatedUser == null) return ctx.render({
|
|
4839
|
-
success:
|
|
4840
|
-
message:
|
|
5389
|
+
success: _faire_auth_core_static.False,
|
|
5390
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_UPDATE_USER
|
|
4841
5391
|
}, 500);
|
|
4842
5392
|
await context.adapter.delete({
|
|
4843
5393
|
model: opts.twoFactorTable,
|
|
@@ -4846,15 +5396,16 @@ const twoFactor = (options) => {
|
|
|
4846
5396
|
value: updatedUser.id
|
|
4847
5397
|
}]
|
|
4848
5398
|
});
|
|
5399
|
+
const newSession = await context.internalAdapter.createSession(updatedUser.id, false, session.session);
|
|
4849
5400
|
/**
|
|
4850
5401
|
* Update the session cookie with the new user data
|
|
4851
5402
|
*/
|
|
4852
5403
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
4853
|
-
session:
|
|
5404
|
+
session: newSession,
|
|
4854
5405
|
user: updatedUser
|
|
4855
5406
|
});
|
|
4856
5407
|
await context.internalAdapter.deleteSession(session.session.token);
|
|
4857
|
-
return ctx.render({ success:
|
|
5408
|
+
return ctx.render({ success: _faire_auth_core_static.True }, 200);
|
|
4858
5409
|
})
|
|
4859
5410
|
},
|
|
4860
5411
|
options: options ?? {},
|
|
@@ -4869,9 +5420,9 @@ const twoFactor = (options) => {
|
|
|
4869
5420
|
const trustDeviceCookie = await (0, require_cookies.cookies_exports.getSignedCookie)(ctx, context.secret, trustDeviceCookieAttrs.name);
|
|
4870
5421
|
if (trustDeviceCookie) {
|
|
4871
5422
|
const [token, sessionToken] = trustDeviceCookie.split("!");
|
|
4872
|
-
if (token === await (0,
|
|
5423
|
+
if (token === await (0, _faire_auth_core_datatypes.createHMAC)("SHA-256", "base64urlnopad").sign(context.secret, `${data.user.id}!${sessionToken}`)) {
|
|
4873
5424
|
const newTrustDeviceCookie = context.createAuthCookie(TRUST_DEVICE_COOKIE_NAME, { maxAge: TRUST_DEVICE_COOKIE_MAX_AGE });
|
|
4874
|
-
const newToken = await (0,
|
|
5425
|
+
const newToken = await (0, _faire_auth_core_datatypes.createHMAC)("SHA-256", "base64urlnopad").sign(context.secret, `${data.user.id}!${data.session.token}`);
|
|
4875
5426
|
await (0, require_cookies.cookies_exports.setSignedCookie)(ctx, newTrustDeviceCookie.name, `${newToken}!${data.session.token}`, context.secret, trustDeviceCookieAttrs.attributes);
|
|
4876
5427
|
return;
|
|
4877
5428
|
}
|
|
@@ -4883,14 +5434,14 @@ const twoFactor = (options) => {
|
|
|
4883
5434
|
await context.internalAdapter.deleteSession(data.session.token);
|
|
4884
5435
|
const maxAge = (options?.otpOptions?.period ?? 3) * 60;
|
|
4885
5436
|
const twoFactorCookie = context.createAuthCookie(TWO_FACTOR_COOKIE_NAME, { maxAge });
|
|
4886
|
-
const identifier = `2fa-${(0,
|
|
5437
|
+
const identifier = `2fa-${(0, _faire_auth_core_crypto.generateRandomString)(20)}`;
|
|
4887
5438
|
await context.internalAdapter.createVerificationValue({
|
|
4888
5439
|
value: data.user.id,
|
|
4889
5440
|
identifier,
|
|
4890
5441
|
expiresAt: new Date(Date.now() + maxAge * 1e3)
|
|
4891
5442
|
});
|
|
4892
5443
|
await (0, require_cookies.cookies_exports.setSignedCookie)(ctx, twoFactorCookie.name, identifier, context.secret, twoFactorCookie.attributes);
|
|
4893
|
-
return ctx.render({ twoFactorRedirect:
|
|
5444
|
+
return ctx.render({ twoFactorRedirect: _faire_auth_core_static.True }, 200);
|
|
4894
5445
|
})
|
|
4895
5446
|
}] },
|
|
4896
5447
|
schema: require_schema.mergeSchema(schema, options?.schema),
|
|
@@ -4902,9 +5453,7 @@ const twoFactor = (options) => {
|
|
|
4902
5453
|
$ERROR_CODES: TWO_FACTOR_ERROR_CODES
|
|
4903
5454
|
};
|
|
4904
5455
|
};
|
|
4905
|
-
|
|
4906
|
-
//#endregion
|
|
4907
|
-
//#region src/plugins/username/error-codes.ts
|
|
5456
|
+
// src/plugins/username/error-codes.ts
|
|
4908
5457
|
const USERNAME_ERROR_CODES = {
|
|
4909
5458
|
INVALID_USERNAME_OR_PASSWORD: "Invalid username or password",
|
|
4910
5459
|
EMAIL_NOT_VERIFIED: "Email not verified",
|
|
@@ -4915,9 +5464,7 @@ const USERNAME_ERROR_CODES = {
|
|
|
4915
5464
|
INVALID_USERNAME: "Username is invalid",
|
|
4916
5465
|
INVALID_DISPLAY_USERNAME: "Display username is invalid"
|
|
4917
5466
|
};
|
|
4918
|
-
|
|
4919
|
-
//#endregion
|
|
4920
|
-
//#region src/plugins/username/schema.ts
|
|
5467
|
+
// src/plugins/username/schema.ts
|
|
4921
5468
|
const getSchema = (normalizer) => {
|
|
4922
5469
|
return { user: { fields: {
|
|
4923
5470
|
username: {
|
|
@@ -4939,17 +5486,15 @@ const getSchema = (normalizer) => {
|
|
|
4939
5486
|
}
|
|
4940
5487
|
} } };
|
|
4941
5488
|
};
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
4945
|
-
function defaultUsernameValidator(username$1) {
|
|
4946
|
-
return /^[a-zA-Z0-9_.]+$/.test(username$1);
|
|
5489
|
+
// src/plugins/username/index.ts
|
|
5490
|
+
function defaultUsernameValidator(username) {
|
|
5491
|
+
return /^[a-zA-Z0-9_.]+$/.test(username);
|
|
4947
5492
|
}
|
|
4948
5493
|
const username = (options) => {
|
|
4949
|
-
const normalizer = (username
|
|
4950
|
-
if (options?.usernameNormalization === false) return username
|
|
4951
|
-
if (options?.usernameNormalization) return options.usernameNormalization(username
|
|
4952
|
-
return username
|
|
5494
|
+
const normalizer = (username) => {
|
|
5495
|
+
if (options?.usernameNormalization === false) return username;
|
|
5496
|
+
if (options?.usernameNormalization) return options.usernameNormalization(username);
|
|
5497
|
+
return username.toLowerCase();
|
|
4953
5498
|
};
|
|
4954
5499
|
const displayUsernameNormalizer = (displayUsername) => {
|
|
4955
5500
|
return options?.displayUsernameNormalization ? options.displayUsernameNormalization(displayUsername) : displayUsername;
|
|
@@ -4957,37 +5502,37 @@ const username = (options) => {
|
|
|
4957
5502
|
const shimUsername = async (input, ctx) => {
|
|
4958
5503
|
if (input.success === false) return;
|
|
4959
5504
|
if (!ctx.get("context")) {
|
|
4960
|
-
|
|
5505
|
+
_faire_auth_core_env.logger.warn("Context not available for username plugin in route hook");
|
|
4961
5506
|
return;
|
|
4962
5507
|
}
|
|
4963
5508
|
const session = ctx.get("session");
|
|
4964
|
-
const username
|
|
4965
|
-
if (username
|
|
5509
|
+
const username = typeof input.data.username === "string" && options?.validationOrder?.username === "post-normalization" ? normalizer(input.data.username) : input.data.username;
|
|
5510
|
+
if (username !== void 0 && typeof username === "string") {
|
|
4966
5511
|
const minUsernameLength = options?.minUsernameLength || 3;
|
|
4967
5512
|
const maxUsernameLength = options?.maxUsernameLength || 30;
|
|
4968
|
-
if (username
|
|
4969
|
-
success:
|
|
5513
|
+
if (username.length < minUsernameLength) return ctx.render({
|
|
5514
|
+
success: _faire_auth_core_static.False,
|
|
4970
5515
|
message: USERNAME_ERROR_CODES.USERNAME_TOO_SHORT
|
|
4971
5516
|
}, 400);
|
|
4972
|
-
if (username
|
|
4973
|
-
success:
|
|
5517
|
+
if (username.length > maxUsernameLength) return ctx.render({
|
|
5518
|
+
success: _faire_auth_core_static.False,
|
|
4974
5519
|
message: USERNAME_ERROR_CODES.USERNAME_TOO_LONG
|
|
4975
5520
|
}, 400);
|
|
4976
|
-
if (!await (options?.usernameValidator ?? defaultUsernameValidator)(username
|
|
4977
|
-
success:
|
|
5521
|
+
if (!await (options?.usernameValidator ?? defaultUsernameValidator)(username)) return ctx.render({
|
|
5522
|
+
success: _faire_auth_core_static.False,
|
|
4978
5523
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME
|
|
4979
5524
|
}, 400);
|
|
4980
5525
|
const user = await ctx.get("context").adapter.findOne({
|
|
4981
5526
|
model: "user",
|
|
4982
5527
|
where: [{
|
|
4983
5528
|
field: "username",
|
|
4984
|
-
value: username
|
|
5529
|
+
value: username
|
|
4985
5530
|
}]
|
|
4986
5531
|
});
|
|
4987
5532
|
const blockChangeSignUp = ctx.get("path") === "/sign-up/email" && user;
|
|
4988
5533
|
const blockChangeUpdateUser = ctx.get("path") === "/update-user" && user && session && user.id !== session.session.userId;
|
|
4989
5534
|
if (blockChangeSignUp || blockChangeUpdateUser) return ctx.render({
|
|
4990
|
-
success:
|
|
5535
|
+
success: _faire_auth_core_static.False,
|
|
4991
5536
|
message: USERNAME_ERROR_CODES.USERNAME_IS_ALREADY_TAKEN
|
|
4992
5537
|
}, 400);
|
|
4993
5538
|
}
|
|
@@ -4995,7 +5540,7 @@ const username = (options) => {
|
|
|
4995
5540
|
if (displayUsername !== void 0 && typeof displayUsername === "string") {
|
|
4996
5541
|
if (options?.displayUsernameValidator) {
|
|
4997
5542
|
if (!await options.displayUsernameValidator(displayUsername)) return ctx.render({
|
|
4998
|
-
success:
|
|
5543
|
+
success: _faire_auth_core_static.False,
|
|
4999
5544
|
message: USERNAME_ERROR_CODES.INVALID_DISPLAY_USERNAME
|
|
5000
5545
|
}, 400);
|
|
5001
5546
|
}
|
|
@@ -5008,82 +5553,82 @@ const username = (options) => {
|
|
|
5008
5553
|
init: (_ctx) => {
|
|
5009
5554
|
return { options: { databaseHooks: { user: {
|
|
5010
5555
|
create: { async before(user, _context) {
|
|
5011
|
-
const username
|
|
5556
|
+
const username = "username" in user ? user["username"] : null;
|
|
5012
5557
|
const displayUsername = "displayUsername" in user ? user["displayUsername"] : null;
|
|
5013
5558
|
return { data: {
|
|
5014
5559
|
...user,
|
|
5015
|
-
...username
|
|
5560
|
+
...username ? { username: normalizer(username) } : {},
|
|
5016
5561
|
...displayUsername ? { displayUsername: displayUsernameNormalizer(displayUsername) } : {}
|
|
5017
5562
|
} };
|
|
5018
5563
|
} },
|
|
5019
5564
|
update: { async before(user, _context) {
|
|
5020
|
-
const username
|
|
5565
|
+
const username = "username" in user ? user["username"] : null;
|
|
5021
5566
|
const displayUsername = "displayUsername" in user ? user["displayUsername"] : null;
|
|
5022
5567
|
return { data: {
|
|
5023
5568
|
...user,
|
|
5024
|
-
...username
|
|
5569
|
+
...username ? { username: normalizer(username) } : {},
|
|
5025
5570
|
...displayUsername ? { displayUsername: displayUsernameNormalizer(displayUsername) } : {}
|
|
5026
5571
|
} };
|
|
5027
5572
|
} }
|
|
5028
5573
|
} } } };
|
|
5029
5574
|
},
|
|
5030
5575
|
routes: {
|
|
5031
|
-
signInUsername: require_session.createEndpoint((0,
|
|
5576
|
+
signInUsername: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
5032
5577
|
operationId: "signInUsername",
|
|
5033
5578
|
method: "post",
|
|
5034
5579
|
path: "/sign-in/username",
|
|
5035
5580
|
summary: "Sign in with username",
|
|
5036
5581
|
description: "Sign in with username",
|
|
5037
|
-
request: (0,
|
|
5582
|
+
request: (0, _faire_auth_core_factory.req)().bdy(zod.object({
|
|
5038
5583
|
username: zod.string().openapi({ description: "The username of the user" }),
|
|
5039
5584
|
password: zod.string().openapi({ description: "The password of the user" }),
|
|
5040
5585
|
rememberMe: zod.boolean().openapi({ description: "Remember the user session" }).optional(),
|
|
5041
5586
|
callbackURL: zod.string().openapi({ description: "The URL to redirect to after email verification" }).optional()
|
|
5042
5587
|
})).bld(),
|
|
5043
|
-
responses: (0,
|
|
5588
|
+
responses: (0, _faire_auth_core_factory.res)(_faire_auth_core_static.SCHEMAS[_faire_auth_core_static.Definitions.TOKEN_USER].default).err(400, "Invalid username").err(401, "Invalid email or password").err(403, "Email not verified").err(500, "Failed to create session").bld()
|
|
5044
5589
|
}), (authOptions) => async (ctx) => {
|
|
5045
5590
|
const context = ctx.get("context");
|
|
5046
|
-
let { username
|
|
5047
|
-
if (!username
|
|
5591
|
+
let { username, password, rememberMe, callbackURL } = ctx.req.valid("json");
|
|
5592
|
+
if (!username || !password) {
|
|
5048
5593
|
context.logger.error("Username or password not found");
|
|
5049
5594
|
return ctx.render({
|
|
5050
|
-
success:
|
|
5595
|
+
success: _faire_auth_core_static.False,
|
|
5051
5596
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME_OR_PASSWORD
|
|
5052
5597
|
}, 401);
|
|
5053
5598
|
}
|
|
5054
|
-
username
|
|
5599
|
+
username = options?.validationOrder?.username === "pre-normalization" ? normalizer(username) : username;
|
|
5055
5600
|
const minUsernameLength = options?.minUsernameLength ?? 3;
|
|
5056
5601
|
const maxUsernameLength = options?.maxUsernameLength ?? 30;
|
|
5057
|
-
if (username
|
|
5058
|
-
context.logger.error("Username too short", { username
|
|
5602
|
+
if (username.length < minUsernameLength) {
|
|
5603
|
+
context.logger.error("Username too short", { username });
|
|
5059
5604
|
return ctx.render({
|
|
5060
|
-
success:
|
|
5605
|
+
success: _faire_auth_core_static.False,
|
|
5061
5606
|
message: USERNAME_ERROR_CODES.USERNAME_TOO_SHORT
|
|
5062
5607
|
}, 400);
|
|
5063
5608
|
}
|
|
5064
|
-
if (username
|
|
5065
|
-
context.logger.error("Username too long", { username
|
|
5609
|
+
if (username.length > maxUsernameLength) {
|
|
5610
|
+
context.logger.error("Username too long", { username });
|
|
5066
5611
|
return ctx.render({
|
|
5067
|
-
success:
|
|
5612
|
+
success: _faire_auth_core_static.False,
|
|
5068
5613
|
message: USERNAME_ERROR_CODES.USERNAME_TOO_LONG
|
|
5069
5614
|
}, 400);
|
|
5070
5615
|
}
|
|
5071
|
-
if (!(options?.usernameValidator ?? defaultUsernameValidator)(username
|
|
5072
|
-
success:
|
|
5616
|
+
if (!(options?.usernameValidator ?? defaultUsernameValidator)(username)) return ctx.render({
|
|
5617
|
+
success: _faire_auth_core_static.False,
|
|
5073
5618
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME
|
|
5074
5619
|
}, 400);
|
|
5075
5620
|
const user = await context.adapter.findOne({
|
|
5076
5621
|
model: "user",
|
|
5077
5622
|
where: [{
|
|
5078
5623
|
field: "username",
|
|
5079
|
-
value: normalizer(username
|
|
5624
|
+
value: normalizer(username)
|
|
5080
5625
|
}]
|
|
5081
5626
|
});
|
|
5082
5627
|
if (!user) {
|
|
5083
5628
|
await context.password.hash(password);
|
|
5084
|
-
context.logger.error("User not found", { username
|
|
5629
|
+
context.logger.error("User not found", { username });
|
|
5085
5630
|
return ctx.render({
|
|
5086
|
-
success:
|
|
5631
|
+
success: _faire_auth_core_static.False,
|
|
5087
5632
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME_OR_PASSWORD
|
|
5088
5633
|
}, 401);
|
|
5089
5634
|
}
|
|
@@ -5098,14 +5643,14 @@ const username = (options) => {
|
|
|
5098
5643
|
}]
|
|
5099
5644
|
});
|
|
5100
5645
|
if (!account) return ctx.render({
|
|
5101
|
-
success:
|
|
5646
|
+
success: _faire_auth_core_static.False,
|
|
5102
5647
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME_OR_PASSWORD
|
|
5103
5648
|
}, 401);
|
|
5104
5649
|
const currentPassword = account?.password;
|
|
5105
5650
|
if (!currentPassword) {
|
|
5106
|
-
context.logger.error("Password not found", { username
|
|
5651
|
+
context.logger.error("Password not found", { username });
|
|
5107
5652
|
return ctx.render({
|
|
5108
|
-
success:
|
|
5653
|
+
success: _faire_auth_core_static.False,
|
|
5109
5654
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME_OR_PASSWORD
|
|
5110
5655
|
}, 401);
|
|
5111
5656
|
}
|
|
@@ -5115,13 +5660,13 @@ const username = (options) => {
|
|
|
5115
5660
|
})) {
|
|
5116
5661
|
context.logger.error("Invalid password");
|
|
5117
5662
|
return ctx.render({
|
|
5118
|
-
success:
|
|
5663
|
+
success: _faire_auth_core_static.False,
|
|
5119
5664
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME_OR_PASSWORD
|
|
5120
5665
|
}, 401);
|
|
5121
5666
|
}
|
|
5122
5667
|
if (authOptions?.emailAndPassword?.requireEmailVerification && !user.emailVerified) {
|
|
5123
5668
|
if (!authOptions?.emailVerification?.sendVerificationEmail) return ctx.render({
|
|
5124
|
-
success:
|
|
5669
|
+
success: _faire_auth_core_static.False,
|
|
5125
5670
|
message: USERNAME_ERROR_CODES.EMAIL_NOT_VERIFIED
|
|
5126
5671
|
}, 403);
|
|
5127
5672
|
if (authOptions?.emailVerification?.sendOnSignIn) {
|
|
@@ -5134,21 +5679,21 @@ const username = (options) => {
|
|
|
5134
5679
|
}, ctx);
|
|
5135
5680
|
}
|
|
5136
5681
|
return ctx.render({
|
|
5137
|
-
success:
|
|
5682
|
+
success: _faire_auth_core_static.False,
|
|
5138
5683
|
message: USERNAME_ERROR_CODES.EMAIL_NOT_VERIFIED
|
|
5139
5684
|
}, 403);
|
|
5140
5685
|
}
|
|
5141
5686
|
const session = await context.internalAdapter.createSession(user.id, rememberMe === false);
|
|
5142
5687
|
if (!session) return ctx.render({
|
|
5143
|
-
success:
|
|
5144
|
-
message:
|
|
5688
|
+
success: _faire_auth_core_static.False,
|
|
5689
|
+
message: _faire_auth_core_error.BASE_ERROR_CODES.FAILED_TO_CREATE_SESSION
|
|
5145
5690
|
}, 500);
|
|
5146
5691
|
await require_cookies.setSessionCookie(ctx, authOptions, {
|
|
5147
5692
|
session,
|
|
5148
5693
|
user
|
|
5149
5694
|
}, rememberMe === false);
|
|
5150
5695
|
return ctx.render({
|
|
5151
|
-
success:
|
|
5696
|
+
success: _faire_auth_core_static.True,
|
|
5152
5697
|
token: session.token,
|
|
5153
5698
|
user: {
|
|
5154
5699
|
id: user.id,
|
|
@@ -5163,34 +5708,34 @@ const username = (options) => {
|
|
|
5163
5708
|
}
|
|
5164
5709
|
}, 200);
|
|
5165
5710
|
}),
|
|
5166
|
-
isUsernameAvailable: require_session.createEndpoint((0,
|
|
5711
|
+
isUsernameAvailable: require_session.createEndpoint((0, _faire_auth_core_factory.createRoute)({
|
|
5167
5712
|
operationId: "isUsernameAvailable",
|
|
5168
5713
|
method: "post",
|
|
5169
5714
|
path: "/is-username-available",
|
|
5170
|
-
request: (0,
|
|
5171
|
-
responses: (0,
|
|
5715
|
+
request: (0, _faire_auth_core_factory.req)().bdy(zod.object({ username: zod.string().openapi({ description: "The username to check" }) })).bld(),
|
|
5716
|
+
responses: (0, _faire_auth_core_factory.res)(zod.object({ available: zod.boolean() }), "Whether or not the username is available").err(400, "Invalid username").bld()
|
|
5172
5717
|
}), (_authOptions) => async (ctx) => {
|
|
5173
5718
|
const context = ctx.get("context");
|
|
5174
|
-
const { username
|
|
5719
|
+
const { username } = ctx.req.valid("json");
|
|
5175
5720
|
const minUsernameLength = options?.minUsernameLength || 3;
|
|
5176
5721
|
const maxUsernameLength = options?.maxUsernameLength || 30;
|
|
5177
|
-
if (username
|
|
5178
|
-
success:
|
|
5722
|
+
if (username.length < minUsernameLength) return ctx.render({
|
|
5723
|
+
success: _faire_auth_core_static.False,
|
|
5179
5724
|
message: USERNAME_ERROR_CODES.USERNAME_TOO_SHORT
|
|
5180
5725
|
}, 400);
|
|
5181
|
-
if (username
|
|
5182
|
-
success:
|
|
5726
|
+
if (username.length > maxUsernameLength) return ctx.render({
|
|
5727
|
+
success: _faire_auth_core_static.False,
|
|
5183
5728
|
message: USERNAME_ERROR_CODES.USERNAME_TOO_LONG
|
|
5184
5729
|
}, 400);
|
|
5185
|
-
if (!await (options?.usernameValidator || defaultUsernameValidator)(username
|
|
5186
|
-
success:
|
|
5730
|
+
if (!await (options?.usernameValidator || defaultUsernameValidator)(username)) return ctx.render({
|
|
5731
|
+
success: _faire_auth_core_static.False,
|
|
5187
5732
|
message: USERNAME_ERROR_CODES.INVALID_USERNAME
|
|
5188
5733
|
}, 400);
|
|
5189
5734
|
if (await context.adapter.findOne({
|
|
5190
5735
|
model: "user",
|
|
5191
5736
|
where: [{
|
|
5192
5737
|
field: "username",
|
|
5193
|
-
value: normalizer(username
|
|
5738
|
+
value: normalizer(username)
|
|
5194
5739
|
}]
|
|
5195
5740
|
})) return ctx.render({ available: false }, 200);
|
|
5196
5741
|
return ctx.render({ available: true }, 200);
|
|
@@ -5207,27 +5752,25 @@ const username = (options) => {
|
|
|
5207
5752
|
$ERROR_CODES: USERNAME_ERROR_CODES
|
|
5208
5753
|
};
|
|
5209
5754
|
};
|
|
5210
|
-
|
|
5211
|
-
//#endregion
|
|
5212
5755
|
exports.TWO_FACTOR_ERROR_CODES = TWO_FACTOR_ERROR_CODES;
|
|
5213
5756
|
exports.USERNAME_ERROR_CODES = USERNAME_ERROR_CODES;
|
|
5214
|
-
exports.bearer =
|
|
5215
|
-
exports.createAccessControl =
|
|
5757
|
+
exports.bearer = require_plugins_bearer_index.bearer;
|
|
5758
|
+
exports.createAccessControl = require_plugins_access_index.createAccessControl;
|
|
5216
5759
|
exports.createEndpoint = require_session.createEndpoint;
|
|
5217
5760
|
exports.createHook = require_middleware.createHook;
|
|
5218
5761
|
exports.createMiddleware = require_middleware.createMiddleware;
|
|
5219
|
-
Object.defineProperty(exports,
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5762
|
+
Object.defineProperty(exports, "createRoute", {
|
|
5763
|
+
enumerable: true,
|
|
5764
|
+
get: function() {
|
|
5765
|
+
return _faire_auth_core_factory.createRoute;
|
|
5766
|
+
}
|
|
5224
5767
|
});
|
|
5225
5768
|
exports.magicLink = magicLink;
|
|
5226
5769
|
exports.oAuthProxy = oAuthProxy;
|
|
5227
5770
|
exports.organization = organization;
|
|
5228
5771
|
exports.parseRoles = parseRoles;
|
|
5229
|
-
exports.passkey =
|
|
5230
|
-
exports.role =
|
|
5772
|
+
exports.passkey = require_plugins_passkey_index.passkey;
|
|
5773
|
+
exports.role = require_plugins_access_index.role;
|
|
5231
5774
|
exports.twoFactor = twoFactor;
|
|
5232
5775
|
exports.twoFactorClient = twoFactorClient;
|
|
5233
|
-
exports.username = username;
|
|
5776
|
+
exports.username = username;
|