@7365admin1/layer-common 4.90.2-staging.487 → 4.90.2-staging.489
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.
|
@@ -88,13 +88,24 @@
|
|
|
88
88
|
persistent-hint
|
|
89
89
|
data-test="invite-fixed-site"
|
|
90
90
|
></v-text-field>
|
|
91
|
+
<!--
|
|
92
|
+
Several sites (owner request 2026-10-02): one invitation per
|
|
93
|
+
site, one e-mail. One role for all of them, so 2+ sites offer
|
|
94
|
+
organisation roles only (see `roleSiteFor`).
|
|
95
|
+
-->
|
|
91
96
|
<v-autocomplete
|
|
92
97
|
v-else
|
|
93
|
-
v-model="invite.
|
|
98
|
+
v-model="invite.sites"
|
|
94
99
|
:items="sites"
|
|
100
|
+
multiple
|
|
101
|
+
chips
|
|
102
|
+
closable-chips
|
|
95
103
|
class="filter-field"
|
|
96
104
|
density="comfortable"
|
|
97
|
-
:rules="[
|
|
105
|
+
:rules="[sitesRule]"
|
|
106
|
+
:hint="invite.sites.length > 1 ? severalSitesHint : ''"
|
|
107
|
+
:persistent-hint="invite.sites.length > 1"
|
|
108
|
+
data-test="invite-sites"
|
|
98
109
|
@update:model-value="handleUpdateSite"
|
|
99
110
|
></v-autocomplete>
|
|
100
111
|
</v-col>
|
|
@@ -163,6 +174,7 @@ import { useLocalSetup } from '../composables/useLocalSetup';
|
|
|
163
174
|
import useRole from '../composables/useRole';
|
|
164
175
|
import useSite from '../composables/useSite';
|
|
165
176
|
import { inviteRoleOptions } from '../utils/invite-role-options';
|
|
177
|
+
import { roleSiteFor } from '../utils/invite-sites';
|
|
166
178
|
import useUser from '../composables/useUser';
|
|
167
179
|
import useUtils from '../composables/useUtils';
|
|
168
180
|
|
|
@@ -276,6 +288,8 @@ const invite = ref<Record<string, any>>({
|
|
|
276
288
|
role: "",
|
|
277
289
|
org: "",
|
|
278
290
|
site: "",
|
|
291
|
+
// the sites picked in the Site field (several allowed); `site` follows it
|
|
292
|
+
sites: [] as string[],
|
|
279
293
|
siteName: "",
|
|
280
294
|
isMemberInvite: false,
|
|
281
295
|
});
|
|
@@ -501,9 +515,17 @@ watchEffect(() => {
|
|
|
501
515
|
|
|
502
516
|
const roleOptions = computed(() => inviteRoleOptions(roles.value));
|
|
503
517
|
|
|
518
|
+
const severalSitesHint =
|
|
519
|
+
"Several sites: pick an organisation role - it applies at each site. For a different role per site, invite one site at a time.";
|
|
520
|
+
|
|
521
|
+
const sitesRule = (v: string[]) =>
|
|
522
|
+
(Array.isArray(v) && v.length > 0) || "Pick at least one site";
|
|
523
|
+
|
|
504
524
|
const noRolesText = computed(() =>
|
|
505
525
|
rolesError?.value
|
|
506
526
|
? "The roles could not be loaded. You may not have access to this organisation's roles; refresh, or sign in again."
|
|
527
|
+
: !fixedSite.value && invite.value.sites.length > 1
|
|
528
|
+
? "No organisation roles for this service yet. Create one in Roles & Permissions (Roles for <service>, use at any site), or invite one site at a time."
|
|
507
529
|
: fixedSite.value
|
|
508
530
|
? "No roles have been created for this site yet. Create one in Roles & Permissions first."
|
|
509
531
|
: "No roles have been created yet. Create one in Roles & Permissions first."
|
|
@@ -525,6 +547,7 @@ const rolesPageLink = computed(() => {
|
|
|
525
547
|
async function handleUpdateApp(value: string) {
|
|
526
548
|
invite.value.role = "";
|
|
527
549
|
if (!fixedSite.value) {
|
|
550
|
+
invite.value.sites = [];
|
|
528
551
|
invite.value.site = "";
|
|
529
552
|
invite.value.siteName = "";
|
|
530
553
|
}
|
|
@@ -544,12 +567,16 @@ function resetInvite() {
|
|
|
544
567
|
invite.value.role = "";
|
|
545
568
|
// Same site as before: a fixed site stays fixed, a picked one is cleared.
|
|
546
569
|
invite.value.site = fixedSite.value;
|
|
570
|
+
invite.value.sites = [];
|
|
547
571
|
if (!invite.value.site) invite.value.siteName = "";
|
|
548
572
|
message.value = "";
|
|
549
573
|
}
|
|
550
574
|
|
|
551
|
-
function handleUpdateSite(
|
|
552
|
-
|
|
575
|
+
function handleUpdateSite(siteIds: string[]) {
|
|
576
|
+
// The roles list follows `site`: the one chosen site, or "" for several
|
|
577
|
+
// (organisation roles only); the role watch clears a role no longer offered.
|
|
578
|
+
invite.value.site = roleSiteFor(siteIds);
|
|
579
|
+
const obj = sites.value.find((x) => x?.value === invite.value.site);
|
|
553
580
|
invite.value.siteName = obj?.title || "";
|
|
554
581
|
}
|
|
555
582
|
|
|
@@ -262,7 +262,10 @@ const {
|
|
|
262
262
|
search: headerSearch.value,
|
|
263
263
|
// type: "user-invite,member-invite",
|
|
264
264
|
type: "member-invite",
|
|
265
|
-
|
|
265
|
+
// The org console (organization app, no site) lists every invitation of
|
|
266
|
+
// the organisation, including the site invitations sent from there
|
|
267
|
+
// (owner request 2026-10-02); the server's list scoping is unchanged.
|
|
268
|
+
app: props.app === "organization" && !props.siteId ? "" : props.app,
|
|
266
269
|
orgId: props.org,
|
|
267
270
|
// A site app lists only THIS site's invitations; the server checks the
|
|
268
271
|
// caller reaches it (owner report 2026-09-28: LakeGarden's invitations
|
package/composables/useUser.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { inviteSitePayload } from "../utils/invite-sites";
|
|
2
|
+
|
|
1
3
|
export default function useUser() {
|
|
2
4
|
function inviteUser({
|
|
3
5
|
email = "",
|
|
@@ -65,7 +67,10 @@ export default function useUser() {
|
|
|
65
67
|
org = "",
|
|
66
68
|
site = "",
|
|
67
69
|
siteName = "",
|
|
70
|
+
sites = [] as string[],
|
|
68
71
|
} = {}) {
|
|
72
|
+
// `sites` = the several chosen sites; the old single `site` still works.
|
|
73
|
+
const chosen = sites.length ? sites : site ? [site] : [];
|
|
69
74
|
return useNuxtApp().$api<Record<string, any>>("/api/auth/invite/member", {
|
|
70
75
|
method: "POST",
|
|
71
76
|
body: {
|
|
@@ -74,8 +79,7 @@ export default function useUser() {
|
|
|
74
79
|
role,
|
|
75
80
|
name,
|
|
76
81
|
org,
|
|
77
|
-
...(
|
|
78
|
-
...(siteName && { siteName }),
|
|
82
|
+
...inviteSitePayload(chosen, siteName),
|
|
79
83
|
},
|
|
80
84
|
});
|
|
81
85
|
}
|
package/middleware/01.auth.ts
CHANGED
|
@@ -4,13 +4,9 @@ export default defineNuxtRouteMiddleware(async (route) => {
|
|
|
4
4
|
// Get access token from cookies
|
|
5
5
|
const sid = useCookie("sid", cookieConfig).value;
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
if (serviceProviderEmail) {
|
|
11
|
-
useCookie("service-provider-email", cookieConfig).value =
|
|
12
|
-
serviceProviderEmail;
|
|
13
|
-
}
|
|
7
|
+
// No longer saves `?email=` as a browser-wide `service-provider-email` cookie
|
|
8
|
+
// (30 days): nothing reads it, and a leftover from another account sent the
|
|
9
|
+
// org app's sign-in to that account's create page.
|
|
14
10
|
|
|
15
11
|
if (!sid) {
|
|
16
12
|
// Redirect to login page if no access token
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@7365admin1/layer-common",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "4.90.2-staging.
|
|
5
|
+
"version": "4.90.2-staging.489",
|
|
6
6
|
"author": "7365admin1",
|
|
7
7
|
"main": "./nuxt.config.ts",
|
|
8
8
|
"//files": "What a consumer extending this layer actually loads. Without this npm ships the whole working tree - the changesets, the CI workflows, the render harness in tools/ and any scratch directory that happened to exist at publish time. Nuxt resolves a layer by directory, so every runtime directory below has to stay listed; adding a new top-level runtime directory means adding it here too.",
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Which sites an "Invite member" request names (owner request 2026-10-02:
|
|
3
|
+
* invite one person to several sites). One site keeps the old `siteId` shape;
|
|
4
|
+
* 2 or more send `siteIds` (the server writes one invitation per site and
|
|
5
|
+
* names every site in one e-mail).
|
|
6
|
+
*/
|
|
7
|
+
export function inviteSitePayload(
|
|
8
|
+
sites: string[],
|
|
9
|
+
siteName = "",
|
|
10
|
+
): Record<string, unknown> {
|
|
11
|
+
if (!sites.length) return {};
|
|
12
|
+
if (sites.length === 1) {
|
|
13
|
+
return { siteId: sites[0], ...(siteName && { siteName }) };
|
|
14
|
+
}
|
|
15
|
+
return { siteIds: sites };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* The one site a role is looked up for: the single chosen site, or "" for 2+
|
|
20
|
+
* (a site role is valid at its own site only, so several sites offer
|
|
21
|
+
* organisation roles only).
|
|
22
|
+
*/
|
|
23
|
+
export function roleSiteFor(sites: string[]): string {
|
|
24
|
+
return sites.length === 1 ? sites[0] : "";
|
|
25
|
+
}
|