Skip to content

Commit

Permalink
Merge pull request #328 from swisstopo/develop
Browse files Browse the repository at this point in the history
INT Release
  • Loading branch information
TIL-EBP authored Oct 30, 2024
2 parents 49d6cd1 + 8a554c8 commit 9359f4f
Show file tree
Hide file tree
Showing 10 changed files with 57 additions and 33 deletions.
8 changes: 4 additions & 4 deletions .github/scripts/remove-packages.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { Octokit } = require("@octokit/rest");

const removePackageVersions = async (imageUrl, imageVersions) => {
const { Octokit } = await import("@octokit/rest");

const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN,
});
Expand All @@ -11,7 +11,7 @@ const removePackageVersions = async (imageUrl, imageVersions) => {
await octokit.rest.packages.deletePackageVersionForOrg({
package_type: "container",
package_name: imageName,
username: imageOwner,
org: imageOwner,
package_version_id: imageId,
});
}
Expand All @@ -26,7 +26,7 @@ const loadOutdatedVersionIds = async (octokit, imageOwner, imageName, versions)
const response = await octokit.rest.packages.getAllPackageVersionsForPackageOwnedByOrg({
package_type: "container",
package_name: imageName,
username: imageOwner,
org: imageOwner,
page,
});
if (response.data.length === 0) {
Expand Down
6 changes: 1 addition & 5 deletions apps/client-asset-sg/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,9 @@ registerLocaleData(locale_deCH, 'de-CH');
matcher: assetsPageMatcher,
loadChildren: () => import('@asset-sg/asset-viewer').then((m) => m.AssetViewerModule),
},
{
path: 'not-found',
component: NotFoundComponent,
},
{
path: '**',
component: RedirectToLangComponent,
component: NotFoundComponent,
},
]),
TranslateModule.forRoot({
Expand Down
1 change: 0 additions & 1 deletion apps/server-asset-sg/src/app.logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export class AppLogger implements LoggerService {
output += level.color(`${message}`);
}
if (params.length !== 0 && !(params.length === 1 && params[0] === undefined)) {
console.log({ params });
output += ' ' + stringify(params, level);
}
if (message instanceof Error) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { PatchAsset } from '@asset-sg/shared';
import { User } from '@asset-sg/shared/v2';
import { Role } from '@asset-sg/shared/v2';
import { AssetEditPolicy } from '@asset-sg/shared/v2';
import { AssetEditPolicy, Role, User } from '@asset-sg/shared/v2';
import { Controller, Get, HttpException, HttpStatus, Param, ParseIntPipe, Post, Put } from '@nestjs/common';
import * as E from 'fp-ts/Either';
import * as O from 'fp-ts/Option';
import { authorize } from '@/core/authorize';
import { CurrentUser } from '@/core/decorators/current-user.decorator';
import { ParseBody } from '@/core/decorators/parse.decorator';
Expand Down Expand Up @@ -69,16 +68,35 @@ const validatePatch = (user: User, patch: PatchAsset, record?: AssetEditDetail)
);
}

const hasStatusChanged = (key: 'internalUse' | 'publicUse') => {
const hasChanged = record == null || record[key].statusAssetUseItemCode !== patch[key].statusAssetUseItemCode;
return (
hasChanged &&
patch[key].statusAssetUseItemCode !== 'tobechecked' &&
((record != null && !policy.hasRole(Role.MasterEditor, record.workgroupId)) ||
!policy.hasRole(Role.MasterEditor, patch.workgroupId))
);
};

// Specialization of the policy where we disallow the internal status to be changed to anything else than `tobechecked`
// if the current user is not a master-editor for the asset's current or future workgroup.
const hasInternalUseChanged =
record == null || record.internalUse.statusAssetUseItemCode !== patch.internalUse.statusAssetUseItemCode;
if (hasStatusChanged('internalUse')) {
throw new HttpException("Changing the asset's internalUse status is not allowed", HttpStatus.FORBIDDEN);
}

// Specialization of the policy where we disallow the public status to be changed to anything else than `tobechecked`
// if the current user is not a master-editor for the asset's current or future workgroup.
if (hasStatusChanged('publicUse')) {
throw new HttpException("Changing the asset's public use status is not allowed", HttpStatus.FORBIDDEN);
}

// Specialization of the policy where we disallow the status work item code to be changed to `published`
// if the current user is not a master-editor for the asset's current or future workgroup.
if (
hasInternalUseChanged &&
patch.internalUse.statusAssetUseItemCode !== 'tobechecked' &&
O.toNullable(patch.newStatusWorkItemCode) === 'published' &&
((record != null && !policy.hasRole(Role.MasterEditor, record.workgroupId)) ||
!policy.hasRole(Role.MasterEditor, patch.workgroupId))
) {
throw new HttpException("Changing the asset's status is not allowed", HttpStatus.FORBIDDEN);
throw new HttpException("Changing the asset's working status is not allowed", HttpStatus.FORBIDDEN);
}
};
3 changes: 2 additions & 1 deletion apps/server-asset-sg/src/features/asset-edit/asset-edit.http
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,6 @@ Content-Type: application/json
"titleOriginal": "My Cool Asset",
"titlePublic": "Our Cool Asset",
"typeNatRels": [],
"workgroupId": 1
"workgroupId": 1,
"assetFiles": []
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Dialog, DialogRef } from '@angular/cdk/dialog';
import { ChangeDetectionStrategy, Component, Input, OnInit, TemplateRef, ViewChild, inject } from '@angular/core';
import { ChangeDetectionStrategy, Component, inject, Input, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { FormGroupDirective } from '@angular/forms';
import { MatCheckboxChange } from '@angular/material/checkbox';
import { LifecycleHooks, LifecycleHooksDirective, fromAppShared } from '@asset-sg/client-shared';
import { fromAppShared, LifecycleHooks, LifecycleHooksDirective } from '@asset-sg/client-shared';
import { isNotNull } from '@asset-sg/core';
import { isMasterEditor } from '@asset-sg/shared/v2';
import * as RD from '@devexperts/remote-data-ts';
Expand All @@ -12,7 +12,7 @@ import { TranslateService } from '@ngx-translate/core';
import { RxState } from '@rx-angular/state';

import * as O from 'fp-ts/Option';
import { Observable, map, of, startWith, switchMap, withLatestFrom, filter } from 'rxjs';
import { filter, map, Observable, of, startWith, switchMap, withLatestFrom } from 'rxjs';
import { AssetEditDetailVM } from '../../models';
import { AssetEditorFormGroup, AssetEditorUsageFormGroup } from '../asset-editor-form-group';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ export class AssetViewerFilesComponent implements OnInit, OnDestroy {
const key = `${this.assetId}/${file.id}/${downloadType}` as const;
this.activeFileDownloads.add(key);
this.httpClient.get(`/api/assets/${this.assetId}/files/${file.id}`, { responseType: 'blob' }).subscribe({
next: (blob) => {
next: async (blob) => {
const isPdf = file.name.endsWith('.pdf');
if (isPdf) {
blob = await blob.arrayBuffer().then((buffer) => new Blob([buffer], { type: 'application/pdf' }));
}
const url = URL.createObjectURL(blob);
const anchor = document.createElement('a');

anchor.setAttribute('style', 'display: none');
anchor.href = url;
anchor.rel = 'noopener noreferrer';
if (downloadType === 'save-file') {
if (!isPdf || downloadType === 'save-file') {
anchor.download = file.name;
} else {
anchor.target = '_blank';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,8 +192,7 @@ export class AssetSearchEffects {
withLatestFrom(this.store.select(selectCurrentAssetDetail)),
filter(([params, storeAssetDetail]) => params.assetId !== storeAssetDetail?.assetId),
map(([params, storeAssetDetail]) => {
const paramsEmpty = Object.values(params.query).every((v) => v == null);
const assetId = paramsEmpty ? storeAssetDetail?.assetId : params.assetId;
const assetId = storeAssetDetail?.assetId ?? params.assetId;
return assetId === undefined ? actions.resetAssetDetail() : actions.showAssetDetail({ assetId });
})
)
Expand All @@ -202,13 +201,14 @@ export class AssetSearchEffects {
public updateQueryParams$ = createEffect(
() =>
this.actions$.pipe(
ofType(actions.updateQueryParams, actions.loadSearch, actions.updateAssetDetail, actions.resetAssetDetail),
ofType(actions.updateQueryParams, actions.updateAssetDetail, actions.resetAssetDetail),
concatLatestFrom(() => [
this.store.select(selectAssetSearchQuery),
this.store.select(selectCurrentAssetDetail),
this.queryParams$,
]),
switchMap(([_, query, assetDetail]) => {
const params: Params = { assetId: assetDetail?.assetId };
switchMap(([_, query, assetDetail, queryParams]) => {
const params: Params = { assetId: assetDetail?.assetId ?? queryParams.assetId };
updatePlainParam(params, QUERY_PARAM_MAPPING.text, query.text);
updateArrayParam(
params,
Expand Down
10 changes: 10 additions & 0 deletions libs/auth/src/lib/services/auth.service.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { HttpClient } from '@angular/common/http';
import { inject, Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { ApiError, appSharedStateActions, AppState } from '@asset-sg/client-shared';
import { ORD } from '@asset-sg/core';
import { User, UserSchema } from '@asset-sg/shared/v2';
Expand All @@ -14,6 +15,7 @@ export class AuthService {
private readonly httpClient = inject(HttpClient);
private readonly oauthService = inject(OAuthService);
private readonly store = inject(Store<AppState>);
private readonly router = inject(Router);

private readonly _state$ = new BehaviorSubject(AuthState.Ongoing);

Expand All @@ -22,6 +24,8 @@ export class AuthService {
this.setState(AuthState.Success);
this.store.dispatch(appSharedStateActions.setAnonymousMode());
} else {
const callbackUrl = sessionStorage.getItem(CALLBACK_PATH_KEY);
sessionStorage.setItem(CALLBACK_PATH_KEY, this.router.url);
this.configureOAuth(
oAuthConfig['oauth_issuer'] as string,
oAuthConfig['oauth_clientId'] as string,
Expand All @@ -30,6 +34,10 @@ export class AuthService {
oAuthConfig['oauth_tokenEndpoint'] as string
);
await this.signIn();
if (callbackUrl != null) {
sessionStorage.removeItem(CALLBACK_PATH_KEY);
await this.router.navigateByUrl(callbackUrl);
}
this.store.dispatch(appSharedStateActions.loadUserProfile());
}
}
Expand Down Expand Up @@ -111,6 +119,8 @@ export class AuthService {
}
}

const CALLBACK_PATH_KEY = 'session.callback_path';

export enum AuthState {
Ongoing,
Aborted,
Expand Down
3 changes: 0 additions & 3 deletions libs/shared/v2/src/lib/models/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ const hasRole = (role: Role) => (user: User | null | undefined, workgroupId?: Wo
if (user == null) {
return false;
}
if (user.isAdmin) {
return true;
}
const roleIndex = getRoleIndex(role);
if (workgroupId != null) {
const role = user.roles.get(workgroupId);
Expand Down

0 comments on commit 9359f4f

Please sign in to comment.