@kernhq/module-quire 0.2.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/LICENSE +662 -0
- package/README.md +71 -0
- package/dist/client/rank.d.ts +42 -0
- package/dist/client/rank.d.ts.map +1 -0
- package/dist/client/rank.js +97 -0
- package/dist/client/rank.js.map +1 -0
- package/dist/contract/capabilities.d.ts +35 -0
- package/dist/contract/capabilities.d.ts.map +1 -0
- package/dist/contract/capabilities.js +35 -0
- package/dist/contract/capabilities.js.map +1 -0
- package/dist/contract/events.d.ts +58 -0
- package/dist/contract/events.d.ts.map +1 -0
- package/dist/contract/events.js +18 -0
- package/dist/contract/events.js.map +1 -0
- package/dist/contract/index.d.ts +6 -0
- package/dist/contract/index.d.ts.map +1 -0
- package/dist/contract/index.js +6 -0
- package/dist/contract/index.js.map +1 -0
- package/dist/contract/models.d.ts +95 -0
- package/dist/contract/models.d.ts.map +1 -0
- package/dist/contract/models.js +82 -0
- package/dist/contract/models.js.map +1 -0
- package/dist/contract/permissions.d.ts +51 -0
- package/dist/contract/permissions.d.ts.map +1 -0
- package/dist/contract/permissions.js +59 -0
- package/dist/contract/permissions.js.map +1 -0
- package/dist/contract/router.d.ts +713 -0
- package/dist/contract/router.d.ts.map +1 -0
- package/dist/contract/router.js +109 -0
- package/dist/contract/router.js.map +1 -0
- package/dist/server/_impl.d.ts +815 -0
- package/dist/server/_impl.d.ts.map +1 -0
- package/dist/server/_impl.js +189 -0
- package/dist/server/_impl.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +87 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/schema.d.ts +540 -0
- package/dist/server/schema.d.ts.map +1 -0
- package/dist/server/schema.js +86 -0
- package/dist/server/schema.js.map +1 -0
- package/dist/server/services/access.d.ts +78 -0
- package/dist/server/services/access.d.ts.map +1 -0
- package/dist/server/services/access.js +96 -0
- package/dist/server/services/access.js.map +1 -0
- package/dist/server/services/index.d.ts +15 -0
- package/dist/server/services/index.d.ts.map +1 -0
- package/dist/server/services/index.js +22 -0
- package/dist/server/services/index.js.map +1 -0
- package/dist/server/services/pages.d.ts +190 -0
- package/dist/server/services/pages.d.ts.map +1 -0
- package/dist/server/services/pages.js +242 -0
- package/dist/server/services/pages.js.map +1 -0
- package/dist/server/services/spaces.d.ts +95 -0
- package/dist/server/services/spaces.d.ts.map +1 -0
- package/dist/server/services/spaces.js +100 -0
- package/dist/server/services/spaces.js.map +1 -0
- package/migrations/0000_init.sql +43 -0
- package/migrations/0001_rls.sql +17 -0
- package/migrations/meta/0000_snapshot.json +358 -0
- package/migrations/meta/_journal.json +20 -0
- package/package.json +78 -0
- package/src/client/index.ts +67 -0
- package/src/client/rank.test.ts +92 -0
- package/src/client/rank.ts +100 -0
- package/src/contract/capabilities.ts +36 -0
- package/src/contract/events.ts +22 -0
- package/src/contract/index.ts +5 -0
- package/src/contract/models.ts +93 -0
- package/src/contract/permissions.ts +59 -0
- package/src/contract/router.ts +121 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_impl.d.ts","sourceRoot":"","sources":["../../src/server/_impl.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,KAAK,MAAM,EACX,cAAc,EACd,KAAK,cAAc,EAGpB,MAAM,gBAAgB,CAAA;AAMvB;;;;;;;GAOG;AACH,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,cAAc,EAAE,CAAA;AAI3D,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+RxC"}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { defineModule, defineServerModule, packageVersion, requires, workspaceScoped, } from '@kernhq/kernel';
|
|
2
|
+
import { implement } from '@orpc/server';
|
|
3
|
+
import { MODULE_ID, quireContract, quireEvents } from '../contract/index.js';
|
|
4
|
+
import { quireServices } from './services/index.js';
|
|
5
|
+
import { documentNameOf } from './services/pages.js';
|
|
6
|
+
/**
|
|
7
|
+
* The router, kept apart from `index.ts` so `module.test.ts` can walk it without booting a kernel.
|
|
8
|
+
*
|
|
9
|
+
* It is deliberately thin: open the workspace-bound transaction, check the space- or page-scoped
|
|
10
|
+
* permission, hand over to a service. `requires` on each procedure is the workspace-level gate — the
|
|
11
|
+
* narrower question ("may you read *this* page") needs the page's ancestor chain, which only exists
|
|
12
|
+
* inside the transaction, so it is asked in the handler through `svc.access`.
|
|
13
|
+
*/
|
|
14
|
+
export { defineModule, defineServerModule, packageVersion };
|
|
15
|
+
const os = implement(quireContract).$context();
|
|
16
|
+
export function implement_(kernel) {
|
|
17
|
+
const scoped = os.use(workspaceScoped(MODULE_ID));
|
|
18
|
+
const svc = quireServices(kernel);
|
|
19
|
+
const run = (context, workspaceId, fn) => kernel.database.withWorkspace(workspaceId, fn, { userId: context.principal.userId });
|
|
20
|
+
/** Both, every time: the event for anything that reacts later, the change for a screen open now. */
|
|
21
|
+
const announce = async (workspaceId, actorId, entity, id, op, scope) => {
|
|
22
|
+
await kernel.realtime.change(workspaceId, { module: MODULE_ID, entity, id, op, scope });
|
|
23
|
+
void actorId;
|
|
24
|
+
};
|
|
25
|
+
return os.router({
|
|
26
|
+
spaces: {
|
|
27
|
+
list: scoped.spaces.list
|
|
28
|
+
.use(requires('quire.space.view'))
|
|
29
|
+
.handler(({ input, context }) => run(context, input.workspaceId, (tx) => svc.spaces.list(tx, context.principal, input.workspaceId, input.includeArchived))),
|
|
30
|
+
get: scoped.spaces.get
|
|
31
|
+
.use(requires('quire.space.view'))
|
|
32
|
+
.handler(({ input, context }) => run(context, input.workspaceId, (tx) => svc.spaces.get(tx, context.principal, input.workspaceId, input.spaceId))),
|
|
33
|
+
create: scoped.spaces.create.use(requires('quire.space.manage')).handler(async ({ input, context }) => {
|
|
34
|
+
const space = await run(context, input.workspaceId, (tx) => svc.spaces.create(tx, context.principal, input.workspaceId, input));
|
|
35
|
+
await kernel.emit(quireEvents.spaceCreated, { spaceId: space.id, workspaceId: input.workspaceId }, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
36
|
+
await announce(input.workspaceId, context.principal.userId, 'space', space.id, 'created');
|
|
37
|
+
return space;
|
|
38
|
+
}),
|
|
39
|
+
update: scoped.spaces.update.use(requires('quire.space.manage')).handler(async ({ input, context }) => {
|
|
40
|
+
const { workspaceId, spaceId, ...patch } = input;
|
|
41
|
+
const space = await run(context, workspaceId, async (tx) => {
|
|
42
|
+
await svc.access.spaceRow(tx, workspaceId, spaceId);
|
|
43
|
+
await svc.access.requireSpace(context.principal, 'quire.space.manage', workspaceId, spaceId);
|
|
44
|
+
return svc.spaces.update(tx, workspaceId, spaceId, patch);
|
|
45
|
+
});
|
|
46
|
+
await kernel.emit(quireEvents.spaceUpdated, { spaceId, workspaceId }, { workspaceId, actorId: context.principal.userId });
|
|
47
|
+
await announce(workspaceId, context.principal.userId, 'space', spaceId, 'updated');
|
|
48
|
+
return space;
|
|
49
|
+
}),
|
|
50
|
+
archive: scoped.spaces.archive
|
|
51
|
+
.use(requires('quire.space.manage'))
|
|
52
|
+
.handler(async ({ input, context }) => {
|
|
53
|
+
const space = await run(context, input.workspaceId, async (tx) => {
|
|
54
|
+
await svc.access.spaceRow(tx, input.workspaceId, input.spaceId);
|
|
55
|
+
await svc.access.requireSpace(context.principal, 'quire.space.manage', input.workspaceId, input.spaceId);
|
|
56
|
+
return svc.spaces.archive(tx, input.workspaceId, input.spaceId, input.archived);
|
|
57
|
+
});
|
|
58
|
+
await kernel.emit(quireEvents.spaceArchived, { spaceId: input.spaceId, workspaceId: input.workspaceId, archived: input.archived }, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
59
|
+
await announce(input.workspaceId, context.principal.userId, 'space', input.spaceId, 'updated');
|
|
60
|
+
return space;
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
pages: {
|
|
64
|
+
tree: scoped.pages.tree.use(requires('quire.page.view')).handler(({ input, context }) => run(context, input.workspaceId, async (tx) => {
|
|
65
|
+
await svc.access.spaceRow(tx, input.workspaceId, input.spaceId);
|
|
66
|
+
await svc.access.requireSpace(context.principal, 'quire.page.view', input.workspaceId, input.spaceId);
|
|
67
|
+
return svc.pages.tree(tx, input.workspaceId, input.spaceId, input.includeArchived);
|
|
68
|
+
})),
|
|
69
|
+
get: scoped.pages.get.use(requires('quire.page.view')).handler(({ input, context }) => run(context, input.workspaceId, async (tx) => {
|
|
70
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.pageId);
|
|
71
|
+
await svc.access.requirePage(context.principal, 'quire.page.view', input.workspaceId, scope);
|
|
72
|
+
return svc.pages.get(tx, input.workspaceId, input.pageId);
|
|
73
|
+
})),
|
|
74
|
+
trash: scoped.pages.trash.use(requires('quire.page.view')).handler(({ input, context }) => run(context, input.workspaceId, async (tx) => {
|
|
75
|
+
await svc.access.spaceRow(tx, input.workspaceId, input.spaceId);
|
|
76
|
+
await svc.access.requireSpace(context.principal, 'quire.page.edit', input.workspaceId, input.spaceId);
|
|
77
|
+
return svc.pages.trash(tx, input.workspaceId, input.spaceId, input.limit, input.cursor ?? null);
|
|
78
|
+
})),
|
|
79
|
+
create: scoped.pages.create.use(requires('quire.page.create')).handler(async ({ input, context }) => {
|
|
80
|
+
const page = await run(context, input.workspaceId, async (tx) => {
|
|
81
|
+
await svc.access.spaceRow(tx, input.workspaceId, input.spaceId);
|
|
82
|
+
await svc.access.requireSpace(context.principal, 'quire.page.create', input.workspaceId, input.spaceId);
|
|
83
|
+
return svc.pages.create(tx, context.principal, input.workspaceId, input);
|
|
84
|
+
});
|
|
85
|
+
await kernel.emit(quireEvents.pageCreated, { pageId: page.id, spaceId: page.spaceId, workspaceId: input.workspaceId }, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
86
|
+
await announce(input.workspaceId, context.principal.userId, 'page', page.id, 'created', {
|
|
87
|
+
spaceId: page.spaceId,
|
|
88
|
+
});
|
|
89
|
+
return page;
|
|
90
|
+
}),
|
|
91
|
+
update: scoped.pages.update.use(requires('quire.page.edit')).handler(async ({ input, context }) => {
|
|
92
|
+
const { workspaceId, pageId, ...patch } = input;
|
|
93
|
+
const page = await run(context, workspaceId, async (tx) => {
|
|
94
|
+
const scope = await svc.access.scopeOf(tx, workspaceId, pageId);
|
|
95
|
+
await svc.access.requirePage(context.principal, 'quire.page.edit', workspaceId, scope);
|
|
96
|
+
return svc.pages.update(tx, context.principal, workspaceId, pageId, patch);
|
|
97
|
+
});
|
|
98
|
+
await kernel.emit(quireEvents.pageUpdated, { pageId, spaceId: page.spaceId, workspaceId }, { workspaceId, actorId: context.principal.userId });
|
|
99
|
+
await announce(workspaceId, context.principal.userId, 'page', pageId, 'updated', {
|
|
100
|
+
spaceId: page.spaceId,
|
|
101
|
+
});
|
|
102
|
+
return page;
|
|
103
|
+
}),
|
|
104
|
+
move: scoped.pages.move.use(requires('quire.page.edit')).handler(async ({ input, context }) => {
|
|
105
|
+
const page = await run(context, input.workspaceId, async (tx) => {
|
|
106
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.pageId);
|
|
107
|
+
await svc.access.requirePage(context.principal, 'quire.page.edit', input.workspaceId, scope);
|
|
108
|
+
return svc.pages.move(tx, context.principal, input.workspaceId, input.pageId, input.parentId, input.afterId);
|
|
109
|
+
});
|
|
110
|
+
await kernel.emit(quireEvents.pageMoved, {
|
|
111
|
+
pageId: page.id,
|
|
112
|
+
spaceId: page.spaceId,
|
|
113
|
+
workspaceId: input.workspaceId,
|
|
114
|
+
parentId: page.parentId,
|
|
115
|
+
}, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
116
|
+
await announce(input.workspaceId, context.principal.userId, 'page', page.id, 'updated', {
|
|
117
|
+
spaceId: page.spaceId,
|
|
118
|
+
});
|
|
119
|
+
return page;
|
|
120
|
+
}),
|
|
121
|
+
archive: scoped.pages.archive.use(requires('quire.page.edit')).handler(async ({ input, context }) => {
|
|
122
|
+
const page = await run(context, input.workspaceId, async (tx) => {
|
|
123
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.pageId);
|
|
124
|
+
await svc.access.requirePage(context.principal, 'quire.page.edit', input.workspaceId, scope);
|
|
125
|
+
return svc.pages.archive(tx, context.principal, input.workspaceId, input.pageId, input.archived);
|
|
126
|
+
});
|
|
127
|
+
await kernel.emit(quireEvents.pageArchived, {
|
|
128
|
+
pageId: page.id,
|
|
129
|
+
spaceId: page.spaceId,
|
|
130
|
+
workspaceId: input.workspaceId,
|
|
131
|
+
archived: input.archived,
|
|
132
|
+
}, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
133
|
+
await announce(input.workspaceId, context.principal.userId, 'page', page.id, 'updated', {
|
|
134
|
+
spaceId: page.spaceId,
|
|
135
|
+
});
|
|
136
|
+
return page;
|
|
137
|
+
}),
|
|
138
|
+
trashPage: scoped.pages.trashPage
|
|
139
|
+
.use(requires('quire.page.edit'))
|
|
140
|
+
.handler(async ({ input, context }) => {
|
|
141
|
+
const { ids, spaceId } = await run(context, input.workspaceId, async (tx) => {
|
|
142
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.pageId);
|
|
143
|
+
await svc.access.requirePage(context.principal, 'quire.page.edit', input.workspaceId, scope);
|
|
144
|
+
const res = await svc.pages.trashPage(tx, input.workspaceId, input.pageId);
|
|
145
|
+
return { ...res, spaceId: scope.spaceId };
|
|
146
|
+
});
|
|
147
|
+
await kernel.emit(quireEvents.pageTrashed, { pageId: input.pageId, spaceId, workspaceId: input.workspaceId, count: ids.length }, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
148
|
+
for (const id of ids)
|
|
149
|
+
await announce(input.workspaceId, context.principal.userId, 'page', id, 'updated', { spaceId });
|
|
150
|
+
return { ok: true, count: ids.length };
|
|
151
|
+
}),
|
|
152
|
+
restore: scoped.pages.restore.use(requires('quire.page.edit')).handler(async ({ input, context }) => {
|
|
153
|
+
const page = await run(context, input.workspaceId, async (tx) => {
|
|
154
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.pageId);
|
|
155
|
+
await svc.access.requirePage(context.principal, 'quire.page.edit', input.workspaceId, scope);
|
|
156
|
+
return svc.pages.restore(tx, input.workspaceId, input.pageId);
|
|
157
|
+
});
|
|
158
|
+
await kernel.emit(quireEvents.pageRestored, { pageId: page.id, spaceId: page.spaceId, workspaceId: input.workspaceId }, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
159
|
+
await announce(input.workspaceId, context.principal.userId, 'page', page.id, 'updated', {
|
|
160
|
+
spaceId: page.spaceId,
|
|
161
|
+
});
|
|
162
|
+
return page;
|
|
163
|
+
}),
|
|
164
|
+
purge: scoped.pages.purge.use(requires('quire.page.delete')).handler(async ({ input, context }) => {
|
|
165
|
+
const { ids, spaceId } = await run(context, input.workspaceId, async (tx) => {
|
|
166
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.pageId);
|
|
167
|
+
await svc.access.requirePage(context.principal, 'quire.page.delete', input.workspaceId, scope);
|
|
168
|
+
const res = await svc.pages.purge(tx, input.workspaceId, input.pageId);
|
|
169
|
+
return { ...res, spaceId: scope.spaceId };
|
|
170
|
+
});
|
|
171
|
+
// Nothing else removes a collaborative document, so a purged page would otherwise keep its
|
|
172
|
+
// prose for ever. Best-effort: the rows are already gone, and a collab service that is
|
|
173
|
+
// briefly down must not turn a successful delete into an error.
|
|
174
|
+
for (const id of ids) {
|
|
175
|
+
await kernel
|
|
176
|
+
.call('collab.document.delete', {
|
|
177
|
+
name: documentNameOf({ workspaceId: input.workspaceId, id }),
|
|
178
|
+
})
|
|
179
|
+
.catch((err) => kernel.log.warn({ err: String(err), pageId: id }, 'could not forget the collab document'));
|
|
180
|
+
}
|
|
181
|
+
await kernel.emit(quireEvents.pageDeleted, { pageId: input.pageId, spaceId, workspaceId: input.workspaceId, pageIds: ids }, { workspaceId: input.workspaceId, actorId: context.principal.userId });
|
|
182
|
+
for (const id of ids)
|
|
183
|
+
await announce(input.workspaceId, context.principal.userId, 'page', id, 'deleted', { spaceId });
|
|
184
|
+
return { ok: true, count: ids.length };
|
|
185
|
+
}),
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=_impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_impl.js","sourceRoot":"","sources":["../../src/server/_impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,WAAW,2IAyEtB,CAAA;AAEF,eAAe,WAAW,CAAA"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { dirname, join } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { CollabAccess, CollabAccessInput } from '@kernhq/contracts';
|
|
4
|
+
import { KernError } from '@kernhq/kernel';
|
|
5
|
+
import { MODULE_ID, quireCapabilities, quireContract, quireEvents, quirePermissions, } from '../contract/index.js';
|
|
6
|
+
import { defineModule, defineServerModule, implement_, packageVersion } from './_impl.js';
|
|
7
|
+
import { schema } from './schema.js';
|
|
8
|
+
import { quireServices } from './services/index.js';
|
|
9
|
+
/** These procedures are reachable only from another Kern service, never from a browser. */
|
|
10
|
+
function requireService(principal) {
|
|
11
|
+
if (principal.kind !== 'service' && !principal.instanceAdmin)
|
|
12
|
+
throw KernError.forbidden();
|
|
13
|
+
}
|
|
14
|
+
export const quireModule = defineServerModule({
|
|
15
|
+
definition: defineModule({
|
|
16
|
+
id: MODULE_ID,
|
|
17
|
+
name: 'Quire',
|
|
18
|
+
version: packageVersion(import.meta.url),
|
|
19
|
+
description: 'Spaces, nested pages and documents a team writes together',
|
|
20
|
+
icon: 'book-open',
|
|
21
|
+
permissions: quirePermissions,
|
|
22
|
+
capabilities: quireCapabilities,
|
|
23
|
+
events: quireEvents,
|
|
24
|
+
/**
|
|
25
|
+
* A page is a first-class object elsewhere in Kern: it can be mentioned, linked, searched and —
|
|
26
|
+
* `channelable` — given its own conversation in chat.
|
|
27
|
+
*/
|
|
28
|
+
objectTypes: [
|
|
29
|
+
{ type: 'page', label: 'Page', icon: 'file-text', channelable: true },
|
|
30
|
+
{ type: 'space', label: 'Space', icon: 'book-open' },
|
|
31
|
+
],
|
|
32
|
+
}),
|
|
33
|
+
/** Attached so the developer panel can check the router against what was promised. */
|
|
34
|
+
contract: quireContract,
|
|
35
|
+
schema,
|
|
36
|
+
migrationsFolder: join(dirname(fileURLToPath(import.meta.url)), '../../migrations'),
|
|
37
|
+
router: implement_,
|
|
38
|
+
procedures: {
|
|
39
|
+
/**
|
|
40
|
+
* Whether a user may open a page's collaborative document.
|
|
41
|
+
*
|
|
42
|
+
* This is what the collab gateway calls before it accepts a WebSocket. The shapes come from
|
|
43
|
+
* `@kernhq/contracts` rather than being spelled out here: the gateway falls back to plain
|
|
44
|
+
* workspace membership when a module does not answer, so a signature that does not match fails
|
|
45
|
+
* silently and looks exactly like a module that works.
|
|
46
|
+
*/
|
|
47
|
+
'collab.access': {
|
|
48
|
+
input: CollabAccessInput,
|
|
49
|
+
output: CollabAccess,
|
|
50
|
+
handler: async (input, { kernel, principal }) => {
|
|
51
|
+
requireService(principal);
|
|
52
|
+
if (input.type !== 'page')
|
|
53
|
+
return { canRead: false, canWrite: false };
|
|
54
|
+
const svc = quireServices(kernel);
|
|
55
|
+
return kernel.database.withWorkspace(input.workspaceId, async (tx) => {
|
|
56
|
+
try {
|
|
57
|
+
const scope = await svc.access.scopeOf(tx, input.workspaceId, input.id);
|
|
58
|
+
// The gateway is a service acting for somebody else, so the subject's own memberships
|
|
59
|
+
// have to come from core rather than from the caller.
|
|
60
|
+
const subject = principal.userId === input.userId
|
|
61
|
+
? principal
|
|
62
|
+
: ((await kernel
|
|
63
|
+
.call('core.users.principal', { userId: input.userId })
|
|
64
|
+
.catch(() => null)) ?? {
|
|
65
|
+
...principal,
|
|
66
|
+
userId: input.userId,
|
|
67
|
+
instanceAdmin: false,
|
|
68
|
+
kind: 'user',
|
|
69
|
+
});
|
|
70
|
+
const canRead = await svc.access.canPage(subject, 'quire.page.view', input.workspaceId, scope);
|
|
71
|
+
const canWrite = canRead && (await svc.access.canPage(subject, 'quire.page.edit', input.workspaceId, scope));
|
|
72
|
+
return { canRead, canWrite };
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
// A page that is missing or forbidden means "no access"; anything else is a real failure
|
|
76
|
+
// and must not be flattened into a silent denial.
|
|
77
|
+
if (err instanceof KernError && (err.code === 'NOT_FOUND' || err.code === 'FORBIDDEN'))
|
|
78
|
+
return { canRead: false, canWrite: false };
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
export default quireModule;
|
|
87
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|