domma-cms 0.2.1 → 0.5.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/README.md +3 -3
- package/admin/css/admin.css +1 -1200
- package/admin/dist/domma/domma-tools.css +2313 -0
- package/admin/dist/domma/domma-tools.min.js +10 -0
- package/admin/index.html +4 -0
- package/admin/js/api.js +1 -242
- package/admin/js/app.js +9 -279
- package/admin/js/config/sidebar-config.js +1 -115
- package/admin/js/lib/card.js +1 -63
- package/admin/js/lib/image-editor.js +1 -869
- package/admin/js/lib/markdown-toolbar.js +54 -421
- package/admin/js/templates/action-editor.html +171 -0
- package/admin/js/templates/actions-list.html +19 -0
- package/admin/js/templates/api-reference.html +1411 -0
- package/admin/js/templates/block-editor.html +158 -0
- package/admin/js/templates/blocks.html +8 -0
- package/admin/js/templates/collection-editor.html +47 -0
- package/admin/js/templates/collection-entries.html +3 -0
- package/admin/js/templates/collections.html +51 -4
- package/admin/js/templates/documentation.html +258 -0
- package/admin/js/templates/form-editor.html +238 -0
- package/{plugins/form-builder/admin → admin/js}/templates/form-submissions.html +30 -30
- package/{plugins/form-builder/admin/templates/forms-list.html → admin/js/templates/forms.html} +17 -17
- package/admin/js/templates/layouts.html +44 -7
- package/admin/js/templates/login.html +29 -4
- package/admin/js/templates/my-profile.html +17 -0
- package/admin/js/templates/page-editor.html +48 -0
- package/admin/js/templates/pages.html +6 -1
- package/admin/js/templates/pro-docs.html +259 -0
- package/admin/js/templates/role-editor.html +59 -0
- package/admin/js/templates/roles.html +10 -0
- package/admin/js/templates/settings.html +137 -18
- package/admin/js/templates/tutorials.html +81 -0
- package/admin/js/templates/user-editor.html +7 -0
- package/admin/js/templates/users.html +3 -1
- package/admin/js/templates/view-editor.html +201 -0
- package/admin/js/templates/view-preview.html +51 -0
- package/admin/js/templates/views-list.html +19 -0
- package/admin/js/views/action-editor.js +1 -0
- package/admin/js/views/actions-list.js +1 -0
- package/admin/js/views/api-reference.js +1 -0
- package/admin/js/views/block-editor.js +8 -0
- package/admin/js/views/blocks.js +4 -0
- package/admin/js/views/collection-editor.js +3 -487
- package/admin/js/views/collection-entries.js +1 -484
- package/admin/js/views/collections.js +1 -153
- package/admin/js/views/dashboard.js +1 -56
- package/admin/js/views/documentation.js +1 -12
- package/admin/js/views/form-editor.js +8 -0
- package/admin/js/views/form-submissions.js +1 -0
- package/admin/js/views/forms.js +1 -0
- package/admin/js/views/index.js +1 -39
- package/admin/js/views/layouts.js +9 -42
- package/admin/js/views/login.js +7 -251
- package/admin/js/views/media.js +1 -240
- package/admin/js/views/my-profile.js +1 -0
- package/admin/js/views/navigation.js +14 -212
- package/admin/js/views/page-editor.js +72 -661
- package/admin/js/views/pages.js +5 -72
- package/admin/js/views/plugins.js +13 -90
- package/admin/js/views/pro-docs.js +1 -0
- package/admin/js/views/role-editor.js +1 -0
- package/admin/js/views/roles.js +4 -0
- package/admin/js/views/settings.js +3 -199
- package/admin/js/views/tutorials.js +1 -12
- package/admin/js/views/user-editor.js +1 -88
- package/admin/js/views/users.js +4 -76
- package/admin/js/views/view-editor.js +1 -0
- package/admin/js/views/view-preview.js +1 -0
- package/admin/js/views/views-list.js +1 -0
- package/bin/cli.js +1 -1
- package/config/auth.json +2 -17
- package/config/connections.json.bak +9 -0
- package/config/connections.json.example +9 -0
- package/config/navigation.json +15 -0
- package/config/plugins.json +19 -29
- package/config/server.json +6 -6
- package/config/site.json +17 -6
- package/package.json +24 -10
- package/plugins/domma-effects/public/celebrations/core/canvas.js +2 -104
- package/plugins/domma-effects/public/celebrations/core/particles.js +1 -144
- package/plugins/domma-effects/public/celebrations/core/physics.js +1 -166
- package/plugins/domma-effects/public/celebrations/index.js +1 -535
- package/plugins/domma-effects/public/celebrations/themes/christmas.js +1 -1805
- package/plugins/domma-effects/public/celebrations/themes/guy-fawkes.js +1 -1477
- package/plugins/domma-effects/public/celebrations/themes/halloween.js +1 -1837
- package/plugins/domma-effects/public/celebrations/themes/st-andrews.js +1 -1175
- package/plugins/domma-effects/public/celebrations/themes/st-davids.js +1 -1258
- package/plugins/domma-effects/public/celebrations/themes/st-georges.js +1 -1754
- package/plugins/domma-effects/public/celebrations/themes/st-patricks.js +1 -1290
- package/plugins/domma-effects/public/celebrations/themes/valentines.js +1 -1361
- package/plugins/example-analytics/stats.json +21 -12
- package/plugins/theme-roller/admin/templates/theme-roller.html +71 -0
- package/plugins/theme-roller/admin/views/theme-roller-view.js +403 -0
- package/plugins/theme-roller/config.js +1 -0
- package/plugins/theme-roller/plugin.js +233 -0
- package/plugins/theme-roller/plugin.json +31 -0
- package/plugins/theme-roller/public/active-theme.css +0 -0
- package/plugins/theme-roller/public/inject-head-late.html +1 -0
- package/public/css/forms.css +1 -0
- package/public/css/site.css +1 -302
- package/public/js/btt.js +1 -90
- package/public/js/cookie-consent.js +1 -61
- package/public/js/form-logic-engine.js +1 -0
- package/public/js/forms.js +1 -0
- package/public/js/site.js +1 -204
- package/scripts/build.js +194 -129
- package/scripts/pro.js +254 -0
- package/scripts/reset.js +33 -8
- package/scripts/seed.js +343 -78
- package/scripts/setup.js +5 -4
- package/server/middleware/auth.js +136 -97
- package/server/routes/api/actions.js +200 -0
- package/server/routes/api/auth.js +292 -116
- package/server/routes/api/blocks.js +84 -0
- package/server/routes/api/collections.js +88 -23
- package/{plugins/form-builder/plugin.js → server/routes/api/forms.js} +483 -505
- package/server/routes/api/layouts.js +49 -25
- package/server/routes/api/media.js +118 -93
- package/server/routes/api/navigation.js +40 -37
- package/server/routes/api/pages.js +132 -118
- package/server/routes/api/plugins.js +6 -3
- package/server/routes/api/settings.js +104 -89
- package/server/routes/api/users.js +27 -21
- package/server/routes/api/views.js +148 -0
- package/server/routes/public.js +124 -108
- package/server/server.js +269 -173
- package/server/services/actions.js +387 -0
- package/server/services/adapterRegistry.js +98 -0
- package/server/services/adapters/FileAdapter.js +192 -0
- package/server/services/adapters/MongoAdapter.js +220 -0
- package/server/services/blocks.js +162 -0
- package/server/services/collections.js +74 -86
- package/server/services/connectionManager.js +102 -0
- package/server/services/content.js +312 -307
- package/{plugins/form-builder → server/services}/email.js +126 -103
- package/server/services/forms.js +173 -0
- package/server/services/markdown.js +1378 -648
- package/server/services/permissionRegistry.js +173 -0
- package/server/services/presetCollections.js +251 -0
- package/server/services/renderer.js +75 -1
- package/server/services/roles.js +227 -0
- package/server/services/rowAccess.js +104 -0
- package/server/services/userProfiles.js +199 -0
- package/server/services/users.js +281 -212
- package/server/services/views.js +280 -0
- package/server/templates/page.html +119 -113
- package/plugins/form-builder/admin/templates/form-editor.html +0 -171
- package/plugins/form-builder/admin/templates/form-settings.html +0 -29
- package/plugins/form-builder/admin/views/form-editor.js +0 -1442
- package/plugins/form-builder/admin/views/form-settings.js +0 -38
- package/plugins/form-builder/admin/views/form-submissions.js +0 -295
- package/plugins/form-builder/admin/views/forms-list.js +0 -164
- package/plugins/form-builder/config.js +0 -9
- package/plugins/form-builder/data/forms/consent.json +0 -104
- package/plugins/form-builder/data/forms/contact-details.json +0 -63
- package/plugins/form-builder/data/forms/contacts.json +0 -66
- package/plugins/form-builder/data/submissions/consent.json +0 -13
- package/plugins/form-builder/data/submissions/contact-details.json +0 -1
- package/plugins/form-builder/data/submissions/contacts.json +0 -26
- package/plugins/form-builder/plugin.json +0 -52
- package/plugins/form-builder/public/form-logic-engine.js +0 -568
- package/plugins/form-builder/public/inject-body.html +0 -352
- package/plugins/form-builder/public/inject-head.html +0 -58
- package/plugins/form-builder/public/package.json +0 -1
- package/scripts/copy-domma.js +0 -48
package/server/routes/public.js
CHANGED
|
@@ -1,108 +1,124 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Public Site Routes
|
|
3
|
-
* Catch-all that resolves URL paths to Markdown pages and renders them server-side.
|
|
4
|
-
* Draft pages are not served publicly.
|
|
5
|
-
* The admin panel is excluded (handled by static serving).
|
|
6
|
-
*/
|
|
7
|
-
import {getPage} from '../services/content.js';
|
|
8
|
-
import {renderPage} from '../services/renderer.js';
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
<
|
|
107
|
-
</
|
|
108
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Public Site Routes
|
|
3
|
+
* Catch-all that resolves URL paths to Markdown pages and renders them server-side.
|
|
4
|
+
* Draft pages are not served publicly.
|
|
5
|
+
* The admin panel is excluded (handled by static serving).
|
|
6
|
+
*/
|
|
7
|
+
import {getPage} from '../services/content.js';
|
|
8
|
+
import {renderPage} from '../services/renderer.js';
|
|
9
|
+
import {getRoleLevel} from '../services/roles.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Escape user-controlled strings before interpolating into HTML.
|
|
13
|
+
* Prevents reflected XSS in error pages.
|
|
14
|
+
*
|
|
15
|
+
* @param {string} str
|
|
16
|
+
* @returns {string}
|
|
17
|
+
*/
|
|
18
|
+
function escapeHtml(str) {
|
|
19
|
+
return String(str)
|
|
20
|
+
.replace(/&/g, '&')
|
|
21
|
+
.replace(/</g, '<')
|
|
22
|
+
.replace(/>/g, '>')
|
|
23
|
+
.replace(/"/g, '"')
|
|
24
|
+
.replace(/'/g, ''');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function publicRoutes(fastify) {
|
|
28
|
+
// Admin panel: serve index.html for all /admin/* paths (SPA fallback)
|
|
29
|
+
fastify.get('/admin', async (request, reply) => {
|
|
30
|
+
return reply.redirect('/admin/');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// Health check
|
|
34
|
+
fastify.get('/api/health', async () => ({ status: 'ok' }));
|
|
35
|
+
|
|
36
|
+
// Public pages catch-all
|
|
37
|
+
fastify.get('/*', async (request, reply) => {
|
|
38
|
+
const rawPath = request.params['*'];
|
|
39
|
+
|
|
40
|
+
// Skip non-page paths (assets handled by static plugin)
|
|
41
|
+
if (rawPath.includes('.')) {
|
|
42
|
+
return reply.callNotFound();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const urlPath = '/' + (rawPath || '');
|
|
46
|
+
|
|
47
|
+
// Try exact path first, then with /index suffix for directory-style URLs
|
|
48
|
+
let page = await getPage(urlPath);
|
|
49
|
+
|
|
50
|
+
// Try fetching index of a directory path
|
|
51
|
+
if (!page && !urlPath.endsWith('/index')) {
|
|
52
|
+
page = await getPage(urlPath.replace(/\/$/, '') || '/');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (!page) {
|
|
56
|
+
reply.status(404);
|
|
57
|
+
return reply.type('text/html').send(await render404(urlPath));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Don't serve draft pages publicly
|
|
61
|
+
if (page.status !== 'published') {
|
|
62
|
+
reply.status(404);
|
|
63
|
+
return reply.type('text/html').send(await render404(urlPath));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Enforce page visibility
|
|
67
|
+
if (page.visibility && page.visibility !== 'public') {
|
|
68
|
+
let userRole = null;
|
|
69
|
+
try {
|
|
70
|
+
const decoded = await request.jwtVerify();
|
|
71
|
+
userRole = decoded.role;
|
|
72
|
+
} catch { /* no token — treat as unauthenticated */
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const userLevel = getRoleLevel(userRole);
|
|
76
|
+
const visibilityLevel = getRoleLevel(page.visibility);
|
|
77
|
+
const requiredLevel = visibilityLevel === Infinity ? 0 : visibilityLevel;
|
|
78
|
+
|
|
79
|
+
if (userLevel > requiredLevel) {
|
|
80
|
+
reply.status(403);
|
|
81
|
+
return reply.type('text/html').send(accessDeniedHtml(urlPath));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const html = await renderPage(page);
|
|
86
|
+
return reply.type('text/html').send(html);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Render a 404 response — tries content/pages/404.md first, falls back to
|
|
92
|
+
* a minimal inline page so the site theme is applied when possible.
|
|
93
|
+
*/
|
|
94
|
+
async function render404(urlPath) {
|
|
95
|
+
try {
|
|
96
|
+
const page404 = await getPage('/404');
|
|
97
|
+
if (page404 && page404.status === 'published') {
|
|
98
|
+
return await renderPage(page404);
|
|
99
|
+
}
|
|
100
|
+
} catch { /* fall through */ }
|
|
101
|
+
return notFoundHtml(urlPath);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function accessDeniedHtml(urlPath) {
|
|
105
|
+
return `<!DOCTYPE html>
|
|
106
|
+
<html lang="en-GB">
|
|
107
|
+
<head><meta charset="UTF-8"><title>403 Access Denied</title>
|
|
108
|
+
<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#111;color:#eee;}
|
|
109
|
+
.box{text-align:center;} h1{font-size:6rem;margin:0;color:#666;} p{color:#999;}</style>
|
|
110
|
+
</head>
|
|
111
|
+
<body><div class="box"><h1>403</h1><p>You don't have permission to view <code>${escapeHtml(urlPath)}</code></p><p><a href="/" style="color:#aaa">Go home</a></p></div></body>
|
|
112
|
+
</html>`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function notFoundHtml(urlPath) {
|
|
116
|
+
return `<!DOCTYPE html>
|
|
117
|
+
<html lang="en-GB">
|
|
118
|
+
<head><meta charset="UTF-8"><title>404 Not Found</title>
|
|
119
|
+
<style>body{font-family:system-ui,sans-serif;display:flex;align-items:center;justify-content:center;min-height:100vh;margin:0;background:#111;color:#eee;}
|
|
120
|
+
.box{text-align:center;} h1{font-size:6rem;margin:0;color:#666;} p{color:#999;}</style>
|
|
121
|
+
</head>
|
|
122
|
+
<body><div class="box"><h1>404</h1><p>No page found at <code>${escapeHtml(urlPath)}</code></p><p><a href="/" style="color:#aaa">Go home</a></p></div></body>
|
|
123
|
+
</html>`;
|
|
124
|
+
}
|