From 41f206d77a1dfb2da731e3a873c9feed0ddc7a3f Mon Sep 17 00:00:00 2001 From: Kai Niebes Date: Wed, 8 Apr 2026 15:46:47 +0200 Subject: [PATCH 1/3] Remove collection password checks Password has been deprecated in favor of "online" field on collections --- bun.lock | 2 +- package.json | 2 +- .../dialog-password.component.html | 20 --- .../dialog-password.component.scss | 19 --- .../dialog-password.component.ts | 51 -------- .../dialog-share-annotation.component.html | 16 --- .../dialog-share-annotation.component.ts | 40 +----- src/app/services/backend/backend.service.ts | 10 +- .../services/processing/processing.service.ts | 114 ++++++++---------- 9 files changed, 64 insertions(+), 210 deletions(-) delete mode 100644 src/app/components/dialogs/dialog-password/dialog-password.component.html delete mode 100644 src/app/components/dialogs/dialog-password/dialog-password.component.scss delete mode 100644 src/app/components/dialogs/dialog-password/dialog-password.component.ts diff --git a/bun.lock b/bun.lock index 6be2dacf..c9e18315 100644 --- a/bun.lock +++ b/bun.lock @@ -450,7 +450,7 @@ "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], - "@kompakkt/common": ["@kompakkt/common@github:Kompakkt/Common#07dd559", {}, "Kompakkt-Common-07dd559", "sha512-eyqhbXaOGgB5eK9f3nxEXV8UMY9DrOT8OcYVnT/4nF8CbuguLRFTxK8yMmMlwSjQArB0L5so7YBriNgFUVWhKw=="], + "@kompakkt/common": ["@kompakkt/common@github:Kompakkt/Common#802b2f0", {}, "Kompakkt-Common-802b2f0", "sha512-oqEJBqsyBNAZ5InLdgd/q+R1PSTHYtSqebAzF9lxQ+kdUyP4G5yKwRvzJjgCDftNh74qRAS07xMuX+gSy6F4Sw=="], "@kompakkt/komponents": ["@kompakkt/komponents@github:Kompakkt/Komponents#6f91b0f", { "dependencies": { "@angular/common": "21.2.6", "@angular/core": "21.2.6", "@angular/forms": "21.2.6", "@angular/platform-browser": "21.2.6", "rxjs": "7.8.2", "tslib": "^2.8.1", "zone.js": "0.16.1" } }, "Kompakkt-Komponents-6f91b0f", "sha512-GC8tDrQ6EQ1XbYgBhP0NYF2J+g42jNKytDjfK2z7erZuVHBuTvVEMDj6tNMSxot2d+vYvJdvGrqZHiYrYOVVOQ=="], diff --git a/package.json b/package.json index a2a063be..c61f9cb7 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@babylonjs/loaders": "9.0.0", "@babylonjs/materials": "9.0.0", "@babylonjs/serializers": "9.0.0", - "@kompakkt/common": "git+https://github.com/Kompakkt/Common#07dd559", + "@kompakkt/common": "git+https://github.com/Kompakkt/Common#802b2f0", "@kompakkt/komponents": "git+https://github.com/Kompakkt/Komponents#6f91b0f", "@kompakkt/plugins": "git+https://github.com/Kompakkt/Plugins#3ef7a55", "bson-objectid": "^2.0.4", diff --git a/src/app/components/dialogs/dialog-password/dialog-password.component.html b/src/app/components/dialogs/dialog-password/dialog-password.component.html deleted file mode 100644 index 0753c7e3..00000000 --- a/src/app/components/dialogs/dialog-password/dialog-password.component.html +++ /dev/null @@ -1,20 +0,0 @@ -
-

{{ 'Protected collection' | translate }}

- -

- {{ 'This collection is protected by a password.' | translate }} -

-

- {{ 'Type in the password to load this collection.' | translate }} -

- - - - - {{ 'Check' | translate }} - - diff --git a/src/app/components/dialogs/dialog-password/dialog-password.component.scss b/src/app/components/dialogs/dialog-password/dialog-password.component.scss deleted file mode 100644 index 9269fe26..00000000 --- a/src/app/components/dialogs/dialog-password/dialog-password.component.scss +++ /dev/null @@ -1,19 +0,0 @@ -:host { - form { - display: flex; - flex-direction: column; - gap: 8px; - padding: 32px; - } - - color: white; - h1 { - font-size: var(--font-size-large); - font-weight: var(--font-weight-bold); - margin: 0; - } - - p { - margin: 0; - } -} diff --git a/src/app/components/dialogs/dialog-password/dialog-password.component.ts b/src/app/components/dialogs/dialog-password/dialog-password.component.ts deleted file mode 100644 index 713e176e..00000000 --- a/src/app/components/dialogs/dialog-password/dialog-password.component.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Component, Inject } from '@angular/core'; -import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { FormsModule } from '@angular/forms'; -import { ButtonComponent, ButtonRowComponent, InputComponent } from '@kompakkt/komponents'; -import { ICompilation } from '@kompakkt/common'; -import { TranslatePipe } from '../../../pipes/translate.pipe'; -import { BackendService } from '../../../services/backend/backend.service'; -import { MessageService } from '../../../services/message/message.service'; - -@Component({ - selector: 'app-password', - templateUrl: './dialog-password.component.html', - styleUrls: ['./dialog-password.component.scss'], - imports: [FormsModule, TranslatePipe, InputComponent, ButtonComponent, ButtonRowComponent], -}) -export class DialogPasswordComponent { - public password = ''; - public identifierCollection: string; - - private compilation: ICompilation | undefined; - - constructor( - private backend: BackendService, - private message: MessageService, - private dialogRef: MatDialogRef, - @Inject(MAT_DIALOG_DATA) data: { id: string }, - ) { - this.identifierCollection = data.id; - } - - public check() { - this.dialogRef.disableClose = true; - if (this.identifierCollection && this.password !== '') { - this.backend - .getCompilation(this.identifierCollection, this.password) - .then(compilation => { - if (!compilation) { - this.message.error('Password is wrong.'); - } else { - this.compilation = compilation as ICompilation; - this.dialogRef.close({ result: true, data: this.compilation }); - } - }) - .catch(error => { - console.error(error); - this.message.error('Connection to server refused.'); - this.dialogRef.close(); - }); - } - } -} diff --git a/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.html b/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.html index f5bad6a1..310a00c1 100644 --- a/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.html +++ b/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.html @@ -18,20 +18,4 @@

{{ 'Share Annotation to Collection' | translate }}

{{ 'Share' | translate }} {{ 'Cancel' | translate }} - - @if (checkPwdMode) { -

{{ 'The target collection is protected by a password.' | translate }}

-

{{ 'Enter the password to continue.' | translate }}

- } - - - - - {{ 'Cancel' | translate }} - {{ 'Check' | translate }} - diff --git a/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.ts b/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.ts index 4fa9df8c..5e0b08c8 100644 --- a/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.ts +++ b/src/app/components/dialogs/dialog-share-annotation/dialog-share-annotation.component.ts @@ -17,10 +17,12 @@ import { TranslatePipe } from '../../../pipes/translate.pipe'; }) export class DialogShareAnnotationComponent { public targetCollectionId = ''; - public checkPwdMode = false; - public passwordCollection = ''; private entityId = ''; - private response: any = { + private response: { + status: boolean; + collectionId: string; + annotationListLength: number; + } = { status: false, collectionId: '', annotationListLength: 1, @@ -40,12 +42,7 @@ export class DialogShareAnnotationComponent { this.backend .getCompilation(this.targetCollectionId) .then(compilation => { - if (!compilation) { - // 'password' - this.checkPwdMode = true; - } else { - // collection is available on server - // loaded' + if (compilation) { compilation = compilation as ICompilation; if (!compilation.entities[this.entityId]) @@ -75,29 +72,4 @@ export class DialogShareAnnotationComponent { console.log('canceled'); this.dialogRef.close(this.response); } - - public checkPwd() { - if (this.targetCollectionId !== '') { - this.backend - .getCompilation(this.targetCollectionId, this.passwordCollection) - .then(compilation => { - if (!compilation) - return this.message.error( - `Password is wrong for collection with ID ${this.targetCollectionId}`, - ); - compilation = compilation as ICompilation; - this.response = { - status: true, - collectionId: this.targetCollectionId, - annotationListLength: Object.keys(compilation.annotations).length ?? 1, - }; - this.dialogRef.close(this.response); - }) - .catch(error => { - console.error(error); - this.message.error('Connection to entity server refused.'); - this.dialogRef.close(this.response); - }); - } - } } diff --git a/src/app/services/backend/backend.service.ts b/src/app/services/backend/backend.service.ts index d1885e88..4cc77ff6 100644 --- a/src/app/services/backend/backend.service.ts +++ b/src/app/services/backend/backend.service.ts @@ -58,14 +58,10 @@ export class BackendService { /** * Fetch a resolved compilation by it's identifier * @param {string} identifier Database _id of the compilation - * @param {string} password (Optional) Password of the compilation - * @param {[type]} [description] - * @return {Promise} Returns the compilation or null if it's password protected + * @return {Promise} Returns the compilation or null */ - public async getCompilation(identifier: string, password?: string): Promise { - return password - ? this.get(`api/v1/get/find/compilation/${identifier}/${password}`) - : this.get(`api/v1/get/find/compilation/${identifier}`); + public async getCompilation(identifier: string): Promise { + return this.get(`api/v1/get/find/compilation/${identifier}`); } public async getEntityMetadata(identifier: string): Promise { diff --git a/src/app/services/processing/processing.service.ts b/src/app/services/processing/processing.service.ts index 01c61d27..1124c8d1 100644 --- a/src/app/services/processing/processing.service.ts +++ b/src/app/services/processing/processing.service.ts @@ -25,7 +25,6 @@ import { settingsKompakktLogo, } from '../../../assets/settings/settings'; // tslint:disable-next-line:max-line-length -import { DialogPasswordComponent } from '../../components/dialogs/dialog-password/dialog-password.component'; import { decodeBase64, decodeURIUntilStable, isBase64 } from '../../helpers'; import { IIIFData, convertIIIFAnnotation, isIIIFData } from '../../helpers/iiif-data-helper'; import { BabylonService } from '../babylon/babylon.service'; @@ -273,7 +272,7 @@ export class ProcessingService { this.babylon.resize(); } - public async updateActiveCompilation(compilation: ICompilation | undefined) { + public updateActiveCompilation(compilation: ICompilation | undefined) { this.compilation$.next(compilation); } @@ -515,57 +514,62 @@ export class ProcessingService { return this.loadEntity(fallbackEntity as IEntity, ''); } - public fetchAndLoad(entityId?: string | null, compilationId?: string | null) { + public async fetchAndLoad(entityId?: string | null, compilationId?: string | null) { if (entityId && !compilationId) { - this.fetchEntityData(entityId); + return this.fetchEntityData(entityId); } if (compilationId) { - this.fetchCompilationData(compilationId, entityId ? entityId : undefined); + return this.fetchCompilationData(compilationId, entityId ? entityId : undefined); } } - private fetchCompilationData(id: string, specifiedEntity?: string, password?: string) { - this.backend - .getCompilation(id, password ?? undefined) - .then(compilation => { - if (compilation) { - this.updateActiveCompilation(compilation as ICompilation); - this.fetchEntityDataAfterCollection(compilation, specifiedEntity); - } else { - const dialogRef = this.dialog.open(DialogPasswordComponent, { - disableClose: true, - autoFocus: true, - data: { id }, - }); - dialogRef - .afterClosed() - .subscribe(({ result, data }: { result: boolean; data: ICompilation }) => { - if (result) { - this.updateActiveCompilation(data); - this.fetchEntityDataAfterCollection(data, specifiedEntity); - } else { - this.loadFallbackEntity(); - this.message.error('Sorry, you are not allowed to load this Collection.'); - } - }); + private async fetchCompilationData(id: string, specifiedEntity?: string) { + return this.backend + .getCompilation(id) + .then(async compilation => { + if (!compilation) { + throw new Error('Compilation not found'); + } + + const isRestricted = typeof compilation.online === 'boolean' && !compilation.online; + if (isRestricted) { + const auth = await this.userdata.userAuthentication(true); + console.log('isRestricted auth check', auth, document); + if (!auth) { + this.message.error('You need to be logged in to access this collection.'); + throw new Error('User authentication failed'); + } + if (!this.userdata.doesUserOwn(compilation)) { + if (!this.userdata.doesUserHaveAccess(compilation)) { + this.message.error('Sorry, you are not allowed to load this collection.'); + throw new Error('User does not have access to this compilation'); + } + } } + + this.updateActiveCompilation(compilation as ICompilation); + return this.fetchEntityDataAfterCollection(compilation, specifiedEntity); }) .catch(error => { + this.message.error('Error loading collection.'); console.error(error); - this.loadFallbackEntity(); + return this.loadFallbackEntity(); }); } - private fetchEntityDataAfterCollection(compilation: ICompilation, specifiedEntity?: string) { + private async fetchEntityDataAfterCollection( + compilation: ICompilation, + specifiedEntity?: string, + ) { const specified = specifiedEntity && compilation.entities[specifiedEntity.toString()]; const entityToLoad = isEntity(specified) ? specified : Object.values(compilation.entities)[0]; - if (isEntity(entityToLoad)) this.fetchEntityData(entityToLoad._id); + if (isEntity(entityToLoad)) return this.fetchEntityData(entityToLoad._id); } - public fetchEntityData(query: string) { - this.backend + public async fetchEntityData(query: string) { + return this.backend .getEntity(query) - .then(entity => { + .then(async entity => { console.log('Received this Entity:', entity); // Force load the entity via query parameter, skipping any checks below. @@ -595,37 +599,25 @@ export class ProcessingService { console.log('Are access to this entity restricted', isRestricted); if (isRestricted) { - console.log(this.fetchRestrictedEntityData, 'f'); + const auth = await this.userdata.userAuthentication(true); + console.log('isRestricted auth check', auth, document); + if (!auth) { + this.message.error('You need to be logged in to access this entity.'); + throw new Error('User authentication failed'); + } + if (!this.userdata.doesUserOwn(entity)) { + if (!this.userdata.doesUserHaveAccess(entity)) { + this.message.error('Sorry, you are not allowed to load this object.'); + throw new Error('User does not have access to this entity'); + } + } } - this.loadEntity(entity); + return this.loadEntity(entity); }) .catch(error => { console.error(error); - this.loadFallbackEntity(); - }); - } - - private async fetchRestrictedEntityData(entity: IEntity) { - this.userdata - .userAuthentication(true) - .then(auth => { - console.log('fetchRestrictedEntityData', auth, entity); - // Check for user authentication - if (!auth) return false; - // Check for ownership - if (!this.userdata.doesUserOwn(entity)) { - if (!this.userdata.doesUserHaveAccess(entity)) return false; - } - return true; - }) - .then(canUserAccess => { - if (canUserAccess) { - this.loadEntity(entity); - } else { - this.message.error('Sorry you are not allowed to load this object.'); - this.loadFallbackEntity(); - } + return this.loadFallbackEntity(); }); } From cb85a22ba90f9fc982ce8fee1f013b2caed8a95f Mon Sep 17 00:00:00 2001 From: Kai Niebes Date: Thu, 9 Apr 2026 12:46:52 +0200 Subject: [PATCH 2/3] Update @kompakkt/komponents To implement a fix regarding autocomplete From 8c23fe72d4900b3ad69c397934677a7433f88301 Mon Sep 17 00:00:00 2001 From: Kai Niebes Date: Thu, 9 Apr 2026 12:52:26 +0200 Subject: [PATCH 3/3] Update @kompakkt-dependencies --- bun.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bun.lock b/bun.lock index c9e18315..5ec7ba37 100644 --- a/bun.lock +++ b/bun.lock @@ -22,14 +22,14 @@ "@babylonjs/loaders": "9.0.0", "@babylonjs/materials": "9.0.0", "@babylonjs/serializers": "9.0.0", - "@kompakkt/common": "git+https://github.com/Kompakkt/Common#07dd559", + "@kompakkt/komponents": "git+https://github.com/Kompakkt/Komponents#6f91b0f", "@kompakkt/plugins": "git+https://github.com/Kompakkt/Plugins#3ef7a55", "bson-objectid": "^2.0.4", "copc": "^0.0.8", "fast-deep-equal": "^3.1.3", "file-saver": "^2.0.5", "fscreen": "^1.2.0", - "@kompakkt/komponents": "git+https://github.com/Kompakkt/Komponents#6f91b0f", + "@kompakkt/common": "git+https://github.com/Kompakkt/Common#802b2f0", "laz-perf": "^0.0.7", "lazts": "^1.0.0", "localforage": "^1.10.0",