domma-cms 0.23.0 → 0.25.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/CLAUDE.md +14 -0
- package/admin/js/api.js +1 -1
- package/admin/js/app.js +4 -4
- package/admin/js/lib/crud-tutorial.js +1 -1
- package/admin/js/lib/project-context.js +1 -1
- package/admin/js/templates/api-endpoint-editor.html +120 -0
- package/admin/js/templates/api-endpoints.html +13 -0
- package/admin/js/templates/api-tokens.html +13 -0
- package/admin/js/templates/effects.html +752 -752
- package/admin/js/templates/form-submissions.html +30 -30
- package/admin/js/templates/forms.html +17 -17
- package/admin/js/templates/my-profile.html +17 -17
- package/admin/js/templates/role-editor.html +70 -70
- package/admin/js/templates/roles.html +10 -10
- package/admin/js/views/api-endpoint-editor.js +1 -0
- package/admin/js/views/api-endpoints.js +7 -0
- package/admin/js/views/api-tokens.js +8 -0
- package/admin/js/views/collection-editor.js +4 -4
- package/admin/js/views/index.js +1 -1
- package/admin/js/views/project-detail.js +1 -1
- package/admin/js/views/roles.js +1 -1
- package/bin/lib/config-merge.js +44 -44
- package/bin/update.js +547 -547
- package/config/menus/admin-sidebar.json +13 -1
- package/package.json +1 -1
- package/server/middleware/auth.js +253 -253
- package/server/routes/api/api-endpoints.js +96 -0
- package/server/routes/api/api-tokens.js +83 -0
- package/server/routes/api/auth.js +309 -309
- package/server/routes/api/collections.js +114 -17
- package/server/routes/api/endpoints-public.js +88 -0
- package/server/routes/api/navigation.js +42 -42
- package/server/routes/api/settings.js +141 -141
- package/server/routes/public.js +202 -202
- package/server/server.js +16 -1
- package/server/services/apiEndpoints.js +402 -0
- package/server/services/apiTokens.js +273 -0
- package/server/services/email.js +167 -167
- package/server/services/permissionRegistry.js +26 -0
- package/server/services/presetCollections.js +54 -0
- package/server/services/projects.js +18 -2
- package/server/services/roles.js +16 -0
- package/server/services/scaffolder.js +54 -1
- package/server/services/sidebar-migration.js +45 -0
- package/server/services/userProfiles.js +199 -199
- package/server/services/users.js +302 -302
- package/config/connections.json.bak +0 -9
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Tokens API
|
|
3
|
+
*
|
|
4
|
+
* GET /api/api-tokens — list tokens visible to the caller (sanitised; never the hash)
|
|
5
|
+
* POST /api/api-tokens — create; response carries the plaintext ONCE
|
|
6
|
+
* PUT /api/api-tokens/:id — rename, enable/disable, edit scopes/expiry
|
|
7
|
+
* DELETE /api/api-tokens/:id — revoke (immediate)
|
|
8
|
+
*
|
|
9
|
+
* Tokens are project-scoped artefacts: non-super-admin users with a
|
|
10
|
+
* `projects: []` access scope only see/manage tokens in their projects.
|
|
11
|
+
* Auth middlewares are accepted as DI options so tests can supply no-ops.
|
|
12
|
+
*/
|
|
13
|
+
import {
|
|
14
|
+
authenticate as defaultAuthenticate,
|
|
15
|
+
requirePermission as defaultRequirePermission
|
|
16
|
+
} from '../../middleware/auth.js';
|
|
17
|
+
import {
|
|
18
|
+
createToken,
|
|
19
|
+
getTokenSanitised,
|
|
20
|
+
listTokensSanitised,
|
|
21
|
+
revokeToken,
|
|
22
|
+
updateToken
|
|
23
|
+
} from '../../services/apiTokens.js';
|
|
24
|
+
import {canSeeArtefact} from '../../services/projects.js';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Register the api-tokens routes.
|
|
28
|
+
*
|
|
29
|
+
* @param {import('fastify').FastifyInstance} fastify
|
|
30
|
+
* @param {{authenticate?: Function, requirePermission?: Function}} [opts]
|
|
31
|
+
* @returns {Promise<void>}
|
|
32
|
+
*/
|
|
33
|
+
export async function apiTokensRoutes(fastify, opts = {}) {
|
|
34
|
+
const authenticate = opts.authenticate || defaultAuthenticate;
|
|
35
|
+
const requirePermission = opts.requirePermission || defaultRequirePermission;
|
|
36
|
+
|
|
37
|
+
const canRead = {preHandler: [authenticate, requirePermission('api-tokens', 'read')]};
|
|
38
|
+
const canCreate = {preHandler: [authenticate, requirePermission('api-tokens', 'create')]};
|
|
39
|
+
const canUpdate = {preHandler: [authenticate, requirePermission('api-tokens', 'update')]};
|
|
40
|
+
const canDelete = {preHandler: [authenticate, requirePermission('api-tokens', 'delete')]};
|
|
41
|
+
|
|
42
|
+
fastify.get('/api-tokens', canRead, async (request) => {
|
|
43
|
+
return listTokensSanitised(request.user);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
fastify.post('/api-tokens', canCreate, async (request, reply) => {
|
|
47
|
+
const {name, project, scopes, expiresAt} = request.body || {};
|
|
48
|
+
if (project && !canSeeArtefact(request.user, {meta: {project}})) {
|
|
49
|
+
return reply.status(403).send({error: 'Access denied for this project'});
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const creator = request.user?.name || request.user?.email || null;
|
|
53
|
+
const {entry, plaintext} = await createToken({name, project, scopes, expiresAt, createdBy: creator});
|
|
54
|
+
// The plaintext appears here and nowhere else — only the hash is stored.
|
|
55
|
+
return reply.status(201).send({token: entry, plaintext});
|
|
56
|
+
} catch (err) {
|
|
57
|
+
return reply.status(400).send({error: err.message});
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
fastify.put('/api-tokens/:id', canUpdate, async (request, reply) => {
|
|
62
|
+
const existing = await getTokenSanitised(request.params.id);
|
|
63
|
+
if (!existing) return reply.status(404).send({error: 'Token not found'});
|
|
64
|
+
if (!canSeeArtefact(request.user, {meta: {project: existing.project}})) {
|
|
65
|
+
return reply.status(403).send({error: 'Access denied for this project'});
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
return await updateToken(request.params.id, request.body || {});
|
|
69
|
+
} catch (err) {
|
|
70
|
+
return reply.status(400).send({error: err.message});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
fastify.delete('/api-tokens/:id', canDelete, async (request, reply) => {
|
|
75
|
+
const existing = await getTokenSanitised(request.params.id);
|
|
76
|
+
if (!existing) return reply.status(404).send({error: 'Token not found'});
|
|
77
|
+
if (!canSeeArtefact(request.user, {meta: {project: existing.project}})) {
|
|
78
|
+
return reply.status(403).send({error: 'Access denied for this project'});
|
|
79
|
+
}
|
|
80
|
+
await revokeToken(request.params.id);
|
|
81
|
+
return {success: true};
|
|
82
|
+
});
|
|
83
|
+
}
|