@7365admin1/layer-common 4.1.0 → 4.1.1
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @iservice365/layer-common
|
|
2
2
|
|
|
3
|
+
## 4.1.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- df2fede: Fix the Service Providers gate: check the permission the estate actually stores
|
|
8
|
+
|
|
9
|
+
`useServiceProviderPermission` shipped in 4.0.3 asking for
|
|
10
|
+
`service-provider:<action>`. Measured read-only against the staging `roles`
|
|
11
|
+
collection on 2026-08-26, that spelling is held by **0 of 428 roles**, while
|
|
12
|
+
`service-provider-mgmt:add-service-provider`, `:invite-service-provider` and
|
|
13
|
+
`:view-service-providers` are held by **79 roles each**. Every role except the 71
|
|
14
|
+
holding `*` was refused, on any consumer that does not bind the three props.
|
|
15
|
+
|
|
16
|
+
The gate now checks `service-provider-mgmt` -- the canonical resource in
|
|
17
|
+
`constants/permissions.ts`, the one the server reads in
|
|
18
|
+
`notification-category.util.ts`, and the one `-property-management`'s own
|
|
19
|
+
`useLocalPermission` has always checked. The view gate accepts both
|
|
20
|
+
`view-service-providers` (what the 79 roles store today) and
|
|
21
|
+
`see-all-service-providers` (canonical), so no role migration is needed for this
|
|
22
|
+
fix to work and none is invalidated later.
|
|
23
|
+
|
|
24
|
+
No permission key is renamed or invented, and no role document changes.
|
|
25
|
+
|
|
3
26
|
## 4.1.0
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
|
@@ -290,11 +313,11 @@
|
|
|
290
313
|
`utils/console-tier.ts` + `composables/useConsoleTier.ts` mirror the server's
|
|
291
314
|
own rule from two endpoints the console already calls, unprojected:
|
|
292
315
|
|
|
293
|
-
|
|
294
|
-
|
|
316
|
+
GET /api/members/user/:user/app/admin the Seven365 staff membership
|
|
317
|
+
GET /api/roles/id/:role that membership's role document
|
|
295
318
|
|
|
296
|
-
|
|
297
|
-
|
|
319
|
+
owner = member.type === "admin" && role.type === "admin" && role.default === true
|
|
320
|
+
staff = member.type === "admin" && role.type === "admin"
|
|
298
321
|
|
|
299
322
|
`role.default` is the marker because it is the only property of a platform
|
|
300
323
|
staff role no API caller can set - `role.controller.ts` validates create and
|
|
@@ -3,26 +3,52 @@ import { useCommonPermissions } from "./useCommonPermission";
|
|
|
3
3
|
export function useServiceProviderPermission() {
|
|
4
4
|
const { hasPermission } = usePermission();
|
|
5
5
|
const { serviceProviderPermissions } = useCommonPermissions();
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
// The resource the estate actually stores. `constants/permissions.ts` settles
|
|
8
|
+
// `service-provider-mgmt` as canonical on rule 1 -- the server reads it at
|
|
9
|
+
// `core/utils/notification-category.util.ts:185` -- and it is what
|
|
10
|
+
// `-property-management`'s own `useLocalPermission` has always checked.
|
|
11
|
+
//
|
|
12
|
+
// This gate shipped asking for `service-provider:<action>` instead, a spelling
|
|
13
|
+
// that exists in no role document: on the staging role catalogue (428 roles)
|
|
14
|
+
// it is held by 0, so every role except the 71 holding `*` was refused. The
|
|
15
|
+
// strings below are held by 79 roles each.
|
|
16
|
+
const permissions: TPermissions = {
|
|
17
|
+
"service-provider-mgmt": {
|
|
18
|
+
...serviceProviderPermissions,
|
|
19
|
+
// `view-service-providers` is the spelling all 79 roles were granted;
|
|
20
|
+
// `see-all-service-providers` is canonical and nobody holds it yet. Both
|
|
21
|
+
// are accepted, so the gate is correct before AND after a role migration
|
|
22
|
+
// -- switching to the canonical string alone is what left pest-control's
|
|
23
|
+
// work-order gate stranding 92 roles. Recorded in
|
|
24
|
+
// `LEGACY_PERMISSION_ALIASES`.
|
|
25
|
+
"view-service-providers": serviceProviderPermissions["see-all-service-providers"],
|
|
26
|
+
},
|
|
27
|
+
};
|
|
7
28
|
|
|
8
29
|
const { userAppRole } = useLocalSetup();
|
|
9
30
|
|
|
31
|
+
// Every gate fails closed while the role is still resolving: `userAppRole` is
|
|
32
|
+
// null on the first tick and a null role must never read as "allowed".
|
|
10
33
|
const canAddServiceProvider = computed(() => {
|
|
11
34
|
if (!userAppRole.value) return false;
|
|
12
35
|
if (userAppRole.value.permissions.includes("*")) return true;
|
|
13
|
-
return hasPermission(userAppRole.value, permissions, "service-provider", "add-service-provider");
|
|
36
|
+
return hasPermission(userAppRole.value, permissions, "service-provider-mgmt", "add-service-provider");
|
|
14
37
|
});
|
|
15
38
|
|
|
16
39
|
const canInviteServiceProvider = computed(() => {
|
|
17
40
|
if (!userAppRole.value) return false;
|
|
18
41
|
if (userAppRole.value.permissions.includes("*")) return true;
|
|
19
|
-
return hasPermission(userAppRole.value, permissions, "service-provider", "invite-service-provider");
|
|
42
|
+
return hasPermission(userAppRole.value, permissions, "service-provider-mgmt", "invite-service-provider");
|
|
20
43
|
});
|
|
21
44
|
|
|
22
45
|
const canViewServiceProviders = computed(() => {
|
|
23
46
|
if (!userAppRole.value) return false;
|
|
24
47
|
if (userAppRole.value.permissions.includes("*")) return true;
|
|
25
|
-
return
|
|
48
|
+
return (
|
|
49
|
+
hasPermission(userAppRole.value, permissions, "service-provider-mgmt", "see-all-service-providers") ||
|
|
50
|
+
hasPermission(userAppRole.value, permissions, "service-provider-mgmt", "view-service-providers")
|
|
51
|
+
);
|
|
26
52
|
});
|
|
27
53
|
|
|
28
54
|
return {
|
package/constants/permissions.ts
CHANGED
|
@@ -592,16 +592,21 @@ export const LEGACY_PERMISSION_ALIASES: Readonly<
|
|
|
592
592
|
"roles-and-permissions:delete-role": "roles:delete-role",
|
|
593
593
|
|
|
594
594
|
// --- service providers ---
|
|
595
|
-
// Needed by:
|
|
596
|
-
// `-mgmt` the server's notification filter expects
|
|
595
|
+
// Needed by: layer-common 4.0.3 and 4.1.0, where `useServiceProviderPermission`
|
|
596
|
+
// dropped the `-mgmt` the server's notification filter expects and asked for a
|
|
597
|
+
// resource 0 of 428 roles hold. The composable checks `service-provider-mgmt`
|
|
598
|
+
// from 4.1.1 on; these three stay because both published versions are still
|
|
599
|
+
// installed across the estate.
|
|
597
600
|
"service-provider:see-all-service-providers":
|
|
598
601
|
"service-provider-mgmt:see-all-service-providers",
|
|
599
602
|
"service-provider:add-service-provider":
|
|
600
603
|
"service-provider-mgmt:add-service-provider",
|
|
601
604
|
"service-provider:invite-service-provider":
|
|
602
605
|
"service-provider-mgmt:invite-service-provider",
|
|
603
|
-
// Needed by: `-property-management
|
|
604
|
-
// `see-all-`.
|
|
606
|
+
// Needed by: `-property-management` AND `useServiceProviderPermission` in this
|
|
607
|
+
// package, which both say `view-` where the canonical spelling says `see-all-`.
|
|
608
|
+
// This is the spelling all 79 granted roles actually store, so it cannot be
|
|
609
|
+
// retired until those roles are migrated.
|
|
605
610
|
"service-provider-mgmt:view-service-providers":
|
|
606
611
|
"service-provider-mgmt:see-all-service-providers",
|
|
607
612
|
});
|
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.1.
|
|
5
|
+
"version": "4.1.1",
|
|
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.",
|