@meith/authorization 0.31.0 → 0.32.0

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meith/authorization",
3
- "version": "0.31.0",
3
+ "version": "0.32.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -19,6 +19,6 @@
19
19
  "access": "public"
20
20
  },
21
21
  "dependencies": {
22
- "@meith/core": "0.31.0"
22
+ "@meith/core": "0.32.0"
23
23
  }
24
24
  }
package/src/index.ts CHANGED
@@ -4,12 +4,20 @@ export type { AuthorizerOptions, BypassEvent } from './authorizer'
4
4
  export { Authorizer } from './authorizer'
5
5
  export { combineGroupValue, combinePermissionSets } from './combine'
6
6
  export {
7
+ buildFieldMatrix,
7
8
  buildPermissionMatrix,
8
9
  type CopyChange,
9
10
  type CopyPlan,
11
+ diffMatrixSubmission,
12
+ type FieldMatrixCell,
13
+ type FieldMatrixRow,
10
14
  type MatrixCell,
15
+ type MatrixColumn,
16
+ type MatrixGroupSubmission,
11
17
  type MatrixInput,
12
18
  type MatrixRow,
19
+ matrixCellName,
20
+ matrixColumns,
13
21
  planCopyToDescendants,
14
22
  readMatrixCell,
15
23
  } from './matrix-editor'
@@ -25,6 +25,50 @@ export interface MatrixInput {
25
25
  readonly overrides: readonly ForumOverride[]
26
26
  }
27
27
 
28
+ export interface MatrixColumn {
29
+ readonly groupId: number
30
+ readonly groupTitle: string
31
+ }
32
+
33
+ export interface FieldMatrixCell {
34
+ readonly groupId: number
35
+ readonly name: string
36
+ readonly stored: boolean | number | null
37
+ readonly control: string
38
+ readonly effective: boolean | number
39
+ readonly inheritedFrom: number | null
40
+ }
41
+
42
+ export interface FieldMatrixRow {
43
+ readonly key: string
44
+ readonly description: string
45
+ readonly kind: PermissionField['kind']
46
+ readonly cells: readonly FieldMatrixCell[]
47
+ }
48
+
49
+ export function matrixColumns(rows: readonly MatrixRow[]): readonly MatrixColumn[] {
50
+ return rows.map((row) => ({ groupId: row.groupId, groupTitle: row.groupTitle }))
51
+ }
52
+
53
+ export function buildFieldMatrix(rows: readonly MatrixRow[]): readonly FieldMatrixRow[] {
54
+ return FORUM_PERMISSION_FIELDS.map((field) => ({
55
+ key: field.key,
56
+ description: field.description,
57
+ kind: field.kind,
58
+ cells: rows.map((row) => {
59
+ const found = row.cells.find((cell) => cell.key === field.key)
60
+ return {
61
+ groupId: row.groupId,
62
+ name: matrixCellName(row.groupId, field.key),
63
+ stored: found?.stored ?? null,
64
+ control: found?.control ?? matrixCellValue({ kind: field.kind, stored: null }),
65
+ effective: found?.effective ?? false,
66
+ inheritedFrom: found?.inheritedFrom ?? null,
67
+ }
68
+ }),
69
+ }))
70
+ }
71
+
28
72
  function index(overrides: readonly ForumOverride[]): Map<string, ForumOverride> {
29
73
  const map = new Map<string, ForumOverride>()
30
74
  for (const override of overrides) map.set(`${override.forumId}:${override.groupId}`, override)
@@ -143,3 +187,36 @@ export function matrixCellValue(cell: Pick<MatrixCell, 'kind' | 'stored'>): stri
143
187
  if (cell.kind === 'numeric') return String(cell.stored)
144
188
  return cell.stored === true ? 'grant' : 'deny'
145
189
  }
190
+
191
+ export function matrixCellName(groupId: number, key: string): string {
192
+ return `${groupId}:${key}`
193
+ }
194
+
195
+ export interface MatrixGroupSubmission {
196
+ readonly groupId: number
197
+ readonly values: Readonly<Record<string, boolean | number | null>>
198
+ }
199
+
200
+ export function diffMatrixSubmission(
201
+ current: readonly ForumOverride[],
202
+ forumId: number,
203
+ submissions: readonly MatrixGroupSubmission[],
204
+ ): readonly MatrixGroupSubmission[] {
205
+ const byGroup = new Map(
206
+ current
207
+ .filter((override) => override.forumId === forumId)
208
+ .map((override) => [override.groupId, override.overrides]),
209
+ )
210
+
211
+ return submissions.filter((submission) => {
212
+ const stored = byGroup.get(submission.groupId) ?? {}
213
+ return FORUM_PERMISSION_FIELDS.some((field) => {
214
+ const before = (stored[field.key as keyof ForumPermissions] ?? null) as
215
+ | boolean
216
+ | number
217
+ | null
218
+ const after = submission.values[field.key] ?? null
219
+ return !Object.is(before, after)
220
+ })
221
+ })
222
+ }