@easy-cms/plugin-multi-tenant 0.47.2 → 0.47.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +44 -9
- package/package.json +7 -7
package/dist/index.js
CHANGED
|
@@ -61,7 +61,7 @@ import {
|
|
|
61
61
|
// src/info.ts
|
|
62
62
|
var INFO = {
|
|
63
63
|
name: "@easy-cms/plugin-multi-tenant",
|
|
64
|
-
...true ? { version: "0.47.
|
|
64
|
+
...true ? { version: "0.47.4" } : {}
|
|
65
65
|
};
|
|
66
66
|
|
|
67
67
|
// src/members.ts
|
|
@@ -70,6 +70,24 @@ import {
|
|
|
70
70
|
NotFoundError,
|
|
71
71
|
ValidationError
|
|
72
72
|
} from "@easy-cms/core";
|
|
73
|
+
async function addedEmail(cms, tenantsSlug, tenant, to, origin) {
|
|
74
|
+
const found = await cms.findById(tenantsSlug, tenant, { depth: 0 });
|
|
75
|
+
const name = typeof found?.name === "string" ? found.name : String(tenant);
|
|
76
|
+
const admin = `${cms.config.serverURL ?? origin}${cms.config.admin.path}`;
|
|
77
|
+
return {
|
|
78
|
+
to,
|
|
79
|
+
subject: `You were added to ${name}`,
|
|
80
|
+
text: [
|
|
81
|
+
`An admin of ${name} added you to it. Sign in as before to work there:`,
|
|
82
|
+
admin,
|
|
83
|
+
"",
|
|
84
|
+
`\u0E1C\u0E39\u0E49\u0E14\u0E39\u0E41\u0E25\u0E02\u0E2D\u0E07 ${name} \u0E40\u0E1E\u0E34\u0E48\u0E21\u0E04\u0E38\u0E13\u0E40\u0E02\u0E49\u0E32\u0E44\u0E1B\u0E41\u0E25\u0E49\u0E27 \u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E14\u0E49\u0E27\u0E22\u0E1A\u0E31\u0E0D\u0E0A\u0E35\u0E40\u0E14\u0E34\u0E21\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E17\u0E33\u0E07\u0E32\u0E19\u0E17\u0E35\u0E48\u0E19\u0E31\u0E48\u0E19:`,
|
|
85
|
+
admin,
|
|
86
|
+
"",
|
|
87
|
+
"If you don't know why, ask your admin. / \u0E2B\u0E32\u0E01\u0E44\u0E21\u0E48\u0E17\u0E23\u0E32\u0E1A\u0E17\u0E35\u0E48\u0E21\u0E32 \u0E42\u0E1B\u0E23\u0E14\u0E2A\u0E2D\u0E1A\u0E16\u0E32\u0E21\u0E1C\u0E39\u0E49\u0E14\u0E39\u0E41\u0E25"
|
|
88
|
+
].join("\n")
|
|
89
|
+
};
|
|
90
|
+
}
|
|
73
91
|
function membersEndpoints(options) {
|
|
74
92
|
const tenantFor = (user, context) => {
|
|
75
93
|
const { tenant } = tenantOf(context);
|
|
@@ -139,6 +157,12 @@ function membersEndpoints(options) {
|
|
|
139
157
|
});
|
|
140
158
|
const existing = docs[0];
|
|
141
159
|
if (existing) {
|
|
160
|
+
const account = { id: existing.id, email, role: existing.role };
|
|
161
|
+
const memberRoles = cms.config.auth.members?.roles ?? [];
|
|
162
|
+
if (memberRoles.includes(String(existing.role)) || options.isSuper(account))
|
|
163
|
+
throw new ValidationError("users", [
|
|
164
|
+
{ field: "email", message: "can't be added to a tenant" }
|
|
165
|
+
]);
|
|
142
166
|
const list = rows(existing).filter((row) => !sameId(row.tenant, tenant));
|
|
143
167
|
const doc2 = await cms.update(
|
|
144
168
|
"users",
|
|
@@ -146,7 +170,17 @@ function membersEndpoints(options) {
|
|
|
146
170
|
{ [MEMBERSHIPS_FIELD]: [...list, { tenant, role }] },
|
|
147
171
|
{ depth: 0 }
|
|
148
172
|
);
|
|
149
|
-
|
|
173
|
+
let invited2 = false;
|
|
174
|
+
if (cms.auth.canSendPasswordLinks(url.origin)) {
|
|
175
|
+
await cms.sendEmail(
|
|
176
|
+
await addedEmail(cms, options.tenantsSlug, tenant, email, url.origin)
|
|
177
|
+
);
|
|
178
|
+
invited2 = true;
|
|
179
|
+
}
|
|
180
|
+
return Response.json(
|
|
181
|
+
{ member: { ...member(doc2, tenant), name: null }, invited: invited2 },
|
|
182
|
+
{ status: 201 }
|
|
183
|
+
);
|
|
150
184
|
}
|
|
151
185
|
const doc = await cms.create(
|
|
152
186
|
"users",
|
|
@@ -238,14 +272,14 @@ function multiTenantPlugin(options) {
|
|
|
238
272
|
throw new Error(
|
|
239
273
|
`multiTenantPlugin: no global ${unknownGlobals.map((g) => `"${g}"`).join(", ")} in the config`
|
|
240
274
|
);
|
|
241
|
-
const
|
|
242
|
-
const
|
|
275
|
+
const superUser = (user, _context) => !!user && user.member !== true && user.scoped !== true && isSuper(user);
|
|
276
|
+
const everywhere = (user, context) => tenantOf(context).allTenants || superUser(user, context);
|
|
243
277
|
const tenantFilter = (args, op) => {
|
|
244
278
|
const { tenant } = tenantOf(args.context);
|
|
245
|
-
if (op === "create") return tenant !== null ||
|
|
279
|
+
if (op === "create") return tenant !== null || superUser(args.user, args.context);
|
|
246
280
|
if (tenant !== null) return { [TENANT_FIELD]: { equals: tenant } };
|
|
247
|
-
if (everywhere(args.user, args.context)
|
|
248
|
-
return
|
|
281
|
+
if (op === "read") return everywhere(args.user, args.context) ? true : NOTHING;
|
|
282
|
+
return superUser(args.user, args.context);
|
|
249
283
|
};
|
|
250
284
|
const narrow = (original, op) => async (args) => {
|
|
251
285
|
const base = await (original ?? isLoggedIn)(args);
|
|
@@ -320,7 +354,7 @@ function multiTenantPlugin(options) {
|
|
|
320
354
|
throw new ValidationError2(slug, [{ field: TENANT_FIELD, message }]);
|
|
321
355
|
};
|
|
322
356
|
if (value === null) fail("is required: choose a tenant");
|
|
323
|
-
if (
|
|
357
|
+
if (superUser(user, context)) return data;
|
|
324
358
|
if (!sameId(value, tenant)) fail("must be the tenant you work in");
|
|
325
359
|
const before = originalDoc?.[TENANT_FIELD] ?? null;
|
|
326
360
|
if (operation === "update" && before !== null && !sameId(before, value))
|
|
@@ -387,6 +421,7 @@ function multiTenantPlugin(options) {
|
|
|
387
421
|
return {
|
|
388
422
|
read: and(custom?.read, ({ user, context }) => {
|
|
389
423
|
if (!user) return false;
|
|
424
|
+
if (user.member === true) return self(user);
|
|
390
425
|
if (superUser(user, context)) return true;
|
|
391
426
|
const { tenant } = tenantOf(context);
|
|
392
427
|
return tenant === null ? self(user) : { or: [self(user), { [`${MEMBERSHIPS_FIELD}.tenant`]: { equals: tenant } }] };
|
|
@@ -661,7 +696,7 @@ of its own. Run it once after adding the plugin to a site that has content.
|
|
|
661
696
|
...config.endpoints ?? [],
|
|
662
697
|
optionsEndpoint,
|
|
663
698
|
impactEndpoint,
|
|
664
|
-
...membersEndpoints({ tenantsSlug, superUser })
|
|
699
|
+
...membersEndpoints({ tenantsSlug, superUser, isSuper })
|
|
665
700
|
],
|
|
666
701
|
commands: [...config.commands ?? [], assign],
|
|
667
702
|
// Audit log entries belong to their tenant: its admins see them.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@easy-cms/plugin-multi-tenant",
|
|
3
|
-
"version": "0.47.
|
|
3
|
+
"version": "0.47.4",
|
|
4
4
|
"description": "Multi-tenant Easy CMS: several sites or clients in one CMS, each with its own content, members and roles",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
"dist"
|
|
18
18
|
],
|
|
19
19
|
"peerDependencies": {
|
|
20
|
-
"@easy-cms/core": "^0.47.
|
|
20
|
+
"@easy-cms/core": "^0.47.4"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"@easy-cms/
|
|
24
|
-
"@easy-cms/db-sqlite": "^0.47.
|
|
25
|
-
"@easy-cms/plugin-form-builder": "^0.47.
|
|
26
|
-
"@easy-cms/plugin-
|
|
27
|
-
"@easy-cms/
|
|
23
|
+
"@easy-cms/core": "^0.47.4",
|
|
24
|
+
"@easy-cms/db-sqlite": "^0.47.4",
|
|
25
|
+
"@easy-cms/plugin-form-builder": "^0.47.4",
|
|
26
|
+
"@easy-cms/plugin-nested-docs": "^0.47.4",
|
|
27
|
+
"@easy-cms/plugin-redirects": "^0.47.4"
|
|
28
28
|
},
|
|
29
29
|
"engines": {
|
|
30
30
|
"node": ">=22.12"
|