@ministryofjustice/hmpps-connect-dps-components 2.2.0 → 3.0.0-beta.1
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/dist/allocationService.d.ts +14 -2
- package/dist/allocationService.test.d.ts +1 -0
- package/dist/caseLoadService.d.ts +14 -2
- package/dist/caseLoadService.test.d.ts +1 -0
- package/dist/componentsService.d.ts +15 -1
- package/dist/componentsService.test.d.ts +1 -0
- package/dist/data/allocationsApi/allocationsApiClient.d.ts +6 -6
- package/dist/data/componentApi/componentApiClient.d.ts +6 -6
- package/dist/data/prisonApi/prisonApiClient.d.ts +6 -6
- package/dist/index.cjs +246 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +152 -66
- package/dist/index.esm.js +242 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/middleware/getFrontendComponents.d.ts +9 -0
- package/dist/types/ConnectDpsComponentLogger.d.ts +2 -0
- package/dist/types/public/middleware/index.d.ts +1 -0
- package/dist/types/public/services/index.d.ts +3 -0
- package/dist/utils/fallbacks.d.ts +1 -1
- package/dist/utils/updateCsp.d.ts +1 -1
- package/dist/utils/updateCsp.test.d.ts +1 -0
- package/package.json +34 -47
- package/dist/allocationService.js +0 -48
- package/dist/allocationService.js.map +0 -1
- package/dist/caseLoadService.js +0 -55
- package/dist/caseLoadService.js.map +0 -1
- package/dist/componentsService.js +0 -61
- package/dist/componentsService.js.map +0 -1
- package/dist/config.d.ts +0 -14
- package/dist/config.js +0 -28
- package/dist/config.js.map +0 -1
- package/dist/data/allocationsApi/allocationsApiClient.js +0 -23
- package/dist/data/allocationsApi/allocationsApiClient.js.map +0 -1
- package/dist/data/componentApi/componentApiClient.js +0 -23
- package/dist/data/componentApi/componentApiClient.js.map +0 -1
- package/dist/data/prisonApi/prisonApiClient.js +0 -24
- package/dist/data/prisonApi/prisonApiClient.js.map +0 -1
- package/dist/index.js +0 -72
- package/dist/index.js.map +0 -1
- package/dist/types/AllocationJobResponsibility.js +0 -3
- package/dist/types/AllocationJobResponsibility.js.map +0 -1
- package/dist/types/AvailableComponent.js +0 -3
- package/dist/types/AvailableComponent.js.map +0 -1
- package/dist/types/CaseLoad.js +0 -3
- package/dist/types/CaseLoad.js.map +0 -1
- package/dist/types/CaseLoadOptions.js +0 -3
- package/dist/types/CaseLoadOptions.js.map +0 -1
- package/dist/types/Component.js +0 -3
- package/dist/types/Component.js.map +0 -1
- package/dist/types/HeaderFooterSharedData.js +0 -3
- package/dist/types/HeaderFooterSharedData.js.map +0 -1
- package/dist/types/HmppsUser.js +0 -3
- package/dist/types/HmppsUser.js.map +0 -1
- package/dist/types/RequestOptions.js +0 -3
- package/dist/types/RequestOptions.js.map +0 -1
- package/dist/types/Service.js +0 -3
- package/dist/types/Service.js.map +0 -1
- package/dist/types/TimeoutOptions.js +0 -3
- package/dist/types/TimeoutOptions.js.map +0 -1
- package/dist/utils/fallbacks.js +0 -36
- package/dist/utils/fallbacks.js.map +0 -1
- package/dist/utils/updateCsp.js +0 -25
- package/dist/utils/updateCsp.js.map +0 -1
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { RestClient, asSystem, asUser } from '@ministryofjustice/hmpps-rest-client';
|
|
2
|
+
import nunjucks from 'nunjucks';
|
|
3
|
+
|
|
4
|
+
class ComponentApiClient extends RestClient {
|
|
5
|
+
constructor(logger, config, authenticationClient) {
|
|
6
|
+
super('Component API Client', config, logger, authenticationClient);
|
|
7
|
+
}
|
|
8
|
+
async getComponents(userToken) {
|
|
9
|
+
return this.get({
|
|
10
|
+
path: `/components`,
|
|
11
|
+
query: 'component=header&component=footer',
|
|
12
|
+
headers: { 'x-user-token': userToken },
|
|
13
|
+
}, asSystem());
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getFallbackHeader(user, requestOptions) {
|
|
18
|
+
const { dpsUrl, environmentName, authUrl, supportUrl } = requestOptions;
|
|
19
|
+
return nunjucks.render('dpsComponents/header-bar.njk', {
|
|
20
|
+
isPrisonUser: !user || user.authSource === 'nomis',
|
|
21
|
+
user,
|
|
22
|
+
dpsUrl,
|
|
23
|
+
environmentName,
|
|
24
|
+
authUrl,
|
|
25
|
+
supportUrl,
|
|
26
|
+
name: initialiseName(user?.displayName),
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function getFallbackFooter(user, requestOptions) {
|
|
30
|
+
const { supportUrl, authUrl } = requestOptions;
|
|
31
|
+
return nunjucks.render('dpsComponents/footer.njk', {
|
|
32
|
+
isPrisonUser: !user || user.authSource === 'nomis',
|
|
33
|
+
supportUrl,
|
|
34
|
+
authUrl,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
function initialiseName(fullName) {
|
|
38
|
+
if (!fullName)
|
|
39
|
+
return null;
|
|
40
|
+
const array = fullName.split(' ');
|
|
41
|
+
return `${array[0][0]}. ${array.reverse()[0]}`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function updateCsp(feComponentsUrl, res) {
|
|
45
|
+
const csp = res.getHeaders()['content-security-policy'];
|
|
46
|
+
const allDirectives = csp?.split(';') ?? [];
|
|
47
|
+
const directivesToUpdate = ['script-src', 'style-src', 'img-src', 'font-src'];
|
|
48
|
+
const updatedCspDirectives = allDirectives.map(directive => {
|
|
49
|
+
// if directive is not in cspToUpdate or includes fe components url already return as is
|
|
50
|
+
if (directive.includes(feComponentsUrl) || !directivesToUpdate.some(p => directive.includes(`${p} `)))
|
|
51
|
+
return directive;
|
|
52
|
+
// if directive is in cspToUpdate and does not have fe components url, add in
|
|
53
|
+
return `${directive} ${feComponentsUrl}`;
|
|
54
|
+
});
|
|
55
|
+
const requiredAndNotPresent = directivesToUpdate
|
|
56
|
+
.filter(p => !updatedCspDirectives.find(directive => directive.includes(`${p} `)))
|
|
57
|
+
.map(p => `${p} 'self' ${feComponentsUrl}`);
|
|
58
|
+
res.set('content-security-policy', [...updatedCspDirectives, ...requiredAndNotPresent].join(';'));
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const defaultOptions = {
|
|
62
|
+
logger: console,
|
|
63
|
+
timeoutOptions: { response: 2500, deadline: 2500 },
|
|
64
|
+
includeSharedData: false,
|
|
65
|
+
useFallbacksByDefault: false,
|
|
66
|
+
};
|
|
67
|
+
class ComponentsService {
|
|
68
|
+
logger;
|
|
69
|
+
componentApiConfig;
|
|
70
|
+
componentApiClient;
|
|
71
|
+
constructor(logger, componentApiConfig, componentApiClient) {
|
|
72
|
+
this.logger = logger;
|
|
73
|
+
this.componentApiConfig = componentApiConfig;
|
|
74
|
+
this.componentApiClient = componentApiClient;
|
|
75
|
+
}
|
|
76
|
+
static create({ logger = console, componentApiConfig, authenticationClient, }) {
|
|
77
|
+
return new ComponentsService(logger, componentApiConfig, new ComponentApiClient(logger, componentApiConfig, authenticationClient));
|
|
78
|
+
}
|
|
79
|
+
getFrontendComponents(requestOptions) {
|
|
80
|
+
const requestOptionsWithDefaults = {
|
|
81
|
+
...defaultOptions,
|
|
82
|
+
...requestOptions,
|
|
83
|
+
};
|
|
84
|
+
const { includeSharedData, useFallbacksByDefault } = {
|
|
85
|
+
...defaultOptions,
|
|
86
|
+
...requestOptions,
|
|
87
|
+
};
|
|
88
|
+
return async (_req, res, next) => {
|
|
89
|
+
const useFallbacks = (user) => {
|
|
90
|
+
res.locals.feComponents = {
|
|
91
|
+
header: getFallbackHeader(user, requestOptionsWithDefaults),
|
|
92
|
+
footer: getFallbackFooter(user, requestOptionsWithDefaults),
|
|
93
|
+
cssIncludes: [],
|
|
94
|
+
jsIncludes: [],
|
|
95
|
+
};
|
|
96
|
+
};
|
|
97
|
+
if (!res.locals.user) {
|
|
98
|
+
this.logger.info('Using fallback frontend components when no user in context');
|
|
99
|
+
useFallbacks(null);
|
|
100
|
+
return next();
|
|
101
|
+
}
|
|
102
|
+
if (useFallbacksByDefault) {
|
|
103
|
+
this.logger.info('Using fallback frontend components by default');
|
|
104
|
+
useFallbacks(res.locals.user);
|
|
105
|
+
return next();
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const { header, footer, meta } = await this.componentApiClient.getComponents(res.locals.user.token);
|
|
109
|
+
res.locals.feComponents = {
|
|
110
|
+
header: header.html,
|
|
111
|
+
footer: footer.html,
|
|
112
|
+
cssIncludes: [...header.css, ...footer.css],
|
|
113
|
+
jsIncludes: [...header.javascript, ...footer.javascript],
|
|
114
|
+
};
|
|
115
|
+
if (includeSharedData) {
|
|
116
|
+
res.locals.feComponents.sharedData = meta;
|
|
117
|
+
}
|
|
118
|
+
updateCsp(this.componentApiConfig.url, res);
|
|
119
|
+
return next();
|
|
120
|
+
}
|
|
121
|
+
catch (_error) {
|
|
122
|
+
this.logger.error('Failed to retrieve front end components, using fallbacks');
|
|
123
|
+
useFallbacks(res.locals.user);
|
|
124
|
+
return next();
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
class PrisonApiClient extends RestClient {
|
|
131
|
+
constructor(logger, config, authenticationClient) {
|
|
132
|
+
super('Prison API Client', config, logger, authenticationClient);
|
|
133
|
+
}
|
|
134
|
+
async getUserCaseLoads(userToken) {
|
|
135
|
+
return this.get({
|
|
136
|
+
path: '/api/users/me/caseloads',
|
|
137
|
+
query: { allCaseloads: true },
|
|
138
|
+
}, asUser(userToken));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
class CaseLoadService {
|
|
143
|
+
logger;
|
|
144
|
+
prisonApiClient;
|
|
145
|
+
constructor(logger, prisonApiClient) {
|
|
146
|
+
this.logger = logger;
|
|
147
|
+
this.prisonApiClient = prisonApiClient;
|
|
148
|
+
}
|
|
149
|
+
static create({ logger = console, prisonApiConfig, authenticationClient, }) {
|
|
150
|
+
return new CaseLoadService(logger, new PrisonApiClient(logger, prisonApiConfig, authenticationClient));
|
|
151
|
+
}
|
|
152
|
+
retrieveCaseLoadData() {
|
|
153
|
+
return async (req, res, next) => {
|
|
154
|
+
if (!req.session)
|
|
155
|
+
throw new Error('User session required in order to cache case loads');
|
|
156
|
+
if (res.locals.user && res.locals.user.token && res.locals.user.authSource === 'nomis') {
|
|
157
|
+
try {
|
|
158
|
+
// Update cache with values from res.feComponents.sharedData if present
|
|
159
|
+
if (res.locals.feComponents && res.locals.feComponents.sharedData) {
|
|
160
|
+
req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads;
|
|
161
|
+
req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad;
|
|
162
|
+
req.session.activeCaseLoadId = res.locals.feComponents.sharedData.activeCaseLoad?.caseLoadId;
|
|
163
|
+
}
|
|
164
|
+
// If cache is empty, fetch data from Prison API
|
|
165
|
+
if (!req.session.caseLoads) {
|
|
166
|
+
this.logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`);
|
|
167
|
+
const userCaseLoads = await this.prisonApiClient.getUserCaseLoads(res.locals.user.token);
|
|
168
|
+
const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP');
|
|
169
|
+
const activeCaseLoad = caseLoads.find((caseLoad) => caseLoad.currentlyActive);
|
|
170
|
+
req.session.caseLoads = caseLoads;
|
|
171
|
+
req.session.activeCaseLoad = activeCaseLoad;
|
|
172
|
+
req.session.activeCaseLoadId = activeCaseLoad?.caseLoadId;
|
|
173
|
+
}
|
|
174
|
+
// Populate res.locals.user with values from cache
|
|
175
|
+
res.locals.user.caseLoads = req.session.caseLoads;
|
|
176
|
+
res.locals.user.activeCaseLoad = req.session.activeCaseLoad;
|
|
177
|
+
res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
this.logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`);
|
|
181
|
+
return next(error);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return next();
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
class AllocationsApiClient extends RestClient {
|
|
190
|
+
constructor(logger, config, authenticationClient) {
|
|
191
|
+
super('Allocations API Client', config, logger, authenticationClient);
|
|
192
|
+
}
|
|
193
|
+
async getStaffAllocationPolicies(user) {
|
|
194
|
+
return this.get({
|
|
195
|
+
path: `/prisons/${user.activeCaseLoadId}/staff/${user.userId}/job-classifications`,
|
|
196
|
+
}, asSystem());
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
class AllocationService {
|
|
201
|
+
logger;
|
|
202
|
+
allocationsApiClient;
|
|
203
|
+
constructor(logger, allocationsApiClient) {
|
|
204
|
+
this.logger = logger;
|
|
205
|
+
this.allocationsApiClient = allocationsApiClient;
|
|
206
|
+
}
|
|
207
|
+
static create({ logger = console, allocationsApiConfig, authenticationClient, }) {
|
|
208
|
+
return new AllocationService(logger, new AllocationsApiClient(logger, allocationsApiConfig, authenticationClient));
|
|
209
|
+
}
|
|
210
|
+
retrieveAllocationJobResponsibilities() {
|
|
211
|
+
return async (req, res, next) => {
|
|
212
|
+
if (!req.session)
|
|
213
|
+
throw new Error('User session required in order to cache allocation job responsibilities');
|
|
214
|
+
if (!res.locals.user.token)
|
|
215
|
+
throw new Error('Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.');
|
|
216
|
+
if (res.locals.user && res.locals.user.authSource === 'nomis') {
|
|
217
|
+
try {
|
|
218
|
+
// Update cache with values from res.feComponents.sharedData if present
|
|
219
|
+
if (res.locals.feComponents && res.locals.feComponents.sharedData) {
|
|
220
|
+
req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities;
|
|
221
|
+
}
|
|
222
|
+
// If cache is empty, fetch data from Prison API
|
|
223
|
+
if (!req.session.allocationJobResponsibilities) {
|
|
224
|
+
this.logger.info(`Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`);
|
|
225
|
+
const allocationPolicies = await this.allocationsApiClient.getStaffAllocationPolicies(res.locals.user);
|
|
226
|
+
req.session.allocationJobResponsibilities = allocationPolicies.policies;
|
|
227
|
+
}
|
|
228
|
+
// Populate res.locals.user with values from cache
|
|
229
|
+
res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities;
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
this.logger.error(error, `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`);
|
|
233
|
+
return next(error);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return next();
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export { AllocationService, CaseLoadService, ComponentsService };
|
|
242
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/data/componentApi/componentApiClient.ts","../src/utils/fallbacks.ts","../src/utils/updateCsp.ts","../src/componentsService.ts","../src/data/prisonApi/prisonApiClient.ts","../src/caseLoadService.ts","../src/data/allocationsApi/allocationsApiClient.ts","../src/allocationService.ts"],"sourcesContent":["import { ApiConfig, asSystem, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport AvailableComponent from '../../types/AvailableComponent'\nimport Component from '../../types/Component'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\nimport { ComponentsSharedData } from '../../types/HeaderFooterSharedData'\n\nexport type ComponentsApiResponse<T extends AvailableComponent[]> = Record<T[number], Component> & {\n meta: ComponentsSharedData[T[number]] // TODO: rename 'meta' in the API response\n}\n\nexport default class ComponentApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Component API Client', config, logger, authenticationClient)\n }\n\n async getComponents<T extends AvailableComponent[]>(userToken: string): Promise<ComponentsApiResponse<T>> {\n return this.get<ComponentsApiResponse<T>>(\n {\n path: `/components`,\n query: 'component=header&component=footer',\n headers: { 'x-user-token': userToken },\n },\n asSystem(),\n )\n }\n}\n","import nunjucks from 'nunjucks'\nimport RequestOptions from '../types/RequestOptions'\nimport { HmppsUser } from '../types/HmppsUser'\n\nexport function getFallbackHeader(user: HmppsUser | null, requestOptions: RequestOptions): string {\n const { dpsUrl, environmentName, authUrl, supportUrl } = requestOptions\n\n return nunjucks.render('dpsComponents/header-bar.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n user,\n dpsUrl,\n environmentName,\n authUrl,\n supportUrl,\n name: initialiseName(user?.displayName),\n })\n}\n\nexport function getFallbackFooter(user: HmppsUser | null, requestOptions: RequestOptions): string {\n const { supportUrl, authUrl } = requestOptions\n return nunjucks.render('dpsComponents/footer.njk', {\n isPrisonUser: !user || user.authSource === 'nomis',\n supportUrl,\n authUrl,\n })\n}\n\nfunction initialiseName(fullName?: string): string | null {\n if (!fullName) return null\n\n const array = fullName.split(' ')\n return `${array[0][0]}. ${array.reverse()[0]}`\n}\n","import { type Response } from 'express'\n\nexport default function updateCsp(feComponentsUrl: string, res: Response) {\n const csp = res.getHeaders()['content-security-policy']\n const allDirectives = csp?.split(';') ?? []\n const directivesToUpdate = ['script-src', 'style-src', 'img-src', 'font-src']\n\n const updatedCspDirectives = allDirectives.map(directive => {\n // if directive is not in cspToUpdate or includes fe components url already return as is\n if (directive.includes(feComponentsUrl as string) || !directivesToUpdate.some(p => directive.includes(`${p} `)))\n return directive\n\n // if directive is in cspToUpdate and does not have fe components url, add in\n return `${directive} ${feComponentsUrl}`\n })\n\n const requiredAndNotPresent = directivesToUpdate\n .filter(p => !updatedCspDirectives.find(directive => directive.includes(`${p} `)))\n .map(p => `${p} 'self' ${feComponentsUrl}`)\n\n res.set('content-security-policy', [...updatedCspDirectives, ...requiredAndNotPresent].join(';'))\n}\n","import { type NextFunction, type Request, type Response, type RequestHandler } from 'express'\nimport { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport ComponentApiClient from './data/componentApi/componentApiClient'\nimport { getFallbackFooter, getFallbackHeader } from './utils/fallbacks'\nimport RequestOptions from './types/RequestOptions'\nimport updateCsp from './utils/updateCsp'\nimport { HmppsUser } from './types/HmppsUser'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nconst defaultOptions: Partial<RequestOptions> = {\n logger: console,\n timeoutOptions: { response: 2500, deadline: 2500 },\n includeSharedData: false,\n useFallbacksByDefault: false,\n}\n\nexport default class ComponentsService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly componentApiConfig: ApiConfig,\n private readonly componentApiClient: ComponentApiClient,\n ) {}\n\n static create({\n logger = console,\n componentApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n componentApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new ComponentsService(\n logger,\n componentApiConfig,\n new ComponentApiClient(logger, componentApiConfig, authenticationClient),\n )\n }\n\n getFrontendComponents(requestOptions: RequestOptions): RequestHandler {\n const requestOptionsWithDefaults = {\n ...defaultOptions,\n ...requestOptions,\n }\n const { includeSharedData, useFallbacksByDefault } = {\n ...defaultOptions,\n ...requestOptions,\n }\n\n return async (_req: Request, res: Response, next: NextFunction) => {\n const useFallbacks = (user: HmppsUser | null) => {\n res.locals.feComponents = {\n header: getFallbackHeader(user, requestOptionsWithDefaults),\n footer: getFallbackFooter(user, requestOptionsWithDefaults),\n cssIncludes: [],\n jsIncludes: [],\n }\n }\n\n if (!res.locals.user) {\n this.logger.info('Using fallback frontend components when no user in context')\n useFallbacks(null)\n return next()\n }\n\n if (useFallbacksByDefault) {\n this.logger.info('Using fallback frontend components by default')\n useFallbacks(res.locals.user)\n return next()\n }\n\n try {\n const { header, footer, meta } = await this.componentApiClient.getComponents(res.locals.user.token as string)\n\n res.locals.feComponents = {\n header: header.html,\n footer: footer.html,\n cssIncludes: [...header.css, ...footer.css],\n jsIncludes: [...header.javascript, ...footer.javascript],\n }\n\n if (includeSharedData) {\n res.locals.feComponents.sharedData = meta\n }\n\n updateCsp(this.componentApiConfig.url, res)\n\n return next()\n } catch (_error) {\n this.logger.error('Failed to retrieve front end components, using fallbacks')\n useFallbacks(res.locals.user)\n return next()\n }\n }\n }\n}\n","import { ApiConfig, asUser, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from '../../types/CaseLoad'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class PrisonApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Prison API Client', config, logger, authenticationClient)\n }\n\n async getUserCaseLoads(userToken: string): Promise<CaseLoad[]> {\n return this.get<CaseLoad[]>(\n {\n path: '/api/users/me/caseloads',\n query: { allCaseloads: true },\n },\n asUser(userToken),\n )\n }\n}\n","import { type RequestHandler } from 'express'\nimport { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport CaseLoad from './types/CaseLoad'\nimport PrisonApiClient from './data/prisonApi/prisonApiClient'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class CaseLoadService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly prisonApiClient: PrisonApiClient,\n ) {}\n\n static create({\n logger = console,\n prisonApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n prisonApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new CaseLoadService(logger, new PrisonApiClient(logger, prisonApiConfig, authenticationClient))\n }\n\n retrieveCaseLoadData(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache case loads')\n\n if (res.locals.user && res.locals.user.token && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads\n req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad\n req.session.activeCaseLoadId = res.locals.feComponents.sharedData.activeCaseLoad?.caseLoadId\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.caseLoads) {\n this.logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`)\n const userCaseLoads = await this.prisonApiClient.getUserCaseLoads(res.locals.user.token)\n const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP')\n const activeCaseLoad = caseLoads.find((caseLoad: CaseLoad) => caseLoad.currentlyActive)\n\n req.session.caseLoads = caseLoads\n req.session.activeCaseLoad = activeCaseLoad\n req.session.activeCaseLoadId = activeCaseLoad?.caseLoadId\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.caseLoads = req.session.caseLoads\n res.locals.user.activeCaseLoad = req.session.activeCaseLoad\n res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId\n } catch (error) {\n this.logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`)\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n","import { ApiConfig, asSystem, AuthenticationClient, RestClient } from '@ministryofjustice/hmpps-rest-client'\nimport { PrisonUser } from '../../types/HmppsUser'\nimport { AllocationJobResponsibility } from '../../types/AllocationJobResponsibility'\nimport { ConnectDpsComponentLogger } from '../../types/ConnectDpsComponentLogger'\n\nexport default class AllocationsApiClient extends RestClient {\n constructor(logger: ConnectDpsComponentLogger, config: ApiConfig, authenticationClient: AuthenticationClient) {\n super('Allocations API Client', config, logger, authenticationClient)\n }\n\n async getStaffAllocationPolicies(user: PrisonUser): Promise<{ policies: AllocationJobResponsibility[] }> {\n return this.get<{ policies: AllocationJobResponsibility[] }>(\n {\n path: `/prisons/${user.activeCaseLoadId}/staff/${user.userId}/job-classifications`,\n },\n asSystem(),\n )\n }\n}\n","import { type RequestHandler } from 'express'\nimport { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client'\nimport AllocationsApiClient from './data/allocationsApi/allocationsApiClient'\nimport { ConnectDpsComponentLogger } from './types/ConnectDpsComponentLogger'\n\nexport default class AllocationService {\n constructor(\n private readonly logger: ConnectDpsComponentLogger,\n private readonly allocationsApiClient: AllocationsApiClient,\n ) {}\n\n static create({\n logger = console,\n allocationsApiConfig,\n authenticationClient,\n }: {\n logger?: ConnectDpsComponentLogger\n allocationsApiConfig: ApiConfig\n authenticationClient: AuthenticationClient\n }) {\n return new AllocationService(logger, new AllocationsApiClient(logger, allocationsApiConfig, authenticationClient))\n }\n\n public retrieveAllocationJobResponsibilities(): RequestHandler {\n return async (req, res, next) => {\n if (!req.session) throw new Error('User session required in order to cache allocation job responsibilities')\n if (!res.locals.user.token)\n throw new Error(\n 'Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.',\n )\n\n if (res.locals.user && res.locals.user.authSource === 'nomis') {\n try {\n // Update cache with values from res.feComponents.sharedData if present\n if (res.locals.feComponents && res.locals.feComponents.sharedData) {\n req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities\n }\n\n // If cache is empty, fetch data from Prison API\n if (!req.session.allocationJobResponsibilities) {\n this.logger.info(\n `Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`,\n )\n const allocationPolicies = await this.allocationsApiClient.getStaffAllocationPolicies(res.locals.user)\n req.session.allocationJobResponsibilities = allocationPolicies.policies\n }\n\n // Populate res.locals.user with values from cache\n res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities\n } catch (error) {\n this.logger.error(\n error,\n `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`,\n )\n return next(error)\n }\n }\n\n return next()\n }\n }\n}\n"],"names":[],"mappings":";;;AAUc,MAAO,kBAAmB,SAAQ,UAAU,CAAA;AACxD,IAAA,WAAA,CAAY,MAAiC,EAAE,MAAiB,EAAE,oBAA0C,EAAA;QAC1G,KAAK,CAAC,sBAAsB,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,CAAC;IACrE;IAEA,MAAM,aAAa,CAAiC,SAAiB,EAAA;QACnE,OAAO,IAAI,CAAC,GAAG,CACb;AACE,YAAA,IAAI,EAAE,CAAA,WAAA,CAAa;AACnB,YAAA,KAAK,EAAE,mCAAmC;AAC1C,YAAA,OAAO,EAAE,EAAE,cAAc,EAAE,SAAS,EAAE;SACvC,EACD,QAAQ,EAAE,CACX;IACH;AACD;;ACrBK,SAAU,iBAAiB,CAAC,IAAsB,EAAE,cAA8B,EAAA;IACtF,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,cAAc;AAEvE,IAAA,OAAO,QAAQ,CAAC,MAAM,CAAC,8BAA8B,EAAE;QACrD,YAAY,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO;QAClD,IAAI;QACJ,MAAM;QACN,eAAe;QACf,OAAO;QACP,UAAU;AACV,QAAA,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC;AACxC,KAAA,CAAC;AACJ;AAEM,SAAU,iBAAiB,CAAC,IAAsB,EAAE,cAA8B,EAAA;AACtF,IAAA,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,cAAc;AAC9C,IAAA,OAAO,QAAQ,CAAC,MAAM,CAAC,0BAA0B,EAAE;QACjD,YAAY,EAAE,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,OAAO;QAClD,UAAU;QACV,OAAO;AACR,KAAA,CAAC;AACJ;AAEA,SAAS,cAAc,CAAC,QAAiB,EAAA;AACvC,IAAA,IAAI,CAAC,QAAQ;AAAE,QAAA,OAAO,IAAI;IAE1B,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC;AACjC,IAAA,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA,EAAA,EAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;AAChD;;AC9Bc,SAAU,SAAS,CAAC,eAAuB,EAAE,GAAa,EAAA;IACtE,MAAM,GAAG,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC,yBAAyB,CAAC;IACvD,MAAM,aAAa,GAAG,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE;IAC3C,MAAM,kBAAkB,GAAG,CAAC,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC;IAE7E,MAAM,oBAAoB,GAAG,aAAa,CAAC,GAAG,CAAC,SAAS,IAAG;;QAEzD,IAAI,SAAS,CAAC,QAAQ,CAAC,eAAyB,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,SAAS,CAAC,QAAQ,CAAC,CAAA,EAAG,CAAC,CAAA,CAAA,CAAG,CAAC,CAAC;AAC7G,YAAA,OAAO,SAAS;;AAGlB,QAAA,OAAO,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,eAAe,EAAE;AAC1C,IAAA,CAAC,CAAC;IAEF,MAAM,qBAAqB,GAAG;SAC3B,MAAM,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,SAAS,IAAI,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA,CAAA,CAAG,CAAC,CAAC;SAChF,GAAG,CAAC,CAAC,IAAI,CAAA,EAAG,CAAC,CAAA,QAAA,EAAW,eAAe,CAAA,CAAE,CAAC;AAE7C,IAAA,GAAG,CAAC,GAAG,CAAC,yBAAyB,EAAE,CAAC,GAAG,oBAAoB,EAAE,GAAG,qBAAqB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AACnG;;ACZA,MAAM,cAAc,GAA4B;AAC9C,IAAA,MAAM,EAAE,OAAO;IACf,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;AAClD,IAAA,iBAAiB,EAAE,KAAK;AACxB,IAAA,qBAAqB,EAAE,KAAK;CAC7B;AAEa,MAAO,iBAAiB,CAAA;AAEjB,IAAA,MAAA;AACA,IAAA,kBAAA;AACA,IAAA,kBAAA;AAHnB,IAAA,WAAA,CACmB,MAAiC,EACjC,kBAA6B,EAC7B,kBAAsC,EAAA;QAFtC,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,kBAAkB,GAAlB,kBAAkB;QAClB,IAAA,CAAA,kBAAkB,GAAlB,kBAAkB;IAClC;IAEH,OAAO,MAAM,CAAC,EACZ,MAAM,GAAG,OAAO,EAChB,kBAAkB,EAClB,oBAAoB,GAKrB,EAAA;AACC,QAAA,OAAO,IAAI,iBAAiB,CAC1B,MAAM,EACN,kBAAkB,EAClB,IAAI,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,EAAE,oBAAoB,CAAC,CACzE;IACH;AAEA,IAAA,qBAAqB,CAAC,cAA8B,EAAA;AAClD,QAAA,MAAM,0BAA0B,GAAG;AACjC,YAAA,GAAG,cAAc;AACjB,YAAA,GAAG,cAAc;SAClB;AACD,QAAA,MAAM,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,GAAG;AACnD,YAAA,GAAG,cAAc;AACjB,YAAA,GAAG,cAAc;SAClB;QAED,OAAO,OAAO,IAAa,EAAE,GAAa,EAAE,IAAkB,KAAI;AAChE,YAAA,MAAM,YAAY,GAAG,CAAC,IAAsB,KAAI;AAC9C,gBAAA,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG;AACxB,oBAAA,MAAM,EAAE,iBAAiB,CAAC,IAAI,EAAE,0BAA0B,CAAC;AAC3D,oBAAA,MAAM,EAAE,iBAAiB,CAAC,IAAI,EAAE,0BAA0B,CAAC;AAC3D,oBAAA,WAAW,EAAE,EAAE;AACf,oBAAA,UAAU,EAAE,EAAE;iBACf;AACH,YAAA,CAAC;AAED,YAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE;AACpB,gBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC;gBAC9E,YAAY,CAAC,IAAI,CAAC;gBAClB,OAAO,IAAI,EAAE;YACf;YAEA,IAAI,qBAAqB,EAAE;AACzB,gBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC;AACjE,gBAAA,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC7B,OAAO,IAAI,EAAE;YACf;AAEA,YAAA,IAAI;gBACF,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAe,CAAC;AAE7G,gBAAA,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG;oBACxB,MAAM,EAAE,MAAM,CAAC,IAAI;oBACnB,MAAM,EAAE,MAAM,CAAC,IAAI;oBACnB,WAAW,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;oBAC3C,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;iBACzD;gBAED,IAAI,iBAAiB,EAAE;oBACrB,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,GAAG,IAAI;gBAC3C;gBAEA,SAAS,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,GAAG,CAAC;gBAE3C,OAAO,IAAI,EAAE;YACf;YAAE,OAAO,MAAM,EAAE;AACf,gBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC;AAC7E,gBAAA,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;gBAC7B,OAAO,IAAI,EAAE;YACf;AACF,QAAA,CAAC;IACH;AACD;;AC3Fa,MAAO,eAAgB,SAAQ,UAAU,CAAA;AACrD,IAAA,WAAA,CAAY,MAAiC,EAAE,MAAiB,EAAE,oBAA0C,EAAA;QAC1G,KAAK,CAAC,mBAAmB,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,CAAC;IAClE;IAEA,MAAM,gBAAgB,CAAC,SAAiB,EAAA;QACtC,OAAO,IAAI,CAAC,GAAG,CACb;AACE,YAAA,IAAI,EAAE,yBAAyB;AAC/B,YAAA,KAAK,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE;AAC9B,SAAA,EACD,MAAM,CAAC,SAAS,CAAC,CAClB;IACH;AACD;;ACZa,MAAO,eAAe,CAAA;AAEf,IAAA,MAAA;AACA,IAAA,eAAA;IAFnB,WAAA,CACmB,MAAiC,EACjC,eAAgC,EAAA;QADhC,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,eAAe,GAAf,eAAe;IAC/B;IAEH,OAAO,MAAM,CAAC,EACZ,MAAM,GAAG,OAAO,EAChB,eAAe,EACf,oBAAoB,GAKrB,EAAA;AACC,QAAA,OAAO,IAAI,eAAe,CAAC,MAAM,EAAE,IAAI,eAAe,CAAC,MAAM,EAAE,eAAe,EAAE,oBAAoB,CAAC,CAAC;IACxG;IAEA,oBAAoB,GAAA;QAClB,OAAO,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,KAAI;YAC9B,IAAI,CAAC,GAAG,CAAC,OAAO;AAAE,gBAAA,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC;YAEvF,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE;AACtF,gBAAA,IAAI;;AAEF,oBAAA,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE;AACjE,wBAAA,GAAG,CAAC,OAAO,CAAC,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS;AACpE,wBAAA,GAAG,CAAC,OAAO,CAAC,cAAc,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc;AAC9E,wBAAA,GAAG,CAAC,OAAO,CAAC,gBAAgB,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc,EAAE,UAAU;oBAC9F;;AAGA,oBAAA,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,SAAS,EAAE;AAC1B,wBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA,uDAAA,EAA0D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAA,CAAE,CAAC;AACtG,wBAAA,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACxF,wBAAA,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,KAAK,CAAC;AAC3E,wBAAA,MAAM,cAAc,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC,QAAkB,KAAK,QAAQ,CAAC,eAAe,CAAC;AAEvF,wBAAA,GAAG,CAAC,OAAO,CAAC,SAAS,GAAG,SAAS;AACjC,wBAAA,GAAG,CAAC,OAAO,CAAC,cAAc,GAAG,cAAc;wBAC3C,GAAG,CAAC,OAAO,CAAC,gBAAgB,GAAG,cAAc,EAAE,UAAU;oBAC3D;;AAGA,oBAAA,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS;AACjD,oBAAA,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC,cAAc;AAC3D,oBAAA,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,GAAG,GAAG,CAAC,OAAO,CAAC,gBAAgB;gBACjE;gBAAE,OAAO,KAAK,EAAE;AACd,oBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA,mCAAA,EAAsC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAA,CAAE,CAAC;AAC1F,oBAAA,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB;YACF;YAEA,OAAO,IAAI,EAAE;AACf,QAAA,CAAC;IACH;AACD;;ACzDa,MAAO,oBAAqB,SAAQ,UAAU,CAAA;AAC1D,IAAA,WAAA,CAAY,MAAiC,EAAE,MAAiB,EAAE,oBAA0C,EAAA;QAC1G,KAAK,CAAC,wBAAwB,EAAE,MAAM,EAAE,MAAM,EAAE,oBAAoB,CAAC;IACvE;IAEA,MAAM,0BAA0B,CAAC,IAAgB,EAAA;QAC/C,OAAO,IAAI,CAAC,GAAG,CACb;YACE,IAAI,EAAE,YAAY,IAAI,CAAC,gBAAgB,CAAA,OAAA,EAAU,IAAI,CAAC,MAAM,CAAA,oBAAA,CAAsB;SACnF,EACD,QAAQ,EAAE,CACX;IACH;AACD;;ACba,MAAO,iBAAiB,CAAA;AAEjB,IAAA,MAAA;AACA,IAAA,oBAAA;IAFnB,WAAA,CACmB,MAAiC,EACjC,oBAA0C,EAAA;QAD1C,IAAA,CAAA,MAAM,GAAN,MAAM;QACN,IAAA,CAAA,oBAAoB,GAApB,oBAAoB;IACpC;IAEH,OAAO,MAAM,CAAC,EACZ,MAAM,GAAG,OAAO,EAChB,oBAAoB,EACpB,oBAAoB,GAKrB,EAAA;AACC,QAAA,OAAO,IAAI,iBAAiB,CAAC,MAAM,EAAE,IAAI,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,EAAE,oBAAoB,CAAC,CAAC;IACpH;IAEO,qCAAqC,GAAA;QAC1C,OAAO,OAAO,GAAG,EAAE,GAAG,EAAE,IAAI,KAAI;YAC9B,IAAI,CAAC,GAAG,CAAC,OAAO;AAAE,gBAAA,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC;AAC5G,YAAA,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK;AACxB,gBAAA,MAAM,IAAI,KAAK,CACb,yKAAyK,CAC1K;AAEH,YAAA,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE;AAC7D,gBAAA,IAAI;;AAEF,oBAAA,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE;AACjE,wBAAA,GAAG,CAAC,OAAO,CAAC,6BAA6B,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,6BAA6B;oBAC9G;;AAGA,oBAAA,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,6BAA6B,EAAE;AAC9C,wBAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,CAAA,sEAAA,EAAyE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAA,CAAE,CACpG;AACD,wBAAA,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC,0BAA0B,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;wBACtG,GAAG,CAAC,OAAO,CAAC,6BAA6B,GAAG,kBAAkB,CAAC,QAAQ;oBACzE;;AAGA,oBAAA,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,GAAG,GAAG,CAAC,OAAO,CAAC,6BAA6B;gBAC3F;gBAAE,OAAO,KAAK,EAAE;AACd,oBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,CACf,KAAK,EACL,CAAA,wDAAA,EAA2D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAA,CAAE,CACtF;AACD,oBAAA,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB;YACF;YAEA,OAAO,IAAI,EAAE;AACf,QAAA,CAAC;IACH;AACD;;;;"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type RequestHandler } from 'express';
|
|
2
|
+
import { ApiConfig, AuthenticationClient } from '@ministryofjustice/hmpps-rest-client';
|
|
3
|
+
import { ConnectDpsComponentLogger } from '../types/ConnectDpsComponentLogger';
|
|
4
|
+
import RequestOptions from '../types/RequestOptions';
|
|
5
|
+
export default function getFrontendComponents({ logger, componentApiConfig, authenticationClient, }: {
|
|
6
|
+
logger?: ConnectDpsComponentLogger;
|
|
7
|
+
componentApiConfig: ApiConfig;
|
|
8
|
+
authenticationClient: AuthenticationClient;
|
|
9
|
+
}): (requestOptions: RequestOptions) => RequestHandler;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { default as getFrontendComponents } from '../../../middleware/getFrontendComponents';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import RequestOptions from '../types/RequestOptions';
|
|
2
2
|
import { HmppsUser } from '../types/HmppsUser';
|
|
3
3
|
export declare function getFallbackHeader(user: HmppsUser | null, requestOptions: RequestOptions): string;
|
|
4
|
-
export declare function getFallbackFooter(user: HmppsUser, requestOptions: RequestOptions): string;
|
|
4
|
+
export declare function getFallbackFooter(user: HmppsUser | null, requestOptions: RequestOptions): string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type Response } from 'express';
|
|
2
|
-
export default function updateCsp(res: Response): void;
|
|
2
|
+
export default function updateCsp(feComponentsUrl: string, res: Response): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,54 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ministryofjustice/hmpps-connect-dps-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
4
|
"description": "A package to allow the inclusion of connect dps micro frontend components within dps applications",
|
|
5
|
-
"main": "./dist/index.
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.esm.js",
|
|
6
7
|
"types": "./dist/index.d.ts",
|
|
7
8
|
"files": [
|
|
8
9
|
"dist/**/*"
|
|
9
10
|
],
|
|
10
11
|
"scripts": {
|
|
11
|
-
"
|
|
12
|
+
"prepare": "hmpps-precommit-hooks-prepare",
|
|
13
|
+
"build": "rollup -c rollup.config.ts --bundleConfigAsCjs && npm run copy:assets",
|
|
12
14
|
"test": "jest",
|
|
13
15
|
"test:ci": "jest --runInBand --passWithNoTests",
|
|
16
|
+
"typecheck": "tsc",
|
|
14
17
|
"lint": "eslint . --cache --max-warnings 0",
|
|
18
|
+
"lint:fix": "eslint . --cache --max-warnings 0 --fix",
|
|
15
19
|
"copy:assets": "rm -rf dist/assets && cp -r src/assets dist/assets",
|
|
16
|
-
"security_audit": "npx audit-ci --config audit-ci.json"
|
|
20
|
+
"security_audit": "npx audit-ci --config audit-ci.json",
|
|
21
|
+
"precommit:secrets": "gitleaks git --pre-commit --redact --staged --verbose --config .gitleaks/config.toml",
|
|
22
|
+
"precommit:lint": "node_modules/.bin/lint-staged",
|
|
23
|
+
"precommit:verify": "npm run typecheck && npm test"
|
|
17
24
|
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
{
|
|
23
|
-
"isolatedModules": true
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
},
|
|
27
|
-
"testMatch": [
|
|
28
|
-
"<rootDir>/**/**/?(*.)(cy|test).{ts,js,jsx,mjs}"
|
|
25
|
+
"lint-staged": {
|
|
26
|
+
"*.{ts,css}": [
|
|
27
|
+
"prettier --write",
|
|
28
|
+
"eslint --fix"
|
|
29
29
|
],
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
"default",
|
|
33
|
-
[
|
|
34
|
-
"jest-junit",
|
|
35
|
-
{
|
|
36
|
-
"outputDirectory": "test_results/jest/"
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
[
|
|
40
|
-
"./node_modules/jest-html-reporter",
|
|
41
|
-
{
|
|
42
|
-
"outputPath": "test_results/unit-test-reports.html"
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
],
|
|
46
|
-
"moduleFileExtensions": [
|
|
47
|
-
"web.js",
|
|
48
|
-
"js",
|
|
49
|
-
"json",
|
|
50
|
-
"node",
|
|
51
|
-
"ts"
|
|
30
|
+
"*.json": [
|
|
31
|
+
"prettier --write"
|
|
52
32
|
]
|
|
53
33
|
},
|
|
54
34
|
"repository": {
|
|
@@ -62,32 +42,39 @@
|
|
|
62
42
|
},
|
|
63
43
|
"homepage": "https://github.com/ministryofjustice/hmpps-connect-dps-components#readme",
|
|
64
44
|
"devDependencies": {
|
|
45
|
+
"@ministryofjustice/eslint-config-hmpps": "^0.0.1",
|
|
46
|
+
"@ministryofjustice/hmpps-auth-clients": "^0.0.1",
|
|
47
|
+
"@ministryofjustice/hmpps-precommit-hooks": "^0.0.3",
|
|
48
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
49
|
+
"@rollup/plugin-multi-entry": "^6.0.1",
|
|
50
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
51
|
+
"@rollup/plugin-typescript": "^12.1.4",
|
|
52
|
+
"@tsconfig/node22": "^22.0.2",
|
|
65
53
|
"@types/bunyan": "^1.8.11",
|
|
66
54
|
"@types/express": "^4.17.22",
|
|
67
55
|
"@types/jest": "^29.5.14",
|
|
68
56
|
"@types/superagent": "^8.1.9",
|
|
69
57
|
"@types/supertest": "^6.0.3",
|
|
70
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
58
|
+
"@typescript-eslint/eslint-plugin": "^8.38.0",
|
|
71
59
|
"cheerio": "^1.0.0",
|
|
72
|
-
"eslint": "^
|
|
73
|
-
"eslint-config-airbnb-base": "^15.0.0",
|
|
74
|
-
"eslint-config-prettier": "^9.1.0",
|
|
75
|
-
"eslint-import-resolver-typescript": "^3.10.1",
|
|
76
|
-
"eslint-plugin-cypress": "^2.15.2",
|
|
77
|
-
"eslint-plugin-import": "^2.31.0",
|
|
60
|
+
"eslint-import-resolver-typescript": "^4.4.4",
|
|
78
61
|
"eslint-plugin-no-only-tests": "^3.3.0",
|
|
79
|
-
"eslint-plugin-prettier": "^5.4.0",
|
|
80
62
|
"express": "^4.21.2",
|
|
81
63
|
"govuk-frontend": "^5.10.1",
|
|
82
64
|
"jest": "^29.7.0",
|
|
83
65
|
"jest-html-reporter": "^3.10.2",
|
|
84
66
|
"jest-junit": "^16.0.0",
|
|
67
|
+
"lint-staged": "^16.1.2",
|
|
85
68
|
"nock": "^13.5.6",
|
|
69
|
+
"rollup": "^4.45.1",
|
|
70
|
+
"rollup-plugin-dts": "^6.2.1",
|
|
86
71
|
"supertest": "^7.1.1",
|
|
87
|
-
"ts-jest": "^29.3.4"
|
|
72
|
+
"ts-jest": "^29.3.4",
|
|
73
|
+
"tslib": "^2.8.1"
|
|
88
74
|
},
|
|
89
75
|
"dependencies": {
|
|
90
|
-
"@
|
|
76
|
+
"@ministryofjustice/hmpps-rest-client": "^0.0.1",
|
|
77
|
+
"@types/node": "22.12.0",
|
|
91
78
|
"@types/nunjucks": "^3.2.6",
|
|
92
79
|
"nunjucks": "^3.2.4",
|
|
93
80
|
"superagent": "^9.0.2"
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const allocationsApiClient_1 = __importDefault(require("./data/allocationsApi/allocationsApiClient"));
|
|
7
|
-
const config_1 = __importDefault(require("./config"));
|
|
8
|
-
const defaultOptions = {
|
|
9
|
-
logger: console,
|
|
10
|
-
timeoutOptions: { response: 2500, deadline: 2500 },
|
|
11
|
-
};
|
|
12
|
-
function retrieveAllocationJobResponsibilities(options) {
|
|
13
|
-
const { logger, timeoutOptions } = {
|
|
14
|
-
...defaultOptions,
|
|
15
|
-
...options,
|
|
16
|
-
};
|
|
17
|
-
if (!config_1.default.apis.allocationsApi.url)
|
|
18
|
-
throw new Error('Environment variable ALLOCATIONS_API_URL must be defined for this middleware to work correctly');
|
|
19
|
-
return async (req, res, next) => {
|
|
20
|
-
if (!req.session)
|
|
21
|
-
throw new Error('User session required in order to cache allocation job responsibilities');
|
|
22
|
-
if (!res.locals.user.token)
|
|
23
|
-
throw new Error('Caseload details needs to be populated before retrieving allocation job responsibilities. Please run retrieveCaseLoadData before retrieveAllocationJobResponsibilities.');
|
|
24
|
-
if (res.locals.user && res.locals.user.authSource === 'nomis') {
|
|
25
|
-
try {
|
|
26
|
-
// Update cache with values from res.feComponents.sharedData if present
|
|
27
|
-
if (res.locals.feComponents && res.locals.feComponents.sharedData) {
|
|
28
|
-
req.session.allocationJobResponsibilities = res.locals.feComponents.sharedData.allocationJobResponsibilities;
|
|
29
|
-
}
|
|
30
|
-
// If cache is empty, fetch data from Prison API
|
|
31
|
-
if (!req.session.allocationJobResponsibilities) {
|
|
32
|
-
logger.info(`Falling back to Allocations API to retrieve job responsibilities for: ${res.locals.user.username}`);
|
|
33
|
-
const allocationPolicies = await allocationsApiClient_1.default.getStaffAllocationPolicies(res.locals.user, timeoutOptions, logger);
|
|
34
|
-
req.session.allocationJobResponsibilities = allocationPolicies.policies;
|
|
35
|
-
}
|
|
36
|
-
// Populate res.locals.user with values from cache
|
|
37
|
-
res.locals.user.allocationJobResponsibilities = req.session.allocationJobResponsibilities;
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
logger.error(error, `Failed to retrieve allocation job responsibilities for: ${res.locals.user.username}`);
|
|
41
|
-
return next(error);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return next();
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
exports.default = retrieveAllocationJobResponsibilities;
|
|
48
|
-
//# sourceMappingURL=allocationService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"allocationService.js","sourceRoot":"","sources":["../src/allocationService.ts"],"names":[],"mappings":";;;;;AAEA,sGAA6E;AAC7E,sDAA6B;AAE7B,MAAM,cAAc,GAAoB;IACtC,MAAM,EAAE,OAAO;IACf,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;CACnD,CAAA;AAED,SAAwB,qCAAqC,CAAC,OAAyB;IACrF,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,GAAG;QACjC,GAAG,cAAc;QACjB,GAAG,OAAO;KACX,CAAA;IAED,IAAI,CAAC,gBAAM,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG;QACjC,MAAM,IAAI,KAAK,CAAC,gGAAgG,CAAC,CAAA;IAEnH,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC9B,IAAI,CAAC,GAAG,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAA;QAC5G,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK;YACxB,MAAM,IAAI,KAAK,CACb,yKAAyK,CAC1K,CAAA;QAEH,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,KAAK,OAAO,EAAE,CAAC;YAC9D,IAAI,CAAC;gBACH,uEAAuE;gBACvE,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,IAAI,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,EAAE,CAAC;oBAClE,GAAG,CAAC,OAAO,CAAC,6BAA6B,GAAG,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,6BAA6B,CAAA;gBAC9G,CAAC;gBAED,gDAAgD;gBAChD,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,6BAA6B,EAAE,CAAC;oBAC/C,MAAM,CAAC,IAAI,CACT,yEAAyE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CACpG,CAAA;oBACD,MAAM,kBAAkB,GAAG,MAAM,8BAAoB,CAAC,0BAA0B,CAC9E,GAAG,CAAC,MAAM,CAAC,IAAI,EACf,cAAc,EACd,MAAM,CACP,CAAA;oBACD,GAAG,CAAC,OAAO,CAAC,6BAA6B,GAAG,kBAAkB,CAAC,QAAQ,CAAA;gBACzE,CAAC;gBAED,kDAAkD;gBAClD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,6BAA6B,GAAG,GAAG,CAAC,OAAO,CAAC,6BAA6B,CAAA;YAC3F,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,2DAA2D,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAA;gBAC1G,OAAO,IAAI,CAAC,KAAK,CAAC,CAAA;YACpB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,EAAE,CAAA;IACf,CAAC,CAAA;AACH,CAAC;AA9CD,wDA8CC"}
|
package/dist/caseLoadService.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const prisonApiClient_1 = __importDefault(require("./data/prisonApi/prisonApiClient"));
|
|
7
|
-
const config_1 = __importDefault(require("./config"));
|
|
8
|
-
const defaultOptions = {
|
|
9
|
-
logger: console,
|
|
10
|
-
timeoutOptions: { response: 2500, deadline: 2500 },
|
|
11
|
-
};
|
|
12
|
-
function retrieveCaseLoadData(caseLoadOptions) {
|
|
13
|
-
const { logger, timeoutOptions } = {
|
|
14
|
-
...defaultOptions,
|
|
15
|
-
...caseLoadOptions,
|
|
16
|
-
};
|
|
17
|
-
if (!config_1.default.apis.prisonApi.url)
|
|
18
|
-
throw new Error('Environment variable PRISON_API_URL must be defined for this middleware to work correctly');
|
|
19
|
-
return async (req, res, next) => {
|
|
20
|
-
var _a;
|
|
21
|
-
if (!req.session)
|
|
22
|
-
throw new Error('User session required in order to cache case loads');
|
|
23
|
-
if (res.locals.user && res.locals.user.authSource === 'nomis') {
|
|
24
|
-
try {
|
|
25
|
-
// Update cache with values from res.feComponents.sharedData if present
|
|
26
|
-
if (res.locals.feComponents && res.locals.feComponents.sharedData) {
|
|
27
|
-
req.session.caseLoads = res.locals.feComponents.sharedData.caseLoads;
|
|
28
|
-
req.session.activeCaseLoad = res.locals.feComponents.sharedData.activeCaseLoad;
|
|
29
|
-
req.session.activeCaseLoadId = (_a = res.locals.feComponents.sharedData.activeCaseLoad) === null || _a === void 0 ? void 0 : _a.caseLoadId;
|
|
30
|
-
}
|
|
31
|
-
// If cache is empty, fetch data from Prison API
|
|
32
|
-
if (!req.session.caseLoads) {
|
|
33
|
-
logger.info(`Falling back to Prison API to retrieve case loads for: ${res.locals.user.username}`);
|
|
34
|
-
const userCaseLoads = await prisonApiClient_1.default.getUserCaseLoads(res.locals.user.token, timeoutOptions, logger);
|
|
35
|
-
const caseLoads = userCaseLoads.filter(caseload => caseload.type !== 'APP');
|
|
36
|
-
const activeCaseLoad = caseLoads.find((caseLoad) => caseLoad.currentlyActive);
|
|
37
|
-
req.session.caseLoads = caseLoads;
|
|
38
|
-
req.session.activeCaseLoad = activeCaseLoad;
|
|
39
|
-
req.session.activeCaseLoadId = activeCaseLoad === null || activeCaseLoad === void 0 ? void 0 : activeCaseLoad.caseLoadId;
|
|
40
|
-
}
|
|
41
|
-
// Populate res.locals.user with values from cache
|
|
42
|
-
res.locals.user.caseLoads = req.session.caseLoads;
|
|
43
|
-
res.locals.user.activeCaseLoad = req.session.activeCaseLoad;
|
|
44
|
-
res.locals.user.activeCaseLoadId = req.session.activeCaseLoadId;
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
logger.error(error, `Failed to retrieve case loads for: ${res.locals.user.username}`);
|
|
48
|
-
return next(error);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return next();
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
exports.default = retrieveCaseLoadData;
|
|
55
|
-
//# sourceMappingURL=caseLoadService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"caseLoadService.js","sourceRoot":"","sources":["../src/caseLoadService.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
const componentApiClient_1 = __importDefault(require("./data/componentApi/componentApiClient"));
|
|
7
|
-
const fallbacks_1 = require("./utils/fallbacks");
|
|
8
|
-
const updateCsp_1 = __importDefault(require("./utils/updateCsp"));
|
|
9
|
-
const defaultOptions = {
|
|
10
|
-
logger: console,
|
|
11
|
-
timeoutOptions: { response: 2500, deadline: 2500 },
|
|
12
|
-
includeSharedData: false,
|
|
13
|
-
useFallbacksByDefault: false,
|
|
14
|
-
};
|
|
15
|
-
function getFrontendComponents(requestOptions) {
|
|
16
|
-
const { logger, timeoutOptions, includeSharedData, useFallbacksByDefault } = {
|
|
17
|
-
...defaultOptions,
|
|
18
|
-
...requestOptions,
|
|
19
|
-
};
|
|
20
|
-
return async (_req, res, next) => {
|
|
21
|
-
const useFallbacks = (user) => {
|
|
22
|
-
res.locals.feComponents = {
|
|
23
|
-
header: (0, fallbacks_1.getFallbackHeader)(user, requestOptions),
|
|
24
|
-
footer: (0, fallbacks_1.getFallbackFooter)(user, requestOptions),
|
|
25
|
-
cssIncludes: [],
|
|
26
|
-
jsIncludes: [],
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
if (!res.locals.user) {
|
|
30
|
-
logger.info('Using fallback frontend components when no user in context');
|
|
31
|
-
useFallbacks(null);
|
|
32
|
-
return next();
|
|
33
|
-
}
|
|
34
|
-
if (useFallbacksByDefault) {
|
|
35
|
-
logger.info('Using fallback frontend components by default');
|
|
36
|
-
useFallbacks(res.locals.user);
|
|
37
|
-
return next();
|
|
38
|
-
}
|
|
39
|
-
try {
|
|
40
|
-
const { header, footer, meta } = await componentApiClient_1.default.getComponents(res.locals.user.token, timeoutOptions, logger);
|
|
41
|
-
res.locals.feComponents = {
|
|
42
|
-
header: header.html,
|
|
43
|
-
footer: footer.html,
|
|
44
|
-
cssIncludes: [...header.css, ...footer.css],
|
|
45
|
-
jsIncludes: [...header.javascript, ...footer.javascript],
|
|
46
|
-
};
|
|
47
|
-
if (includeSharedData) {
|
|
48
|
-
res.locals.feComponents.sharedData = meta;
|
|
49
|
-
}
|
|
50
|
-
(0, updateCsp_1.default)(res);
|
|
51
|
-
return next();
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
logger.error('Failed to retrieve front end components, using fallbacks');
|
|
55
|
-
useFallbacks(res.locals.user);
|
|
56
|
-
return next();
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
exports.default = getFrontendComponents;
|
|
61
|
-
//# sourceMappingURL=componentsService.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"componentsService.js","sourceRoot":"","sources":["../src/componentsService.ts"],"names":[],"mappings":";;;;;AACA,gGAAuE;AACvE,iDAAwE;AAExE,kEAAyC;AAGzC,MAAM,cAAc,GAA4B;IAC9C,MAAM,EAAE,OAAO;IACf,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;IAClD,iBAAiB,EAAE,KAAK;IACxB,qBAAqB,EAAE,KAAK;CAC7B,CAAA;AAED,SAAwB,qBAAqB,CAAC,cAA+B;IAC3E,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,GAAG;QAC3E,GAAG,cAAc;QACjB,GAAG,cAAc;KAClB,CAAA;IAED,OAAO,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAC/B,MAAM,YAAY,GAAG,CAAC,IAAe,EAAE,EAAE;YACvC,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG;gBACxB,MAAM,EAAE,IAAA,6BAAiB,EAAC,IAAI,EAAE,cAAc,CAAC;gBAC/C,MAAM,EAAE,IAAA,6BAAiB,EAAC,IAAI,EAAE,cAAc,CAAC;gBAC/C,WAAW,EAAE,EAAE;gBACf,UAAU,EAAE,EAAE;aACf,CAAA;QACH,CAAC,CAAA;QAED,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAA;YACzE,YAAY,CAAC,IAAI,CAAC,CAAA;YAClB,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QAED,IAAI,qBAAqB,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAA;YAC5D,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC7B,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QAED,IAAI,CAAC;YACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,4BAAkB,CAAC,aAAa,CACrE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EACrB,cAAc,EACd,MAAM,CACP,CAAA;YAED,GAAG,CAAC,MAAM,CAAC,YAAY,GAAG;gBACxB,MAAM,EAAE,MAAM,CAAC,IAAI;gBACnB,MAAM,EAAE,MAAM,CAAC,IAAI;gBACnB,WAAW,EAAE,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,CAAC;gBAC3C,UAAU,EAAE,CAAC,GAAG,MAAM,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC;aACzD,CAAA;YAED,IAAI,iBAAiB,EAAE,CAAC;gBACtB,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,GAAG,IAAI,CAAA;YAC3C,CAAC;YAED,IAAA,mBAAS,EAAC,GAAG,CAAC,CAAA;YAEd,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAA;YACxE,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;YAC7B,OAAO,IAAI,EAAE,CAAA;QACf,CAAC;IACH,CAAC,CAAA;AACH,CAAC;AAvDD,wCAuDC"}
|