nestjs-slightly-better-auth 1.0.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/LICENSE +7 -0
- package/README.md +57 -0
- package/dist/admin.cjs +88 -0
- package/dist/admin.cjs.map +1 -0
- package/dist/admin.d.cts +14 -0
- package/dist/admin.d.cts.map +1 -0
- package/dist/admin.d.mts +14 -0
- package/dist/admin.d.mts.map +1 -0
- package/dist/admin.mjs +85 -0
- package/dist/admin.mjs.map +1 -0
- package/dist/api-key.cjs +163 -0
- package/dist/api-key.cjs.map +1 -0
- package/dist/api-key.d.cts +42 -0
- package/dist/api-key.d.cts.map +1 -0
- package/dist/api-key.d.mts +42 -0
- package/dist/api-key.d.mts.map +1 -0
- package/dist/api-key.mjs +159 -0
- package/dist/api-key.mjs.map +1 -0
- package/dist/auth-contracts-BBA1C1gj.d.cts +1635 -0
- package/dist/auth-contracts-BBA1C1gj.d.cts.map +1 -0
- package/dist/auth-contracts-tqsfBZ8B.d.mts +1635 -0
- package/dist/auth-contracts-tqsfBZ8B.d.mts.map +1 -0
- package/dist/auth-decorators-CwW5JY4y.cjs +1274 -0
- package/dist/auth-decorators-CwW5JY4y.cjs.map +1 -0
- package/dist/auth-decorators-DfAJbHar.mjs +849 -0
- package/dist/auth-decorators-DfAJbHar.mjs.map +1 -0
- package/dist/auth-errors-CQjfgjaO.mjs +283 -0
- package/dist/auth-errors-CQjfgjaO.mjs.map +1 -0
- package/dist/auth-errors-CsERBNWI.cjs +348 -0
- package/dist/auth-errors-CsERBNWI.cjs.map +1 -0
- package/dist/express.cjs +247 -0
- package/dist/express.cjs.map +1 -0
- package/dist/express.d.cts +37 -0
- package/dist/express.d.cts.map +1 -0
- package/dist/express.d.mts +37 -0
- package/dist/express.d.mts.map +1 -0
- package/dist/express.mjs +245 -0
- package/dist/express.mjs.map +1 -0
- package/dist/fastify.cjs +215 -0
- package/dist/fastify.cjs.map +1 -0
- package/dist/fastify.d.cts +28 -0
- package/dist/fastify.d.cts.map +1 -0
- package/dist/fastify.d.mts +28 -0
- package/dist/fastify.d.mts.map +1 -0
- package/dist/fastify.mjs +213 -0
- package/dist/fastify.mjs.map +1 -0
- package/dist/index.cjs +2634 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.mjs +2556 -0
- package/dist/index.mjs.map +1 -0
- package/dist/organization.cjs +191 -0
- package/dist/organization.cjs.map +1 -0
- package/dist/organization.d.cts +40 -0
- package/dist/organization.d.cts.map +1 -0
- package/dist/organization.d.mts +40 -0
- package/dist/organization.d.mts.map +1 -0
- package/dist/organization.mjs +177 -0
- package/dist/organization.mjs.map +1 -0
- package/dist/platform.cjs +393 -0
- package/dist/platform.cjs.map +1 -0
- package/dist/platform.d.cts +43 -0
- package/dist/platform.d.cts.map +1 -0
- package/dist/platform.d.mts +43 -0
- package/dist/platform.d.mts.map +1 -0
- package/dist/platform.mjs +385 -0
- package/dist/platform.mjs.map +1 -0
- package/dist/plugin.cjs +312 -0
- package/dist/plugin.cjs.map +1 -0
- package/dist/plugin.d.cts +26 -0
- package/dist/plugin.d.cts.map +1 -0
- package/dist/plugin.d.mts +26 -0
- package/dist/plugin.d.mts.map +1 -0
- package/dist/plugin.mjs +310 -0
- package/dist/plugin.mjs.map +1 -0
- package/package.json +186 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_auth_errors = require("./auth-errors-CsERBNWI.cjs");
|
|
3
|
+
const require_auth_decorators = require("./auth-decorators-CwW5JY4y.cjs");
|
|
4
|
+
let better_auth_api = require("better-auth/api");
|
|
5
|
+
//#region src/organization.ts
|
|
6
|
+
const ACTIVE_ORGANIZATION_ID = Symbol.for("nestjs-slightly-better-auth:org:active-organization-id");
|
|
7
|
+
const ACTIVE_MEMBER_ROLE = Symbol.for("nestjs-slightly-better-auth:org:active-member-role");
|
|
8
|
+
const ActiveOrganizationId = require_auth_decorators.defineInvocationParam(ACTIVE_ORGANIZATION_ID, { missing: "ORGANIZATION_REQUIRED" });
|
|
9
|
+
const ActiveMemberRole = require_auth_decorators.defineInvocationParam(ACTIVE_MEMBER_ROLE, { missing: "MEMBER_ROLE_REQUIRED" });
|
|
10
|
+
const REF = Symbol.for("nestjs-slightly-better-auth:org:ref");
|
|
11
|
+
function organizationRef(resolve, options = {}) {
|
|
12
|
+
return Object.assign((ctx) => resolve(ctx), options);
|
|
13
|
+
}
|
|
14
|
+
function activeOrganization() {
|
|
15
|
+
return Object.assign(organizationRef(async (ctx) => {
|
|
16
|
+
const value = ctx.principal.session.session?.activeOrganizationId;
|
|
17
|
+
if (value !== void 0) return value;
|
|
18
|
+
if (!await ctx.auth.hasPlugin("custom-session")) return;
|
|
19
|
+
try {
|
|
20
|
+
return (await ctx.memo(JSON.stringify(["org:activeMember"]), () => ctx.auth.run({
|
|
21
|
+
cookies: ctx.cookies,
|
|
22
|
+
inbound: () => ctx.headers,
|
|
23
|
+
internal: true
|
|
24
|
+
}, () => ctx.auth.api.getActiveMember({ headers: ctx.headers }))))?.organizationId;
|
|
25
|
+
} catch (error) {
|
|
26
|
+
if ((0, better_auth_api.isAPIError)(error) && error.statusCode === 400 && (error.body?.code === "NO_ACTIVE_ORGANIZATION" || error.body?.code === "MEMBER_NOT_FOUND")) return;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}, { missingReason: "NO_ACTIVE_ORGANIZATION" }), { [REF]: { kind: "active" } });
|
|
30
|
+
}
|
|
31
|
+
function fromParam(name) {
|
|
32
|
+
return Object.assign(organizationRef((ctx) => ctx.param(name)), { [REF]: {
|
|
33
|
+
kind: "param",
|
|
34
|
+
name
|
|
35
|
+
} });
|
|
36
|
+
}
|
|
37
|
+
function fromHeader(name) {
|
|
38
|
+
return organizationRef((ctx) => ctx.headers.get(name));
|
|
39
|
+
}
|
|
40
|
+
function requirements(expressions) {
|
|
41
|
+
return expressions.flatMap((expression) => "anyOf" in expression ? requirements(expression.anyOf) : "allOf" in expression ? requirements(expression.allOf) : [expression]);
|
|
42
|
+
}
|
|
43
|
+
function advise(ctx, policy) {
|
|
44
|
+
const advice = [];
|
|
45
|
+
for (const handler of ctx.handlers) for (const requirement of requirements(handler.plan.requirements)) {
|
|
46
|
+
if (requirement.policy !== policy) continue;
|
|
47
|
+
const marker = requirement.params.organization[REF];
|
|
48
|
+
if (marker?.kind === "active") {
|
|
49
|
+
const input = handler.inputs.find((name) => [
|
|
50
|
+
"orgId",
|
|
51
|
+
"organizationId",
|
|
52
|
+
"organization",
|
|
53
|
+
"orgSlug"
|
|
54
|
+
].includes(name));
|
|
55
|
+
if (input) advice.push({
|
|
56
|
+
level: "warn",
|
|
57
|
+
code: "W_ORG_PARAM_IGNORED",
|
|
58
|
+
message: `${handler.plan.site} checks the active organization but accepts ${input}.`,
|
|
59
|
+
hint: input === "orgSlug" ? "Map the slug to an ID with organizationRef and auth.api.listOrganizations({ headers })." : `Use fromParam('${input}').`
|
|
60
|
+
});
|
|
61
|
+
} else if (marker?.kind === "param" && !handler.inputs.includes(marker.name)) advice.push({
|
|
62
|
+
level: "warn",
|
|
63
|
+
code: "W_ORG_PARAM_MISSING",
|
|
64
|
+
message: `${handler.plan.site} reads ${marker.name}, absent from claimed inputs: ${handler.inputs.join(", ") || "none"}.`,
|
|
65
|
+
hint: "Use the correct input name, a method-level organizationRef, or SkipDefaultRequirements with a method-level requirement."
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return advice;
|
|
69
|
+
}
|
|
70
|
+
const requires = {
|
|
71
|
+
plugins: ["organization"],
|
|
72
|
+
principals: ["session"],
|
|
73
|
+
presentsCredentials: true
|
|
74
|
+
};
|
|
75
|
+
const orgPermissionPolicy = {
|
|
76
|
+
id: "better-auth:organization/permission",
|
|
77
|
+
requires,
|
|
78
|
+
advise: (ctx) => advise(ctx, orgPermissionPolicy),
|
|
79
|
+
validate({ permissions }) {
|
|
80
|
+
if (!Object.keys(permissions).length || Object.values(permissions).some((actions) => !Array.isArray(actions) || !actions.length)) throw new require_auth_errors.BetterAuthConfigurationError("EMPTY_PERMISSIONS", "Organization permissions must contain a resource and actions.");
|
|
81
|
+
},
|
|
82
|
+
async evaluate({ permissions, organization }, context) {
|
|
83
|
+
const organizationId = await organization(context);
|
|
84
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) return {
|
|
85
|
+
effect: "deny",
|
|
86
|
+
reason: organization.missingReason ?? "ORGANIZATION_REQUIRED"
|
|
87
|
+
};
|
|
88
|
+
const stable = Object.entries(permissions).sort(([a], [b]) => a.localeCompare(b)).map(([resource, actions]) => [resource, [...actions].sort()]);
|
|
89
|
+
try {
|
|
90
|
+
if (!(await context.memo(JSON.stringify([
|
|
91
|
+
"org:hasPermission",
|
|
92
|
+
organizationId,
|
|
93
|
+
stable
|
|
94
|
+
]), () => context.auth.run({
|
|
95
|
+
cookies: context.cookies,
|
|
96
|
+
inbound: () => context.headers,
|
|
97
|
+
internal: true
|
|
98
|
+
}, () => context.auth.api.hasPermission({
|
|
99
|
+
headers: context.headers,
|
|
100
|
+
body: {
|
|
101
|
+
organizationId,
|
|
102
|
+
permissions
|
|
103
|
+
}
|
|
104
|
+
})))).success) return {
|
|
105
|
+
effect: "deny",
|
|
106
|
+
reason: "MISSING_PERMISSION"
|
|
107
|
+
};
|
|
108
|
+
context.provide(ACTIVE_ORGANIZATION_ID, organizationId);
|
|
109
|
+
return { effect: "allow" };
|
|
110
|
+
} catch (error) {
|
|
111
|
+
if ((0, better_auth_api.isAPIError)(error) && error.body?.code === "USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION") return {
|
|
112
|
+
effect: "deny",
|
|
113
|
+
reason: "USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION"
|
|
114
|
+
};
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const orgMemberPolicy = {
|
|
120
|
+
id: "better-auth:organization/member",
|
|
121
|
+
requires,
|
|
122
|
+
advise: (ctx) => advise(ctx, orgMemberPolicy),
|
|
123
|
+
async evaluate({ organization }, context) {
|
|
124
|
+
const organizationId = await organization(context);
|
|
125
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) return {
|
|
126
|
+
effect: "deny",
|
|
127
|
+
reason: organization.missingReason ?? "ORGANIZATION_REQUIRED"
|
|
128
|
+
};
|
|
129
|
+
try {
|
|
130
|
+
const result = await context.memo(JSON.stringify(["org:activeMemberRole", organizationId]), () => context.auth.run({
|
|
131
|
+
cookies: context.cookies,
|
|
132
|
+
inbound: () => context.headers,
|
|
133
|
+
internal: true
|
|
134
|
+
}, () => context.auth.api.getActiveMemberRole({
|
|
135
|
+
headers: context.headers,
|
|
136
|
+
query: { organizationId }
|
|
137
|
+
})));
|
|
138
|
+
if (typeof result.role !== "string" || !result.role.trim()) return {
|
|
139
|
+
effect: "deny",
|
|
140
|
+
reason: "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION"
|
|
141
|
+
};
|
|
142
|
+
context.provide(ACTIVE_ORGANIZATION_ID, organizationId);
|
|
143
|
+
context.provide(ACTIVE_MEMBER_ROLE, result.role);
|
|
144
|
+
return { effect: "allow" };
|
|
145
|
+
} catch (error) {
|
|
146
|
+
if ((0, better_auth_api.isAPIError)(error) && error.body?.code === "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION") return {
|
|
147
|
+
effect: "deny",
|
|
148
|
+
reason: "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION"
|
|
149
|
+
};
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
function orgPermission(permissions, options = {}) {
|
|
155
|
+
return {
|
|
156
|
+
policy: orgPermissionPolicy,
|
|
157
|
+
params: {
|
|
158
|
+
permissions,
|
|
159
|
+
organization: options.organization ?? activeOrganization()
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function RequireOrgPermission(permissions, options) {
|
|
164
|
+
return require_auth_decorators.Require(orgPermission(permissions, options));
|
|
165
|
+
}
|
|
166
|
+
function orgMember(options = {}) {
|
|
167
|
+
return {
|
|
168
|
+
policy: orgMemberPolicy,
|
|
169
|
+
params: { organization: options.organization ?? activeOrganization() }
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
function RequireOrgMember(options) {
|
|
173
|
+
return require_auth_decorators.Require(orgMember(options));
|
|
174
|
+
}
|
|
175
|
+
//#endregion
|
|
176
|
+
exports.ACTIVE_MEMBER_ROLE = ACTIVE_MEMBER_ROLE;
|
|
177
|
+
exports.ACTIVE_ORGANIZATION_ID = ACTIVE_ORGANIZATION_ID;
|
|
178
|
+
exports.ActiveMemberRole = ActiveMemberRole;
|
|
179
|
+
exports.ActiveOrganizationId = ActiveOrganizationId;
|
|
180
|
+
exports.RequireOrgMember = RequireOrgMember;
|
|
181
|
+
exports.RequireOrgPermission = RequireOrgPermission;
|
|
182
|
+
exports.activeOrganization = activeOrganization;
|
|
183
|
+
exports.fromHeader = fromHeader;
|
|
184
|
+
exports.fromParam = fromParam;
|
|
185
|
+
exports.orgMember = orgMember;
|
|
186
|
+
exports.orgMemberPolicy = orgMemberPolicy;
|
|
187
|
+
exports.orgPermission = orgPermission;
|
|
188
|
+
exports.orgPermissionPolicy = orgPermissionPolicy;
|
|
189
|
+
exports.organizationRef = organizationRef;
|
|
190
|
+
|
|
191
|
+
//# sourceMappingURL=organization.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.cjs","names":["defineInvocationParam","isAPIError","BetterAuthConfigurationError","Require"],"sources":["../src/organization.ts"],"sourcesContent":["import { isAPIError } from \"better-auth/api\";\nimport type {\n AuthorizationContext,\n AuthorizationPolicy,\n BootAdvice,\n BootAdviceContext,\n Requirement,\n RequirementExpr,\n} from \"./auth-contracts.js\";\nimport { defineInvocationParam, Require } from \"./auth-decorators.js\";\nimport { BetterAuthConfigurationError } from \"./auth-errors.js\";\nimport type { OrgPermissions, SessionPrincipal } from \"./auth-types.js\";\nexport type { OrgPermissions } from \"./auth-types.js\";\nexport interface OrganizationRef {\n (ctx: AuthorizationContext): unknown | Promise<unknown>;\n readonly missingReason?: string;\n}\nexport interface OrgPermissionParams {\n readonly permissions: OrgPermissions;\n readonly organization: OrganizationRef;\n}\nexport interface OrgMemberParams {\n readonly organization: OrganizationRef;\n}\nexport const ACTIVE_ORGANIZATION_ID = Symbol.for(\n \"nestjs-slightly-better-auth:org:active-organization-id\",\n);\nexport const ACTIVE_MEMBER_ROLE = Symbol.for(\n \"nestjs-slightly-better-auth:org:active-member-role\",\n);\nexport const ActiveOrganizationId = defineInvocationParam(\n ACTIVE_ORGANIZATION_ID,\n { missing: \"ORGANIZATION_REQUIRED\" },\n);\nexport const ActiveMemberRole = defineInvocationParam(ACTIVE_MEMBER_ROLE, {\n missing: \"MEMBER_ROLE_REQUIRED\",\n});\nconst REF = Symbol.for(\"nestjs-slightly-better-auth:org:ref\");\ntype MarkedRef = OrganizationRef & {\n readonly [REF]?: { kind: \"active\" } | { kind: \"param\"; name: string };\n};\ninterface OrgApi {\n hasPermission(input: {\n headers: Headers;\n body: { organizationId: string; permissions: OrgPermissions };\n }): Promise<{ success: boolean }>;\n getActiveMemberRole(input: {\n headers: Headers;\n query: { organizationId: string };\n }): Promise<{ role?: string | null }>;\n getActiveMember(input: {\n headers: Headers;\n }): Promise<{ organizationId?: string }>;\n}\nexport function organizationRef(\n resolve: (ctx: AuthorizationContext) => unknown | Promise<unknown>,\n options: { missingReason?: string } = {},\n): OrganizationRef {\n return Object.assign((ctx: AuthorizationContext) => resolve(ctx), options);\n}\nexport function activeOrganization(): OrganizationRef {\n return Object.assign(\n organizationRef(\n async (ctx) => {\n const session = (ctx.principal as SessionPrincipal).session as {\n session?: { activeOrganizationId?: unknown };\n };\n const value = session.session?.activeOrganizationId;\n if (value !== undefined) {\n return value;\n }\n if (!(await ctx.auth.hasPlugin(\"custom-session\"))) {\n return undefined;\n }\n try {\n const member = await ctx.memo(\n JSON.stringify([\"org:activeMember\"]),\n () =>\n ctx.auth.run(\n {\n cookies: ctx.cookies,\n inbound: () => ctx.headers,\n internal: true,\n },\n () =>\n (ctx.auth.api as unknown as OrgApi).getActiveMember({\n headers: ctx.headers,\n }),\n ),\n );\n return member?.organizationId;\n } catch (error) {\n if (\n isAPIError(error) &&\n error.statusCode === 400 &&\n (error.body?.code === \"NO_ACTIVE_ORGANIZATION\" ||\n error.body?.code === \"MEMBER_NOT_FOUND\")\n ) {\n return undefined;\n }\n throw error;\n }\n },\n { missingReason: \"NO_ACTIVE_ORGANIZATION\" },\n ),\n { [REF]: { kind: \"active\" as const } },\n );\n}\nexport function fromParam(name: string): OrganizationRef {\n return Object.assign(\n organizationRef((ctx) => ctx.param(name)),\n { [REF]: { kind: \"param\" as const, name } },\n );\n}\nexport function fromHeader(name: string): OrganizationRef {\n return organizationRef((ctx) => ctx.headers.get(name));\n}\nfunction requirements(expressions: readonly RequirementExpr[]): Requirement[] {\n return expressions.flatMap((expression) =>\n \"anyOf\" in expression\n ? requirements(expression.anyOf)\n : \"allOf\" in expression\n ? requirements(expression.allOf)\n : [expression],\n );\n}\nfunction advise(\n ctx: BootAdviceContext,\n policy: AuthorizationPolicy<any, any>,\n): BootAdvice[] {\n const advice: BootAdvice[] = [];\n for (const handler of ctx.handlers) {\n for (const requirement of requirements(handler.plan.requirements)) {\n if (requirement.policy !== policy) {\n continue;\n }\n const ref = (requirement.params as OrgMemberParams)\n .organization as MarkedRef;\n const marker = ref[REF];\n if (marker?.kind === \"active\") {\n const input = handler.inputs.find((name) =>\n [\"orgId\", \"organizationId\", \"organization\", \"orgSlug\"].includes(name),\n );\n if (input) {\n advice.push({\n level: \"warn\",\n code: \"W_ORG_PARAM_IGNORED\",\n message: `${handler.plan.site} checks the active organization but accepts ${input}.`,\n hint:\n input === \"orgSlug\"\n ? \"Map the slug to an ID with organizationRef and auth.api.listOrganizations({ headers }).\"\n : `Use fromParam('${input}').`,\n });\n }\n } else if (\n marker?.kind === \"param\" &&\n !handler.inputs.includes(marker.name)\n ) {\n advice.push({\n level: \"warn\",\n code: \"W_ORG_PARAM_MISSING\",\n message: `${handler.plan.site} reads ${marker.name}, absent from claimed inputs: ${handler.inputs.join(\", \") || \"none\"}.`,\n hint: \"Use the correct input name, a method-level organizationRef, or SkipDefaultRequirements with a method-level requirement.\",\n });\n }\n }\n }\n return advice;\n}\nconst requires = {\n plugins: [\"organization\"],\n principals: [\"session\" as const],\n presentsCredentials: true,\n};\nexport const orgPermissionPolicy: AuthorizationPolicy<\n OrgPermissionParams,\n SessionPrincipal\n> = {\n id: \"better-auth:organization/permission\", // gitleaks:allow: public policy identifier\n requires,\n advise: (ctx) => advise(ctx, orgPermissionPolicy),\n validate({ permissions }) {\n if (\n !Object.keys(permissions).length ||\n Object.values(permissions).some(\n (actions) => !Array.isArray(actions) || !actions.length,\n )\n ) {\n throw new BetterAuthConfigurationError(\n \"EMPTY_PERMISSIONS\",\n \"Organization permissions must contain a resource and actions.\",\n );\n }\n },\n async evaluate({ permissions, organization }, context) {\n const organizationId = await organization(context);\n if (typeof organizationId !== \"string\" || !organizationId.trim()) {\n return {\n effect: \"deny\",\n reason: organization.missingReason ?? \"ORGANIZATION_REQUIRED\",\n };\n }\n const stable = Object.entries(permissions)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([resource, actions]) => [resource, [...actions].sort()]);\n try {\n const result = await context.memo(\n JSON.stringify([\"org:hasPermission\", organizationId, stable]),\n () =>\n context.auth.run(\n {\n cookies: context.cookies,\n inbound: () => context.headers,\n internal: true,\n },\n () =>\n (context.auth.api as unknown as OrgApi).hasPermission({\n headers: context.headers,\n body: { organizationId, permissions },\n }),\n ),\n );\n if (!result.success) {\n return { effect: \"deny\", reason: \"MISSING_PERMISSION\" };\n }\n context.provide(ACTIVE_ORGANIZATION_ID, organizationId);\n return { effect: \"allow\" };\n } catch (error) {\n if (\n isAPIError(error) &&\n error.body?.code === \"USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION\"\n ) {\n return {\n effect: \"deny\",\n reason: \"USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION\",\n };\n }\n throw error;\n }\n },\n};\nexport const orgMemberPolicy: AuthorizationPolicy<\n OrgMemberParams,\n SessionPrincipal\n> = {\n id: \"better-auth:organization/member\",\n requires,\n advise: (ctx) => advise(ctx, orgMemberPolicy),\n async evaluate({ organization }, context) {\n const organizationId = await organization(context);\n if (typeof organizationId !== \"string\" || !organizationId.trim()) {\n return {\n effect: \"deny\",\n reason: organization.missingReason ?? \"ORGANIZATION_REQUIRED\",\n };\n }\n try {\n const result = await context.memo(\n JSON.stringify([\"org:activeMemberRole\", organizationId]),\n () =>\n context.auth.run(\n {\n cookies: context.cookies,\n inbound: () => context.headers,\n internal: true,\n },\n () =>\n (context.auth.api as unknown as OrgApi).getActiveMemberRole({\n headers: context.headers,\n query: { organizationId },\n }),\n ),\n );\n if (typeof result.role !== \"string\" || !result.role.trim()) {\n return {\n effect: \"deny\",\n reason: \"YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION\",\n };\n }\n context.provide(ACTIVE_ORGANIZATION_ID, organizationId);\n context.provide(ACTIVE_MEMBER_ROLE, result.role);\n return { effect: \"allow\" };\n } catch (error) {\n if (\n isAPIError(error) &&\n error.body?.code === \"YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION\"\n ) {\n return {\n effect: \"deny\",\n reason: \"YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION\",\n };\n }\n throw error;\n }\n },\n};\nexport function orgPermission<N extends string = \"default\">(\n permissions: OrgPermissions<N>,\n options: { organization?: OrganizationRef } = {},\n): Requirement<OrgPermissionParams> {\n return {\n policy: orgPermissionPolicy,\n params: {\n permissions: permissions as OrgPermissions,\n organization: options.organization ?? activeOrganization(),\n },\n };\n}\nexport function RequireOrgPermission<N extends string = \"default\">(\n permissions: OrgPermissions<N>,\n options?: { organization?: OrganizationRef },\n): ClassDecorator & MethodDecorator {\n return Require(orgPermission<N>(permissions, options));\n}\nexport function orgMember(\n options: { organization?: OrganizationRef } = {},\n): Requirement<OrgMemberParams> {\n return {\n policy: orgMemberPolicy,\n params: { organization: options.organization ?? activeOrganization() },\n };\n}\nexport function RequireOrgMember(options?: {\n organization?: OrganizationRef;\n}): ClassDecorator & MethodDecorator {\n return Require(orgMember(options));\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Ft as SessionPrincipal, Ot as OrgPermissions, f as AuthorizationPolicy, l as AuthorizationContext, nt as Requirement } from "./auth-contracts-BBA1C1gj.cjs";
|
|
2
|
+
//#region src/organization.d.ts
|
|
3
|
+
export interface OrganizationRef {
|
|
4
|
+
(ctx: AuthorizationContext): unknown | Promise<unknown>;
|
|
5
|
+
readonly missingReason?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface OrgPermissionParams {
|
|
8
|
+
readonly permissions: OrgPermissions;
|
|
9
|
+
readonly organization: OrganizationRef;
|
|
10
|
+
}
|
|
11
|
+
export interface OrgMemberParams {
|
|
12
|
+
readonly organization: OrganizationRef;
|
|
13
|
+
}
|
|
14
|
+
export declare const ACTIVE_ORGANIZATION_ID: unique symbol;
|
|
15
|
+
export declare const ACTIVE_MEMBER_ROLE: unique symbol;
|
|
16
|
+
export declare const ActiveOrganizationId: () => ParameterDecorator;
|
|
17
|
+
export declare const ActiveMemberRole: () => ParameterDecorator;
|
|
18
|
+
export declare function organizationRef(resolve: (ctx: AuthorizationContext) => unknown | Promise<unknown>, options?: {
|
|
19
|
+
missingReason?: string;
|
|
20
|
+
}): OrganizationRef;
|
|
21
|
+
export declare function activeOrganization(): OrganizationRef;
|
|
22
|
+
export declare function fromParam(name: string): OrganizationRef;
|
|
23
|
+
export declare function fromHeader(name: string): OrganizationRef;
|
|
24
|
+
export declare const orgPermissionPolicy: AuthorizationPolicy<OrgPermissionParams, SessionPrincipal>;
|
|
25
|
+
export declare const orgMemberPolicy: AuthorizationPolicy<OrgMemberParams, SessionPrincipal>;
|
|
26
|
+
export declare function orgPermission<N extends string = "default">(permissions: OrgPermissions<N>, options?: {
|
|
27
|
+
organization?: OrganizationRef;
|
|
28
|
+
}): Requirement<OrgPermissionParams>;
|
|
29
|
+
export declare function RequireOrgPermission<N extends string = "default">(permissions: OrgPermissions<N>, options?: {
|
|
30
|
+
organization?: OrganizationRef;
|
|
31
|
+
}): ClassDecorator & MethodDecorator;
|
|
32
|
+
export declare function orgMember(options?: {
|
|
33
|
+
organization?: OrganizationRef;
|
|
34
|
+
}): Requirement<OrgMemberParams>;
|
|
35
|
+
export declare function RequireOrgMember(options?: {
|
|
36
|
+
organization?: OrganizationRef;
|
|
37
|
+
}): ClassDecorator & MethodDecorator;
|
|
38
|
+
//#endregion
|
|
39
|
+
export type { OrgPermissions };
|
|
40
|
+
//# sourceMappingURL=organization.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.d.cts","names":[],"sources":["../src/organization.ts"],"mappings":";;iBAaiB;GACd,KAAK,iCAAiC;WAC9B;;iBAEM;WACN,aAAa;WACb,cAAc;;iBAER;WACN,cAAc;;qBAEZ;qBAGA;qBAGA,4BAAoB;qBAIpB,wBAAgB;wBAoBb,gBACd,UAAU,KAAK,mCAAmC,kBAClD;EAAW;IACV;wBAGa,sBAAsB;wBAgDtB,UAAU,eAAe;wBAMzB,WAAW,eAAe;qBA4D7B,qBAAqB,oBAChC,qBACA;qBAiEW,iBAAiB,oBAC5B,iBACA;wBAqDc,cAAc,8BAC5B,aAAa,eAAe,IAC5B;EAAW,eAAe;IACzB,YAAY;wBASC,qBAAqB,8BACnC,aAAa,eAAe,IAC5B;EAAY,eAAe;IAC1B,iBAAiB;wBAGJ,UACd;EAAW,eAAe;IACzB,YAAY;wBAMC,iBAAiB;EAC/B,eAAe;IACb,iBAAiB"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Ft as SessionPrincipal, Ot as OrgPermissions, f as AuthorizationPolicy, l as AuthorizationContext, nt as Requirement } from "./auth-contracts-tqsfBZ8B.mjs";
|
|
2
|
+
//#region src/organization.d.ts
|
|
3
|
+
export interface OrganizationRef {
|
|
4
|
+
(ctx: AuthorizationContext): unknown | Promise<unknown>;
|
|
5
|
+
readonly missingReason?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface OrgPermissionParams {
|
|
8
|
+
readonly permissions: OrgPermissions;
|
|
9
|
+
readonly organization: OrganizationRef;
|
|
10
|
+
}
|
|
11
|
+
export interface OrgMemberParams {
|
|
12
|
+
readonly organization: OrganizationRef;
|
|
13
|
+
}
|
|
14
|
+
export declare const ACTIVE_ORGANIZATION_ID: unique symbol;
|
|
15
|
+
export declare const ACTIVE_MEMBER_ROLE: unique symbol;
|
|
16
|
+
export declare const ActiveOrganizationId: () => ParameterDecorator;
|
|
17
|
+
export declare const ActiveMemberRole: () => ParameterDecorator;
|
|
18
|
+
export declare function organizationRef(resolve: (ctx: AuthorizationContext) => unknown | Promise<unknown>, options?: {
|
|
19
|
+
missingReason?: string;
|
|
20
|
+
}): OrganizationRef;
|
|
21
|
+
export declare function activeOrganization(): OrganizationRef;
|
|
22
|
+
export declare function fromParam(name: string): OrganizationRef;
|
|
23
|
+
export declare function fromHeader(name: string): OrganizationRef;
|
|
24
|
+
export declare const orgPermissionPolicy: AuthorizationPolicy<OrgPermissionParams, SessionPrincipal>;
|
|
25
|
+
export declare const orgMemberPolicy: AuthorizationPolicy<OrgMemberParams, SessionPrincipal>;
|
|
26
|
+
export declare function orgPermission<N extends string = "default">(permissions: OrgPermissions<N>, options?: {
|
|
27
|
+
organization?: OrganizationRef;
|
|
28
|
+
}): Requirement<OrgPermissionParams>;
|
|
29
|
+
export declare function RequireOrgPermission<N extends string = "default">(permissions: OrgPermissions<N>, options?: {
|
|
30
|
+
organization?: OrganizationRef;
|
|
31
|
+
}): ClassDecorator & MethodDecorator;
|
|
32
|
+
export declare function orgMember(options?: {
|
|
33
|
+
organization?: OrganizationRef;
|
|
34
|
+
}): Requirement<OrgMemberParams>;
|
|
35
|
+
export declare function RequireOrgMember(options?: {
|
|
36
|
+
organization?: OrganizationRef;
|
|
37
|
+
}): ClassDecorator & MethodDecorator;
|
|
38
|
+
//#endregion
|
|
39
|
+
export type { OrgPermissions };
|
|
40
|
+
//# sourceMappingURL=organization.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.d.mts","names":[],"sources":["../src/organization.ts"],"mappings":";;iBAaiB;GACd,KAAK,iCAAiC;WAC9B;;iBAEM;WACN,aAAa;WACb,cAAc;;iBAER;WACN,cAAc;;qBAEZ;qBAGA;qBAGA,4BAAoB;qBAIpB,wBAAgB;wBAoBb,gBACd,UAAU,KAAK,mCAAmC,kBAClD;EAAW;IACV;wBAGa,sBAAsB;wBAgDtB,UAAU,eAAe;wBAMzB,WAAW,eAAe;qBA4D7B,qBAAqB,oBAChC,qBACA;qBAiEW,iBAAiB,oBAC5B,iBACA;wBAqDc,cAAc,8BAC5B,aAAa,eAAe,IAC5B;EAAW,eAAe;IACzB,YAAY;wBASC,qBAAqB,8BACnC,aAAa,eAAe,IAC5B;EAAY,eAAe;IAC1B,iBAAiB;wBAGJ,UACd;EAAW,eAAe;IACzB,YAAY;wBAMC,iBAAiB;EAC/B,eAAe;IACb,iBAAiB"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { n as BetterAuthConfigurationError } from "./auth-errors-CQjfgjaO.mjs";
|
|
2
|
+
import { u as Require, v as defineInvocationParam } from "./auth-decorators-DfAJbHar.mjs";
|
|
3
|
+
import { isAPIError } from "better-auth/api";
|
|
4
|
+
//#region src/organization.ts
|
|
5
|
+
const ACTIVE_ORGANIZATION_ID = Symbol.for("nestjs-slightly-better-auth:org:active-organization-id");
|
|
6
|
+
const ACTIVE_MEMBER_ROLE = Symbol.for("nestjs-slightly-better-auth:org:active-member-role");
|
|
7
|
+
const ActiveOrganizationId = defineInvocationParam(ACTIVE_ORGANIZATION_ID, { missing: "ORGANIZATION_REQUIRED" });
|
|
8
|
+
const ActiveMemberRole = defineInvocationParam(ACTIVE_MEMBER_ROLE, { missing: "MEMBER_ROLE_REQUIRED" });
|
|
9
|
+
const REF = Symbol.for("nestjs-slightly-better-auth:org:ref");
|
|
10
|
+
function organizationRef(resolve, options = {}) {
|
|
11
|
+
return Object.assign((ctx) => resolve(ctx), options);
|
|
12
|
+
}
|
|
13
|
+
function activeOrganization() {
|
|
14
|
+
return Object.assign(organizationRef(async (ctx) => {
|
|
15
|
+
const value = ctx.principal.session.session?.activeOrganizationId;
|
|
16
|
+
if (value !== void 0) return value;
|
|
17
|
+
if (!await ctx.auth.hasPlugin("custom-session")) return;
|
|
18
|
+
try {
|
|
19
|
+
return (await ctx.memo(JSON.stringify(["org:activeMember"]), () => ctx.auth.run({
|
|
20
|
+
cookies: ctx.cookies,
|
|
21
|
+
inbound: () => ctx.headers,
|
|
22
|
+
internal: true
|
|
23
|
+
}, () => ctx.auth.api.getActiveMember({ headers: ctx.headers }))))?.organizationId;
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (isAPIError(error) && error.statusCode === 400 && (error.body?.code === "NO_ACTIVE_ORGANIZATION" || error.body?.code === "MEMBER_NOT_FOUND")) return;
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}, { missingReason: "NO_ACTIVE_ORGANIZATION" }), { [REF]: { kind: "active" } });
|
|
29
|
+
}
|
|
30
|
+
function fromParam(name) {
|
|
31
|
+
return Object.assign(organizationRef((ctx) => ctx.param(name)), { [REF]: {
|
|
32
|
+
kind: "param",
|
|
33
|
+
name
|
|
34
|
+
} });
|
|
35
|
+
}
|
|
36
|
+
function fromHeader(name) {
|
|
37
|
+
return organizationRef((ctx) => ctx.headers.get(name));
|
|
38
|
+
}
|
|
39
|
+
function requirements(expressions) {
|
|
40
|
+
return expressions.flatMap((expression) => "anyOf" in expression ? requirements(expression.anyOf) : "allOf" in expression ? requirements(expression.allOf) : [expression]);
|
|
41
|
+
}
|
|
42
|
+
function advise(ctx, policy) {
|
|
43
|
+
const advice = [];
|
|
44
|
+
for (const handler of ctx.handlers) for (const requirement of requirements(handler.plan.requirements)) {
|
|
45
|
+
if (requirement.policy !== policy) continue;
|
|
46
|
+
const marker = requirement.params.organization[REF];
|
|
47
|
+
if (marker?.kind === "active") {
|
|
48
|
+
const input = handler.inputs.find((name) => [
|
|
49
|
+
"orgId",
|
|
50
|
+
"organizationId",
|
|
51
|
+
"organization",
|
|
52
|
+
"orgSlug"
|
|
53
|
+
].includes(name));
|
|
54
|
+
if (input) advice.push({
|
|
55
|
+
level: "warn",
|
|
56
|
+
code: "W_ORG_PARAM_IGNORED",
|
|
57
|
+
message: `${handler.plan.site} checks the active organization but accepts ${input}.`,
|
|
58
|
+
hint: input === "orgSlug" ? "Map the slug to an ID with organizationRef and auth.api.listOrganizations({ headers })." : `Use fromParam('${input}').`
|
|
59
|
+
});
|
|
60
|
+
} else if (marker?.kind === "param" && !handler.inputs.includes(marker.name)) advice.push({
|
|
61
|
+
level: "warn",
|
|
62
|
+
code: "W_ORG_PARAM_MISSING",
|
|
63
|
+
message: `${handler.plan.site} reads ${marker.name}, absent from claimed inputs: ${handler.inputs.join(", ") || "none"}.`,
|
|
64
|
+
hint: "Use the correct input name, a method-level organizationRef, or SkipDefaultRequirements with a method-level requirement."
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return advice;
|
|
68
|
+
}
|
|
69
|
+
const requires = {
|
|
70
|
+
plugins: ["organization"],
|
|
71
|
+
principals: ["session"],
|
|
72
|
+
presentsCredentials: true
|
|
73
|
+
};
|
|
74
|
+
const orgPermissionPolicy = {
|
|
75
|
+
id: "better-auth:organization/permission",
|
|
76
|
+
requires,
|
|
77
|
+
advise: (ctx) => advise(ctx, orgPermissionPolicy),
|
|
78
|
+
validate({ permissions }) {
|
|
79
|
+
if (!Object.keys(permissions).length || Object.values(permissions).some((actions) => !Array.isArray(actions) || !actions.length)) throw new BetterAuthConfigurationError("EMPTY_PERMISSIONS", "Organization permissions must contain a resource and actions.");
|
|
80
|
+
},
|
|
81
|
+
async evaluate({ permissions, organization }, context) {
|
|
82
|
+
const organizationId = await organization(context);
|
|
83
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) return {
|
|
84
|
+
effect: "deny",
|
|
85
|
+
reason: organization.missingReason ?? "ORGANIZATION_REQUIRED"
|
|
86
|
+
};
|
|
87
|
+
const stable = Object.entries(permissions).sort(([a], [b]) => a.localeCompare(b)).map(([resource, actions]) => [resource, [...actions].sort()]);
|
|
88
|
+
try {
|
|
89
|
+
if (!(await context.memo(JSON.stringify([
|
|
90
|
+
"org:hasPermission",
|
|
91
|
+
organizationId,
|
|
92
|
+
stable
|
|
93
|
+
]), () => context.auth.run({
|
|
94
|
+
cookies: context.cookies,
|
|
95
|
+
inbound: () => context.headers,
|
|
96
|
+
internal: true
|
|
97
|
+
}, () => context.auth.api.hasPermission({
|
|
98
|
+
headers: context.headers,
|
|
99
|
+
body: {
|
|
100
|
+
organizationId,
|
|
101
|
+
permissions
|
|
102
|
+
}
|
|
103
|
+
})))).success) return {
|
|
104
|
+
effect: "deny",
|
|
105
|
+
reason: "MISSING_PERMISSION"
|
|
106
|
+
};
|
|
107
|
+
context.provide(ACTIVE_ORGANIZATION_ID, organizationId);
|
|
108
|
+
return { effect: "allow" };
|
|
109
|
+
} catch (error) {
|
|
110
|
+
if (isAPIError(error) && error.body?.code === "USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION") return {
|
|
111
|
+
effect: "deny",
|
|
112
|
+
reason: "USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION"
|
|
113
|
+
};
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const orgMemberPolicy = {
|
|
119
|
+
id: "better-auth:organization/member",
|
|
120
|
+
requires,
|
|
121
|
+
advise: (ctx) => advise(ctx, orgMemberPolicy),
|
|
122
|
+
async evaluate({ organization }, context) {
|
|
123
|
+
const organizationId = await organization(context);
|
|
124
|
+
if (typeof organizationId !== "string" || !organizationId.trim()) return {
|
|
125
|
+
effect: "deny",
|
|
126
|
+
reason: organization.missingReason ?? "ORGANIZATION_REQUIRED"
|
|
127
|
+
};
|
|
128
|
+
try {
|
|
129
|
+
const result = await context.memo(JSON.stringify(["org:activeMemberRole", organizationId]), () => context.auth.run({
|
|
130
|
+
cookies: context.cookies,
|
|
131
|
+
inbound: () => context.headers,
|
|
132
|
+
internal: true
|
|
133
|
+
}, () => context.auth.api.getActiveMemberRole({
|
|
134
|
+
headers: context.headers,
|
|
135
|
+
query: { organizationId }
|
|
136
|
+
})));
|
|
137
|
+
if (typeof result.role !== "string" || !result.role.trim()) return {
|
|
138
|
+
effect: "deny",
|
|
139
|
+
reason: "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION"
|
|
140
|
+
};
|
|
141
|
+
context.provide(ACTIVE_ORGANIZATION_ID, organizationId);
|
|
142
|
+
context.provide(ACTIVE_MEMBER_ROLE, result.role);
|
|
143
|
+
return { effect: "allow" };
|
|
144
|
+
} catch (error) {
|
|
145
|
+
if (isAPIError(error) && error.body?.code === "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION") return {
|
|
146
|
+
effect: "deny",
|
|
147
|
+
reason: "YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION"
|
|
148
|
+
};
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
function orgPermission(permissions, options = {}) {
|
|
154
|
+
return {
|
|
155
|
+
policy: orgPermissionPolicy,
|
|
156
|
+
params: {
|
|
157
|
+
permissions,
|
|
158
|
+
organization: options.organization ?? activeOrganization()
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function RequireOrgPermission(permissions, options) {
|
|
163
|
+
return Require(orgPermission(permissions, options));
|
|
164
|
+
}
|
|
165
|
+
function orgMember(options = {}) {
|
|
166
|
+
return {
|
|
167
|
+
policy: orgMemberPolicy,
|
|
168
|
+
params: { organization: options.organization ?? activeOrganization() }
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function RequireOrgMember(options) {
|
|
172
|
+
return Require(orgMember(options));
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
export { ACTIVE_MEMBER_ROLE, ACTIVE_ORGANIZATION_ID, ActiveMemberRole, ActiveOrganizationId, RequireOrgMember, RequireOrgPermission, activeOrganization, fromHeader, fromParam, orgMember, orgMemberPolicy, orgPermission, orgPermissionPolicy, organizationRef };
|
|
176
|
+
|
|
177
|
+
//# sourceMappingURL=organization.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization.mjs","names":[],"sources":["../src/organization.ts"],"sourcesContent":["import { isAPIError } from \"better-auth/api\";\nimport type {\n AuthorizationContext,\n AuthorizationPolicy,\n BootAdvice,\n BootAdviceContext,\n Requirement,\n RequirementExpr,\n} from \"./auth-contracts.js\";\nimport { defineInvocationParam, Require } from \"./auth-decorators.js\";\nimport { BetterAuthConfigurationError } from \"./auth-errors.js\";\nimport type { OrgPermissions, SessionPrincipal } from \"./auth-types.js\";\nexport type { OrgPermissions } from \"./auth-types.js\";\nexport interface OrganizationRef {\n (ctx: AuthorizationContext): unknown | Promise<unknown>;\n readonly missingReason?: string;\n}\nexport interface OrgPermissionParams {\n readonly permissions: OrgPermissions;\n readonly organization: OrganizationRef;\n}\nexport interface OrgMemberParams {\n readonly organization: OrganizationRef;\n}\nexport const ACTIVE_ORGANIZATION_ID = Symbol.for(\n \"nestjs-slightly-better-auth:org:active-organization-id\",\n);\nexport const ACTIVE_MEMBER_ROLE = Symbol.for(\n \"nestjs-slightly-better-auth:org:active-member-role\",\n);\nexport const ActiveOrganizationId = defineInvocationParam(\n ACTIVE_ORGANIZATION_ID,\n { missing: \"ORGANIZATION_REQUIRED\" },\n);\nexport const ActiveMemberRole = defineInvocationParam(ACTIVE_MEMBER_ROLE, {\n missing: \"MEMBER_ROLE_REQUIRED\",\n});\nconst REF = Symbol.for(\"nestjs-slightly-better-auth:org:ref\");\ntype MarkedRef = OrganizationRef & {\n readonly [REF]?: { kind: \"active\" } | { kind: \"param\"; name: string };\n};\ninterface OrgApi {\n hasPermission(input: {\n headers: Headers;\n body: { organizationId: string; permissions: OrgPermissions };\n }): Promise<{ success: boolean }>;\n getActiveMemberRole(input: {\n headers: Headers;\n query: { organizationId: string };\n }): Promise<{ role?: string | null }>;\n getActiveMember(input: {\n headers: Headers;\n }): Promise<{ organizationId?: string }>;\n}\nexport function organizationRef(\n resolve: (ctx: AuthorizationContext) => unknown | Promise<unknown>,\n options: { missingReason?: string } = {},\n): OrganizationRef {\n return Object.assign((ctx: AuthorizationContext) => resolve(ctx), options);\n}\nexport function activeOrganization(): OrganizationRef {\n return Object.assign(\n organizationRef(\n async (ctx) => {\n const session = (ctx.principal as SessionPrincipal).session as {\n session?: { activeOrganizationId?: unknown };\n };\n const value = session.session?.activeOrganizationId;\n if (value !== undefined) {\n return value;\n }\n if (!(await ctx.auth.hasPlugin(\"custom-session\"))) {\n return undefined;\n }\n try {\n const member = await ctx.memo(\n JSON.stringify([\"org:activeMember\"]),\n () =>\n ctx.auth.run(\n {\n cookies: ctx.cookies,\n inbound: () => ctx.headers,\n internal: true,\n },\n () =>\n (ctx.auth.api as unknown as OrgApi).getActiveMember({\n headers: ctx.headers,\n }),\n ),\n );\n return member?.organizationId;\n } catch (error) {\n if (\n isAPIError(error) &&\n error.statusCode === 400 &&\n (error.body?.code === \"NO_ACTIVE_ORGANIZATION\" ||\n error.body?.code === \"MEMBER_NOT_FOUND\")\n ) {\n return undefined;\n }\n throw error;\n }\n },\n { missingReason: \"NO_ACTIVE_ORGANIZATION\" },\n ),\n { [REF]: { kind: \"active\" as const } },\n );\n}\nexport function fromParam(name: string): OrganizationRef {\n return Object.assign(\n organizationRef((ctx) => ctx.param(name)),\n { [REF]: { kind: \"param\" as const, name } },\n );\n}\nexport function fromHeader(name: string): OrganizationRef {\n return organizationRef((ctx) => ctx.headers.get(name));\n}\nfunction requirements(expressions: readonly RequirementExpr[]): Requirement[] {\n return expressions.flatMap((expression) =>\n \"anyOf\" in expression\n ? requirements(expression.anyOf)\n : \"allOf\" in expression\n ? requirements(expression.allOf)\n : [expression],\n );\n}\nfunction advise(\n ctx: BootAdviceContext,\n policy: AuthorizationPolicy<any, any>,\n): BootAdvice[] {\n const advice: BootAdvice[] = [];\n for (const handler of ctx.handlers) {\n for (const requirement of requirements(handler.plan.requirements)) {\n if (requirement.policy !== policy) {\n continue;\n }\n const ref = (requirement.params as OrgMemberParams)\n .organization as MarkedRef;\n const marker = ref[REF];\n if (marker?.kind === \"active\") {\n const input = handler.inputs.find((name) =>\n [\"orgId\", \"organizationId\", \"organization\", \"orgSlug\"].includes(name),\n );\n if (input) {\n advice.push({\n level: \"warn\",\n code: \"W_ORG_PARAM_IGNORED\",\n message: `${handler.plan.site} checks the active organization but accepts ${input}.`,\n hint:\n input === \"orgSlug\"\n ? \"Map the slug to an ID with organizationRef and auth.api.listOrganizations({ headers }).\"\n : `Use fromParam('${input}').`,\n });\n }\n } else if (\n marker?.kind === \"param\" &&\n !handler.inputs.includes(marker.name)\n ) {\n advice.push({\n level: \"warn\",\n code: \"W_ORG_PARAM_MISSING\",\n message: `${handler.plan.site} reads ${marker.name}, absent from claimed inputs: ${handler.inputs.join(\", \") || \"none\"}.`,\n hint: \"Use the correct input name, a method-level organizationRef, or SkipDefaultRequirements with a method-level requirement.\",\n });\n }\n }\n }\n return advice;\n}\nconst requires = {\n plugins: [\"organization\"],\n principals: [\"session\" as const],\n presentsCredentials: true,\n};\nexport const orgPermissionPolicy: AuthorizationPolicy<\n OrgPermissionParams,\n SessionPrincipal\n> = {\n id: \"better-auth:organization/permission\", // gitleaks:allow: public policy identifier\n requires,\n advise: (ctx) => advise(ctx, orgPermissionPolicy),\n validate({ permissions }) {\n if (\n !Object.keys(permissions).length ||\n Object.values(permissions).some(\n (actions) => !Array.isArray(actions) || !actions.length,\n )\n ) {\n throw new BetterAuthConfigurationError(\n \"EMPTY_PERMISSIONS\",\n \"Organization permissions must contain a resource and actions.\",\n );\n }\n },\n async evaluate({ permissions, organization }, context) {\n const organizationId = await organization(context);\n if (typeof organizationId !== \"string\" || !organizationId.trim()) {\n return {\n effect: \"deny\",\n reason: organization.missingReason ?? \"ORGANIZATION_REQUIRED\",\n };\n }\n const stable = Object.entries(permissions)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([resource, actions]) => [resource, [...actions].sort()]);\n try {\n const result = await context.memo(\n JSON.stringify([\"org:hasPermission\", organizationId, stable]),\n () =>\n context.auth.run(\n {\n cookies: context.cookies,\n inbound: () => context.headers,\n internal: true,\n },\n () =>\n (context.auth.api as unknown as OrgApi).hasPermission({\n headers: context.headers,\n body: { organizationId, permissions },\n }),\n ),\n );\n if (!result.success) {\n return { effect: \"deny\", reason: \"MISSING_PERMISSION\" };\n }\n context.provide(ACTIVE_ORGANIZATION_ID, organizationId);\n return { effect: \"allow\" };\n } catch (error) {\n if (\n isAPIError(error) &&\n error.body?.code === \"USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION\"\n ) {\n return {\n effect: \"deny\",\n reason: \"USER_IS_NOT_A_MEMBER_OF_THE_ORGANIZATION\",\n };\n }\n throw error;\n }\n },\n};\nexport const orgMemberPolicy: AuthorizationPolicy<\n OrgMemberParams,\n SessionPrincipal\n> = {\n id: \"better-auth:organization/member\",\n requires,\n advise: (ctx) => advise(ctx, orgMemberPolicy),\n async evaluate({ organization }, context) {\n const organizationId = await organization(context);\n if (typeof organizationId !== \"string\" || !organizationId.trim()) {\n return {\n effect: \"deny\",\n reason: organization.missingReason ?? \"ORGANIZATION_REQUIRED\",\n };\n }\n try {\n const result = await context.memo(\n JSON.stringify([\"org:activeMemberRole\", organizationId]),\n () =>\n context.auth.run(\n {\n cookies: context.cookies,\n inbound: () => context.headers,\n internal: true,\n },\n () =>\n (context.auth.api as unknown as OrgApi).getActiveMemberRole({\n headers: context.headers,\n query: { organizationId },\n }),\n ),\n );\n if (typeof result.role !== \"string\" || !result.role.trim()) {\n return {\n effect: \"deny\",\n reason: \"YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION\",\n };\n }\n context.provide(ACTIVE_ORGANIZATION_ID, organizationId);\n context.provide(ACTIVE_MEMBER_ROLE, result.role);\n return { effect: \"allow\" };\n } catch (error) {\n if (\n isAPIError(error) &&\n error.body?.code === \"YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION\"\n ) {\n return {\n effect: \"deny\",\n reason: \"YOU_ARE_NOT_A_MEMBER_OF_THIS_ORGANIZATION\",\n };\n }\n throw error;\n }\n },\n};\nexport function orgPermission<N extends string = \"default\">(\n permissions: OrgPermissions<N>,\n options: { organization?: OrganizationRef } = {},\n): Requirement<OrgPermissionParams> {\n return {\n policy: orgPermissionPolicy,\n params: {\n permissions: permissions as OrgPermissions,\n organization: options.organization ?? activeOrganization(),\n },\n };\n}\nexport function RequireOrgPermission<N extends string = \"default\">(\n permissions: OrgPermissions<N>,\n options?: { organization?: OrganizationRef },\n): ClassDecorator & MethodDecorator {\n return Require(orgPermission<N>(permissions, options));\n}\nexport function orgMember(\n options: { organization?: OrganizationRef } = {},\n): Requirement<OrgMemberParams> {\n return {\n policy: orgMemberPolicy,\n params: { organization: options.organization ?? activeOrganization() },\n };\n}\nexport function RequireOrgMember(options?: {\n organization?: OrganizationRef;\n}): ClassDecorator & MethodDecorator {\n return Require(orgMember(options));\n}\n"],"mappings":"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"}
|