From ea8adfa2cb872758c3aa01eb112e33ce8f4afad0 Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Tue, 30 Apr 2024 11:29:15 -0700 Subject: [PATCH 01/21] Always send emails for applications when submitting to LG * Remove check and unit test that blocked this --- .../application-submission.controller.spec.ts | 50 ------------------ .../application-submission.controller.ts | 52 +++++++------------ 2 files changed, 19 insertions(+), 83 deletions(-) diff --git a/services/apps/alcs/src/portal/application-submission/application-submission.controller.spec.ts b/services/apps/alcs/src/portal/application-submission/application-submission.controller.spec.ts index f493844a05..80a6465209 100644 --- a/services/apps/alcs/src/portal/application-submission/application-submission.controller.spec.ts +++ b/services/apps/alcs/src/portal/application-submission/application-submission.controller.spec.ts @@ -610,56 +610,6 @@ describe('ApplicationSubmissionController', () => { }); }); - it('should only send status email for first time non-TUR applications', async () => { - const mockFileId = 'file-id'; - mockAppSubmissionService.submitToLg.mockResolvedValue( - new ApplicationSubmissionToSubmissionStatus(), - ); - const mockOwner = new ApplicationOwner({ uuid: primaryContactOwnerUuid }); - const mockApplicationSubmission = new ApplicationSubmission({ - typeCode: 'NOT-TURP', - owners: [mockOwner], - primaryContactOwnerUuid, - localGovernmentUuid, - submissionStatuses: [ - new ApplicationSubmissionToSubmissionStatus({ - statusTypeCode: SUBMISSION_STATUS.INCOMPLETE, - submissionUuid: 'fake', - effectiveDate: new Date(), - }), - ], - }); - mockAppSubmissionService.verifyAccessByUuid.mockResolvedValue( - mockApplicationSubmission, - ); - mockAppValidationService.validateSubmission.mockResolvedValue({ - submission: mockApplicationSubmission as ValidatedApplicationSubmission, - errors: [], - }); - mockStatusEmailService.sendApplicationStatusEmail.mockResolvedValue(); - - const mockGovernment = new LocalGovernment({ uuid: localGovernmentUuid }); - mockStatusEmailService.getApplicationEmailData.mockResolvedValue({ - applicationSubmission: mockApplicationSubmission, - primaryContact: mockOwner, - submissionGovernment: mockGovernment, - }); - - await controller.submitAsApplicant(mockFileId, { - user: { - entity: new User(), - }, - }); - - expect(mockAppSubmissionService.verifyAccessByUuid).toHaveBeenCalledTimes( - 1, - ); - expect(mockAppSubmissionService.submitToLg).toHaveBeenCalledTimes(1); - expect( - mockStatusEmailService.sendApplicationStatusEmail, - ).toHaveBeenCalledTimes(0); - }); - it('should throw an exception if application fails validation', async () => { const mockFileId = 'file-id'; const mockApplicationSubmission = new ApplicationSubmission({ diff --git a/services/apps/alcs/src/portal/application-submission/application-submission.controller.ts b/services/apps/alcs/src/portal/application-submission/application-submission.controller.ts index dc317ddb00..ecd7d0a4b4 100644 --- a/services/apps/alcs/src/portal/application-submission/application-submission.controller.ts +++ b/services/apps/alcs/src/portal/application-submission/application-submission.controller.ts @@ -16,8 +16,8 @@ import { } from '../../../../../libs/common/src/exceptions/base.exception'; import { generateCANCApplicationHtml } from '../../../../../templates/emails/cancelled'; import { - generateSUBGTurApplicantHtml, generateSUBGNoReviewGovernmentTemplateEmail, + generateSUBGTurApplicantHtml, } from '../../../../../templates/emails/submitted-to-alc'; import { generateSUBGCoveApplicantHtml } from '../../../../../templates/emails/submitted-to-alc/cove-applicant.template'; import { @@ -288,39 +288,25 @@ export class ApplicationSubmissionController { ); if (matchingType.requiresGovernmentReview) { - const wasSubmittedToLfng = validatedSubmission.submissionStatuses.find( - (s) => - [ - SUBMISSION_STATUS.SUBMITTED_TO_LG, - SUBMISSION_STATUS.IN_REVIEW_BY_LG, - SUBMISSION_STATUS.WRONG_GOV, - SUBMISSION_STATUS.INCOMPLETE, - ].includes(s.statusTypeCode as SUBMISSION_STATUS) && - !!s.effectiveDate, - ); - - // Send status emails for first time submissions - if (!wasSubmittedToLfng) { - if (primaryContact) { - await this.statusEmailService.sendApplicationStatusEmail({ - generateStatusHtml: generateSUBGApplicantHtml, - status: SUBMISSION_STATUS.SUBMITTED_TO_LG, - applicationSubmission: validatedSubmission, - government: submissionGovernment, - parentType: PARENT_TYPE.APPLICATION, - primaryContact, - }); - } + if (primaryContact) { + await this.statusEmailService.sendApplicationStatusEmail({ + generateStatusHtml: generateSUBGApplicantHtml, + status: SUBMISSION_STATUS.SUBMITTED_TO_LG, + applicationSubmission: validatedSubmission, + government: submissionGovernment, + parentType: PARENT_TYPE.APPLICATION, + primaryContact, + }); + } - if (submissionGovernment) { - await this.statusEmailService.sendApplicationStatusEmail({ - generateStatusHtml: generateSUBGGovernmentHtml, - status: SUBMISSION_STATUS.SUBMITTED_TO_LG, - applicationSubmission: validatedSubmission, - government: submissionGovernment, - parentType: PARENT_TYPE.APPLICATION, - }); - } + if (submissionGovernment) { + await this.statusEmailService.sendApplicationStatusEmail({ + generateStatusHtml: generateSUBGGovernmentHtml, + status: SUBMISSION_STATUS.SUBMITTED_TO_LG, + applicationSubmission: validatedSubmission, + government: submissionGovernment, + parentType: PARENT_TYPE.APPLICATION, + }); } return await this.applicationSubmissionService.submitToLg( From 2ae8f9f4262b2b86497e2e32a1b8ddbefb46359c Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Tue, 30 Apr 2024 16:24:44 -0700 Subject: [PATCH 02/21] Allow Snowplow via CSP * Track page changes --- alcs-frontend/nginx.conf | 2 +- alcs-frontend/src/app/app.component.ts | 11 +++++++++-- alcs-frontend/src/app/app.module.ts | 2 ++ .../app/services/analytics/analytics.service.ts | 17 +++++++++++++++++ portal-frontend/nginx.conf | 2 +- portal-frontend/src/app/app.component.ts | 1 + 6 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 alcs-frontend/src/app/services/analytics/analytics.service.ts diff --git a/alcs-frontend/nginx.conf b/alcs-frontend/nginx.conf index 6ccc98d57e..b7847867d7 100644 --- a/alcs-frontend/nginx.conf +++ b/alcs-frontend/nginx.conf @@ -19,7 +19,7 @@ http { add_header 'X-XSS-Protection' '1; mode=block'; add_header 'Strict-Transport-Security' 'max-age=31536000; includeSubDomains; preload'; add_header 'Cache-control' 'no-cache'; - add_header 'Content-Security-Policy' "default-src 'self';img-src 'self';style-src 'unsafe-inline' 'self';connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://alcs-metabase-test.apps.silver.devops.gov.bc.ca https://alcs-metabase-prod.apps.silver.devops.gov.bc.ca https://nrs.objectstore.gov.bc.ca;"; + add_header 'Content-Security-Policy' "default-src 'self'; img-src 'self'; style-src 'unsafe-inline' 'self'; connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://alcs-metabase-test.apps.silver.devops.gov.bc.ca https://alcs-metabase-prod.apps.silver.devops.gov.bc.ca https://nrs.objectstore.gov.bc.ca; script-src 'self' https://www2.gov.bc.ca"; add_header 'Permissions-Policy' 'camera=(), geolocation=(), microphone=()'; add_header 'Referrer-Policy' 'same-origin'; diff --git a/alcs-frontend/src/app/app.component.ts b/alcs-frontend/src/app/app.component.ts index fd3a584643..295e4b5efb 100644 --- a/alcs-frontend/src/app/app.component.ts +++ b/alcs-frontend/src/app/app.component.ts @@ -1,10 +1,17 @@ -import { Component } from '@angular/core'; +import { Component, OnInit } from '@angular/core'; +import { AnalyticsService } from './services/analytics/analytics.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) -export class AppComponent { +export class AppComponent implements OnInit { title = 'alcs-frontend'; + + constructor(private analyticsService: AnalyticsService) {} + + ngOnInit(): void { + this.analyticsService.init(); + } } diff --git a/alcs-frontend/src/app/app.module.ts b/alcs-frontend/src/app/app.module.ts index dda3216465..f6f7d1d014 100644 --- a/alcs-frontend/src/app/app.module.ts +++ b/alcs-frontend/src/app/app.module.ts @@ -12,6 +12,7 @@ import { AuthorizationComponent } from './features/authorization/authorization.c import { NotFoundComponent } from './features/errors/not-found/not-found.component'; import { LoginComponent } from './features/login/login.component'; import { ProvisionComponent } from './features/provision/provision.component'; +import { AnalyticsService } from './services/analytics/analytics.service'; import { AuthInterceptor } from './services/authentication/auth.interceptor'; import { TokenRefreshService } from './services/authentication/token-refresh.service'; import { UnauthorizedInterceptor } from './services/authentication/unauthorized.interceptor'; @@ -37,6 +38,7 @@ import { SharedModule } from './shared/shared.module'; ], imports: [BrowserModule, BrowserAnimationsModule, SharedModule.forRoot(), AppRoutingModule, MomentDateModule], providers: [ + AnalyticsService, { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: UnauthorizedInterceptor, multi: true }, { provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { panelClass: 'mat-dialog-override' } }, diff --git a/alcs-frontend/src/app/services/analytics/analytics.service.ts b/alcs-frontend/src/app/services/analytics/analytics.service.ts new file mode 100644 index 0000000000..107e47bf05 --- /dev/null +++ b/alcs-frontend/src/app/services/analytics/analytics.service.ts @@ -0,0 +1,17 @@ +import { Injectable } from '@angular/core'; +import { NavigationEnd, Router } from '@angular/router'; + +@Injectable({ + providedIn: 'root', +}) +export class AnalyticsService { + constructor(private router: Router) {} + + init() { + this.router.events.subscribe((event) => { + if (event instanceof NavigationEnd) { + (window as any).snowplow('trackPageView'); + } + }); + } +} diff --git a/portal-frontend/nginx.conf b/portal-frontend/nginx.conf index 8db9efc810..09766604d8 100644 --- a/portal-frontend/nginx.conf +++ b/portal-frontend/nginx.conf @@ -19,7 +19,7 @@ http { add_header 'X-XSS-Protection' '1; mode=block'; add_header 'Strict-Transport-Security' 'max-age=31536000; includeSubDomains; preload'; add_header 'Cache-control' 'no-cache'; - add_header 'Content-Security-Policy' "default-src 'self';img-src 'self';style-src 'unsafe-inline' 'self';connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://nrs.objectstore.gov.bc.ca;"; + add_header 'Content-Security-Policy' "default-src 'self'; img-src 'self'; style-src 'unsafe-inline' 'self'; connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://nrs.objectstore.gov.bc.ca; script-src 'self' https://www2.gov.bc.ca;"; add_header 'Permissions-Policy' 'camera=(), geolocation=(), microphone=()'; add_header 'Referrer-Policy' 'same-origin'; diff --git a/portal-frontend/src/app/app.component.ts b/portal-frontend/src/app/app.component.ts index a0fdf755fe..b3aa9e931c 100644 --- a/portal-frontend/src/app/app.component.ts +++ b/portal-frontend/src/app/app.component.ts @@ -17,6 +17,7 @@ export class AppComponent implements OnInit { this.router.events.subscribe((event) => { if (event instanceof NavigationEnd) { this.showHeaderFooter = !event.url.includes('/alcs/'); + (window as any).snowplow('trackPageView'); } }); } From fa771d6eec605ae2a08af83b356976c2a2d08d3f Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Tue, 30 Apr 2024 16:53:53 -0700 Subject: [PATCH 03/21] Move snowplow to its own script --- portal-frontend/src/assets/snowplow.js | 30 +++++++++++++++++++++ portal-frontend/src/index.html | 36 +------------------------- 2 files changed, 31 insertions(+), 35 deletions(-) create mode 100644 portal-frontend/src/assets/snowplow.js diff --git a/portal-frontend/src/assets/snowplow.js b/portal-frontend/src/assets/snowplow.js new file mode 100644 index 0000000000..d87b492873 --- /dev/null +++ b/portal-frontend/src/assets/snowplow.js @@ -0,0 +1,30 @@ +// +(function(p, l, o, w, i, n, g) { + if (!p[i]) { + p.GlobalSnowplowNamespace = p.GlobalSnowplowNamespace || []; + p.GlobalSnowplowNamespace.push(i); + p[i] = function() { + (p[i].q = p[i].q || []).push(arguments); + }; + p[i].q = p[i].q || []; + n = l.createElement(o); + g = l.getElementsByTagName(o)[0]; + n.async = 1; + n.src = w; + g.parentNode.insertBefore(n, g); + } +})(window, document, "script", "https://www2.gov.bc.ca/StaticWebResources/static/sp/sp-2-14-0.js", "snowplow"); +var collector = "spm.apps.gov.bc.ca"; +window.snowplow("newTracker", "rt", collector, { + appId: "Snowplow_standalone", + cookieLifetime: 86400 * 548, + platform: "web", + post: true, + forceSecureTracker: true, + contexts: { + webPage: true, performanceTiming: true + } +}); +window.snowplow("enableActivityTracking", 30, 30); // Ping every 30 seconds after 30 seconds +window.snowplow("enableLinkClickTracking"); +// diff --git a/portal-frontend/src/index.html b/portal-frontend/src/index.html index ca34a10771..8f28f22c83 100644 --- a/portal-frontend/src/index.html +++ b/portal-frontend/src/index.html @@ -9,41 +9,7 @@ - - + From 878c4cc5be4a8bebf5dd921a4a5031c4644904dc Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Wed, 1 May 2024 10:40:35 -0700 Subject: [PATCH 04/21] More Snowplow * Add script hash to enable it to load inline * Remove analytics service from ALCS, we are only doing tracking on portal --- alcs-frontend/src/app/app.component.ts | 11 +++-------- alcs-frontend/src/app/app.module.ts | 2 -- .../app/services/analytics/analytics.service.ts | 17 ----------------- portal-frontend/nginx.conf | 2 +- 4 files changed, 4 insertions(+), 28 deletions(-) delete mode 100644 alcs-frontend/src/app/services/analytics/analytics.service.ts diff --git a/alcs-frontend/src/app/app.component.ts b/alcs-frontend/src/app/app.component.ts index 295e4b5efb..b9e3e83ade 100644 --- a/alcs-frontend/src/app/app.component.ts +++ b/alcs-frontend/src/app/app.component.ts @@ -1,17 +1,12 @@ -import { Component, OnInit } from '@angular/core'; -import { AnalyticsService } from './services/analytics/analytics.service'; +import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) -export class AppComponent implements OnInit { +export class AppComponent { title = 'alcs-frontend'; - constructor(private analyticsService: AnalyticsService) {} - - ngOnInit(): void { - this.analyticsService.init(); - } + constructor() {} } diff --git a/alcs-frontend/src/app/app.module.ts b/alcs-frontend/src/app/app.module.ts index f6f7d1d014..dda3216465 100644 --- a/alcs-frontend/src/app/app.module.ts +++ b/alcs-frontend/src/app/app.module.ts @@ -12,7 +12,6 @@ import { AuthorizationComponent } from './features/authorization/authorization.c import { NotFoundComponent } from './features/errors/not-found/not-found.component'; import { LoginComponent } from './features/login/login.component'; import { ProvisionComponent } from './features/provision/provision.component'; -import { AnalyticsService } from './services/analytics/analytics.service'; import { AuthInterceptor } from './services/authentication/auth.interceptor'; import { TokenRefreshService } from './services/authentication/token-refresh.service'; import { UnauthorizedInterceptor } from './services/authentication/unauthorized.interceptor'; @@ -38,7 +37,6 @@ import { SharedModule } from './shared/shared.module'; ], imports: [BrowserModule, BrowserAnimationsModule, SharedModule.forRoot(), AppRoutingModule, MomentDateModule], providers: [ - AnalyticsService, { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true }, { provide: HTTP_INTERCEPTORS, useClass: UnauthorizedInterceptor, multi: true }, { provide: MAT_DIALOG_DEFAULT_OPTIONS, useValue: { panelClass: 'mat-dialog-override' } }, diff --git a/alcs-frontend/src/app/services/analytics/analytics.service.ts b/alcs-frontend/src/app/services/analytics/analytics.service.ts deleted file mode 100644 index 107e47bf05..0000000000 --- a/alcs-frontend/src/app/services/analytics/analytics.service.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Injectable } from '@angular/core'; -import { NavigationEnd, Router } from '@angular/router'; - -@Injectable({ - providedIn: 'root', -}) -export class AnalyticsService { - constructor(private router: Router) {} - - init() { - this.router.events.subscribe((event) => { - if (event instanceof NavigationEnd) { - (window as any).snowplow('trackPageView'); - } - }); - } -} diff --git a/portal-frontend/nginx.conf b/portal-frontend/nginx.conf index 09766604d8..24ca3ba89c 100644 --- a/portal-frontend/nginx.conf +++ b/portal-frontend/nginx.conf @@ -19,7 +19,7 @@ http { add_header 'X-XSS-Protection' '1; mode=block'; add_header 'Strict-Transport-Security' 'max-age=31536000; includeSubDomains; preload'; add_header 'Cache-control' 'no-cache'; - add_header 'Content-Security-Policy' "default-src 'self'; img-src 'self'; style-src 'unsafe-inline' 'self'; connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://nrs.objectstore.gov.bc.ca; script-src 'self' https://www2.gov.bc.ca;"; + add_header 'Content-Security-Policy' "default-src 'self'; img-src 'self'; style-src 'unsafe-inline' 'self'; connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://nrs.objectstore.gov.bc.ca; script-src 'self' https://www2.gov.bc.ca sha256-evje5KswYvntfuZqc5jmvUSANhIntI7Or6vVnjxGGQE=;"; add_header 'Permissions-Policy' 'camera=(), geolocation=(), microphone=()'; add_header 'Referrer-Policy' 'same-origin'; From d354fb3a4b21300f760b7d873437c8af544d4d41 Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Wed, 1 May 2024 11:40:56 -0700 Subject: [PATCH 05/21] Add connect-src for snowplower, fix main docker --- alcs-frontend/Dockerfile | 6 ++++-- portal-frontend/Dockerfile | 2 ++ portal-frontend/nginx.conf | 2 +- services/config/default.json | 12 ++++++++---- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/alcs-frontend/Dockerfile b/alcs-frontend/Dockerfile index 8b3552cf30..0e4e9569d5 100644 --- a/alcs-frontend/Dockerfile +++ b/alcs-frontend/Dockerfile @@ -5,14 +5,16 @@ FROM node:20-alpine AS build WORKDIR /app # Copy package.json file -COPY package.json . +COPY package.json package-lock.json ./ # Install dependencies -RUN npm install +RUN npm ci # Copy the source code to the /app directory COPY . . +ENV NODE_OPTIONS="--max-old-space-size=2048" + # Build the application RUN npm run build -- --output-path=dist --output-hashing=all diff --git a/portal-frontend/Dockerfile b/portal-frontend/Dockerfile index 8b3f351595..212720b0e3 100644 --- a/portal-frontend/Dockerfile +++ b/portal-frontend/Dockerfile @@ -13,6 +13,8 @@ RUN npm ci # Copy the source code to the /app directory COPY . . +ENV NODE_OPTIONS="--max-old-space-size=2048" + # Build the application RUN npm run build -- --output-path=dist --output-hashing=all diff --git a/portal-frontend/nginx.conf b/portal-frontend/nginx.conf index 24ca3ba89c..4f9a35f8a8 100644 --- a/portal-frontend/nginx.conf +++ b/portal-frontend/nginx.conf @@ -19,7 +19,7 @@ http { add_header 'X-XSS-Protection' '1; mode=block'; add_header 'Strict-Transport-Security' 'max-age=31536000; includeSubDomains; preload'; add_header 'Cache-control' 'no-cache'; - add_header 'Content-Security-Policy' "default-src 'self'; img-src 'self'; style-src 'unsafe-inline' 'self'; connect-src $ENABLED_CONNECT_SRC; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://nrs.objectstore.gov.bc.ca; script-src 'self' https://www2.gov.bc.ca sha256-evje5KswYvntfuZqc5jmvUSANhIntI7Or6vVnjxGGQE=;"; + add_header 'Content-Security-Policy' "default-src 'self'; img-src 'self'; style-src 'unsafe-inline' 'self'; connect-src $ENABLED_CONNECT_SRC https://spm.apps.gov.bc.ca; font-src 'self' https://fonts.gstatic.com https://fonts.googleapis.com; base-uri 'self'; object-src https://nrs.objectstore.gov.bc.ca; frame-src https://nrs.objectstore.gov.bc.ca; script-src 'self' https://www2.gov.bc.ca 'sha256-evje5KswYvntfuZqc5jmvUSANhIntI7Or6vVnjxGGQE=';"; add_header 'Permissions-Policy' 'camera=(), geolocation=(), microphone=()'; add_header 'Referrer-Policy' 'same-origin'; diff --git a/services/config/default.json b/services/config/default.json index f4b411c42c..6cfa5e4351 100644 --- a/services/config/default.json +++ b/services/config/default.json @@ -32,7 +32,9 @@ "AUTH_SERVER": "test.loginproxy.gov.bc.ca", "AUTH_SERVER_URL": "https://test.loginproxy.gov.bc.ca/auth", "AUTH_TOKEN_URL": "https://test.loginproxy.gov.bc.ca/auth/realms/standard/protocol/openid-connect/token", - "SCOPES": ["openid"], + "SCOPES": [ + "openid" + ], "REALM": "standard" }, "SITEMINDER": { @@ -61,12 +63,14 @@ "MAX_FILE_SIZE": 104857600 }, "REDIS": { - "HOST": "localhost", + "HOST": "redis", "PORT": "6379", - "PASSWORD": "" + "PASSWORD": "redis" }, "EMAIL": { - "DEFAULT_ADMINS": [""] + "DEFAULT_ADMINS": [ + "" + ] }, "GRPC": { "BIND_URL": "localhost:50057", From 7c1bb20ac31263ae9406de58334d9a42fbc4a44e Mon Sep 17 00:00:00 2001 From: Mekhti Date: Thu, 2 May 2024 11:51:02 -0700 Subject: [PATCH 06/21] fix send email on LFNG change --- .../notice-of-intent-submission-status.service.ts | 1 - .../notice-of-intent-submission-draft.service.spec.ts | 6 +++--- .../notice-of-intent-submission-draft.service.ts | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/services/apps/alcs/src/alcs/notice-of-intent/notice-of-intent-submission-status/notice-of-intent-submission-status.service.ts b/services/apps/alcs/src/alcs/notice-of-intent/notice-of-intent-submission-status/notice-of-intent-submission-status.service.ts index 87e7c14355..f523b6d3de 100644 --- a/services/apps/alcs/src/alcs/notice-of-intent/notice-of-intent-submission-status/notice-of-intent-submission-status.service.ts +++ b/services/apps/alcs/src/alcs/notice-of-intent/notice-of-intent-submission-status/notice-of-intent-submission-status.service.ts @@ -166,7 +166,6 @@ export class NoticeOfIntentSubmissionStatusService { async saveSubmissionToSubmissionStatus( submissionStatus: NoticeOfIntentSubmissionToSubmissionStatus, ) { - console.log('save', submissionStatus); return await this.statusesRepository.save(submissionStatus); } } diff --git a/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.spec.ts b/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.spec.ts index a76135884e..1c2a6e49cb 100644 --- a/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.spec.ts +++ b/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.spec.ts @@ -228,7 +228,7 @@ describe('NoticeOfIntentSubmissionDraftService', () => { mockGenerateSubmissionDocumentService.generateUpdate.mockResolvedValue(); mockNoiSubmissionStatusService.removeStatuses.mockResolvedValue({} as any); mockNoiService.updateNoticeOfIntentInfo.mockResolvedValue(); - mockLocalGovernmentService.getByGuid.mockResolvedValue( + mockLocalGovernmentService.getByUuid.mockResolvedValue( new LocalGovernment({ uuid: 'new' }), ); mockStatusEmailService.sendNoticeOfIntentStatusEmail.mockResolvedValue(); @@ -248,8 +248,8 @@ describe('NoticeOfIntentSubmissionDraftService', () => { mockGenerateSubmissionDocumentService.generateUpdate, ).toHaveBeenCalledTimes(1); expect(mockNoiService.updateNoticeOfIntentInfo).toHaveBeenCalledTimes(1); - expect(mockLocalGovernmentService.getByGuid).toHaveBeenCalledTimes(1); - expect(mockLocalGovernmentService.getByGuid).toHaveBeenCalledWith('new'); + expect(mockLocalGovernmentService.getByUuid).toHaveBeenCalledTimes(1); + expect(mockLocalGovernmentService.getByUuid).toHaveBeenCalledWith('new'); expect( mockStatusEmailService.sendNoticeOfIntentStatusEmail, ).toHaveBeenCalledTimes(1); diff --git a/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.ts b/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.ts index c953e175fd..53ddf6feb5 100644 --- a/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.ts +++ b/services/apps/alcs/src/portal/notice-of-intent-submission-draft/notice-of-intent-submission-draft.service.ts @@ -244,7 +244,7 @@ export class NoticeOfIntentSubmissionDraftService { } private async sendGovernmentEmail(savedDraft: NoticeOfIntentSubmission) { - const submissionGovernment = await this.localGovernmentService.getByGuid( + const submissionGovernment = await this.localGovernmentService.getByUuid( savedDraft.localGovernmentUuid!, ); @@ -267,7 +267,7 @@ export class NoticeOfIntentSubmissionDraftService { ); } catch (error) { this.logger.error( - `Error generating NOI submission document {error}`, + `Error generating NOI submission document ${error}`, error, ); } From 3a9411b2068bae6a35c4ca488e5dd456aa0a948f Mon Sep 17 00:00:00 2001 From: "to. sandra" <76515860+sandratoh@users.noreply.github.com> Date: Thu, 2 May 2024 13:49:36 -0700 Subject: [PATCH 07/21] Navigate to planning review detail view from header search (#1650) --- .../src/app/shared/header/search-bar/search-bar.component.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/alcs-frontend/src/app/shared/header/search-bar/search-bar.component.ts b/alcs-frontend/src/app/shared/header/search-bar/search-bar.component.ts index d2c74f9367..513172ba6a 100644 --- a/alcs-frontend/src/app/shared/header/search-bar/search-bar.component.ts +++ b/alcs-frontend/src/app/shared/header/search-bar/search-bar.component.ts @@ -97,9 +97,7 @@ export class SearchBarComponent implements AfterViewInit { break; case 'COV': case 'PLAN': - await this.router.navigateByUrl( - `/board/${result.boardCode}?card=${result.referenceId}&type=${result.type}`, - ); + await this.router.navigate(['planning-review', result.referenceId]); break; default: this.toastService.showErrorToast(`Unable to navigate to ${result.referenceId}`); From 194ba0810f10e2f4b5f97d6bec65f99aa16f0333 Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Mon, 6 May 2024 13:28:43 -0700 Subject: [PATCH 08/21] Do not count planning referrals without cards for PR header * Prevents showing go to card when the referral has no card --- .../src/app/features/board/board.component.ts | 12 ++++++------ .../create-planning-review-dialog.component.ts | 2 +- .../planning-review-dialog.component.ts | 8 ++++---- .../app/features/home/assigned/assigned.component.ts | 12 ++++++------ .../planning-review/header/header.component.ts | 10 ++++++---- .../services/planning-review/planning-review.dto.ts | 2 +- 6 files changed, 24 insertions(+), 22 deletions(-) diff --git a/alcs-frontend/src/app/features/board/board.component.ts b/alcs-frontend/src/app/features/board/board.component.ts index 0fd0d029fb..5ad6ca0e88 100644 --- a/alcs-frontend/src/app/features/board/board.component.ts +++ b/alcs-frontend/src/app/features/board/board.component.ts @@ -390,18 +390,18 @@ export class BoardComponent implements OnInit, OnDestroy { private mapPlanningReferralToCard(referral: PlanningReferralDto): CardData { return { - status: referral.card.status.code, + status: referral.card!.status.code, typeLabel: 'Planning Review', title: `${referral.planningReview.fileNumber} (${referral.planningReview.documentName})`, titleTooltip: referral.planningReview.type.label, - assignee: referral.card.assignee, - id: referral.card.uuid, + assignee: referral.card!.assignee, + id: referral.card!.uuid, labels: [referral.planningReview.type], cardType: CardType.PLAN, paused: false, - highPriority: referral.card.highPriority, - cardUuid: referral.card.uuid, - dateReceived: referral.card.createdAt, + highPriority: referral.card!.highPriority, + cardUuid: referral.card!.uuid, + dateReceived: referral.card!.createdAt, dueDate: referral.dueDate ? new Date(referral.dueDate) : undefined, decisionMeetings: referral.planningReview.meetings, showDueDate: true, diff --git a/alcs-frontend/src/app/features/board/dialogs/planning-review/create/create-planning-review-dialog.component.ts b/alcs-frontend/src/app/features/board/dialogs/planning-review/create/create-planning-review-dialog.component.ts index c23c38c897..2feac68d92 100644 --- a/alcs-frontend/src/app/features/board/dialogs/planning-review/create/create-planning-review-dialog.component.ts +++ b/alcs-frontend/src/app/features/board/dialogs/planning-review/create/create-planning-review-dialog.component.ts @@ -91,7 +91,7 @@ export class CreatePlanningReviewDialogComponent implements OnInit, OnDestroy { this.dialogRef.close(true); if (res) { await this.router.navigate(this.activatedRoute.snapshot.url, { - queryParams: res.card.uuid && res.card.type ? { card: res.card.uuid, type: res.card.type } : {}, + queryParams: res.card && res.card.uuid && res.card.type ? { card: res.card.uuid, type: res.card.type } : {}, relativeTo: this.activatedRoute, }); } diff --git a/alcs-frontend/src/app/features/board/dialogs/planning-review/planning-review-dialog.component.ts b/alcs-frontend/src/app/features/board/dialogs/planning-review/planning-review-dialog.component.ts index 3da9313146..0289809c2d 100644 --- a/alcs-frontend/src/app/features/board/dialogs/planning-review/planning-review-dialog.component.ts +++ b/alcs-frontend/src/app/features/board/dialogs/planning-review/planning-review-dialog.component.ts @@ -55,7 +55,7 @@ export class PlanningReviewDialogComponent extends CardDialogComponent implement ...this.data.planningReview.type, borderColor: this.data.planningReview.type.backgroundColor, }; - this.populateCardData(this.data.card); + this.populateCardData(this.data.card!); this.selectedRegion = this.data.planningReview.region.code; this.cardTitle = `${this.data.planningReview.fileNumber} (${this.data.planningReview.documentName})`; @@ -64,16 +64,16 @@ export class PlanningReviewDialogComponent extends CardDialogComponent implement } private async reload() { - const planningReferral = await this.planningReferralService.fetchByCardUuid(this.planningReferral.card.uuid); + const planningReferral = await this.planningReferralService.fetchByCardUuid(this.planningReferral.card!.uuid); if (planningReferral) { - await this.populateCardData(planningReferral.card); + await this.populateCardData(planningReferral.card!); } } async onBoardSelected(board: BoardWithFavourite) { this.selectedBoard = board.code; try { - await this.boardService.changeBoard(this.planningReferral.card.uuid, board.code); + await this.boardService.changeBoard(this.planningReferral.card!.uuid, board.code); const loadedBoard = await this.boardService.fetchBoardDetail(board.code); if (loadedBoard) { this.boardStatuses = loadedBoard.statuses; diff --git a/alcs-frontend/src/app/features/home/assigned/assigned.component.ts b/alcs-frontend/src/app/features/home/assigned/assigned.component.ts index c956801892..84f9f730d9 100644 --- a/alcs-frontend/src/app/features/home/assigned/assigned.component.ts +++ b/alcs-frontend/src/app/features/home/assigned/assigned.component.ts @@ -98,11 +98,11 @@ export class AssignedComponent implements OnInit { this.planningReferrals = [ ...planningReferrals - .filter((r) => r.card.highPriority) + .filter((r) => r.card!.highPriority) .map((r) => this.mapPlanningReferral(r)) .sort((a, b) => a.date! - b.date!), ...planningReferrals - .filter((r) => !r.card.highPriority) + .filter((r) => !r.card!.highPriority) .map((r) => this.mapPlanningReferral(r)) .sort((a, b) => a.date! - b.date!), ]; @@ -139,10 +139,10 @@ export class AssignedComponent implements OnInit { private mapPlanningReferral(p: PlanningReferralDto): AssignedToMeFile { return { title: `${p.planningReview.fileNumber} (${p.planningReview.documentName})`, - type: p.card.type, - date: p.card.createdAt, - card: p.card, - highPriority: p.card.highPriority, + type: p.card!.type, + date: p.card!.createdAt, + card: p.card!, + highPriority: p.card!.highPriority, labels: [p.planningReview.type], }; } diff --git a/alcs-frontend/src/app/features/planning-review/header/header.component.ts b/alcs-frontend/src/app/features/planning-review/header/header.component.ts index 488602c79d..2646bcb6f4 100644 --- a/alcs-frontend/src/app/features/planning-review/header/header.component.ts +++ b/alcs-frontend/src/app/features/planning-review/header/header.component.ts @@ -32,10 +32,12 @@ export class HeaderComponent implements OnChanges { async setupLinkedCards() { if ('referrals' in this.planningReview) { for (const [index, referral] of this.planningReview.referrals.entries()) { - this.linkedCards.push({ - ...referral.card, - displayName: `Referral #${this.planningReview.referrals.length - index}`, - }); + if (referral.card) { + this.linkedCards.push({ + ...referral.card, + displayName: `Referral #${this.planningReview.referrals.length - index}`, + }); + } } } } diff --git a/alcs-frontend/src/app/services/planning-review/planning-review.dto.ts b/alcs-frontend/src/app/services/planning-review/planning-review.dto.ts index 60cada333a..00616cc4ea 100644 --- a/alcs-frontend/src/app/services/planning-review/planning-review.dto.ts +++ b/alcs-frontend/src/app/services/planning-review/planning-review.dto.ts @@ -60,7 +60,7 @@ export interface PlanningReferralDto { responseDescription?: string; submissionDate: number; planningReview: PlanningReviewDto; - card: CardDto; + card?: CardDto; } export interface UpdatePlanningReviewDto { From b80dc5c1c452426ee21108618b51ed21df20a5b2 Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Mon, 6 May 2024 13:44:01 -0700 Subject: [PATCH 09/21] Add inquiry to assigned and subtask counts * Was missing from some subtask views --- .../src/app/features/home/assigned/assigned.component.ts | 3 ++- .../src/app/features/home/subtask/subtask.component.ts | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/alcs-frontend/src/app/features/home/assigned/assigned.component.ts b/alcs-frontend/src/app/features/home/assigned/assigned.component.ts index c956801892..4588ee8213 100644 --- a/alcs-frontend/src/app/features/home/assigned/assigned.component.ts +++ b/alcs-frontend/src/app/features/home/assigned/assigned.component.ts @@ -133,7 +133,8 @@ export class AssignedComponent implements OnInit { this.applications.length + this.planningReferrals.length + this.noticeOfIntents.length + - this.notifications.length; + this.notifications.length + + this.inquiries.length; } private mapPlanningReferral(p: PlanningReferralDto): AssignedToMeFile { diff --git a/alcs-frontend/src/app/features/home/subtask/subtask.component.ts b/alcs-frontend/src/app/features/home/subtask/subtask.component.ts index c52f114f97..f5e1bf47a1 100644 --- a/alcs-frontend/src/app/features/home/subtask/subtask.component.ts +++ b/alcs-frontend/src/app/features/home/subtask/subtask.component.ts @@ -100,7 +100,10 @@ export class SubtaskComponent implements OnInit, OnDestroy { if (this.showAppAndNonApp) { this.totalSubtaskCount = - this.applicationSubtasks.length + this.planningReviewSubtasks.length + this.notificationSubtasks.length; + this.applicationSubtasks.length + + this.planningReviewSubtasks.length + + this.notificationSubtasks.length + + this.inquirySubtasks.length; } if (this.showAppAndNonApp && this.showNoi) { From ae50ceefe1136932f6d03c9c888782799ce326e6 Mon Sep 17 00:00:00 2001 From: Mekhti Date: Mon, 6 May 2024 15:01:43 -0700 Subject: [PATCH 10/21] do not populate visibility flag on Planning Review documents --- .../alcs_documents_to_planning_review_documents.py | 2 +- .../alcs_documents_to_planning_review_documents.sql | 9 --------- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/bin/migrate-oats-data/documents/post_launch/alcs_documents_to_planning_review_documents.py b/bin/migrate-oats-data/documents/post_launch/alcs_documents_to_planning_review_documents.py index 3c17808a21..54dbb39dff 100644 --- a/bin/migrate-oats-data/documents/post_launch/alcs_documents_to_planning_review_documents.py +++ b/bin/migrate-oats-data/documents/post_launch/alcs_documents_to_planning_review_documents.py @@ -119,7 +119,7 @@ def _map_data(row): "planning_review_uuid": row["planning_review_uuid"], "document_uuid": row["document_uuid"], "type_code": row["type_code"], - "visibility_flags": row["visibility_flags"], + "visibility_flags": '{""}', "oats_document_id": row["oats_document_id"], "oats_planning_review_id": row["oats_planning_review_id"], "audit_created_by": OATS_ETL_USER, diff --git a/bin/migrate-oats-data/documents/post_launch/sql/planning_review/alcs_documents_to_planning_review_documents.sql b/bin/migrate-oats-data/documents/post_launch/sql/planning_review/alcs_documents_to_planning_review_documents.sql index a9ebec6a29..4dfa1d8340 100644 --- a/bin/migrate-oats-data/documents/post_launch/sql/planning_review/alcs_documents_to_planning_review_documents.sql +++ b/bin/migrate-oats-data/documents/post_launch/sql/planning_review/alcs_documents_to_planning_review_documents.sql @@ -15,15 +15,6 @@ with oats_documents_to_map as ( select otm.planning_review_uuid, otm.document_uuid, otm.code as type_code, - ( - case - when is_public = 'Y' - and is_app_lg = 'Y' then '{P, A, C, G}'::text [] - when is_public = 'Y' then '{P}'::text [] - when is_app_lg = 'Y' then '{A, C, G}'::text [] - else '{}'::text [] - end - ) as visibility_flags, oats_document_id, oats_planning_review_id, otm."description" From 755ad1d480b93c242b8b7275b65dd7252a9a6d31 Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Mon, 6 May 2024 15:49:07 -0700 Subject: [PATCH 11/21] Retain file type when renaming file * This retains the type so not everything it octet-stream * Code was already in place for applications --- .../decision-document-upload-dialog.component.ts | 2 +- .../decision-document-upload-dialog.component.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts index 216603ce5d..97ada1a8c9 100644 --- a/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts +++ b/alcs-frontend/src/app/features/notice-of-intent/decision/decision-v2/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts @@ -69,7 +69,7 @@ export class DecisionDocumentUploadDialogComponent implements OnInit { async onSubmit() { const file = this.pendingFile; if (file) { - const renamedFile = new File([file], this.name.value + this.extension ?? file.name); + const renamedFile = new File([file], this.name.value + this.extension ?? file.name, { type: file.type }); this.isSaving = true; if (this.data.existingDocument) { await this.decisionService.deleteFile(this.data.decisionUuid, this.data.existingDocument.uuid); diff --git a/alcs-frontend/src/app/features/planning-review/decision/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts b/alcs-frontend/src/app/features/planning-review/decision/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts index 8cb4121902..0aa89857bc 100644 --- a/alcs-frontend/src/app/features/planning-review/decision/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts +++ b/alcs-frontend/src/app/features/planning-review/decision/decision-input/decision-file-upload-dialog/decision-document-upload-dialog.component.ts @@ -66,7 +66,7 @@ export class DecisionDocumentUploadDialogComponent implements OnInit { async onSubmit() { const file = this.pendingFile; if (file) { - const renamedFile = new File([file], this.name.value + this.extension ?? file.name); + const renamedFile = new File([file], this.name.value + this.extension ?? file.name, { type: file.type }); this.isSaving = true; if (this.data.existingDocument) { await this.decisionService.deleteFile(this.data.decisionUuid, this.data.existingDocument.uuid); From 048d8e1c8db7e6094c8aea35719758e729fdb1e7 Mon Sep 17 00:00:00 2001 From: "to. sandra" <76515860+sandratoh@users.noreply.github.com> Date: Mon, 6 May 2024 16:05:02 -0700 Subject: [PATCH 12/21] Add submission date to PR search results and update default sor field (#1656) --- .../inquiry-search-table/inquiry-search-table.component.ts | 2 +- .../planning-review-search-table.component.html | 7 +++++++ .../planning-review-search-table.component.ts | 5 +++-- services/apps/alcs/src/alcs/search/search.controller.ts | 1 + services/apps/alcs/src/alcs/search/search.dto.ts | 1 + 5 files changed, 13 insertions(+), 3 deletions(-) diff --git a/alcs-frontend/src/app/features/search/inquiry-search-table/inquiry-search-table.component.ts b/alcs-frontend/src/app/features/search/inquiry-search-table/inquiry-search-table.component.ts index d8a054aee8..3ef4122bd8 100644 --- a/alcs-frontend/src/app/features/search/inquiry-search-table/inquiry-search-table.component.ts +++ b/alcs-frontend/src/app/features/search/inquiry-search-table/inquiry-search-table.component.ts @@ -43,7 +43,7 @@ export class InquirySearchTableComponent { itemsPerPage = 20; total = 0; sortDirection: SortDirection = 'desc'; - sortField = 'fileId'; + sortField = 'dateSubmitted'; isLoading = false; constructor(private router: Router) {} diff --git a/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.html b/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.html index 8e329d8fa1..cce82b4163 100644 --- a/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.html +++ b/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.html @@ -16,6 +16,13 @@ + + Date Submitted to ALC + + {{ element.dateSubmitted | date | emptyColumn }} + + + Type diff --git a/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.ts b/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.ts index 9aeb07a46a..03b7cbb667 100644 --- a/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.ts +++ b/alcs-frontend/src/app/features/search/planning-review-search-table/planning-review-search-table.component.ts @@ -8,6 +8,7 @@ import { TableChange } from '../search.interface'; interface SearchResult { fileNumber: string; + dateSubmitted: number; applicant: string; localGovernmentName?: string; referenceId: string; @@ -36,13 +37,13 @@ export class PlanningReviewSearchTableComponent { @Output() tableChange = new EventEmitter(); - displayedColumns = ['fileId', 'type', 'applicant', 'government', 'status']; + displayedColumns = ['fileId', 'dateSubmitted', 'type', 'applicant', 'government', 'status']; dataSource: PlanningReviewSearchResultDto[] = []; itemsPerPage = 20; total = 0; sortDirection: SortDirection = 'desc'; - sortField = 'fileId'; + sortField = 'dateSubmitted'; isLoading = false; constructor(private router: Router) {} diff --git a/services/apps/alcs/src/alcs/search/search.controller.ts b/services/apps/alcs/src/alcs/search/search.controller.ts index f4472d5949..600c99d0fd 100644 --- a/services/apps/alcs/src/alcs/search/search.controller.ts +++ b/services/apps/alcs/src/alcs/search/search.controller.ts @@ -581,6 +581,7 @@ export class SearchController { documentName: planningReview.documentName, referenceId: planningReview.fileNumber, fileNumber: planningReview.fileNumber, + dateSubmitted: planningReview.dateSubmittedToAlc, open: planningReview.open, type: { code: planningReview.planningReviewType_code, diff --git a/services/apps/alcs/src/alcs/search/search.dto.ts b/services/apps/alcs/src/alcs/search/search.dto.ts index c4b714c64b..b37361d719 100644 --- a/services/apps/alcs/src/alcs/search/search.dto.ts +++ b/services/apps/alcs/src/alcs/search/search.dto.ts @@ -56,6 +56,7 @@ export class PlanningReviewSearchResultDto { documentName: string | null; referenceId: string | null; localGovernmentName: string | null; + dateSubmitted: number; fileNumber: string; class: SearchEntityClass; open: boolean; From 85a908dfcc4b56d63169220022e617bcebc7817c Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Mon, 6 May 2024 16:29:35 -0700 Subject: [PATCH 13/21] Filter out PRs without Cards from Schedule --- .../alcs/src/alcs/meetings/decision-meeting.controller.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/services/apps/alcs/src/alcs/meetings/decision-meeting.controller.ts b/services/apps/alcs/src/alcs/meetings/decision-meeting.controller.ts index e88280287f..32daf27aaf 100644 --- a/services/apps/alcs/src/alcs/meetings/decision-meeting.controller.ts +++ b/services/apps/alcs/src/alcs/meetings/decision-meeting.controller.ts @@ -192,7 +192,7 @@ export class DecisionMeetingController { (meeting) => meeting.uuid === planningReferral.planningReview.uuid, ); - if (!meetingDate) { + if (!meetingDate || !planningReferral.card) { return []; } @@ -201,10 +201,10 @@ export class DecisionMeetingController { meetingDate: new Date(meetingDate.next_meeting).getTime(), fileNumber: planningReferral.planningReview.fileNumber, applicant: planningReferral.planningReview.documentName, - boardCode: planningReferral.card!.board.code, + boardCode: planningReferral.card.board.code, type: CARD_TYPE.PLAN, assignee: this.mapper.map( - planningReferral.card!.assignee, + planningReferral.card.assignee, User, UserDto, ), From 1f4c9520c5b15bcdf09e0260b13edf76c0f710b3 Mon Sep 17 00:00:00 2001 From: Mekhti Date: Tue, 7 May 2024 11:15:46 -0700 Subject: [PATCH 14/21] Fix for PR decision indexing --- .../init_planning_review_decisions.py | 29 +++++++++++++++---- .../planning_review_decisions_insert.sql | 3 +- .../planning-review-decision.controller.ts | 26 ++++++++--------- .../planning-review-decision.service.ts | 2 +- 4 files changed, 39 insertions(+), 21 deletions(-) diff --git a/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py b/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py index a9bab23e14..5cc7f90a7a 100644 --- a/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py +++ b/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py @@ -5,6 +5,8 @@ add_timezone_and_keep_date_part, OatsToAlcsDecisionOutcomes, AlcsPlanningReviewOutcomes, + to_alcs_format, + get_now_with_offset, ) from db import inject_conn_pool from psycopg2.extras import RealDictCursor, execute_batch @@ -39,6 +41,8 @@ def process_planning_review_decisions(conn=None, batch_size=BATCH_UPLOAD_SIZE): failed_inserts_count = 0 successful_inserts_count = 0 last_planning_decision_id = 0 + last_file_number = 0 + last_decision_date = "" with open( "planning_review/sql/decisions/planning_review_decisions_insert.sql", @@ -47,10 +51,16 @@ def process_planning_review_decisions(conn=None, batch_size=BATCH_UPLOAD_SIZE): ) as sql_file: query = sql_file.read() while True: + query_condition = "" + if last_decision_date: + query_condition = f"WHERE pr.file_number::bigint >= {last_file_number} AND opd.decision_date >= {last_decision_date} AND opd.planning_decision_id > {last_planning_decision_id} ORDER BY pr.file_number::bigint, opd.decision_date, opd.planning_decision_id;" + else: + query_condition = f"WHERE pr.file_number::bigint >= {last_file_number} AND opd.planning_decision_id > {last_planning_decision_id} ORDER BY pr.file_number::bigint, opd.decision_date, opd.planning_decision_id;" + cursor.execute( f""" {query} - WHERE opd.planning_decision_id > {last_planning_decision_id} ORDER BY opd.planning_decision_id; + {query_condition} """ ) @@ -64,9 +74,10 @@ def process_planning_review_decisions(conn=None, batch_size=BATCH_UPLOAD_SIZE): successful_inserts_count = successful_inserts_count + len( inserted_data ) - last_planning_decision_id = dict(inserted_data[-1])[ - "planning_decision_id" - ] + last_record = dict(inserted_data[-1]) + last_planning_decision_id = last_record["planning_decision_id"] + last_file_number = last_record["file_number"] + last_decision_date = last_record["decision_date"] logger.debug( f"Retrieved/updated items count: {len(inserted_data)}; total successfully inserted planning referral so far {successful_inserts_count}; last updated planning_decision_id: {last_planning_decision_id}" @@ -106,7 +117,8 @@ def _insert_base_fields(conn, batch_size, cursor, rows): outcome_code, resolution_number, resolution_year, - date + date, + created_at ) VALUES ( %(review_uuid)s, @@ -116,13 +128,16 @@ def _insert_base_fields(conn, batch_size, cursor, rows): %(outcome_code)s, %(resolution_number)s, %(resolution_year)s, - %(date)s + %(date)s, + %(created_at)s ) + ON CONFLICT DO NOTHING; """ def _prepare_oats_planning_review_data(row_data_list): mapped_data_list = [] + insert_index = 0 for row in row_data_list: mapped_data_list.append( { @@ -134,8 +149,10 @@ def _prepare_oats_planning_review_data(row_data_list): "outcome_code": _map_outcome_code(row), "resolution_number": row["resolution_number"], "resolution_year": _map_resolution_year(row), + "created_at": to_alcs_format(get_now_with_offset(insert_index)), } ) + insert_index += 1 return mapped_data_list diff --git a/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql b/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql index cbd40c3352..321fecc8cf 100644 --- a/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql +++ b/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql @@ -5,7 +5,8 @@ SELECT opd.planning_acceptance_code, pr."uuid", opd.resolution_number, - opd.planning_decision_id + opd.planning_decision_id, + pr.file_number FROM oats.oats_planning_decisions opd JOIN alcs.planning_review pr ON opd.planning_review_id::TEXT = pr.file_number \ No newline at end of file diff --git a/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.controller.ts b/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.controller.ts index 7df9104110..0a24379981 100644 --- a/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.controller.ts +++ b/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.controller.ts @@ -32,7 +32,7 @@ import { PlanningReviewDecisionService } from './planning-review-decision.servic @UseGuards(RolesGuard) export class PlanningReviewDecisionController { constructor( - private plannigReviewDecisionService: PlanningReviewDecisionService, + private planningReviewDecisionService: PlanningReviewDecisionService, @InjectMapper() private mapper: Mapper, ) {} @@ -42,7 +42,7 @@ export class PlanningReviewDecisionController { @Param('fileNumber') fileNumber, ): Promise { const decisions = - await this.plannigReviewDecisionService.getByFileNumber(fileNumber); + await this.planningReviewDecisionService.getByFileNumber(fileNumber); return await this.mapper.mapArrayAsync( decisions, @@ -54,7 +54,7 @@ export class PlanningReviewDecisionController { @Get('/codes') @UserRoles(...ANY_AUTH_ROLE) async getCodes() { - const codes = await this.plannigReviewDecisionService.fetchCodes(); + const codes = await this.planningReviewDecisionService.fetchCodes(); return await this.mapper.mapArrayAsync( codes.outcomes, PlanningReviewDecisionOutcomeCode, @@ -65,7 +65,7 @@ export class PlanningReviewDecisionController { @Get('/:uuid') @UserRoles(...ANY_AUTH_ROLE) async get(@Param('uuid') uuid: string): Promise { - const decision = await this.plannigReviewDecisionService.get(uuid); + const decision = await this.planningReviewDecisionService.get(uuid); return this.mapper.mapAsync( decision, @@ -80,7 +80,7 @@ export class PlanningReviewDecisionController { @Body() createDto: CreatePlanningReviewDecisionDto, ): Promise { const newDecision = - await this.plannigReviewDecisionService.create(createDto); + await this.planningReviewDecisionService.create(createDto); return this.mapper.mapAsync( newDecision, @@ -95,7 +95,7 @@ export class PlanningReviewDecisionController { @Param('uuid') uuid: string, @Body() updateDto: UpdatePlanningReviewDecisionDto, ): Promise { - const updatedDecision = await this.plannigReviewDecisionService.update( + const updatedDecision = await this.planningReviewDecisionService.update( uuid, updateDto, ); @@ -110,7 +110,7 @@ export class PlanningReviewDecisionController { @Delete('/:uuid') @UserRoles(...ANY_AUTH_ROLE) async delete(@Param('uuid') uuid: string) { - return await this.plannigReviewDecisionService.delete(uuid); + return await this.planningReviewDecisionService.delete(uuid); } @Post('/:uuid/file') @@ -121,7 +121,7 @@ export class PlanningReviewDecisionController { } const file = req.body.file; - await this.plannigReviewDecisionService.attachDocument( + await this.planningReviewDecisionService.attachDocument( decisionUuid, file, req.user.entity, @@ -138,7 +138,7 @@ export class PlanningReviewDecisionController { @Param('documentUuid') documentUuid: string, @Body() body: { fileName: string }, ) { - await this.plannigReviewDecisionService.updateDocument( + await this.planningReviewDecisionService.updateDocument( documentUuid, body.fileName, ); @@ -154,7 +154,7 @@ export class PlanningReviewDecisionController { @Param('fileUuid') documentUuid: string, ) { const downloadUrl = - await this.plannigReviewDecisionService.getDownloadUrl(documentUuid); + await this.planningReviewDecisionService.getDownloadUrl(documentUuid); return { url: downloadUrl, }; @@ -166,7 +166,7 @@ export class PlanningReviewDecisionController { @Param('uuid') decisionUuid: string, @Param('fileUuid') documentUuid: string, ) { - const downloadUrl = await this.plannigReviewDecisionService.getDownloadUrl( + const downloadUrl = await this.planningReviewDecisionService.getDownloadUrl( documentUuid, true, ); @@ -181,7 +181,7 @@ export class PlanningReviewDecisionController { @Param('uuid') decisionUuid: string, @Param('fileUuid') documentUuid: string, ) { - await this.plannigReviewDecisionService.deleteDocument(documentUuid); + await this.planningReviewDecisionService.deleteDocument(documentUuid); return {}; } @@ -190,7 +190,7 @@ export class PlanningReviewDecisionController { async getNextAvailableResolutionNumber( @Param('resolutionYear') resolutionYear: number, ) { - return this.plannigReviewDecisionService.generateResolutionNumber( + return this.planningReviewDecisionService.generateResolutionNumber( resolutionYear, ); } diff --git a/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.service.ts b/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.service.ts index c9c12901f3..0e0dac8c1e 100644 --- a/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.service.ts +++ b/services/apps/alcs/src/alcs/planning-review/planning-review-decision/planning-review-decision.service.ts @@ -5,7 +5,7 @@ import { import { MultipartFile } from '@fastify/multipart'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { In, IsNull, Repository } from 'typeorm'; +import { IsNull, Repository } from 'typeorm'; import { DOCUMENT_SOURCE, DOCUMENT_SYSTEM, From dc71b5c6bfad767aca04b412b030b6d7baf02c20 Mon Sep 17 00:00:00 2001 From: Tristan Slater <1631008+trslater@users.noreply.github.com> Date: Tue, 7 May 2024 11:28:41 -0700 Subject: [PATCH 15/21] Filter out empty emails Empty strings as emails were causing it to fail. --- .../notification-submission/notification-submission.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts index e69108c141..a5fc12c29d 100644 --- a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts +++ b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts @@ -470,7 +470,7 @@ export class NotificationSubmissionService { ); if (localGovernment && localGovernment.emails) { - ccEmails = localGovernment.emails; + ccEmails = localGovernment.emails.filter((email) => email !== ''); } } From 73224d4a0307246eb871fe36f3e2c021316af4f7 Mon Sep 17 00:00:00 2001 From: Tristan Slater <1631008+trslater@users.noreply.github.com> Date: Tue, 7 May 2024 15:59:01 -0700 Subject: [PATCH 16/21] Fail resend if email isn't sent - Return email sent status to resend endpoint - Have resend endpoint fail if email not sent --- .../notification/notification.controller.ts | 22 +++++++++++++----- .../notification-submission.service.ts | 23 +++++++++++-------- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/services/apps/alcs/src/alcs/notification/notification.controller.ts b/services/apps/alcs/src/alcs/notification/notification.controller.ts index 016b6b9536..ed7b14ca28 100644 --- a/services/apps/alcs/src/alcs/notification/notification.controller.ts +++ b/services/apps/alcs/src/alcs/notification/notification.controller.ts @@ -1,4 +1,7 @@ -import { ServiceNotFoundException } from '@app/common/exceptions/base.exception'; +import { + BaseServiceException, + ServiceNotFoundException, +} from '@app/common/exceptions/base.exception'; import { Body, Controller, @@ -120,11 +123,18 @@ export class NotificationController { ); if (document) { - await this.notificationSubmissionService.sendAndRecordLTSAPackage( - submission, - document, - user, - ); + const emailDidSend = + await this.notificationSubmissionService.sendAndRecordLTSAPackage( + submission, + document, + user, + ); + + if (!emailDidSend) { + throw new BaseServiceException( + `Failed to send LTSA Package ${fileNumber}`, + ); + } } else { throw new ServiceNotFoundException( `Failed to find LTSA Letter on File Number ${fileNumber}`, diff --git a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts index a5fc12c29d..957c2803e5 100644 --- a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts +++ b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts @@ -406,18 +406,19 @@ export class NotificationSubmissionService { submission: NotificationSubmission, document: NotificationDocument, user: User, - ) { + ): Promise { const templateData = await this.generateSrwEmailData(submission, document); - const didSend = await this.emailService.sendEmail({ - to: [templateData.to], - body: templateData.html, - subject: `Agricultural Land Commission SRW${submission.fileNumber} (${submission.applicant})`, - parentType: PARENT_TYPE.NOTIFICATION, - parentId: templateData.parentId, - cc: templateData.cc, - attachments: [document.document], - }); + const didSend = + (await this.emailService.sendEmail({ + to: [templateData.to], + body: templateData.html, + subject: `Agricultural Land Commission SRW${submission.fileNumber} (${submission.applicant})`, + parentType: PARENT_TYPE.NOTIFICATION, + parentId: templateData.parentId, + cc: templateData.cc, + attachments: [document.document], + })) ?? false; if (didSend) { const fileBuffer = Buffer.from(templateData.html); @@ -442,6 +443,8 @@ export class NotificationSubmissionService { NOTIFICATION_STATUS.ALC_RESPONSE_SENT, ); } + + return didSend; } private async generateSrwEmailData( From ec6143e04d18951d72f156c7fafcdb8caee39f85 Mon Sep 17 00:00:00 2001 From: Tristan Slater <1631008+trslater@users.noreply.github.com> Date: Tue, 7 May 2024 16:09:33 -0700 Subject: [PATCH 17/21] Return strict boolean from email service --- .../notification-submission.service.ts | 19 +++++++++---------- .../alcs/src/providers/email/email.service.ts | 4 ++-- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts index 957c2803e5..72c6777912 100644 --- a/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts +++ b/services/apps/alcs/src/portal/notification-submission/notification-submission.service.ts @@ -409,16 +409,15 @@ export class NotificationSubmissionService { ): Promise { const templateData = await this.generateSrwEmailData(submission, document); - const didSend = - (await this.emailService.sendEmail({ - to: [templateData.to], - body: templateData.html, - subject: `Agricultural Land Commission SRW${submission.fileNumber} (${submission.applicant})`, - parentType: PARENT_TYPE.NOTIFICATION, - parentId: templateData.parentId, - cc: templateData.cc, - attachments: [document.document], - })) ?? false; + const didSend = await this.emailService.sendEmail({ + to: [templateData.to], + body: templateData.html, + subject: `Agricultural Land Commission SRW${submission.fileNumber} (${submission.applicant})`, + parentType: PARENT_TYPE.NOTIFICATION, + parentId: templateData.parentId, + cc: templateData.cc, + attachments: [document.document], + }); if (didSend) { const fileBuffer = Buffer.from(templateData.html); diff --git a/services/apps/alcs/src/providers/email/email.service.ts b/services/apps/alcs/src/providers/email/email.service.ts index eccac508bd..5a0394348d 100644 --- a/services/apps/alcs/src/providers/email/email.service.ts +++ b/services/apps/alcs/src/providers/email/email.service.ts @@ -102,7 +102,7 @@ export class EmailService { parentId?: string; triggerStatus?: string; attachments?: Document[]; - }) { + }): Promise { const serviceUrl = this.config.get('CHES.URL'); const from = this.config.get('CHES.FROM'); const token = await this.getToken(); @@ -134,7 +134,7 @@ export class EmailService { { to, body, subject, cc, bcc }, 'EmailService did not send the email. Set CHES.MODE to production if you need to send an email.', ); - return; + return false; } const res = await firstValueFrom( this.httpService.post<{ From e1c6b43b783dc7fd784188105ab7926f95ed72b3 Mon Sep 17 00:00:00 2001 From: Mekhti Date: Wed, 8 May 2024 09:54:20 -0700 Subject: [PATCH 18/21] properly retrieve properties for PR insert --- .../init_planning_review_decisions.py | 19 ++++++++++++++----- .../planning_review_decisions_insert.sql | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py b/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py index 5cc7f90a7a..6dba932cf4 100644 --- a/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py +++ b/bin/migrate-oats-data/planning_review/decisions/init_planning_review_decisions.py @@ -53,10 +53,10 @@ def process_planning_review_decisions(conn=None, batch_size=BATCH_UPLOAD_SIZE): while True: query_condition = "" if last_decision_date: - query_condition = f"WHERE pr.file_number::bigint >= {last_file_number} AND opd.decision_date >= {last_decision_date} AND opd.planning_decision_id > {last_planning_decision_id} ORDER BY pr.file_number::bigint, opd.decision_date, opd.planning_decision_id;" - else: + query_condition = f"WHERE pr.file_number::bigint >= {last_file_number} AND opd.decision_date >= '{last_decision_date}' AND opd.planning_decision_id > {last_planning_decision_id} ORDER BY pr.file_number::bigint, opd.decision_date, opd.planning_decision_id;" + else: query_condition = f"WHERE pr.file_number::bigint >= {last_file_number} AND opd.planning_decision_id > {last_planning_decision_id} ORDER BY pr.file_number::bigint, opd.decision_date, opd.planning_decision_id;" - + cursor.execute( f""" {query} @@ -76,8 +76,16 @@ def process_planning_review_decisions(conn=None, batch_size=BATCH_UPLOAD_SIZE): ) last_record = dict(inserted_data[-1]) last_planning_decision_id = last_record["planning_decision_id"] - last_file_number = last_record["file_number"] - last_decision_date = last_record["decision_date"] + last_inserted_row = next( + ( + row + for row in rows + if row["uuid"] == last_record["review_uuid"] + ), + None, + ) + last_file_number = last_inserted_row["file_number"] + last_decision_date = last_inserted_row["decision_date"] logger.debug( f"Retrieved/updated items count: {len(inserted_data)}; total successfully inserted planning referral so far {successful_inserts_count}; last updated planning_decision_id: {last_planning_decision_id}" @@ -150,6 +158,7 @@ def _prepare_oats_planning_review_data(row_data_list): "resolution_number": row["resolution_number"], "resolution_year": _map_resolution_year(row), "created_at": to_alcs_format(get_now_with_offset(insert_index)), + "file_number": row["file_number"], } ) insert_index += 1 diff --git a/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql b/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql index 321fecc8cf..906ec68ada 100644 --- a/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql +++ b/bin/migrate-oats-data/planning_review/sql/decisions/planning_review_decisions_insert.sql @@ -6,7 +6,7 @@ SELECT pr."uuid", opd.resolution_number, opd.planning_decision_id, - pr.file_number + pr.file_number::bigint FROM oats.oats_planning_decisions opd JOIN alcs.planning_review pr ON opd.planning_review_id::TEXT = pr.file_number \ No newline at end of file From 0c30d2168591efdbb959305b287c2d6de51c805b Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Wed, 8 May 2024 10:23:04 -0700 Subject: [PATCH 19/21] Downgrade CLS Package * Potential issues --- services/package-lock.json | 10 +++++----- services/package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/services/package-lock.json b/services/package-lock.json index 8cf3cdb67f..42dac96d78 100644 --- a/services/package-lock.json +++ b/services/package-lock.json @@ -41,7 +41,7 @@ "mjml": "^4.15.3", "nest-keycloak-connect": "^1.10.0", "nest-winston": "^1.9.4", - "nestjs-cls": "^4.3.0", + "nestjs-cls": "~3.6.0", "nestjs-grpc-reflection": "^0.2.2", "nestjs-spelunker": "^1.3.0", "node-jose": "^2.2.0", @@ -11177,11 +11177,11 @@ } }, "node_modules/nestjs-cls": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-4.3.0.tgz", - "integrity": "sha512-MVTun6tqCZih8AJXRj8uBuuFyJhQrIA9m9fStiQjbBXUkE3BrlMRvmLzyw8UcneB3xtFFTfwkAh5PYKRulyaOg==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-3.6.0.tgz", + "integrity": "sha512-hAu8Pyhl0okB7LgQFoxP8kq26izBh0UCnDLfE2Ze9eJAz2A8XdFkBNIVca868T1Yf8bsLzvfsKPTxCQZ0hTMDQ==", "engines": { - "node": ">=16" + "node": ">=12.17.0" }, "peerDependencies": { "@nestjs/common": "> 7.0.0 < 11", diff --git a/services/package.json b/services/package.json index 04d3277cb5..78a7c5afb2 100644 --- a/services/package.json +++ b/services/package.json @@ -60,7 +60,7 @@ "mjml": "^4.15.3", "nest-keycloak-connect": "^1.10.0", "nest-winston": "^1.9.4", - "nestjs-cls": "^4.3.0", + "nestjs-cls": "~3.6.0", "nestjs-grpc-reflection": "^0.2.2", "nestjs-spelunker": "^1.3.0", "node-jose": "^2.2.0", From d5ebc0202ad2439bf34d7e3dbb93292e25241546 Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Wed, 8 May 2024 10:53:18 -0700 Subject: [PATCH 20/21] Mount CLS directly --- services/apps/alcs/src/main.module.ts | 1 - services/apps/alcs/src/main.ts | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/services/apps/alcs/src/main.module.ts b/services/apps/alcs/src/main.module.ts index 1349193ce5..a64db47502 100644 --- a/services/apps/alcs/src/main.module.ts +++ b/services/apps/alcs/src/main.module.ts @@ -38,7 +38,6 @@ import { UserModule } from './user/user.module'; }), ClsModule.forRoot({ global: true, - middleware: { mount: true }, }), WinstonModule, DocumentModule, diff --git a/services/apps/alcs/src/main.ts b/services/apps/alcs/src/main.ts index 1079e75b4e..e30e641492 100644 --- a/services/apps/alcs/src/main.ts +++ b/services/apps/alcs/src/main.ts @@ -9,6 +9,7 @@ import { } from '@nestjs/platform-fastify'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import * as config from 'config'; +import { ClsMiddleware } from 'nestjs-cls'; import { S3StreamLogger } from 's3-streamlogger'; import { install } from 'source-map-support'; import * as winston from 'winston'; @@ -148,7 +149,6 @@ function setupLogger() { http: 4, debug: 5, verbose: 6, - log: 7, }, transports: config.get('ENV') === 'production' @@ -170,6 +170,7 @@ async function bootstrap() { }, ); app.useLogger(logger); + app.use(new ClsMiddleware().use); const extraArg = process.argv[2]; if (extraArg === 'graph') { From 867c74bc03d89e5bc7a4bc3dcdacfd0bb0e2f31c Mon Sep 17 00:00:00 2001 From: Daniel Haselhan Date: Wed, 8 May 2024 11:46:02 -0700 Subject: [PATCH 21/21] Re-update CLS --- services/package-lock.json | 10 +++++----- services/package.json | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/services/package-lock.json b/services/package-lock.json index 42dac96d78..8cf3cdb67f 100644 --- a/services/package-lock.json +++ b/services/package-lock.json @@ -41,7 +41,7 @@ "mjml": "^4.15.3", "nest-keycloak-connect": "^1.10.0", "nest-winston": "^1.9.4", - "nestjs-cls": "~3.6.0", + "nestjs-cls": "^4.3.0", "nestjs-grpc-reflection": "^0.2.2", "nestjs-spelunker": "^1.3.0", "node-jose": "^2.2.0", @@ -11177,11 +11177,11 @@ } }, "node_modules/nestjs-cls": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-3.6.0.tgz", - "integrity": "sha512-hAu8Pyhl0okB7LgQFoxP8kq26izBh0UCnDLfE2Ze9eJAz2A8XdFkBNIVca868T1Yf8bsLzvfsKPTxCQZ0hTMDQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/nestjs-cls/-/nestjs-cls-4.3.0.tgz", + "integrity": "sha512-MVTun6tqCZih8AJXRj8uBuuFyJhQrIA9m9fStiQjbBXUkE3BrlMRvmLzyw8UcneB3xtFFTfwkAh5PYKRulyaOg==", "engines": { - "node": ">=12.17.0" + "node": ">=16" }, "peerDependencies": { "@nestjs/common": "> 7.0.0 < 11", diff --git a/services/package.json b/services/package.json index 78a7c5afb2..04d3277cb5 100644 --- a/services/package.json +++ b/services/package.json @@ -60,7 +60,7 @@ "mjml": "^4.15.3", "nest-keycloak-connect": "^1.10.0", "nest-winston": "^1.9.4", - "nestjs-cls": "~3.6.0", + "nestjs-cls": "^4.3.0", "nestjs-grpc-reflection": "^0.2.2", "nestjs-spelunker": "^1.3.0", "node-jose": "^2.2.0",