diff --git a/CHANGELOG.md b/CHANGELOG.md index 5eed40c572..b7b7be8084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,41 @@ # Changelog +## [11.3.3](https://github.com/dasch-swiss/dsp-das/compare/v11.3.2...v11.3.3) (2024-02-01) + + +### Bug Fixes + +* add cookie auth for iiif resources ([#1425](https://github.com/dasch-swiss/dsp-das/issues/1425)) ([dfeec97](https://github.com/dasch-swiss/dsp-das/commit/dfeec97c78ac0dcd5d262d09a67198e0854173d0)) + +## [11.3.2](https://github.com/dasch-swiss/dsp-das/compare/v11.3.1...v11.3.2) (2024-02-01) + + +### Bug Fixes + +* string instead of enum for environment config ([#1423](https://github.com/dasch-swiss/dsp-das/issues/1423)) ([fc92eaa](https://github.com/dasch-swiss/dsp-das/commit/fc92eaa88f768338dcc1e2fa07295c93c03098b2)) + +## [11.3.1](https://github.com/dasch-swiss/dsp-das/compare/v11.3.0...v11.3.1) (2024-01-31) + + +### Bug Fixes + +* display resource permission warning message ([#1414](https://github.com/dasch-swiss/dsp-das/issues/1414)) ([5a8d739](https://github.com/dasch-swiss/dsp-das/commit/5a8d7393ee164ee4a4bee4bb5b6d0a7f4596cdd8)) +* **dsp-app:** resource link permissions (DEV-3252) ([#1419](https://github.com/dasch-swiss/dsp-das/issues/1419)) ([72132f0](https://github.com/dasch-swiss/dsp-das/commit/72132f035b3ed7f269539d947c150d868bb6248c)) +* **dsp-das:** Enables rich text saving when creating new text value f… ([#1417](https://github.com/dasch-swiss/dsp-das/issues/1417)) ([f3c9204](https://github.com/dasch-swiss/dsp-das/commit/f3c92049d53668d2915313f37c61959fa7e91d73)) +* no bearer auth on iiif images ([#1410](https://github.com/dasch-swiss/dsp-das/issues/1410)) ([a5a00e9](https://github.com/dasch-swiss/dsp-das/commit/a5a00e9dbcdc5ee6d5a27948ac9da00f284ca73f)) +* no faro in dev ([#1412](https://github.com/dasch-swiss/dsp-das/issues/1412)) ([22ce0eb](https://github.com/dasch-swiss/dsp-das/commit/22ce0eb1c55de424f519a025d8b1b929a45471a6)) +* test pass instrumentation validation ([#1421](https://github.com/dasch-swiss/dsp-das/issues/1421)) ([36fd44a](https://github.com/dasch-swiss/dsp-das/commit/36fd44a56d4ba4b121b95dedb42185ae110c98a6)) +* testing passes ([#1422](https://github.com/dasch-swiss/dsp-das/issues/1422)) ([66fd88e](https://github.com/dasch-swiss/dsp-das/commit/66fd88e59f8f5e56e5b5e5a169c976326454aa1b)) +* various errors ([#1416](https://github.com/dasch-swiss/dsp-das/issues/1416)) ([534e96b](https://github.com/dasch-swiss/dsp-das/commit/534e96bd7b5140aa7e078c39140d2dd88e90e3a0)) +* various fixes ([#1418](https://github.com/dasch-swiss/dsp-das/issues/1418)) ([c2db7bf](https://github.com/dasch-swiss/dsp-das/commit/c2db7bf1adf64076f7f9897e56d0f37dab17b1c1)) +* various fixes ([#1420](https://github.com/dasch-swiss/dsp-das/issues/1420)) ([d88aa17](https://github.com/dasch-swiss/dsp-das/commit/d88aa175c1bf469eb265b044cbf0c0a0e24a5bc2)) + + +### Maintenance + +* **boolean-value:** assign class to get the same height as other forms ([#1415](https://github.com/dasch-swiss/dsp-das/issues/1415)) ([7768c2d](https://github.com/dasch-swiss/dsp-das/commit/7768c2d14d1f07614437c0aaa9fa4729e762574b)) +* remove datadog ([#1413](https://github.com/dasch-swiss/dsp-das/issues/1413)) ([bda4786](https://github.com/dasch-swiss/dsp-das/commit/bda4786bdb6ac96e2bf937c086e9adb7d89aac3d)) + ## [11.3.0](https://github.com/dasch-swiss/dsp-das/compare/v11.2.0...v11.3.0) (2024-01-30) diff --git a/apps/dsp-app/cypress/e2e/system-admin/dashboard.cy.ts b/apps/dsp-app/cypress/e2e/system-admin/dashboard.cy.ts index c3f41b276d..b414ade4ec 100644 --- a/apps/dsp-app/cypress/e2e/system-admin/dashboard.cy.ts +++ b/apps/dsp-app/cypress/e2e/system-admin/dashboard.cy.ts @@ -2,7 +2,7 @@ const MY_TOKEN = ''; localStorage.setItem('ACCESS_TOKEN', MY_TOKEN); describe('ADMIN TEST', () => { - it('should load clickable projects on the home page', () => { + it.skip('should load clickable projects on the home page', () => { cy.visit('/'); const projectTileSelector = '[data-cy=tile]'; diff --git a/apps/dsp-app/src/app/app.module.ts b/apps/dsp-app/src/app/app.module.ts index 7fad9dc78c..0199e54aed 100644 --- a/apps/dsp-app/src/app/app.module.ts +++ b/apps/dsp-app/src/app/app.module.ts @@ -58,6 +58,7 @@ import { GridComponent } from './main/grid/grid.component'; import { HeaderComponent } from './main/header/header.component'; import { HelpComponent } from './main/help/help.component'; import { AuthInterceptor } from './main/http-interceptors/auth-interceptor'; +import { IiifWithCredentialsInterceptor } from './main/http-interceptors/iiif-with-credentials.interceptor'; import { FormattedBooleanPipe } from './main/pipes/formatting/formatted-boolean.pipe'; import { KnoraDatePipe } from './main/pipes/formatting/knoradate.pipe'; import { IsFalsyPipe } from './main/pipes/isFalsy.piipe'; @@ -388,6 +389,11 @@ export function httpLoaderFactory(httpClient: HttpClient) { useClass: AuthInterceptor, multi: true, }, + { + provide: HTTP_INTERCEPTORS, + useClass: IiifWithCredentialsInterceptor, + multi: true, + }, ], bootstrap: [AppComponent], }) diff --git a/apps/dsp-app/src/app/main/http-interceptors/iiif-with-credentials.interceptor.ts b/apps/dsp-app/src/app/main/http-interceptors/iiif-with-credentials.interceptor.ts new file mode 100644 index 0000000000..f680e57117 --- /dev/null +++ b/apps/dsp-app/src/app/main/http-interceptors/iiif-with-credentials.interceptor.ts @@ -0,0 +1,22 @@ +import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { Observable } from 'rxjs'; + +// TODO remove this Interceptor and add all IIIF requests to a IIIFApiService that adds withCredentials true. +/** + * Add withCredentials true (sends cookies, used for authentication)to any iiif request + */ +@Injectable() +export class IiifWithCredentialsInterceptor implements HttpInterceptor { + intercept(request: HttpRequest, next: HttpHandler): Observable> { + console.log(request.url); + if (request.url.startsWith('https://iiif')) { + const modifiedRequest = request.clone({ withCredentials: true }); + console.log('good for', request.url, modifiedRequest); + return next.handle(modifiedRequest); + } + + // If the URL doesn't match, proceed with the original request + return next.handle(request); + } +} diff --git a/apps/dsp-app/src/app/project/reusable-project-form/shortcode-exists.validator.ts b/apps/dsp-app/src/app/project/reusable-project-form/shortcode-exists.validator.ts index 17ee1c540b..78134f1e6f 100644 --- a/apps/dsp-app/src/app/project/reusable-project-form/shortcode-exists.validator.ts +++ b/apps/dsp-app/src/app/project/reusable-project-form/shortcode-exists.validator.ts @@ -1,4 +1,4 @@ -import { AbstractControl, ValidatorFn, ValidationErrors } from '@angular/forms'; +import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms'; /** * shortcodeValidator: Validate the shortcode value against @@ -7,6 +7,8 @@ import { AbstractControl, ValidatorFn, ValidationErrors } from '@angular/forms'; */ export function shortcodeExistsValidator(shortcodes: string[]): ValidatorFn { return (control: AbstractControl): ValidationErrors | null => { - return shortcodes.includes(control.value) ? { shortcodeExists: true } : null; + return shortcodes.some(e => e.toLowerCase().search(control.value.toLowerCase()) !== -1) + ? { shortcodeExists: true } + : null; }; } diff --git a/apps/dsp-app/src/app/workspace/resource/representation/representation.service.ts b/apps/dsp-app/src/app/workspace/resource/representation/representation.service.ts index 6c8a53b895..aa92898a58 100644 --- a/apps/dsp-app/src/app/workspace/resource/representation/representation.service.ts +++ b/apps/dsp-app/src/app/workspace/resource/representation/representation.service.ts @@ -24,7 +24,7 @@ export class RepresentationService { pathToJson = `${url.substring(0, url.lastIndexOf('/'))}/knora.json`; } - return this._http.get(pathToJson); + return this._http.get(pathToJson, { withCredentials: true }); } /** diff --git a/apps/dsp-app/src/config/config.prod.json b/apps/dsp-app/src/config/config.prod.json index dd7d7c0267..4d78e834e5 100644 --- a/apps/dsp-app/src/config/config.prod.json +++ b/apps/dsp-app/src/config/config.prod.json @@ -13,7 +13,7 @@ "logErrors": false, "iriBase": "http://rdfh.ch", "instrumentation": { - "environment": "prod", + "environment": "production", "rollbar": { "enabled": false, "accessToken": "" diff --git a/libs/vre/shared/app-config/src/lib/app-config/app-config.service.spec.ts b/libs/vre/shared/app-config/src/lib/app-config/app-config.service.spec.ts index 3ac0f54dfa..085f4939cc 100644 --- a/libs/vre/shared/app-config/src/lib/app-config/app-config.service.spec.ts +++ b/libs/vre/shared/app-config/src/lib/app-config/app-config.service.spec.ts @@ -26,7 +26,7 @@ describe('AppConfigService with dev config', () => { geonameToken: 'geoname_token', iriBase: 'http://rdfh.ch', instrumentation: { - environment: 'local-dev', + environment: 'dev-server', rollbar: { enabled: false, }, @@ -50,7 +50,7 @@ describe('AppConfigService with dev config', () => { }); it('should process the fully specified config (dev mode)', async () => { - expect(service.dspConfig.environment).toEqual('local-dev'); + expect(service.dspConfig.environment).toEqual('dev-server'); expect(service.dspConfig.color).toEqual('accent'); expect(service.dspConfig.production).toEqual(false); expect(service.dspApiConfig.apiProtocol).toEqual('http'); @@ -65,7 +65,7 @@ describe('AppConfigService with dev config', () => { expect(service.dspApiConfig.logErrors).toEqual(true); expect(service.dspAppConfig.geonameToken).toEqual('geoname_token'); expect(service.dspAppConfig.iriBase).toEqual('http://rdfh.ch'); - expect(service.dspInstrumentationConfig.environment).toEqual('local-dev'); + expect(service.dspInstrumentationConfig.environment).toEqual('dev-server'); expect(service.dspInstrumentationConfig.rollbar.enabled).toEqual(false); expect(service.dspInstrumentationConfig.rollbar.accessToken).toBeUndefined(); }); diff --git a/libs/vre/shared/app-config/src/lib/app-config/app-config.ts b/libs/vre/shared/app-config/src/lib/app-config/app-config.ts index 39d77e973c..413da8579c 100644 --- a/libs/vre/shared/app-config/src/lib/app-config/app-config.ts +++ b/libs/vre/shared/app-config/src/lib/app-config/app-config.ts @@ -14,7 +14,7 @@ export const Rollbar = z.discriminatedUnion('enabled', [ export type Rollbar = z.infer; export const Instrumentation = z.object({ - environment: z.enum(['local-dev', 'dev-server', 'test-server', 'ls-test-server', 'staging-server', 'prod']), + environment: z.string(), rollbar: Rollbar, }); diff --git a/libs/vre/shared/app-error-handler/src/lib/app-error-handler.ts b/libs/vre/shared/app-error-handler/src/lib/app-error-handler.ts index 45e6ec9c4c..05d6e3f0d0 100644 --- a/libs/vre/shared/app-error-handler/src/lib/app-error-handler.ts +++ b/libs/vre/shared/app-error-handler/src/lib/app-error-handler.ts @@ -28,12 +28,19 @@ export class AppErrorHandler implements ErrorHandler { private handleHttpErrorResponse(error: HttpErrorResponse) { if (error.status === 400) { - const readableErrorMatch = error.error.error.match(/dsp\.errors\.BadRequestException:(.*)$/); - this.displayNotification(readableErrorMatch[1]); - return; - } else if (error.status >= 400 && error.status < 500) { - const readableErrorMatch = error.error.error.match(/\((.*)\)$/); - this.displayNotification(readableErrorMatch[1]); + if (error.error?.error) { + const badRequestRegexMatch = error.error.error.match(/dsp\.errors\.BadRequestException:(.*)$/); + + if (badRequestRegexMatch) { + this.displayNotification(badRequestRegexMatch[1]); + } + + this.testInvalidRequest(error.error.error); + } else if (typeof error.error === 'string') { + this.testInvalidRequest(error.error); + } else if (error.error.message) { + this.displayNotification(error.error.message); + } return; } @@ -63,4 +70,12 @@ export class AppErrorHandler implements ErrorHandler { private displayNotification(message: string) { this._notification.openSnackBar(message, 'error'); } + + // TODO ask the backend to uniformize their response, so that this method is only called once. + private testInvalidRequest(error: string) { + const invalidRequestRegexMatch = error.match(/\((.*)\)$/); + if (invalidRequestRegexMatch) { + this.displayNotification(invalidRequestRegexMatch[1]); + } + } } diff --git a/package-lock.json b/package-lock.json index 6ef0dc1de2..0442fb9c1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dsp-app", - "version": "11.3.0", + "version": "11.3.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dsp-app", - "version": "11.3.0", + "version": "11.3.3", "dependencies": { "@angular/animations": "^16.2.12", "@angular/cdk": "^16.2.12", diff --git a/package.json b/package.json index 793b606a94..f48d58376b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dsp-app", - "version": "11.3.0", + "version": "11.3.3", "repository": { "type": "git", "url": "https://github.com/dasch-swiss/dsp-app.git"