@revealui/core 0.14.7 → 0.15.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.
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session cookie domain for a request host (GAP-343).
|
|
3
|
+
*
|
|
4
|
+
* Staging hosts always resolve to `staging.revealui.com` so a production
|
|
5
|
+
* `SESSION_COOKIE_DOMAIN` (for example `.revealui.com`) is not attached to
|
|
6
|
+
* the staging subtree. Every other host returns `configuredDomain` unchanged.
|
|
7
|
+
* This function does not read the environment and does not apply the
|
|
8
|
+
* production-only gate. Callers keep that gate.
|
|
9
|
+
*/
|
|
10
|
+
/** Cookie Domain attribute for the staging.revealui.com subtree. No leading dot. */
|
|
11
|
+
export declare const STAGING_SESSION_COOKIE_DOMAIN = "staging.revealui.com";
|
|
12
|
+
/**
|
|
13
|
+
* Hostname from a Host or X-Forwarded-Host value.
|
|
14
|
+
* Strips a scheme, path, trailing dot, and numeric port. Uses the first
|
|
15
|
+
* comma-separated entry. Returns null when nothing usable remains.
|
|
16
|
+
* String methods only (no regular expressions).
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizeRequestHost(raw: string | null | undefined): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* True for `staging.revealui.com` and any host under `*.staging.revealui.com`.
|
|
21
|
+
* Label-boundary match: `evilstaging.revealui.com` and
|
|
22
|
+
* `staging.revealui.com.evil.com` are not staging hosts.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isStagingRevealHost(requestHost: string | null | undefined): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Cookie Domain for this request.
|
|
27
|
+
*
|
|
28
|
+
* Staging hosts return `staging.revealui.com` even when `configuredDomain`
|
|
29
|
+
* is the production domain or unset. Every other host, including a missing
|
|
30
|
+
* host, returns `configuredDomain` exactly (including `undefined`).
|
|
31
|
+
*/
|
|
32
|
+
export declare function sessionCookieDomainForHost(requestHost: string | null | undefined, configuredDomain: string | undefined): string | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Public request host. Prefer `Host` so a client-supplied `X-Forwarded-Host`
|
|
35
|
+
* cannot override the host the platform already set. Fall back to
|
|
36
|
+
* `X-Forwarded-Host` only when `Host` is absent.
|
|
37
|
+
*/
|
|
38
|
+
export declare function requestHostFromHeaders(getHeader: (name: string) => string | null | undefined): string | null;
|
|
39
|
+
//# sourceMappingURL=session-cookie-domain.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-cookie-domain.d.ts","sourceRoot":"","sources":["../src/session-cookie-domain.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,oFAAoF;AACpF,eAAO,MAAM,6BAA6B,yBAAyB,CAAC;AAEpE;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CA0ClF;AAUD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAKnF;AAED;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EACtC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GACnC,MAAM,GAAG,SAAS,CAKpB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,GAAG,SAAS,GACrD,MAAM,GAAG,IAAI,CAMf"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session cookie domain for a request host (GAP-343).
|
|
3
|
+
*
|
|
4
|
+
* Staging hosts always resolve to `staging.revealui.com` so a production
|
|
5
|
+
* `SESSION_COOKIE_DOMAIN` (for example `.revealui.com`) is not attached to
|
|
6
|
+
* the staging subtree. Every other host returns `configuredDomain` unchanged.
|
|
7
|
+
* This function does not read the environment and does not apply the
|
|
8
|
+
* production-only gate. Callers keep that gate.
|
|
9
|
+
*/
|
|
10
|
+
/** Cookie Domain attribute for the staging.revealui.com subtree. No leading dot. */
|
|
11
|
+
export const STAGING_SESSION_COOKIE_DOMAIN = 'staging.revealui.com';
|
|
12
|
+
/**
|
|
13
|
+
* Hostname from a Host or X-Forwarded-Host value.
|
|
14
|
+
* Strips a scheme, path, trailing dot, and numeric port. Uses the first
|
|
15
|
+
* comma-separated entry. Returns null when nothing usable remains.
|
|
16
|
+
* String methods only (no regular expressions).
|
|
17
|
+
*/
|
|
18
|
+
export function normalizeRequestHost(raw) {
|
|
19
|
+
if (raw == null)
|
|
20
|
+
return null;
|
|
21
|
+
let value = raw.trim().toLowerCase();
|
|
22
|
+
if (value.length === 0)
|
|
23
|
+
return null;
|
|
24
|
+
const comma = value.indexOf(',');
|
|
25
|
+
if (comma !== -1) {
|
|
26
|
+
value = value.slice(0, comma).trim();
|
|
27
|
+
}
|
|
28
|
+
if (value.length === 0)
|
|
29
|
+
return null;
|
|
30
|
+
const scheme = value.indexOf('://');
|
|
31
|
+
if (scheme !== -1) {
|
|
32
|
+
value = value.slice(scheme + 3);
|
|
33
|
+
}
|
|
34
|
+
const slash = value.indexOf('/');
|
|
35
|
+
if (slash !== -1) {
|
|
36
|
+
value = value.slice(0, slash);
|
|
37
|
+
}
|
|
38
|
+
if (value.startsWith('[')) {
|
|
39
|
+
const end = value.indexOf(']');
|
|
40
|
+
if (end === -1)
|
|
41
|
+
return null;
|
|
42
|
+
const bracketed = value.slice(0, end + 1);
|
|
43
|
+
return bracketed.length > 2 ? bracketed : null;
|
|
44
|
+
}
|
|
45
|
+
const colon = value.lastIndexOf(':');
|
|
46
|
+
if (colon !== -1) {
|
|
47
|
+
const port = value.slice(colon + 1);
|
|
48
|
+
if (port.length > 0 && isAllDigits(port)) {
|
|
49
|
+
value = value.slice(0, colon);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (value.endsWith('.')) {
|
|
53
|
+
value = value.slice(0, -1);
|
|
54
|
+
}
|
|
55
|
+
if (value.length === 0)
|
|
56
|
+
return null;
|
|
57
|
+
return value;
|
|
58
|
+
}
|
|
59
|
+
function isAllDigits(value) {
|
|
60
|
+
for (let i = 0; i < value.length; i++) {
|
|
61
|
+
const code = value.charCodeAt(i);
|
|
62
|
+
if (code < 48 || code > 57)
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* True for `staging.revealui.com` and any host under `*.staging.revealui.com`.
|
|
69
|
+
* Label-boundary match: `evilstaging.revealui.com` and
|
|
70
|
+
* `staging.revealui.com.evil.com` are not staging hosts.
|
|
71
|
+
*/
|
|
72
|
+
export function isStagingRevealHost(requestHost) {
|
|
73
|
+
const host = normalizeRequestHost(requestHost);
|
|
74
|
+
if (!host)
|
|
75
|
+
return false;
|
|
76
|
+
if (host === STAGING_SESSION_COOKIE_DOMAIN)
|
|
77
|
+
return true;
|
|
78
|
+
return host.endsWith(`.${STAGING_SESSION_COOKIE_DOMAIN}`);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Cookie Domain for this request.
|
|
82
|
+
*
|
|
83
|
+
* Staging hosts return `staging.revealui.com` even when `configuredDomain`
|
|
84
|
+
* is the production domain or unset. Every other host, including a missing
|
|
85
|
+
* host, returns `configuredDomain` exactly (including `undefined`).
|
|
86
|
+
*/
|
|
87
|
+
export function sessionCookieDomainForHost(requestHost, configuredDomain) {
|
|
88
|
+
if (isStagingRevealHost(requestHost)) {
|
|
89
|
+
return STAGING_SESSION_COOKIE_DOMAIN;
|
|
90
|
+
}
|
|
91
|
+
return configuredDomain;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Public request host. Prefer `Host` so a client-supplied `X-Forwarded-Host`
|
|
95
|
+
* cannot override the host the platform already set. Fall back to
|
|
96
|
+
* `X-Forwarded-Host` only when `Host` is absent.
|
|
97
|
+
*/
|
|
98
|
+
export function requestHostFromHeaders(getHeader) {
|
|
99
|
+
const host = getHeader('host');
|
|
100
|
+
if (typeof host === 'string' && host.trim().length > 0)
|
|
101
|
+
return host;
|
|
102
|
+
const forwarded = getHeader('x-forwarded-host');
|
|
103
|
+
if (typeof forwarded === 'string' && forwarded.trim().length > 0)
|
|
104
|
+
return forwarded;
|
|
105
|
+
return null;
|
|
106
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "RevealUI's runtime engine — admin UI, REST API, auth, rich text, plugin system, and access control. The heart of the open-source platform.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"dependencies": {
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"pg": "^8.22.0",
|
|
24
24
|
"yjs": "^13.6.31",
|
|
25
25
|
"zod": "^4.4.3",
|
|
26
|
-
"@revealui/contracts": "0.
|
|
27
|
-
"@revealui/presentation": "0.14.
|
|
26
|
+
"@revealui/contracts": "0.12.0",
|
|
27
|
+
"@revealui/presentation": "0.14.8",
|
|
28
28
|
"@revealui/resilience": "0.2.4",
|
|
29
29
|
"@revealui/security": "0.8.2",
|
|
30
30
|
"@revealui/utils": "0.3.6"
|
|
@@ -66,6 +66,11 @@
|
|
|
66
66
|
"import": "./dist/deployment-mode.js",
|
|
67
67
|
"default": "./dist/deployment-mode.js"
|
|
68
68
|
},
|
|
69
|
+
"./session-cookie-domain": {
|
|
70
|
+
"types": "./dist/session-cookie-domain.d.ts",
|
|
71
|
+
"import": "./dist/session-cookie-domain.js",
|
|
72
|
+
"default": "./dist/session-cookie-domain.js"
|
|
73
|
+
},
|
|
69
74
|
"./margin-governor": {
|
|
70
75
|
"types": "./dist/margin-governor.d.ts",
|
|
71
76
|
"import": "./dist/margin-governor.js",
|