@crombolo/core 0.13.2 → 0.14.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/package.json +1 -1
- package/src/content-types.ts +12 -0
- package/src/index.ts +1 -0
- package/src/permissions.ts +13 -0
- package/src/public-access.ts +41 -0
package/package.json
CHANGED
package/src/content-types.ts
CHANGED
|
@@ -36,8 +36,18 @@ export interface PropertyTypeModel {
|
|
|
36
36
|
* unchanged on a save, which is what a backoffice save sends.
|
|
37
37
|
*/
|
|
38
38
|
searchable?: boolean
|
|
39
|
+
/**
|
|
40
|
+
* How much the property counts in site search, or false to leave it out.
|
|
41
|
+
* Absent means unchanged on a save, as for `searchable`.
|
|
42
|
+
*/
|
|
43
|
+
siteSearch?: SiteSearchLevel | false
|
|
39
44
|
}
|
|
40
45
|
|
|
46
|
+
/** A property's weight in site search; the page name always ranks above all three. */
|
|
47
|
+
export type SiteSearchLevel = 'high' | 'normal' | 'low'
|
|
48
|
+
|
|
49
|
+
export const SITE_SEARCH_LEVELS: readonly SiteSearchLevel[] = ['high', 'normal', 'low']
|
|
50
|
+
|
|
41
51
|
export interface PropertyGroupModel {
|
|
42
52
|
key: string
|
|
43
53
|
name: string | null
|
|
@@ -89,6 +99,8 @@ export interface ContentTypeAggregate {
|
|
|
89
99
|
parentKey: string | null
|
|
90
100
|
sinceVersion?: string | null
|
|
91
101
|
pending?: { version: string; revision: string } | null
|
|
102
|
+
/** False leaves every page of the type out of site search. Absent means unchanged on a save. */
|
|
103
|
+
siteSearch?: boolean
|
|
92
104
|
}
|
|
93
105
|
|
|
94
106
|
/**
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ export * from './paging.ts'
|
|
|
10
10
|
export * from './permissions.ts'
|
|
11
11
|
export * from './problem-details.ts'
|
|
12
12
|
export * from './property-values.ts'
|
|
13
|
+
export * from './public-access.ts'
|
|
13
14
|
export * from './return-urls.ts'
|
|
14
15
|
export * from './sections.ts'
|
|
15
16
|
export * from './uploads.ts'
|
package/src/permissions.ts
CHANGED
|
@@ -54,6 +54,19 @@ export const FormPermissions = {
|
|
|
54
54
|
|
|
55
55
|
export type FormVerb = (typeof FormPermissions)[keyof typeof FormPermissions]
|
|
56
56
|
|
|
57
|
+
/**
|
|
58
|
+
* Sending and receiving whole sites through the remote protocol (story 107).
|
|
59
|
+
* A full pull carries people, and a push to a protected environment replaces
|
|
60
|
+
* something people rely on, so each is a grant of its own.
|
|
61
|
+
*/
|
|
62
|
+
export const RemotePermissions = {
|
|
63
|
+
Pull: 'Crombolo.Remote.Pull',
|
|
64
|
+
PullFull: 'Crombolo.Remote.PullFull',
|
|
65
|
+
Push: 'Crombolo.Remote.Push',
|
|
66
|
+
PushProtected: 'Crombolo.Remote.PushProtected',
|
|
67
|
+
} as const
|
|
68
|
+
export type RemoteVerb = (typeof RemotePermissions)[keyof typeof RemotePermissions]
|
|
69
|
+
|
|
57
70
|
/** The discriminator on a granular permission row. */
|
|
58
71
|
export type PermissionContext = 'Document' | 'Element' | 'DocumentTypeProperty'
|
|
59
72
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Members-only pages: who a protection rule lets in, and which protected
|
|
3
|
+
* branches that leaves a member — one check for rendering a page, the Delivery
|
|
4
|
+
* API and site search. The nearest protected ancestor governs, as in Umbraco.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/** Who a protected page lets in: members named by user name, or in a named group. */
|
|
8
|
+
export interface MemberRule {
|
|
9
|
+
memberUserNames: readonly string[]
|
|
10
|
+
memberGroupNames: readonly string[]
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** The member asking, by user name and the names of their groups. */
|
|
14
|
+
export interface RuleMember {
|
|
15
|
+
username: string
|
|
16
|
+
groups: readonly string[]
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/** Whether a rule lets a member in. Names and groups both match in any case. Pure. */
|
|
20
|
+
export function memberMayOpen(rule: MemberRule, member: RuleMember | undefined): boolean {
|
|
21
|
+
if (!member) return false
|
|
22
|
+
const name = member.username.toLowerCase()
|
|
23
|
+
if (rule.memberUserNames.some((n) => n.toLowerCase() === name)) return true
|
|
24
|
+
const groups = new Set(member.groups.map((g) => g.toLowerCase()))
|
|
25
|
+
return rule.memberGroupNames.some((g) => groups.has(g.toLowerCase()))
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The protected nodes a member may not open (`denied`) and may (`allowed`). A
|
|
30
|
+
* page is closed to them when the nearest protected node on its path is
|
|
31
|
+
* denied: a denied branch can hold an allowed one below it. Pure.
|
|
32
|
+
*/
|
|
33
|
+
export function branchAccess(
|
|
34
|
+
rules: ReadonlyArray<MemberRule & { nodeId: number }>,
|
|
35
|
+
member: RuleMember | undefined,
|
|
36
|
+
): { denied: number[]; allowed: number[] } {
|
|
37
|
+
const denied: number[] = []
|
|
38
|
+
const allowed: number[] = []
|
|
39
|
+
for (const rule of rules) (memberMayOpen(rule, member) ? allowed : denied).push(rule.nodeId)
|
|
40
|
+
return { denied, allowed }
|
|
41
|
+
}
|