@eeacms/volto-cca-policy 0.3.123 → 0.3.124

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
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. Dates are d
4
4
 
5
5
  Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
6
 
7
+ ### [0.3.124](https://github.com/eea/volto-cca-policy/compare/0.3.123...0.3.124) - 12 May 2026
8
+
9
+ #### :bug: Bug Fixes
10
+
11
+ - fix: remove error logging from RSS middleware [kreafox - [`eae5722`](https://github.com/eea/volto-cca-policy/commit/eae5722a3c438542156a69344fa88e826e01c58a)]
12
+ - fix: remove localhost fallback from RSS middleware [kreafox - [`6a3eba6`](https://github.com/eea/volto-cca-policy/commit/6a3eba614ba7158a9ccb95d43456b3555ec95c6d)]
13
+ - fix: redo some changes, cleanup, improve image generation, use addHeadersFactory from volto [kreafox - [`94784a5`](https://github.com/eea/volto-cca-policy/commit/94784a5ab00a9e97b713ee4d9cd8d1ccc2adaec2)]
14
+ - fix: normalize API path handling in RSS middleware [kreafox - [`f8ba94c`](https://github.com/eea/volto-cca-policy/commit/f8ba94c500ebabd7938547620dad3b673b8f1d5f)]
15
+ - fix: normalize API path handling in RSS middleware [kreafox - [`4ce5633`](https://github.com/eea/volto-cca-policy/commit/4ce5633ec048132c07fc461d08d4ea3a8c6caa00)]
16
+
7
17
  ### [0.3.123](https://github.com/eea/volto-cca-policy/compare/0.3.122...0.3.123) - 11 May 2026
8
18
 
9
19
  #### :bug: Bug Fixes
@@ -306,7 +316,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
306
316
 
307
317
  #### :house: Internal changes
308
318
 
309
- - chore: [JENKINSFILE] add package version in sonarqube [valentinab25 - [`e901251`](https://github.com/eea/volto-cca-policy/commit/e901251592eb54609fbc7eb8fcf7bd452c2da9cd)]
310
319
 
311
320
  ### [0.3.102](https://github.com/eea/volto-cca-policy/compare/0.3.101...0.3.102) - 24 February 2026
312
321
 
@@ -316,7 +325,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
316
325
 
317
326
  #### :house: Internal changes
318
327
 
319
- - chore: [JENKINSFILE] use sonarqube branches [EEA Jenkins - [`8b3699a`](https://github.com/eea/volto-cca-policy/commit/8b3699a6cbaef662b5e80884ac2c1f7dc9c6591e)]
320
328
 
321
329
  ### [0.3.101](https://github.com/eea/volto-cca-policy/compare/0.3.100...0.3.101) - 28 January 2026
322
330
 
@@ -604,7 +612,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
604
612
  - style: fix item spacing [kreafox - [`7d4535d`](https://github.com/eea/volto-cca-policy/commit/7d4535dbc486e6cb80fc55d6ac8c7c01d9cf48af)]
605
613
  - chore: code cleanup [kreafox - [`842419b`](https://github.com/eea/volto-cca-policy/commit/842419b1bce3dc624755c81c9dea672198cab9e2)]
606
614
  - style: update teaser block styling [kreafox - [`1e0cad8`](https://github.com/eea/volto-cca-policy/commit/1e0cad8e1ed3ae827ee868dce8ad50b292a937ba)]
607
- - chore: update Makefile, run yarn i18n [kreafox - [`61e6962`](https://github.com/eea/volto-cca-policy/commit/61e6962901068ae6512265417a730bd9befd65fe)]
608
615
  - chore: move styling to theme folder [kreafox - [`8cf6a1b`](https://github.com/eea/volto-cca-policy/commit/8cf6a1b8b14abf472a9c61b28db574f6d9e0bd3b)]
609
616
  - chore: remove ArrayWidget customization [kreafox - [`249bf93`](https://github.com/eea/volto-cca-policy/commit/249bf93054f7726c3d57a8b8ca01b75cd0d30522)]
610
617
  - chore: remove Footer customization [kreafox - [`7038af3`](https://github.com/eea/volto-cca-policy/commit/7038af37d48a328dfc31746f3fa84973e2f840ab)]
@@ -3367,13 +3374,10 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
3367
3374
  - Refs #260715 rast-block wip [Tripon Eugen - [`f19d54e`](https://github.com/eea/volto-cca-policy/commit/f19d54e0b9a6a86bf344eb85b6a1cda7f3de91bf)]
3368
3375
  - Refs #260715 rast-block wip [Tripon Eugen - [`2828537`](https://github.com/eea/volto-cca-policy/commit/2828537b6c084cd1a82162d552fb4ef025b71f9f)]
3369
3376
  - Refs #260715 rast-block updates [Tripon Eugen - [`1e803e5`](https://github.com/eea/volto-cca-policy/commit/1e803e5bd3d3fb7558f261c76c68866be7beb8b5)]
3370
- - test: [JENKINS] Use java17 for sonarqube scanner [valentinab25 - [`0a15e1b`](https://github.com/eea/volto-cca-policy/commit/0a15e1b2ad081233685e80d5b3c60a8663f6b896)]
3371
- - test: [JENKINS] Run cypress in started frontend container [valentinab25 - [`9554e44`](https://github.com/eea/volto-cca-policy/commit/9554e44c92a621a52b2adb5a4830fb084ee5734b)]
3372
3377
  ### [0.1.49](https://github.com/eea/volto-cca-policy/compare/0.1.48...0.1.49) - 15 November 2023
3373
3378
 
3374
3379
  #### :house: Internal changes
3375
3380
 
3376
- - chore: [JENKINS] Refactor automated testing [valentinab25 - [`7b820a6`](https://github.com/eea/volto-cca-policy/commit/7b820a6369c2ddd5203b1a4abe352cb4bb43db7a)]
3377
3381
  - chore: husky, lint-staged use fixed versions [valentinab25 - [`f0a8061`](https://github.com/eea/volto-cca-policy/commit/f0a8061c275c236deb00087c23fac9860a073106)]
3378
3382
 
3379
3383
  #### :hammer_and_wrench: Others
@@ -3390,9 +3394,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
3390
3394
  - Refs #259267 - jenkins test [Tripon Eugen - [`cacd31e`](https://github.com/eea/volto-cca-policy/commit/cacd31e7b1afe0983674ed5c7632d2e1d7fa752e)]
3391
3395
  - Refs #259267 - jenkins [Tripon Eugen - [`5b3affe`](https://github.com/eea/volto-cca-policy/commit/5b3affee8401239de10097884c1b7f2349d15ec0)]
3392
3396
  - Refs #259267 - add When, lead image and title to files [Tripon Eugen - [`2cedb23`](https://github.com/eea/volto-cca-policy/commit/2cedb237f898af9057e13fba94b615ef71077204)]
3393
- - test: [JENKINS] Add cpu limit on cypress docker [valentinab25 - [`4d607a5`](https://github.com/eea/volto-cca-policy/commit/4d607a576e9d0a5c34e48c41b409e7df616ee3d6)]
3394
- - test: [JENKINS] Increase shm-size to cypress docker [valentinab25 - [`b7f74d5`](https://github.com/eea/volto-cca-policy/commit/b7f74d53513a6edbfbca5cb6d19687929bb1e5db)]
3395
- - test: [JENKINS] Improve cypress time [valentinab25 - [`db65617`](https://github.com/eea/volto-cca-policy/commit/db656173391f65157098d95d388c25f6429753d8)]
3396
3397
  - Refs #259267 - cca event blocks attachments and check not mandatoty fields [Tripon Eugen - [`3138e5a`](https://github.com/eea/volto-cca-policy/commit/3138e5afb5bfbdbed14e27ed457b16867b7fa414)]
3397
3398
  - Refs #256681 - Fix error in CCA Event view menu. ([React Intl] An id must be provided to format a message.) [GhitaB - [`517eeb8`](https://github.com/eea/volto-cca-policy/commit/517eeb817264a47bbfd6b9b7d22aaf22d44ed224)]
3398
3399
  - Refs #161485 - Fix ECDE name conflict. [GhitaB - [`8bfd99f`](https://github.com/eea/volto-cca-policy/commit/8bfd99ff68bb82a04d1c0ed625fa514fcf46289e)]
@@ -3609,7 +3610,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
3609
3610
 
3610
3611
  #### :house: Internal changes
3611
3612
 
3612
- - chore: [JENKINS] Remove alpha testing version [valentinab25 - [`ad1ced0`](https://github.com/eea/volto-cca-policy/commit/ad1ced0971ba116c13a3b5fcc039172cc915c919)]
3613
3613
 
3614
3614
  #### :hammer_and_wrench: Others
3615
3615
 
@@ -4090,7 +4090,6 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
4090
4090
  #### :hammer_and_wrench: Others
4091
4091
 
4092
4092
  - Refs #158294 - Update supported languages list. [GhitaB - [`0a4f91f`](https://github.com/eea/volto-cca-policy/commit/0a4f91f39b7edc367bd4c127d6a8f273c7788361)]
4093
- - Add Sonarqube tag using cca-frontend addons list [EEA Jenkins - [`8f1f9ce`](https://github.com/eea/volto-cca-policy/commit/8f1f9ce6c22805670cc0800d3c779b6d619d0f31)]
4094
4093
  ### [0.1.1](https://github.com/eea/volto-cca-policy/compare/0.1.0...0.1.1) - 13 December 2022
4095
4094
 
4096
4095
  #### :hammer_and_wrench: Others
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eeacms/volto-cca-policy",
3
- "version": "0.3.123",
3
+ "version": "0.3.124",
4
4
  "description": "@eeacms/volto-cca-policy: Volto add-on",
5
5
  "main": "src/index.js",
6
6
  "author": "European Environment Agency: IDM2 A-Team",
@@ -1,8 +1,9 @@
1
1
  import express from 'express';
2
2
  import superagent from 'superagent';
3
3
  import RSS from 'rss';
4
- import { findBlocks } from '@plone/volto/helpers';
4
+ import { findBlocks, toPublicURL } from '@plone/volto/helpers';
5
5
  import config from '@plone/volto/registry';
6
+ import { addHeadersFactory } from '@plone/volto/helpers/Proxy/Proxy';
6
7
 
7
8
  /**
8
9
  * Retrieves the query data (search criteria) used by the listing block of the rss_feed content type
@@ -33,76 +34,68 @@ import config from '@plone/volto/registry';
33
34
  * @throws Will throw an error if no query data is found in the listing block or if the request fails.
34
35
  */
35
36
  async function getRssFeedData(apiPath, APISUFFIX, req, settings) {
36
- const url = `${apiPath}${__DEVELOPMENT__ ? '' : APISUFFIX}${req.path.replace(
37
- '/rss.xml',
38
- '',
39
- )}`;
40
-
41
- // eslint-disable-next-line no-console
42
- console.error('[RSS] Fetching feed data from:', url);
43
-
44
- const request = superagent.get(url).accept('json');
45
-
46
- const authToken = req.universalCookies?.get?.('auth_token');
47
- if (authToken) {
48
- request.set('Authorization', `Bearer ${authToken}`);
49
- }
50
-
51
- const response = await request;
52
- const json = response.body;
53
- const listingBlocks = findBlocks(json.blocks, 'listing');
54
- const listingBlockId = Array.isArray(listingBlocks)
55
- ? listingBlocks[0]
56
- : listingBlocks;
57
-
58
- const queryData = listingBlockId
59
- ? json.blocks?.[listingBlockId]?.querystring
60
- : null;
61
- const language = json.language?.token ?? 'en';
62
- const description = json.description ?? 'A Volto RSS Feed';
63
- const title = json.title;
64
- const subjects = json.subjects;
65
- const date = json.effective;
66
- const max_description_length = json.max_description_length;
67
- const max_title_length = json.max_title_length;
68
- if (!queryData) {
69
- throw new Error('No query data found in listing block');
70
- }
71
-
72
- const normalizedQueryData = { ...queryData };
73
-
74
- if (normalizedQueryData.sort_order != null) {
75
- if (typeof normalizedQueryData.sort_order === 'boolean') {
76
- normalizedQueryData.sort_order = normalizedQueryData.sort_order
77
- ? 'reverse'
78
- : 'ascending';
37
+ try {
38
+ const request = superagent
39
+ .get(
40
+ `${apiPath}${__DEVELOPMENT__ ? '' : APISUFFIX}${req.path.replace(
41
+ '/rss.xml',
42
+ '',
43
+ )}`,
44
+ )
45
+ .accept('json')
46
+ .use(addHeadersFactory(req));
47
+
48
+ const authToken = req.universalCookies?.get?.('auth_token');
49
+ if (authToken) {
50
+ request.set('Authorization', `Bearer ${authToken}`);
79
51
  }
80
52
 
81
- if (normalizedQueryData.sort_order === 'descending') {
82
- normalizedQueryData.sort_order = 'reverse';
53
+ const response = await request;
54
+ const json = JSON.parse(JSON.stringify(response.body));
55
+ const listingBlock = findBlocks(json.blocks, 'listing');
56
+ const queryData = json.blocks?.[listingBlock]?.querystring;
57
+ const language = json.language?.token ?? 'en';
58
+ const description = json.description ?? 'A Volto RSS Feed';
59
+ const title = json.title;
60
+ const subjects = json.subjects;
61
+ const date = json.effective;
62
+ const max_description_length = json.max_description_length;
63
+ const max_title_length = json.max_title_length;
64
+ if (!queryData) {
65
+ throw new Error('No query data found in listing block');
83
66
  }
84
- }
85
67
 
86
- const query = {
87
- ...normalizedQueryData,
88
- ...(!normalizedQueryData.b_size && {
89
- b_size: settings.defaultPageSize,
90
- }),
91
- query: normalizedQueryData?.query,
92
- metadata_fields: '_all',
93
- b_start: 0,
94
- };
68
+ if (queryData?.sort_order != null) {
69
+ if (typeof queryData.sort_order === 'boolean') {
70
+ queryData.sort_order = queryData.sort_order
71
+ ? 'descending'
72
+ : 'ascending';
73
+ }
74
+ }
95
75
 
96
- return {
97
- query,
98
- language,
99
- description,
100
- title,
101
- subjects,
102
- date,
103
- max_description_length,
104
- max_title_length,
105
- };
76
+ const query = {
77
+ ...queryData,
78
+ ...(!queryData.b_size && {
79
+ b_size: settings.defaultPageSize,
80
+ }),
81
+ query: queryData?.query,
82
+ metadata_fields: '_all',
83
+ b_start: 0,
84
+ };
85
+
86
+ return {
87
+ query,
88
+ language,
89
+ description,
90
+ title,
91
+ subjects,
92
+ date,
93
+ max_description_length,
94
+ max_title_length,
95
+ };
96
+ } catch (err) {
97
+ throw err;
98
+ }
106
99
  }
107
100
 
108
101
  /**
@@ -120,39 +113,22 @@ async function getRssFeedData(apiPath, APISUFFIX, req, settings) {
120
113
  * @return {Array} An array of items that match the query criteria.
121
114
  * @throws Will throw an error if the request fails.
122
115
  */
123
- async function fetchListingItems(query, apiPath, APISUFFIX, authToken) {
124
- const request = superagent
125
- .post(`${apiPath}${__DEVELOPMENT__ ? '' : APISUFFIX}/@querystring-search`)
126
- .send(query)
127
- .accept('json');
128
-
129
- if (authToken) {
130
- request.set('Authorization', `Bearer ${authToken}`);
131
- }
132
-
133
- const response = await request;
134
- return response.body.items || [];
135
- }
136
-
137
- function normalizeFeedURL(url, publicURL, apiPath) {
138
- if (!url) return publicURL;
139
-
116
+ async function fetchListingItems(query, apiPath, APISUFFIX, authToken, req) {
140
117
  try {
141
- const parsedUrl = new URL(url, publicURL);
142
-
143
- if (apiPath) {
144
- const apiOrigin = new URL(apiPath).origin;
145
- const publicOrigin = new URL(publicURL).origin;
146
-
147
- if (parsedUrl.origin === apiOrigin) {
148
- parsedUrl.protocol = new URL(publicOrigin).protocol;
149
- parsedUrl.host = new URL(publicOrigin).host;
150
- }
118
+ const request = superagent
119
+ .post(`${apiPath}${__DEVELOPMENT__ ? '' : APISUFFIX}/@querystring-search`)
120
+ .send(query)
121
+ .accept('json')
122
+ .use(addHeadersFactory(req));
123
+
124
+ if (authToken) {
125
+ request.set('Authorization', `Bearer ${authToken}`);
151
126
  }
152
127
 
153
- return parsedUrl.toString();
154
- } catch {
155
- return url;
128
+ const response = await request;
129
+ return response.body?.items || [];
130
+ } catch (err) {
131
+ throw err;
156
132
  }
157
133
  }
158
134
 
@@ -168,28 +144,6 @@ function truncateText(text = '', maxLength) {
168
144
  return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
169
145
  }
170
146
 
171
- function safeDate(value) {
172
- if (!value) return undefined;
173
- const d = new Date(value);
174
- if (Number.isNaN(d.getTime()) || d.getTime() <= 0) return undefined;
175
- return d;
176
- }
177
-
178
- function resolveImageUrl(download, itemUrl, publicURL, apiPath) {
179
- if (!download || !itemUrl) return undefined;
180
-
181
- try {
182
- const base = itemUrl.endsWith('/') ? itemUrl : `${itemUrl}/`;
183
- return normalizeFeedURL(
184
- new URL(download, base).toString(),
185
- publicURL,
186
- apiPath,
187
- );
188
- } catch {
189
- return undefined;
190
- }
191
- }
192
-
193
147
  /**
194
148
  * Creates an Express middleware for generating an RSS feed using the listing block of the
195
149
  * rss_feed content type.
@@ -204,9 +158,6 @@ function make_rssMiddleware() {
204
158
  const { settings } = config;
205
159
  const APISUFFIX = settings.legacyTraverse ? '' : '/++api++';
206
160
  let apiPath = '';
207
- const host = process.env.HOST || 'localhost';
208
- const port = process.env.PORT || '3000';
209
- const ProdapiPath = `http://${host}:${port}`;
210
161
  if (settings.internalApiPath && __SERVER__) {
211
162
  apiPath = settings.internalApiPath;
212
163
  } else if (__DEVELOPMENT__ && settings.devProxyToApiPath) {
@@ -214,9 +165,6 @@ function make_rssMiddleware() {
214
165
  } else {
215
166
  apiPath = settings.apiPath;
216
167
  }
217
- if (apiPath === '') {
218
- apiPath = ProdapiPath;
219
- }
220
168
 
221
169
  async function rssMiddleware(req, res, next) {
222
170
  try {
@@ -235,46 +183,48 @@ function make_rssMiddleware() {
235
183
  apiPath,
236
184
  APISUFFIX,
237
185
  req.universalCookies?.get?.('auth_token'),
186
+ req,
238
187
  );
239
188
  const feedOptions = {
240
189
  title: truncateText(title, max_title_length),
241
190
  description: truncateText(description, max_description_length),
242
- feed_url: normalizeFeedURL(req.path, settings.publicURL, apiPath),
191
+ feed_url: `${settings.publicURL}${req.path}`,
243
192
  site_url: settings.publicURL,
244
193
  generator: 'RSS Feed Generator',
245
194
  language: language,
246
- pubDate: safeDate(date),
195
+ pubDate: new Date(date),
247
196
  categories: subjects || [],
248
197
  };
249
198
 
250
199
  const feed = new RSS(feedOptions);
251
200
 
252
201
  items.forEach((item) => {
253
- const link = normalizeFeedURL(item.getURL, settings.publicURL, apiPath);
202
+ let link = toPublicURL(item['getURL']);
254
203
  let enclosure = undefined;
255
-
256
- const imageData = item.image_scales?.[item.image_field]?.[0];
257
- const previewScale = imageData?.scales?.preview;
258
- const imageDownload = previewScale?.download || imageData?.download;
259
- const imageSize = previewScale?.size || imageData?.size;
260
- const imageType =
261
- previewScale?.['content-type'] || imageData?.['content-type'];
262
-
263
- const imageUrl = resolveImageUrl(
264
- imageDownload,
265
- link,
266
- settings.publicURL,
267
- apiPath,
268
- );
269
-
270
- const numericImageSize = Number(imageSize);
271
-
272
- if (imageUrl && Number.isFinite(numericImageSize) && imageType) {
273
- enclosure = {
274
- url: imageUrl,
275
- type: imageType,
276
- size: numericImageSize,
277
- };
204
+ if (
205
+ item.image_field &&
206
+ item.image_scales &&
207
+ item.image_scales[item.image_field] &&
208
+ item.image_scales[item.image_field].length > 0
209
+ ) {
210
+ const imageData = item.image_scales[item.image_field][0];
211
+ const scales = imageData.scales || {};
212
+ const scale =
213
+ scales.preview ||
214
+ scales.large ||
215
+ scales.teaser ||
216
+ Object.values(scales)[0];
217
+
218
+ if (scale && scale.download) {
219
+ const imageUrl = `${link}/${scale.download}`;
220
+ const mimeType = item['content-type'];
221
+ const originalSize = imageData.size;
222
+ enclosure = {
223
+ url: imageUrl,
224
+ type: mimeType,
225
+ size: originalSize,
226
+ };
227
+ }
278
228
  }
279
229
  feed.item({
280
230
  title: truncateText(item.title, max_title_length),
@@ -284,7 +234,7 @@ function make_rssMiddleware() {
284
234
  ),
285
235
  url: link,
286
236
  guid: item.UID,
287
- date: safeDate(item.effective || item.created || item.modified),
237
+ date: new Date(item.effective),
288
238
  author: item.listCreators?.join(', '),
289
239
  categories: item.Subject ? item.Subject : [],
290
240
  enclosure: enclosure || undefined,
@@ -295,14 +245,6 @@ function make_rssMiddleware() {
295
245
  res.setHeader('Content-Type', 'application/rss+xml; charset=utf-8');
296
246
  res.send(xml);
297
247
  } catch (err) {
298
- // eslint-disable-next-line no-console
299
- console.error('[RSS] Failed', {
300
- path: req.path,
301
- apiPath,
302
- APISUFFIX,
303
- message: err.message,
304
- stack: err.stack,
305
- });
306
248
  if (err.response && err.response.status === 401) {
307
249
  // Handle unauthorized errors
308
250
  res.status(401).json({
@@ -335,7 +277,7 @@ function make_rssMiddleware() {
335
277
  export default function makeMiddlewares() {
336
278
  const middleware = express.Router();
337
279
  middleware.use(express.urlencoded({ extended: true }));
338
- middleware.get('**/rss.xml', make_rssMiddleware());
280
+ middleware.all('**/rss.xml', make_rssMiddleware());
339
281
 
340
282
  middleware.id = 'rss-middleware';
341
283