From c1ab00ca5b16bcd3b0ee3e6f4bf39b112a002fa1 Mon Sep 17 00:00:00 2001 From: Irmantas Kaukas Date: Mon, 8 Jan 2024 13:23:00 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20removeFromProjectMembership=20API=20http?= =?UTF-8?q?=20method,=20project=20membership=20=E2=80=A6=20(#1330)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../collaboration.component.html | 6 +- .../collaboration/collaboration.component.ts | 13 ++- .../edit-list-item.component.ts | 10 +-- .../project/ontology/ontology.component.ts | 8 +- apps/dsp-app/src/app/project/project-base.ts | 80 ++++++++++--------- .../project-tile/project-tile.component.ts | 9 +-- .../users-list/users-list.component.html | 4 +- .../users/users-list/users-list.component.ts | 61 ++++++-------- .../src/app/user/profile/profile.component.ts | 7 +- .../properties/properties.component.ts | 7 +- .../lib/services/admin/user-api.service.ts | 2 +- .../src/lib/project.service.ts | 29 +++---- .../current-project.selectors.ts | 0 .../current-project.state-model.ts | 0 .../src/lib/projects/projects.selectors.ts | 2 +- 15 files changed, 115 insertions(+), 123 deletions(-) delete mode 100644 libs/vre/shared/app-state/src/lib/current-project/current-project.selectors.ts delete mode 100644 libs/vre/shared/app-state/src/lib/current-project/current-project.state-model.ts diff --git a/apps/dsp-app/src/app/project/collaboration/collaboration.component.html b/apps/dsp-app/src/app/project/collaboration/collaboration.component.html index d07bf9d262..296b3a9fa8 100644 --- a/apps/dsp-app/src/app/project/collaboration/collaboration.component.html +++ b/apps/dsp-app/src/app/project/collaboration/collaboration.component.html @@ -1,10 +1,10 @@
-
+
@@ -28,7 +28,7 @@
-
+
diff --git a/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts b/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts index 8fdf4f6992..bd0b495e90 100644 --- a/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts +++ b/apps/dsp-app/src/app/project/collaboration/collaboration.component.ts @@ -3,7 +3,12 @@ import { Title } from '@angular/platform-browser'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { ReadProject, ReadUser } from '@dasch-swiss/dsp-js'; import { ProjectService } from '@dasch-swiss/vre/shared/app-helper-services'; -import { LoadProjectMembersAction, ProjectsSelectors, UserSelectors } from '@dasch-swiss/vre/shared/app-state'; +import { + IKeyValuePairs, + LoadProjectMembersAction, + ProjectsSelectors, + UserSelectors, +} from '@dasch-swiss/vre/shared/app-state'; import { Actions, Select, Store } from '@ngxs/store'; import { Observable, Subject } from 'rxjs'; import { map, takeUntil } from 'rxjs/operators'; @@ -47,9 +52,9 @@ export class CollaborationComponent extends ProjectBase implements OnInit, OnDes ); } - @Select(ProjectsSelectors.projectMembers) projectMembers$: Observable; - @Select(ProjectsSelectors.isProjectsLoading) - isProjectsLoading$: Observable; + @Select(ProjectsSelectors.projectMembers) projectMembers$: Observable>; + @Select(ProjectsSelectors.isProjectsLoading) isProjectsLoading$: Observable; + @Select(ProjectsSelectors.isCurrentProjectAdminOrSysAdmin) isCurrentProjectAdminOrSysAdmin$: Observable; @Select(UserSelectors.isSysAdmin) isSysAdmin$: Observable; @Select(UserSelectors.user) user$: Observable; @Select(ProjectsSelectors.currentProject) project$: Observable; diff --git a/apps/dsp-app/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts b/apps/dsp-app/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts index a4da2217e2..2019c51bdd 100644 --- a/apps/dsp-app/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts +++ b/apps/dsp-app/src/app/project/list/list-item-form/edit-list-item/edit-list-item.component.ts @@ -3,7 +3,6 @@ import { ChangeDetectorRef, Component, EventEmitter, - Inject, Input, OnInit, Output, @@ -11,15 +10,12 @@ import { import { ApiResponseError, CreateChildNodeRequest, - KnoraApiConnection, List, ListNodeInfo, StringLiteral, UpdateChildNodeRequest, } from '@dasch-swiss/dsp-js'; import { ListApiService } from '@dasch-swiss/vre/shared/app-api'; -import { DspApiConnectionToken } from '@dasch-swiss/vre/shared/app-config'; -import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { ProjectService } from '@dasch-swiss/vre/shared/app-helper-services'; @Component({ @@ -72,11 +68,7 @@ export class EditListItemComponent implements OnInit { formInvalidMessage: string; constructor( - @Inject(DspApiConnectionToken) - private _dspApiConnection: KnoraApiConnection, private _listApiService: ListApiService, - private _errorHandler: AppErrorHandler, - private _projectService: ProjectService, private _cd: ChangeDetectorRef ) {} @@ -178,7 +170,7 @@ export class EditListItemComponent implements OnInit { */ insertChildNode() { const createChildNodeRequest: CreateChildNodeRequest = new CreateChildNodeRequest(); - createChildNodeRequest.name = `${this._projectService.iriToUuid(this.projectIri)}-${Math.random() + createChildNodeRequest.name = `${ProjectService.IriToUuid(this.projectIri)}-${Math.random() .toString(36) .substring(2)}${Math.random().toString(36).substring(2)}`; createChildNodeRequest.parentNodeIri = this.parentIri; diff --git a/apps/dsp-app/src/app/project/ontology/ontology.component.ts b/apps/dsp-app/src/app/project/ontology/ontology.component.ts index b6e7cd8b8f..c3820a1e89 100644 --- a/apps/dsp-app/src/app/project/ontology/ontology.component.ts +++ b/apps/dsp-app/src/app/project/ontology/ontology.component.ts @@ -34,13 +34,13 @@ import { import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { DefaultClass, + DefaultProperties, DefaultResourceClasses, - SortingService, + OntologyService, ProjectService, - DefaultProperties, PropertyCategory, PropertyInfoObject, - OntologyService, + SortingService, } from '@dasch-swiss/vre/shared/app-helper-services'; import { ClearCurrentOntologyAction, @@ -429,7 +429,7 @@ export class OntologyComponent extends ProjectBase implements OnInit, OnDestroy const ontology = this._store.selectSnapshot(OntologiesSelectors.currentOntology); const title = iri ? ontology.label : 'Data model'; - const uuid = this._projectService.iriToUuid(this.projectUuid); + const uuid = ProjectService.IriToUuid(this.projectUuid); const existingOntologyNames = this._store.selectSnapshot(OntologiesSelectors.currentProjectExistingOntologyNames); const dialogConfig: MatDialogConfig = { diff --git a/apps/dsp-app/src/app/project/project-base.ts b/apps/dsp-app/src/app/project/project-base.ts index e5a4897102..cc873262a6 100644 --- a/apps/dsp-app/src/app/project/project-base.ts +++ b/apps/dsp-app/src/app/project/project-base.ts @@ -4,6 +4,7 @@ import { ActivatedRoute, NavigationEnd, Router } from '@angular/router'; import { ReadProject, ReadUser } from '@dasch-swiss/dsp-js'; import { ProjectService } from '@dasch-swiss/vre/shared/app-helper-services'; import { + IKeyValuePairs, LoadProjectAction, LoadProjectOntologiesAction, OntologiesSelectors, @@ -22,35 +23,30 @@ export class ProjectBase implements OnInit, OnDestroy { project: ReadProject; // TODO use project$ instead // permissions of logged-in user - get isAdmin$(): Observable { - return combineLatest([ - this.user$.pipe(filter(user => user !== null)), - this.userProjectAdminGroups$, - this._route.params, - this._route.parent.params, - ]).pipe( - takeUntil(this.destroyed), - map(([user, userProjectGroups, params, parentParams]) => { - const projectIri = this._projectService.uuidToIri(params.uuid ? params.uuid : parentParams.uuid); - return ProjectService.IsProjectAdminOrSysAdmin(user, userProjectGroups, projectIri); - }) - ); - } + isAdmin$: Observable = combineLatest([ + this._store.select(UserSelectors.user).pipe(filter(user => user !== null)) as Observable, + this._store.select(UserSelectors.userProjectAdminGroups), + this._route.params, + this._route.parent.params, + ]).pipe( + takeUntil(this.destroyed), + map(([user, userProjectGroups, params, parentParams]) => { + const projectIri = this._projectService.uuidToIri(params.uuid ? params.uuid : parentParams.uuid); + return ProjectService.IsProjectAdminOrSysAdmin(user, userProjectGroups, projectIri); + }) + ); get projectIri() { return this._projectService.uuidToIri(this.projectUuid); } @Select(UserSelectors.user) user$: Observable; - @Select(UserSelectors.userProjectAdminGroups) - userProjectAdminGroups$: Observable; - @Select(ProjectsSelectors.isCurrentProjectAdmin) - isProjectAdmin$: Observable; - @Select(ProjectsSelectors.isCurrentProjectMember) - isProjectMember$: Observable; + @Select(UserSelectors.userProjectAdminGroups) userProjectAdminGroups$: Observable; + @Select(ProjectsSelectors.isCurrentProjectAdminOrSysAdmin) isCurrentProjectAdminOrSysAdmin: Observable; + @Select(ProjectsSelectors.isCurrentProjectMember) isProjectMember$: Observable; @Select(ProjectsSelectors.currentProject) project$: Observable; - @Select(ProjectsSelectors.isProjectsLoading) - isProjectsLoading$: Observable; + @Select(ProjectsSelectors.isProjectsLoading) isProjectsLoading$: Observable; + @Select(ProjectsSelectors.projectMembers) projectMembers$: Observable>; constructor( protected _store: Store, @@ -68,16 +64,7 @@ export class ProjectBase implements OnInit, OnDestroy { } ngOnInit(): void { - this.project = this._store.selectSnapshot(ProjectsSelectors.currentProject); - if (this.projectUuid && (!this.project || this.project.id !== this.projectIri)) { - // get current project data, project members and project groups - // and set the project state here - this.loadProject(); - } else if (!this.isOntologiesAvailable()) { - this.isProjectsLoading$.pipe(takeWhile(isLoading => isLoading === false)).subscribe((isLoading: boolean) => { - this._store.dispatch(new LoadProjectOntologiesAction(this.projectUuid)); - }); - } + this.loadProject(); } ngOnDestroy(): void { @@ -95,11 +82,30 @@ export class ProjectBase implements OnInit, OnDestroy { } private loadProject(): void { - this._store.dispatch(new LoadProjectAction(this.projectUuid, true)); - this._actions$ - .pipe(ofActionSuccessful(LoadProjectAction)) - .pipe(take(1)) - .subscribe(() => this.setProjectData()); + this.isProjectsLoading$ + .pipe( + takeWhile(isLoading => isLoading === false && this.projectUuid !== undefined), + take(1) + ) + .subscribe({ + next: () => { + const projectMembers = this._store.selectSnapshot(ProjectsSelectors.projectMembers)[this.projectIri]; + this.project = this._store.selectSnapshot(ProjectsSelectors.currentProject); + if (!this.project || this.project.id !== this.projectIri || !projectMembers) { + // get current project data, project members and project groups + // and set the project state here + this._store.dispatch(new LoadProjectAction(this.projectUuid, true)); + } else if (!this.isOntologiesAvailable()) { + this._store.dispatch(new LoadProjectOntologiesAction(this.projectUuid)); + } + }, + complete: () => { + this._actions$ + .pipe(ofActionSuccessful(LoadProjectAction)) + .pipe(take(1)) + .subscribe(() => this.setProjectData()); + }, + }); } private setProjectData(): void { diff --git a/apps/dsp-app/src/app/system/project-tile/project-tile.component.ts b/apps/dsp-app/src/app/system/project-tile/project-tile.component.ts index 68bf4c2d74..28ba67db19 100644 --- a/apps/dsp-app/src/app/system/project-tile/project-tile.component.ts +++ b/apps/dsp-app/src/app/system/project-tile/project-tile.component.ts @@ -13,18 +13,15 @@ export class ProjectTileComponent { @Input() project: StoredProject; @Input() sysAdmin: boolean; // used to show settings button - constructor( - private _router: Router, - private _projectService: ProjectService - ) {} + constructor(private _router: Router) {} navigateToProject(id: string) { - const uuid = this._projectService.iriToUuid(id); + const uuid = ProjectService.IriToUuid(id); this._router.navigate([RouteConstants.project, uuid]); } navigateToSettings(id: string) { - const uuid = this._projectService.iriToUuid(id); + const uuid = ProjectService.IriToUuid(id); this._router.navigate([RouteConstants.project, uuid, RouteConstants.settings, RouteConstants.collaboration]); } } diff --git a/apps/dsp-app/src/app/system/users/users-list/users-list.component.html b/apps/dsp-app/src/app/system/users/users-list/users-list.component.html index 32cf0b32fc..20a6dac4db 100644 --- a/apps/dsp-app/src/app/system/users/users-list/users-list.component.html +++ b/apps/dsp-app/src/app/system/users/users-list/users-list.component.html @@ -66,7 +66,7 @@
- diff --git a/apps/dsp-app/src/app/system/users/users-list/users-list.component.ts b/apps/dsp-app/src/app/system/users/users-list/users-list.component.ts index 037863de2f..1c67b75567 100644 --- a/apps/dsp-app/src/app/system/users/users-list/users-list.component.ts +++ b/apps/dsp-app/src/app/system/users/users-list/users-list.component.ts @@ -3,23 +3,15 @@ import { ChangeDetectorRef, Component, EventEmitter, - Inject, Input, OnInit, Output, } from '@angular/core'; import { MatDialog, MatDialogConfig } from '@angular/material/dialog'; import { ActivatedRoute, Params, Router } from '@angular/router'; -import { - ApiResponseError, - Constants, - KnoraApiConnection, - Permissions, - ReadProject, - ReadUser, -} from '@dasch-swiss/dsp-js'; +import { ApiResponseError, Constants, Permissions, ReadProject, ReadUser } from '@dasch-swiss/dsp-js'; import { UserApiService } from '@dasch-swiss/vre/shared/app-api'; -import { DspApiConnectionToken, RouteConstants } from '@dasch-swiss/vre/shared/app-config'; +import { RouteConstants } from '@dasch-swiss/vre/shared/app-config'; import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { ProjectService, SortingService } from '@dasch-swiss/vre/shared/app-helper-services'; import { @@ -31,9 +23,9 @@ import { SetUserAction, UserSelectors, } from '@dasch-swiss/vre/shared/app-state'; -import { Actions, ofActionSuccessful, Select, Store } from '@ngxs/store'; -import { Observable } from 'rxjs'; -import { switchMap, take } from 'rxjs/operators'; +import { Actions, Select, Store, ofActionSuccessful } from '@ngxs/store'; +import { Observable, combineLatest } from 'rxjs'; +import { map, switchMap, take } from 'rxjs/operators'; import { ConfirmDialogComponent } from '../../../main/action/confirm-dialog/confirm-dialog.component'; import { DialogComponent } from '../../../main/dialog/dialog.component'; @@ -105,19 +97,30 @@ export class UsersListComponent implements OnInit { // ... and sort by 'username' sortBy = 'username'; + disableMenu$: Observable = combineLatest([ + this._store.select(ProjectsSelectors.isCurrentProjectAdminOrSysAdmin), + this._store.select(UserSelectors.isSysAdmin), + ]).pipe( + map(([isCurrentProjectAdminOrSysAdmin, isSysAdmin]) => { + if (this.project && this.project.status === false) { + return true; + } else { + const isProjectAdmin = this.projectUuid ? isCurrentProjectAdminOrSysAdmin : false; + return !isProjectAdmin && !isSysAdmin; + } + }) + ); + @Select(UserSelectors.isSysAdmin) isSysAdmin$: Observable; @Select(UserSelectors.user) user$: Observable; @Select(UserSelectors.username) username$: Observable; - @Select(ProjectsSelectors.isCurrentProjectAdmin) - isProjectAdmin$: Observable; + @Select(UserSelectors.userProjectAdminGroups) userProjectAdminGroups$: Observable; + @Select(ProjectsSelectors.isCurrentProjectAdminOrSysAdmin) isCurrentProjectAdminOrSysAdmin$: Observable; @Select(ProjectsSelectors.currentProject) project$: Observable; - @Select(ProjectsSelectors.isProjectsLoading) - isProjectsLoading$: Observable; + @Select(ProjectsSelectors.isProjectsLoading) isProjectsLoading$: Observable; @Select(UserSelectors.isLoading) isUsersLoading$: Observable; constructor( - @Inject(DspApiConnectionToken) - private _dspApiConnection: KnoraApiConnection, private _userApiService: UserApiService, private _dialog: MatDialog, private _errorHandler: AppErrorHandler, @@ -125,7 +128,6 @@ export class UsersListComponent implements OnInit { private _router: Router, private _sortingService: SortingService, private _store: Store, - private _projectService: ProjectService, private _actions$: Actions, private _cd: ChangeDetectorRef ) { @@ -238,9 +240,9 @@ export class UsersListComponent implements OnInit { */ updateProjectAdminMembership(id: string, permissions: Permissions): void { const currentUser = this._store.selectSnapshot(UserSelectors.user); - if (this.userIsProjectAdmin(permissions)) { + const userIsProjectAdmin = this.userIsProjectAdmin(permissions); + if (userIsProjectAdmin) { // true = user is already project admin --> remove from admin rights - this._userApiService.removeFromProjectMembership(id, this.project.id, true).subscribe( response => { // if this user is not the logged-in user @@ -281,7 +283,7 @@ export class UsersListComponent implements OnInit { ); } else { // false: user isn't project admin yet --> add admin rights - this._userApiService.addToProjectMembership(id, this.project.id).subscribe( + this._userApiService.addToProjectMembership(id, this.project.id, true).subscribe( response => { if (currentUser.username !== response.user.username) { this._store.dispatch(new SetUserAction(response.user)); @@ -438,19 +440,6 @@ export class UsersListComponent implements OnInit { ); } - disableMenu(): boolean { - // disable menu in case of: - // project.status = false - if (this.project && this.project.status === false) { - return true; - } else { - return ( - !this._store.selectSnapshot(UserSelectors.isSysAdmin) && - !this._store.selectSnapshot(ProjectsSelectors.isCurrentProjectAdmin) - ); - } - } - sortList(key: any) { this.sortBy = key; this.list = this._sortingService.keySortByAlphabetical(this.list, this.sortBy as any); diff --git a/apps/dsp-app/src/app/user/profile/profile.component.ts b/apps/dsp-app/src/app/user/profile/profile.component.ts index 5664742ab2..b2524c5af2 100644 --- a/apps/dsp-app/src/app/user/profile/profile.component.ts +++ b/apps/dsp-app/src/app/user/profile/profile.component.ts @@ -5,7 +5,7 @@ import { ReadUser } from '@dasch-swiss/dsp-js'; import { LoadUserAction, UserSelectors } from '@dasch-swiss/vre/shared/app-state'; import { Select, Store } from '@ngxs/store'; import { Observable, Subject } from 'rxjs'; -import { takeUntil } from 'rxjs/operators'; +import { takeUntil, takeWhile } from 'rxjs/operators'; import { DialogComponent } from '../../main/dialog/dialog.component'; @Component({ @@ -33,7 +33,10 @@ export class ProfileComponent implements OnInit, OnDestroy { ngOnInit() { this.user$ - .pipe(takeUntil(this.ngUnsubscribe)) + .pipe( + takeUntil(this.ngUnsubscribe), + takeWhile(user => user !== null) + ) .subscribe(user => this._titleService.setTitle(`${user.username} (${user.givenName} ${user.familyName})`)); } diff --git a/apps/dsp-app/src/app/workspace/resource/properties/properties.component.ts b/apps/dsp-app/src/app/workspace/resource/properties/properties.component.ts index f9a9b37b4a..0f83b58964 100644 --- a/apps/dsp-app/src/app/workspace/resource/properties/properties.component.ts +++ b/apps/dsp-app/src/app/workspace/resource/properties/properties.component.ts @@ -41,12 +41,12 @@ import { DspApiConnectionToken } from '@dasch-swiss/vre/shared/app-config'; import { AppErrorHandler } from '@dasch-swiss/vre/shared/app-error-handler'; import { ProjectService, SortingService } from '@dasch-swiss/vre/shared/app-helper-services'; import { NotificationService } from '@dasch-swiss/vre/shared/app-notification'; -import { forkJoin, Observable, Subscription } from 'rxjs'; +import { Observable, Subscription, forkJoin } from 'rxjs'; import { ConfirmationWithComment, DialogComponent } from '../../../main/dialog/dialog.component'; import { + Events as CommsEvents, ComponentCommunicationEventService, EmitEvent, - Events as CommsEvents, } from '../../../main/services/component-communication-event.service'; import { DspResource } from '../dsp-resource'; import { RepresentationConstants } from '../representation/file-representation'; @@ -172,7 +172,6 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy { private _valueOperationEventService: ValueOperationEventService, private _valueService: ValueService, private _componentCommsService: ComponentCommunicationEventService, - private _projectService: ProjectService, private _sortingService: SortingService, private _cd: ChangeDetectorRef ) {} @@ -265,7 +264,7 @@ export class PropertiesComponent implements OnInit, OnChanges, OnDestroy { * @param project */ openProject(project: ReadProject) { - const uuid = this._projectService.iriToUuid(project.id); + const uuid = ProjectService.IriToUuid(project.id); window.open(`/project/${uuid}`, '_blank'); } diff --git a/libs/vre/shared/app-api/src/lib/services/admin/user-api.service.ts b/libs/vre/shared/app-api/src/lib/services/admin/user-api.service.ts index 053c6ceeaa..eaff9c1707 100644 --- a/libs/vre/shared/app-api/src/lib/services/admin/user-api.service.ts +++ b/libs/vre/shared/app-api/src/lib/services/admin/user-api.service.ts @@ -93,7 +93,7 @@ export class UserApiService extends BaseApi { } removeFromProjectMembership(userIri: string, projectIri: string, adminProject = false) { - return this._http.post( + return this._http.delete( `${this._userRoute(userIri)}/project-${adminProject ? 'admin-' : ''}memberships/${encodeURIComponent( projectIri )}`, diff --git a/libs/vre/shared/app-helper-services/src/lib/project.service.ts b/libs/vre/shared/app-helper-services/src/lib/project.service.ts index 9a6e9eb2dc..35414c4cad 100644 --- a/libs/vre/shared/app-helper-services/src/lib/project.service.ts +++ b/libs/vre/shared/app-helper-services/src/lib/project.service.ts @@ -13,15 +13,6 @@ import { AppConfigService } from '@dasch-swiss/vre/shared/app-config'; export class ProjectService { constructor(private _acs: AppConfigService) {} - iriToUuid(iri: string): string { - if (iri) { - const array = iri.split('/'); - return array[array.length - 1]; - } - - return ''; - } - static IriToUuid(iri: string): string { if (iri) { const array = iri.split('/'); @@ -40,11 +31,21 @@ export class ProjectService { } static IsInProjectGroup = (userProjectGroups: string[], projectIri: string): boolean => - userProjectGroups.some(e => e === projectIri); + userProjectGroups.some(e => ProjectService.IriToUuid(e) === ProjectService.IriToUuid(projectIri)); + + static IsMemberOfProjectAdminGroup(groupsPerProject: { [key: string]: string[] }, projectIri: string): boolean { + if (!groupsPerProject || Object.keys(groupsPerProject).length === 0) { + return false; + } + + const groups: { [key: string]: string[] } = {}; + Object.keys(groupsPerProject).forEach(group => { + groups[ProjectService.IriToUuid(group)] = groupsPerProject[group]; + }); - static IsMemberOfProjectAdminGroup = (groupsPerProject: { [key: string]: string[] }, projectIri: string): boolean => - (groupsPerProject && groupsPerProject[projectIri]) !== undefined && - groupsPerProject[projectIri].indexOf(Constants.ProjectAdminGroupIRI) > -1; + const groupValue = groups[ProjectService.IriToUuid(projectIri)]; + return groupValue !== undefined && groupValue.indexOf(Constants.ProjectAdminGroupIRI) > -1; + } static IsMemberOfSystemAdminGroup = (groupsPerProject: { [key: string]: string[] }): boolean => (groupsPerProject && groupsPerProject[Constants.SystemProjectIRI]) !== undefined && @@ -82,7 +83,7 @@ export class ProjectService { return isProjectAdmin ? // check if the user is member of the current project(id contains the iri) true - : user.projects.length === 0 + : !user || user.projects.length === 0 ? false : user.projects.some(p => ProjectService.IriToUuid(p.id) === projectUuid); } diff --git a/libs/vre/shared/app-state/src/lib/current-project/current-project.selectors.ts b/libs/vre/shared/app-state/src/lib/current-project/current-project.selectors.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/vre/shared/app-state/src/lib/current-project/current-project.state-model.ts b/libs/vre/shared/app-state/src/lib/current-project/current-project.state-model.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/libs/vre/shared/app-state/src/lib/projects/projects.selectors.ts b/libs/vre/shared/app-state/src/lib/projects/projects.selectors.ts index 29426414da..6b5fc4902b 100644 --- a/libs/vre/shared/app-state/src/lib/projects/projects.selectors.ts +++ b/libs/vre/shared/app-state/src/lib/projects/projects.selectors.ts @@ -74,7 +74,7 @@ export class ProjectsSelectors { } @Selector([ProjectsState, UserSelectors.user, UserSelectors.userProjectAdminGroups, RouterSelectors.params]) - static isCurrentProjectAdmin( + static isCurrentProjectAdminOrSysAdmin( state: ProjectsStateModel, user: ReadUser, userProjectGroups: string[],