@adobe/helix-html-pipeline 6.0.0 → 6.1.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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ # [6.1.0](https://github.com/adobe/helix-html-pipeline/compare/v6.0.1...v6.1.0) (2024-01-13)
2
+
3
+
4
+ ### Features
5
+
6
+ * export state decoding ([#489](https://github.com/adobe/helix-html-pipeline/issues/489)) ([dd60f81](https://github.com/adobe/helix-html-pipeline/commit/dd60f81e52e52652616edd67779f6e9098e50a1b))
7
+
8
+ ## [6.0.1](https://github.com/adobe/helix-html-pipeline/compare/v6.0.0...v6.0.1) (2024-01-11)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * enforce rso ([#488](https://github.com/adobe/helix-html-pipeline/issues/488)) ([4b38e25](https://github.com/adobe/helix-html-pipeline/commit/4b38e2524514a3d64a041d456bf14fe8b2e416cb))
14
+
1
15
  # [6.0.0](https://github.com/adobe/helix-html-pipeline/compare/v5.4.4...v6.0.0) (2024-01-10)
2
16
 
3
17
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adobe/helix-html-pipeline",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
4
4
  "description": "Helix HTML Pipeline",
5
5
  "main": "src/index.js",
6
6
  "types": "src/index.d.ts",
@@ -43,6 +43,8 @@ declare interface PipelineOptions {
43
43
  path: string;
44
44
  timer: PipelineTimer;
45
45
  env: object;
46
+ site: string;
47
+ org: string;
46
48
  }
47
49
 
48
50
  declare class PipelineState {
@@ -70,6 +72,16 @@ declare class PipelineState {
70
72
  */
71
73
  partition: string;
72
74
 
75
+ /**
76
+ * project site
77
+ */
78
+ site: string;
79
+
80
+ /**
81
+ * project org
82
+ */
83
+ org: string;
84
+
73
85
  /**
74
86
  * Repository owner
75
87
  */
@@ -31,6 +31,8 @@ export class PipelineState {
31
31
  config: opts.config,
32
32
  content: new PipelineContent(),
33
33
  contentBusId: opts.config.contentBusId,
34
+ site: opts.site,
35
+ org: opts.org,
34
36
  owner: opts.config.owner,
35
37
  repo: opts.config.repo,
36
38
  ref: opts.ref,
@@ -44,6 +46,11 @@ export class PipelineState {
44
46
  timer: opts.timer,
45
47
  type: 'html',
46
48
  });
49
+ for (const prop of ['org', 'site', 'contentBusId', 'repo', 'owner', 'ref', 'partition']) {
50
+ if (!this[prop]) {
51
+ throw new Error(`${prop} required`);
52
+ }
53
+ }
47
54
  }
48
55
 
49
56
  // eslint-disable-next-line class-methods-use-this
package/src/html-pipe.js CHANGED
@@ -36,7 +36,7 @@ import tohtml from './steps/stringify-response.js';
36
36
  import { PipelineStatusError } from './PipelineStatusError.js';
37
37
  import { PipelineResponse } from './PipelineResponse.js';
38
38
  import { validatePathInfo } from './utils/path.js';
39
- import { initAuthRoute } from './utils/auth.js';
39
+ import { getAuthInfo } from './utils/auth.js';
40
40
  import fetchMappedMetadata from './steps/fetch-mapped-metadata.js';
41
41
 
42
42
  /**
@@ -104,11 +104,18 @@ export async function htmlPipe(state, req) {
104
104
  },
105
105
  });
106
106
 
107
- // check if .auth request
108
- if (state.partition === '.auth' || state.info.path === '/.auth') {
109
- if (!await initAuthRoute(state, req, res)) {
110
- return res;
107
+ // check if `.auth` route to validate and exchange token
108
+ if (state.partition === '.auth') {
109
+ const authInfo = await getAuthInfo(state, req);
110
+ await authInfo.exchangeToken(state, req, res);
111
+ /* c8 ignore next */
112
+ const level = res.status >= 500 ? 'error' : 'info';
113
+ log[level](`pipeline status: ${res.status} ${res.error}`);
114
+ res.headers.set('x-error', cleanupHeaderValue(res.error));
115
+ if (res.status < 500) {
116
+ await setCustomResponseHeaders(state, req, res);
111
117
  }
118
+ return res;
112
119
  }
113
120
 
114
121
  try {
package/src/index.js CHANGED
@@ -17,3 +17,4 @@ export * from './PipelineRequest.js';
17
17
  export * from './PipelineResponse.js';
18
18
  export * from './PipelineState.js';
19
19
  export * from './PipelineStatusError.js';
20
+ export { validateAuthState } from './utils/auth.js';
@@ -36,13 +36,6 @@ export function isAllowed(email = '', allows = []) {
36
36
  * @returns {Promise<void>}
37
37
  */
38
38
  export async function authenticate(state, req, res) {
39
- // check if `.auth` route to validate and exchange token
40
- if (state.info.path === '/.auth') {
41
- const authInfo = await getAuthInfo(state, req);
42
- await authInfo.exchangeToken(state, req, res);
43
- return;
44
- }
45
-
46
39
  // get partition relative auth info
47
40
  const access = state.config.access?.[state.partition] || {
48
41
  allow: [],
@@ -24,10 +24,6 @@ export default async function fetchContent(state, req, res) {
24
24
  const {
25
25
  log, contentBusId, info, partition, owner, repo, ref,
26
26
  } = state;
27
- if (info.resourcePath === '/.auth') {
28
- return;
29
- }
30
-
31
27
  const isCode = state.content.sourceBus === 'code';
32
28
  const key = isCode
33
29
  ? `${owner}/${repo}/${ref}${info.resourcePath}`
package/src/utils/auth.js CHANGED
@@ -239,8 +239,9 @@ export class AuthInfo {
239
239
  const url = new URL(idp.discovery.authorization_endpoint);
240
240
 
241
241
  const tokenState = await signJWT(state, new SignJWT({
242
- owner: state.owner,
243
- repo: state.repo,
242
+ ref: state.ref,
243
+ org: state.org,
244
+ site: state.site,
244
245
  // this is our own login redirect, i.e. the current document
245
246
  requestPath: state.info.path,
246
247
  requestHost: host,
@@ -369,9 +370,8 @@ export class AuthInfo {
369
370
  }
370
371
  }
371
372
 
372
- export async function initAuthRoute(state, req, res) {
373
- const { log } = state;
374
-
373
+ export async function validateAuthState(ctx, req) {
374
+ const { log } = ctx;
375
375
  // use request headers if present
376
376
  if (req.headers.get('x-hlx-auth-state')) {
377
377
  log.info('[auth] override params.state from header.');
@@ -384,28 +384,24 @@ export async function initAuthRoute(state, req, res) {
384
384
 
385
385
  if (!req.params.state) {
386
386
  log.warn('[auth] unable to exchange token: no state.');
387
- makeAuthError(state, req, res, 'missing state parameter.');
388
- return false;
387
+ throw new Error('missing state parameter.');
389
388
  }
390
389
 
391
390
  try {
392
391
  req.params.rawState = req.params.state;
393
- req.params.state = await verifyJwt(state, req.params.state);
392
+ req.params.state = await verifyJwt(ctx, req.params.state);
394
393
  delete req.params.state.aud;
395
394
  delete req.params.state.iss;
396
395
  } catch (e) {
397
396
  log.warn(`[auth] error decoding state parameter: invalid state: ${e.message}`);
398
- makeAuthError(state, req, res, 'missing state parameter.');
399
- return false;
397
+ throw new Error('invalid state parameter.');
400
398
  }
401
399
 
402
- // fixup pipeline state
403
- state.owner = req.params.state.owner;
404
- state.repo = req.params.state.repo;
405
- state.ref = 'main';
406
- state.partition = 'preview';
407
- state.info.path = '/.auth';
408
- return true;
400
+ return {
401
+ ref: req.params.state.ref,
402
+ site: req.params.state.site,
403
+ org: req.params.state.org,
404
+ };
409
405
  }
410
406
 
411
407
  /**