@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.
Files changed (2) hide show
  1. package/dist/index.js +44 -9
  2. 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.2" } : {}
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
- return { member: member(doc2, tenant), invited: false };
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 everywhere = (user, context) => tenantOf(context).allTenants || !!user && user.scoped !== true && isSuper(user);
242
- const superUser = (user, context) => !!user && everywhere(user, context);
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 || everywhere(args.user, args.context);
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)) return true;
248
- return op === "read" ? NOTHING : false;
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 (everywhere(user, context)) return data;
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.2",
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.2"
20
+ "@easy-cms/core": "^0.47.4"
21
21
  },
22
22
  "devDependencies": {
23
- "@easy-cms/plugin-nested-docs": "^0.47.2",
24
- "@easy-cms/db-sqlite": "^0.47.2",
25
- "@easy-cms/plugin-form-builder": "^0.47.2",
26
- "@easy-cms/plugin-redirects": "^0.47.2",
27
- "@easy-cms/core": "^0.47.2"
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"