domma-cms 1.8.40 → 1.8.41
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/CHANGELOG.md +4 -0
- package/docs/DommaFeatures.md +1 -0
- package/docs/configuration.md +1 -0
- package/package.json +1 -1
- package/server/server.js +3 -2
- package/server/services/embedCsp.js +19 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.8.41] - 2026-10-23
|
|
4
|
+
|
|
5
|
+
- **A page can show images from another site.** `csp.imgHosts` in `config/server.json` adds hosts to the Content-Security-Policy's `img-src` (`imageSources()` in `server/services/embedCsp.js`, beside `connectSources()`; bare hostnames, https only). The policy allowed only the site's own images, so an `<img>` from anywhere else - a "Featured on" badge, say - was blocked.
|
|
6
|
+
|
|
3
7
|
## [1.8.40] - 2026-10-22
|
|
4
8
|
|
|
5
9
|
- **Every collection entry is in the page for robots.** An interactive collection or view now puts every entry in the page HTML for robots that run no JavaScript, also when it loads its pages from the server, up to 1,000 (was 200, and only the first page in server mode). A collection past 1,000 shows as a warning in the SEO audit.
|
package/docs/DommaFeatures.md
CHANGED
|
@@ -1334,6 +1334,7 @@ The four Tools below were plugins until 0.67.0 and are now part of the CMS. They
|
|
|
1334
1334
|
- **`TRUST_PROXY`** - Takes Fastify's own values: `loopback` (recommended behind Apache or the manager, and the default for new sites the manager creates), a list of addresses or CIDR ranges, or a hop count. `1` or `true` trusts every hop, which lets a visitor spoof their IP address.
|
|
1335
1335
|
Where: `server/services/network.js` - Since: 0.83.0.
|
|
1336
1336
|
- **Reading other sites from a page** - `csp.connectHosts` in `config/server.json` lets public pages fetch from the listed hosts (added to the CSP's `connect-src`, https only); domma-cms.com's Pricing page reads the Pro Tool prices from dcm this way.
|
|
1337
|
+
- **Showing images from other sites** - `csp.imgHosts` in `config/server.json` lets public pages show images from the listed hosts (added to the CSP's `img-src`, https only); without it only the site's own images load.
|
|
1337
1338
|
- **Public asset CORS** - `cors.publicPrefixes` in `config/server.json` adds `Access-Control-Allow-Origin: *` to GET and HEAD requests under the listed paths only, so other sites can import scripts or assets from them.
|
|
1338
1339
|
Where: `server/services/publicCors.js`.
|
|
1339
1340
|
- **Email service** - A Nodemailer transport built from the SMTP settings in `site.json`, used for form emails, password resets and notices. With no SMTP host set, mail goes to a throwaway Ethereal test inbox, which reports success but delivers to nobody. The CMS makes this visible in Settings, in health checks and with an "Email not set up" notification. New sites ship with an SMTP host, defaulting to a local mail server on port 25 or taken from the environment.
|
package/docs/configuration.md
CHANGED
|
@@ -27,6 +27,7 @@ Controls the HTTP server.
|
|
|
27
27
|
| `cors.origin` | boolean / string / string[] | `false` | Passed directly to `@fastify/cors`. `false` disables CORS. Set to `"*"` or a domain to allow cross-origin requests |
|
|
28
28
|
| `cors.publicPrefixes` | string[] | `[]` | Absolute path prefixes whose **GET and HEAD** responses carry `Access-Control-Allow-Origin: *`, so other origins can hot-link those assets. A module script is fetched in CORS mode, so this is what makes e.g. `/public/demos/` importable from elsewhere. `@fastify/cors` decides per origin and cannot express a path, hence the separate key. Reads only - it never widens a write, and it applies to listed prefixes only. A value that is not an absolute path is ignored |
|
|
29
29
|
| `csp.connectHosts` | string[] | `[]` | Other sites a public page may read from in the browser (`fetch`), added to the Content-Security-Policy's `connect-src` as `https://<host>`. The site itself and cdn.jsdelivr.net are always allowed. Bare hostnames only (`dcm.dommajs.org`); a scheme, path, port or wildcard is ignored. Read at boot, so restart after changing it |
|
|
30
|
+
| `csp.imgHosts` | string[] | `[]` | Other sites a public page may show images from (an `<img>` hosted elsewhere, such as a badge or partner logo), added to the Content-Security-Policy's `img-src` as `https://<host>`. The site itself, `data:` and `blob:` are always allowed; without this an image from another site is blocked - upload it to Media instead if you can. Bare hostnames only (`statics.startupbase.io`); a scheme, path, port or wildcard is ignored. Read at boot, so restart after changing it |
|
|
30
31
|
| `uploads.maxFileSize` | number | `10485760` (10 MB) | Maximum allowed upload size in bytes |
|
|
31
32
|
| `logging.level` | string | Log verbosity: `fatal`, `error`, `warn`, `info`, `debug`, `trace`, `silent`. Defaults to `info` in development, `warn` otherwise. `warn` hides 4xx responses and plugin `log.info` output, so a failed admin action leaves no trace - raise it to `info` if you need to diagnose one. Overridden by the `LOG_LEVEL` env var. |
|
|
32
33
|
| `restartOnPluginToggle` | boolean | `true` | Restart the server automatically when an admin enables or disables a plugin. See **Plugin toggles restart the server** below |
|
package/package.json
CHANGED
package/server/server.js
CHANGED
|
@@ -33,7 +33,7 @@ import * as cache from './services/cache/index.js';
|
|
|
33
33
|
import {parseTrustProxy} from './services/network.js';
|
|
34
34
|
import {requestSerializer} from './services/request-log.js';
|
|
35
35
|
import {rateLimitOptions} from './services/rate-limit.js';
|
|
36
|
-
import {connectSources, frameSources} from './services/embedCsp.js';
|
|
36
|
+
import {connectSources, frameSources, imageSources} from './services/embedCsp.js';
|
|
37
37
|
import {cspSources as gaSources} from './services/googleAnalytics.js';
|
|
38
38
|
|
|
39
39
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -128,7 +128,8 @@ await app.register(helmet, {
|
|
|
128
128
|
// (services/googleAnalytics.js) - a site without one keeps exactly this policy.
|
|
129
129
|
scriptSrc: ["'self'", "'unsafe-inline'", "'wasm-unsafe-eval'", 'https://cdn.jsdelivr.net', gaSources('script')],
|
|
130
130
|
styleSrc: ["'self'", "'unsafe-inline'", 'https://cdn.jsdelivr.net', 'https://fonts.googleapis.com'],
|
|
131
|
-
|
|
131
|
+
// config/server.json csp.imgHosts: other sites a page may show images from (services/embedCsp.js).
|
|
132
|
+
imgSrc: [...imageSources(serverConfig.csp?.imgHosts), gaSources('img')],
|
|
132
133
|
fontSrc: ["'self'", 'data:', 'https://fonts.gstatic.com'],
|
|
133
134
|
// config/server.json csp.connectHosts: other sites a page may read from (services/embedCsp.js).
|
|
134
135
|
connectSrc: [...connectSources(serverConfig.csp?.connectHosts), gaSources('connect')],
|
|
@@ -50,3 +50,22 @@ export function connectSources(connectHosts = []) {
|
|
|
50
50
|
.map(h => `https://${h}`);
|
|
51
51
|
return [...new Set([...ALWAYS_CONNECTED, ...extra])];
|
|
52
52
|
}
|
|
53
|
+
|
|
54
|
+
/** What a page may always show images from: the site itself, and inline/data and blob images. */
|
|
55
|
+
export const ALWAYS_IMAGED = ["'self'", 'data:', 'blob:'];
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The img-src: the site, data: and blob:, and every host in config/server.json `csp.imgHosts` - for a page
|
|
59
|
+
* that shows an image hosted elsewhere (a badge, a partner logo). Bare hostnames only, served over https;
|
|
60
|
+
* anything else is dropped. Read at boot, like connect-src.
|
|
61
|
+
*
|
|
62
|
+
* @param {string[]} imgHosts - config/server.json csp.imgHosts
|
|
63
|
+
* @returns {string[]} img-src sources
|
|
64
|
+
*/
|
|
65
|
+
export function imageSources(imgHosts = []) {
|
|
66
|
+
const extra = (Array.isArray(imgHosts) ? imgHosts : [])
|
|
67
|
+
.map(h => String(h).trim().toLowerCase())
|
|
68
|
+
.filter(h => HOST_RE.test(h))
|
|
69
|
+
.map(h => `https://${h}`);
|
|
70
|
+
return [...new Set([...ALWAYS_IMAGED, ...extra])];
|
|
71
|
+
}
|