diff --git a/smp-angular/src/app/app.module.ts b/smp-angular/src/app/app.module.ts index eeda238ab9bfbb1f5dbdf2edb55d160a4fd7d1f7..a84724a1dffb18370b7dfc4c07a2614d7c59e52c 100644 --- a/smp-angular/src/app/app.module.ts +++ b/smp-angular/src/app/app.module.ts @@ -150,6 +150,8 @@ import {GroupResourcePanelComponent} from "./edit/edit-group/group-resource-pane import { ResourceDialogComponent } from "./edit/edit-group/group-resource-panel/resource-dialog/resource-dialog.component"; +import {EditResourceComponent} from "./edit/edit-resources/edit-resource.component"; +import {EditResourceService} from "./edit/edit-resources/edit-resource.service"; @NgModule({ @@ -188,6 +190,7 @@ import { DomainSelectorComponent, EditDomainComponent, EditGroupComponent, + EditResourceComponent, ExpiredPasswordDialogComponent, ExtensionComponent, ExtensionPanelComponent, @@ -285,6 +288,7 @@ import { DownloadService, EditDomainService, EditGroupService, + EditResourceService, ExtensionService, GlobalLookups, HttpEventService, diff --git a/smp-angular/src/app/app.routes.ts b/smp-angular/src/app/app.routes.ts index 7ff9afaa2c3f572b797749400bed11f96b99f492..8af043f98f05e98a12756880f473e308ee958376 100644 --- a/smp-angular/src/app/app.routes.ts +++ b/smp-angular/src/app/app.routes.ts @@ -15,6 +15,7 @@ import {dirtyDeactivateGuard} from "./guards/dirty.guard"; import {AdminUserComponent} from "./system-settings/admin-users/admin-user.component"; import {EditDomainComponent} from "./edit/edit-domain/edit-domain.component"; import {EditGroupComponent} from "./edit/edit-group/edit-group.component"; +import {EditResourceComponent} from "./edit/edit-resources/edit-resource.component"; const appRoutes: Routes = [ @@ -28,7 +29,7 @@ const appRoutes: Routes = [ children: [ {path: 'edit-domain', component: EditDomainComponent, canDeactivate: [dirtyDeactivateGuard]}, {path: 'edit-group', component: EditGroupComponent, canDeactivate: [dirtyDeactivateGuard]}, - {path: 'edit-resource', component: PropertyComponent, canDeactivate: [dirtyDeactivateGuard]} + {path: 'edit-resource', component: EditResourceComponent, canDeactivate: [dirtyDeactivateGuard]} ] }, { diff --git a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts index 1e44d16085724d2d1496b0f1c3af2d2f9eb9eeb6..e0f0b7c3f6e6d0a91f113612f8a3701fd297aaf7 100644 --- a/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts +++ b/smp-angular/src/app/common/dialogs/member-dialog/member-dialog.component.ts @@ -10,6 +10,7 @@ import {DomainRo} from "../../model/domain-ro.model"; import {MemberTypeEnum} from "../../enums/member-type.enum"; import {AlertMessageService} from "../../alert-message/alert-message.service"; import {GroupRo} from "../../model/group-ro.model"; +import {ResourceRo} from "../../model/resource-ro.model"; @Component({ @@ -28,6 +29,7 @@ export class MemberDialogComponent implements OnInit { _currentMember: MemberRo; _currentDomain: DomainRo; _currentGroup: GroupRo; + _currentResource: ResourceRo; membershipType: MemberTypeEnum = MemberTypeEnum.DOMAIN; filteredOptions: Observable<SearchUserRo[]>; @@ -46,6 +48,7 @@ export class MemberDialogComponent implements OnInit { dialogRef.disableClose = true;//disable default close operation this._currentDomain = data.domain; this._currentGroup = data.group; + this._currentResource = data.resource; this.membershipType= data.membershipType; this.memberForm = formBuilder.group({ @@ -113,7 +116,7 @@ export class MemberDialogComponent implements OnInit { case MemberTypeEnum.GROUP: return " group ["+this._currentGroup?.groupName+"]" case MemberTypeEnum.RESOURCE: - return " resource" + return " resource ["+this._currentResource?.resourceTypeIdentifier+"]" } return " target not selected!" } @@ -160,7 +163,7 @@ export class MemberDialogComponent implements OnInit { case MemberTypeEnum.GROUP: return this.membershipService.addEditMemberToGroup(this._currentGroup.groupId,this._currentDomain.domainId, this.member) case MemberTypeEnum.RESOURCE: - return null; + return this.membershipService.addEditMemberToResource(this._currentResource, this._currentGroup,this._currentDomain, this.member) } } } diff --git a/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts b/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts index d9af579f8dd12e3c0ffed3be0951760c4a910e2f..34c0774ce777f942421ae5517b8efdde8a1a5c29 100644 --- a/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts +++ b/smp-angular/src/app/common/panels/membership-panel/membership-panel.component.ts @@ -16,6 +16,7 @@ import {GroupRo} from "../../model/group-ro.model"; import {Observable} from "rxjs"; import {SearchTableResult} from "../../search-table/search-table-result.model"; import {ConfirmationDialogComponent} from "../../dialogs/confirmation-dialog/confirmation-dialog.component"; +import {ResourceRo} from "../../model/resource-ro.model"; @Component({ @@ -29,6 +30,7 @@ export class MembershipPanelComponent implements BeforeLeaveGuard { private _domain: DomainRo; private _group: GroupRo; + private _resource: ResourceRo; displayedColumns: string[] = ['username', 'fullName', 'roleType', 'memberOf']; @@ -94,7 +96,21 @@ export class MembershipPanelComponent implements BeforeLeaveGuard { this.isLoadingResults = false; } } + get resource(): ResourceRo { + return this._resource; + } + + @Input() set resource(value: ResourceRo) { + this._resource = value; + if (!!value) { + if (this.membershipType == MemberTypeEnum.RESOURCE) { + this.loadMembershipData(); + } + } else { + this.isLoadingResults = false; + } + } onPageChanged(page: PageEvent) { this.loadMembershipData(); @@ -162,6 +178,7 @@ export class MembershipPanelComponent implements BeforeLeaveGuard { membershipType: this.membershipType, domain: this._domain, group: this._group, + resource: this._resource, member: member, } }).afterClosed().subscribe(value => { @@ -201,7 +218,7 @@ export class MembershipPanelComponent implements BeforeLeaveGuard { case MemberTypeEnum.GROUP: return !this._group; case MemberTypeEnum.RESOURCE: - return false; + return !this._resource; } } @@ -212,7 +229,8 @@ export class MembershipPanelComponent implements BeforeLeaveGuard { case MemberTypeEnum.GROUP: return this.membershipService.getGroupMembersObservable(this._group.groupId, this._domain.domainId, this.filter, this.paginator.pageIndex, this.paginator.pageSize); case MemberTypeEnum.RESOURCE: - return null; + return this.membershipService.getResourceMembersObservable(this._resource, this._group, this._domain, this.filter, this.paginator.pageIndex, this.paginator.pageSize); + } } @@ -223,7 +241,7 @@ export class MembershipPanelComponent implements BeforeLeaveGuard { case MemberTypeEnum.GROUP: return this.membershipService.deleteMemberFromGroup(this._group.groupId, this._domain.domainId, this.selectedMember); case MemberTypeEnum.RESOURCE: - return null; + return this.membershipService.deleteMemberFromResource(this._resource, this._group, this._domain, this.selectedMember); } } } diff --git a/smp-angular/src/app/common/panels/membership-panel/membership.service.ts b/smp-angular/src/app/common/panels/membership-panel/membership.service.ts index 795032eaa358b43ff6b42f79d8c005a8158cf01c..b8a021288cb16bcaee07f2d4a73dec4cfb6b7834 100644 --- a/smp-angular/src/app/common/panels/membership-panel/membership.service.ts +++ b/smp-angular/src/app/common/panels/membership-panel/membership.service.ts @@ -9,6 +9,9 @@ import {AlertMessageService} from "../../alert-message/alert-message.service"; import {MemberRo} from "../../model/member-ro.model"; import {TableResult} from "../../model/table-result.model"; import {SearchUserRo} from "../../model/search-user-ro.model"; +import {ResourceRo} from "../../model/resource-ro.model"; +import {GroupRo} from "../../model/group-ro.model"; +import {DomainRo} from "../../model/domain-ro.model"; @Injectable() @@ -54,13 +57,32 @@ export class MembershipService { params = params.set(filterProperty, encodeURIComponent(filter[filterProperty])); } } - return this.http.get<TableResult<MemberRo>>(SmpConstants.REST_EDIT_GROUP_MEMBER .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId) .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, groupId), {params}); } + getResourceMembersObservable(resource: ResourceRo, group: GroupRo, domain: DomainRo, filter: any, page: number, pageSize: number): Observable<SearchTableResult> { + const currentUser: User = this.securityService.getCurrentUser(); + + let params: HttpParams = new HttpParams() + .set('page', page.toString()) + .set('pageSize', pageSize.toString()); + + for (let filterProperty in filter) { + if (filter.hasOwnProperty(filterProperty)) { + // must encode else problem with + sign + params = params.set(filterProperty, encodeURIComponent(filter[filterProperty])); + } + } + return this.http.get<TableResult<MemberRo>>(SmpConstants.REST_EDIT_RESOURCE_MEMBER + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group.groupId) + .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource.resourceId), {params}); + } + getUserLookupObservable(filter: string): Observable<SearchUserRo[]> { const currentUser: User = this.securityService.getCurrentUser(); let params: HttpParams = new HttpParams() @@ -77,6 +99,7 @@ export class MembershipService { .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domainId), member); } + addEditMemberToGroup(groupId: string, domainId: string, member: MemberRo): Observable<MemberRo> { const currentUser: User = this.securityService.getCurrentUser(); @@ -86,6 +109,16 @@ export class MembershipService { .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, groupId), member); } + addEditMemberToResource(resource: ResourceRo, group: GroupRo, domain: DomainRo, member: MemberRo): Observable<MemberRo> { + const currentUser: User = this.securityService.getCurrentUser(); + + return this.http.put<MemberRo>(SmpConstants.REST_EDIT_RESOURCE_MEMBER_PUT + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group.groupId) + .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource.resourceId), member); + } + deleteMemberFromDomain(domainId: string, member: MemberRo): Observable<MemberRo> { const currentUser: User = this.securityService.getCurrentUser(); @@ -95,7 +128,7 @@ export class MembershipService { .replace(SmpConstants.PATH_PARAM_ENC_MEMBER_ID, member.memberId)); } - deleteMemberFromGroup(groupId: string,domainId: string, member: MemberRo): Observable<MemberRo> { + deleteMemberFromGroup(groupId: string, domainId: string, member: MemberRo): Observable<MemberRo> { const currentUser: User = this.securityService.getCurrentUser(); return this.http.delete<MemberRo>(SmpConstants.REST_EDIT_GROUP_MEMBER_DELETE @@ -105,4 +138,15 @@ export class MembershipService { .replace(SmpConstants.PATH_PARAM_ENC_MEMBER_ID, member.memberId)); } + deleteMemberFromResource(resource:ResourceRo, group:GroupRo, domain: DomainRo, member: MemberRo): Observable<MemberRo> { + const currentUser: User = this.securityService.getCurrentUser(); + + return this.http.delete<MemberRo>(SmpConstants.REST_EDIT_RESOURCE_MEMBER_DELETE + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group.groupId) + .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource.resourceId) + .replace(SmpConstants.PATH_PARAM_ENC_MEMBER_ID, member.memberId)); + } + } diff --git a/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts b/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts index df96222d9721fc858c55935ff1303b1b48ac6abb..afd6f447cebebdfc2907c7dc26545a0bb7bd1c4a 100644 --- a/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts +++ b/smp-angular/src/app/edit/edit-domain/edit-domain.service.ts @@ -34,6 +34,13 @@ export class EditDomainService { return this.getDomainsForUserRoleTypeObservable("group-admin") } + /** + * Method fetches all domains where logged user is admin + */ + public getDomainsForResourceAdminUserObservable():Observable<DomainRo[]> { + return this.getDomainsForUserRoleTypeObservable("resource-admin") + } + public getDomainsForUserRoleTypeObservable(type: string) :Observable<DomainRo[]> { let params: HttpParams = new HttpParams() .set(SmpConstants.PATH_QUERY_FILTER_TYPE, type); diff --git a/smp-angular/src/app/edit/edit-group/edit-group.component.ts b/smp-angular/src/app/edit/edit-group/edit-group.component.ts index 9e6e3d2a16bc7979743001a605696b631f9d118e..d88624fc2bf2b54cc716172d632d34b7dc02c947 100644 --- a/smp-angular/src/app/edit/edit-group/edit-group.component.ts +++ b/smp-angular/src/app/edit/edit-group/edit-group.component.ts @@ -75,7 +75,7 @@ export class EditGroupComponent implements AfterViewInit, BeforeLeaveGuard { this.updateGroupList([]); return; } - this.groupService.getDomainGroupsForGroupAdmin(this.selectedDomain) + this.groupService.getDomainGroupsForGroupAdminObservable(this.selectedDomain) .subscribe((result: GroupRo[]) => { this.updateGroupList(result) }, (error: any) => { @@ -107,11 +107,6 @@ export class EditGroupComponent implements AfterViewInit, BeforeLeaveGuard { } } - public onGroupSelected(event) { - this.selectedGroup = event.value; - } - - isDirty(): boolean { return false; } diff --git a/smp-angular/src/app/edit/edit-group/edit-group.service.ts b/smp-angular/src/app/edit/edit-group/edit-group.service.ts index 4c5d06a1a9ac4ef058be599fbe023e2a95f0e424..82c952e3a3c99dbb7413af86e0cdce803d54a63a 100644 --- a/smp-angular/src/app/edit/edit-group/edit-group.service.ts +++ b/smp-angular/src/app/edit/edit-group/edit-group.service.ts @@ -3,7 +3,6 @@ import {Observable} from 'rxjs'; import {HttpClient, HttpParams} from '@angular/common/http'; import {SecurityService} from "../../security/security.service"; -import {AlertMessageService} from "../../common/alert-message/alert-message.service"; import {User} from "../../security/user.model"; import {SmpConstants} from "../../smp.constants"; import {GroupRo} from "../../common/model/group-ro.model"; @@ -17,13 +16,20 @@ export class EditGroupService { constructor( private http: HttpClient, - private securityService: SecurityService, - private alertService: AlertMessageService) { + private securityService: SecurityService) { } - public getDomainGroupsForGroupAdmin(domain: DomainRo): Observable<GroupRo[]> { + public getDomainGroupsForGroupAdminObservable(domain: DomainRo): Observable<GroupRo[]> { + return this.getDomainGroupsForUserRoleTypeObservable('group-admin', domain); + } + + public getDomainGroupsForResourceAdminObservable(domain: DomainRo): Observable<GroupRo[]> { + return this.getDomainGroupsForUserRoleTypeObservable('resource-admin', domain); + } + + public getDomainGroupsForUserRoleTypeObservable(userType: string, domain: DomainRo): Observable<GroupRo[]> { let params: HttpParams = new HttpParams() - .set(SmpConstants.PATH_QUERY_FILTER_TYPE, 'group-admin'); + .set(SmpConstants.PATH_QUERY_FILTER_TYPE, userType); const currentUser: User = this.securityService.getCurrentUser(); return this.http.get<GroupRo[]>(SmpConstants.REST_EDIT_DOMAIN_GROUP @@ -31,9 +37,15 @@ export class EditGroupService { .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain?.domainId), {params}); } + public getGroupResourcesForGroupAdminObservable(group: GroupRo, domain: DomainRo, filter: any, page: number, pageSize: number): Observable<TableResult<ResourceRo>> { + return this.getGroupResourcesForUserTypeObservable('group-admin',group, domain, filter, page, pageSize); + + } + + public getGroupResourcesForUserTypeObservable(userType: string, group: GroupRo, domain: DomainRo, filter: any, page: number, pageSize: number): Observable<TableResult<ResourceRo>> { let params: HttpParams = new HttpParams() - .set(SmpConstants.PATH_QUERY_FILTER_TYPE, 'resource-admin') + .set(SmpConstants.PATH_QUERY_FILTER_TYPE, userType) .set('page', page.toString()) .set('pageSize', pageSize.toString()); diff --git a/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts b/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts index 16f35824c3272c7b02367b1eea8bfa3a1014cba0..3b7d1b88376d32520f040495806cdd23a4fbe777 100644 --- a/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts +++ b/smp-angular/src/app/edit/edit-group/group-resource-panel/group-resource-panel.component.ts @@ -24,6 +24,7 @@ export class GroupResourcePanelComponent implements BeforeLeaveGuard { title: string = "Group resources"; private _group: GroupRo; + @Input() resource: ResourceRo; @Input() domain: DomainRo; @Input() domainResourceDefs: ResourceDefinitionRo[]; displayedColumns: string[] = ['identifierValue', 'identifierScheme']; @@ -37,8 +38,6 @@ export class GroupResourcePanelComponent implements BeforeLeaveGuard { constructor(private editGroupService: EditGroupService, private alertService: AlertMessageService, private dialog: MatDialog) { - - } diff --git a/smp-angular/src/app/edit/edit-resources/edit-resource.component.css b/smp-angular/src/app/edit/edit-resources/edit-resource.component.css new file mode 100644 index 0000000000000000000000000000000000000000..8804b9226b630794f542140ace0814e7b3646e1c --- /dev/null +++ b/smp-angular/src/app/edit/edit-resources/edit-resource.component.css @@ -0,0 +1,19 @@ + +#admin-resource--panel { + display: flex; + flex-flow: column; + align-items: center; + height: 100%; + min-height: 600px; + padding: 0 2em; +} +#resource--filter { + width: 100%; + padding-top: 1em; +} + + +#admin-resource--table { + width: 100%; + padding-top: 1em; +} diff --git a/smp-angular/src/app/edit/edit-resources/edit-resource.component.html b/smp-angular/src/app/edit/edit-resources/edit-resource.component.html new file mode 100644 index 0000000000000000000000000000000000000000..6e77594b7a925aad3661fe7eb884cdbc42471a48 --- /dev/null +++ b/smp-angular/src/app/edit/edit-resources/edit-resource.component.html @@ -0,0 +1,120 @@ +<div id="admin-resource-panel"> + <data-panel id="admin-resource-data-panel" + title="Edit Resource" + text="Edit resource administration panel is a tool for resource administrators to administer the resource" + [labelColumnContent]="searchGroupPanel"> + + <mat-tab-group #domainTabs style="height: 100%"> + <mat-tab> + <ng-template mat-tab-label> + <smp-label icon="groups" label="Members"></smp-label> + </ng-template> + <domain-member-panel #groupMemberPanelComponent + [membershipType]="groupMembershipType" + [domain]="selectedDomain" + [group]="selectedGroup" + [resource]="selectedResource" + + ></domain-member-panel> + </mat-tab> + <mat-tab> + <ng-template mat-tab-label> + <smp-label icon="group" label="Resources"></smp-label> + </ng-template> + <group-resource-panel + [domainResourceDefs]="_selectedDomainResourceDef" + [domain]="selectedDomain" + [group]="selectedGroup" + [resource]="selectedResource" + ></group-resource-panel> + </mat-tab> + </mat-tab-group> + </data-panel> +</div> + +<ng-template #searchGroupPanel> + <mat-form-field style="width:100%"> + <mat-label>Selected domain</mat-label> + <mat-select placeholder="Select domain" + matTooltip="Select domain." + id="domain_id" + [value]="selectedDomain" + required> + <mat-option *ngFor="let domain of domainList" + [value]="domain" + > + {{domain.domainCode}} + </mat-option> + + </mat-select> + </mat-form-field> + + <mat-form-field style="width:100%"> + <mat-label>Selected Group</mat-label> + <mat-select placeholder="Select group" + matTooltip="Select group." + id="group_id" + [value]="selectedGroup" + required> + <mat-option *ngFor="let group of groupList" + [value]="group">{{group.groupName}}</mat-option> + </mat-select> + </mat-form-field> + + <div class="edit-resource-container mat-elevation-z2"> + <div class="edit-resource-loading-shade" + *ngIf="isLoadingResults"> + <mat-spinner *ngIf="isLoadingResults"></mat-spinner> + </div> + + <div class="edit-resource-table-container"> + + <mat-form-field id="edit-resource-filter" style="width: 100%"> + <mat-label>Resource filter</mat-label> + <input matInput (keyup)="applyResourceFilter($event)" + placeholder="Resource filter" + [disabled]="disabledResourceFilter" + #inputDomainMemberFilter> + </mat-form-field> + + <table class="mat-elevation-z2" mat-table [dataSource]="data"> + + <ng-container matColumnDef="identifierScheme"> + <th mat-header-cell *matHeaderCellDef>Scheme</th> + <td mat-cell *matCellDef="let row">{{row.identifierScheme}}</td> + </ng-container> + + <ng-container matColumnDef="identifierValue"> + <th mat-header-cell *matHeaderCellDef>Identifier</th> + <td mat-cell *matCellDef="let row">{{row.identifierValue}}</td> + </ng-container> + + + + <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> + <tr mat-row *matRowDef="let odd = odd; let row; columns: displayedColumns;" + (click)="onResourceSelected(row)" + [ngClass]="{'datatable-row-selected': row==selectedResource,'datatable-row-odd': odd}" + ></tr> + + <tr class="mat-row" *matNoDataRow> + <td *ngIf="inputDomainMemberFilter.value;else noDataFound" class="mat-cell" colspan="2">No resources + matching the filter + "{{inputDomainMemberFilter.value}}" + </td> + <ng-template #noDataFound> + <td class="mat-cell" colspan="2">No direct members for the domain</td> + </ng-template> + </tr> + </table> + </div> + + <mat-paginator class="mat-elevation-z2" [length]="resultsLength" + (page)="onPageChanged($event)" + [pageSize]="5" + [pageSizeOptions]="[5, 10, 25]" + [disabled]="disabledForm" + aria-label="Select pages"></mat-paginator> + </div> + +</ng-template> diff --git a/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts b/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts new file mode 100644 index 0000000000000000000000000000000000000000..f15bdd42dc2d002831b823a858dd40b2b9221dd7 --- /dev/null +++ b/smp-angular/src/app/edit/edit-resources/edit-resource.component.ts @@ -0,0 +1,181 @@ +import {AfterViewInit, Component, Input, ViewChild} from '@angular/core'; +import {BeforeLeaveGuard} from "../../window/sidenav/navigation-on-leave-guard"; +import {MatPaginator} from "@angular/material/paginator"; +import {AlertMessageService} from "../../common/alert-message/alert-message.service"; +import {EditDomainService} from "../edit-domain/edit-domain.service"; +import {DomainRo} from "../../common/model/domain-ro.model"; +import {GroupRo} from "../../common/model/group-ro.model"; +import {MemberTypeEnum} from "../../common/enums/member-type.enum"; +import {ResourceDefinitionRo} from "../../system-settings/admin-extension/resource-definition-ro.model"; +import {EditGroupService} from "../edit-group/edit-group.service"; +import {ResourceRo} from "../../common/model/resource-ro.model"; +import {EditResourceService} from "./edit-resource.service"; +import {group} from "@angular/animations"; +import {TableResult} from "../../common/model/table-result.model"; + + +@Component({ + moduleId: module.id, + templateUrl: './edit-resource.component.html', + styleUrls: ['./edit-resource.component.css'] +}) +export class EditResourceComponent implements AfterViewInit, BeforeLeaveGuard { + groupMembershipType: MemberTypeEnum = MemberTypeEnum.RESOURCE; + domainList: DomainRo[] = []; + groupList: GroupRo[] = []; + resourceList: ResourceRo[] = []; + + _selectedDomain: DomainRo; + _selectedGroup: GroupRo; + + _selectedResource: ResourceRo; + _selectedDomainResourceDef: ResourceDefinitionRo[]; + + displayedColumns: string[] = ['identifierValue', 'identifierScheme']; + + data: ResourceRo[] = []; + selected: ResourceRo; + filter: any = {}; + resultsLength = 0; + isLoadingResults = false; + + @ViewChild(MatPaginator) paginator: MatPaginator; + + get selectedDomain(): DomainRo { + return this._selectedDomain; + }; + + @Input() set selectedDomain(domain: DomainRo) { + this._selectedDomain = domain; + if (!!this.selectedDomain) { + this.refreshGroups(); + this.refreshDomainsResourceDefinitions(); + } else { + this.groupList = []; + this._selectedDomainResourceDef = []; + } + + }; + + get selectedGroup(): GroupRo { + return this._selectedGroup; + }; + + @Input() set selectedGroup(resource: GroupRo) { + this._selectedGroup = resource; + if (!!this._selectedGroup) { + this.refreshResources(); + } else { + this.resourceList = []; + } + }; + get selectedResource(): ResourceRo { + return this._selectedResource; + }; + + @Input() set selectedResource(resource: ResourceRo) { + this._selectedResource = resource; + }; + + onResourceSelected(resource: ResourceRo){ + this.selectedResource = resource; + } + + constructor(private domainService: EditDomainService, + private groupService: EditGroupService, + private resourceService: EditResourceService, + private alertService: AlertMessageService) { + + } + + ngAfterViewInit() { + this.refreshDomains(); + } + + refreshDomains() { + this.domainService.getDomainsForResourceAdminUserObservable() + .subscribe((result: DomainRo[]) => { + this.updateDomainList(result) + }, (error: any) => { + this.alertService.error(error.error?.errorDescription) + }); + } + + refreshGroups() { + if (!this.selectedDomain) { + this.updateGroupList([]); + return; + } + this.groupService.getDomainGroupsForResourceAdminObservable(this.selectedDomain) + .subscribe((result: GroupRo[]) => { + this.updateGroupList(result) + }, (error: any) => { + this.alertService.error(error.error?.errorDescription) + }); + } + + refreshResources() { + if (!this.selectedGroup) { + this.updateResourceList([]); + return; + } + + this.resourceService.getGroupResourcesForResourceAdminObservable(this.selectedGroup, this.selectedDomain, this.filter, this.paginator.pageIndex, this.paginator.pageSize) + .subscribe((result: TableResult<ResourceRo>) => { + console.log("got resources: " + JSON.stringify(result)) + this.updateResourceList(result.serviceEntities) + this.data = [...result.serviceEntities]; + this.resultsLength = result.count; + }, (error: any) => { + this.alertService.error(error.error?.errorDescription) + }); + + + } + + refreshDomainsResourceDefinitions() { + this.domainService.getDomainResourceDefinitionsObservable(this.selectedDomain) + .subscribe((result: ResourceDefinitionRo[]) => { + this._selectedDomainResourceDef = result + }, (error: any) => { + this.alertService.error(error.error?.errorDescription) + }); + } + + updateDomainList(list: DomainRo[]) { + this.domainList = list; + if (!!this.domainList && this.domainList.length > 0) { + + this.selectedDomain = this.domainList[0]; + } + } + + updateGroupList(list: GroupRo[]) { + this.groupList = list + if (!!this.groupList && this.groupList.length > 0) { + this.selectedGroup = this.groupList[0]; + } + } + + updateResourceList(list: ResourceRo[]) { + this.resourceList = list + if (!!this.resourceList && this.resourceList.length > 0) { + this.selectedResource = this.resourceList[0]; + } + } + + applyResourceFilter(event: Event) { + const filterValue = (event.target as HTMLInputElement).value; + this.filter["filter"] = filterValue.trim().toLowerCase(); + this.refreshResources(); + } + + get disabledResourceFilter(): boolean{ + return !this._selectedGroup; + } + + isDirty(): boolean { + return false; + } + +} diff --git a/smp-angular/src/app/edit/edit-resources/edit-resource.service.ts b/smp-angular/src/app/edit/edit-resources/edit-resource.service.ts new file mode 100644 index 0000000000000000000000000000000000000000..0f6e9c71f8f73a6e4a66baedbf4b414bfb266e0a --- /dev/null +++ b/smp-angular/src/app/edit/edit-resources/edit-resource.service.ts @@ -0,0 +1,81 @@ +import {Injectable} from '@angular/core'; +import {Observable} from 'rxjs'; + +import {HttpClient, HttpParams} from '@angular/common/http'; +import {SecurityService} from "../../security/security.service"; +import {User} from "../../security/user.model"; +import {SmpConstants} from "../../smp.constants"; +import {GroupRo} from "../../common/model/group-ro.model"; +import {ResourceRo} from "../../common/model/resource-ro.model"; +import {TableResult} from "../../common/model/table-result.model"; +import {DomainRo} from "../../common/model/domain-ro.model"; + +@Injectable() +export class EditResourceService { + + + constructor( + private http: HttpClient, + private securityService: SecurityService) { + } + + + public getGroupResourcesForGroupAdminObservable(group: GroupRo, domain: DomainRo, filter: any, page: number, pageSize: number): Observable<TableResult<ResourceRo>> { + return this.getGroupResourcesForUserTypeObservable('group-admin', group, domain, filter, page, pageSize); + } + + public getGroupResourcesForResourceAdminObservable(group: GroupRo, domain: DomainRo, filter: any, page: number, pageSize: number): Observable<TableResult<ResourceRo>> { + return this.getGroupResourcesForUserTypeObservable('resource-admin', group, domain, filter, page, pageSize); + } + + public getGroupResourcesForUserTypeObservable(userType: string, group: GroupRo, domain: DomainRo, filter: any, page: number, pageSize: number): Observable<TableResult<ResourceRo>> { + + let params: HttpParams = new HttpParams() + .set(SmpConstants.PATH_QUERY_FILTER_TYPE, userType) + .set('page', page.toString()) + .set('pageSize', pageSize.toString()); + + if (!!filter) { + for (let filterProperty in filter) { + if (filter.hasOwnProperty(filterProperty)) { + // must encode else problem with + sign + params = params.set(filterProperty, encodeURIComponent(filter[filterProperty])); + } + } + } + + + const currentUser: User = this.securityService.getCurrentUser(); + return this.http.get<TableResult<ResourceRo>>(SmpConstants.REST_EDIT_RESOURCE + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain?.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group?.groupId), {params}); + } + + deleteResourceFromGroup(resource: ResourceRo, group: GroupRo, domain: DomainRo): Observable<ResourceRo> { + const currentUser: User = this.securityService.getCurrentUser(); + return this.http.delete<ResourceRo>(SmpConstants.REST_EDIT_RESOURCE_DELETE + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group?.groupId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain?.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource.resourceId)); + } + + createResourceForGroup(resource: ResourceRo, group: GroupRo, domain: DomainRo): Observable<ResourceRo> { + const currentUser: User = this.securityService.getCurrentUser(); + return this.http.put<ResourceRo>(SmpConstants.REST_EDIT_RESOURCE_CREATE + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain?.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group?.groupId), resource); + } + + updateResourceForGroup(resource: ResourceRo, group: GroupRo, domain: DomainRo): Observable<ResourceRo> { + const currentUser: User = this.securityService.getCurrentUser(); + + return this.http.post<ResourceRo>(SmpConstants.REST_EDIT_RESOURCE_UPDATE + .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, currentUser.userId) + .replace(SmpConstants.PATH_PARAM_ENC_DOMAIN_ID, domain?.domainId) + .replace(SmpConstants.PATH_PARAM_ENC_GROUP_ID, group?.groupId) + .replace(SmpConstants.PATH_PARAM_ENC_RESOURCE_ID, resource?.resourceId), resource); + } +} diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts index b0bc948d09835ab9be881c9eb84475649370d513..36da555613cf7a808be695d199cec25ff3d2df08 100644 --- a/smp-angular/src/app/smp.constants.ts +++ b/smp-angular/src/app/smp.constants.ts @@ -78,6 +78,11 @@ export class SmpConstants { public static readonly REST_EDIT_RESOURCE_DELETE = SmpConstants.REST_EDIT_RESOURCE + '/' + SmpConstants.PATH_PARAM_ENC_RESOURCE_ID + '/' + SmpConstants.PATH_ACTION_DELETE; + public static readonly REST_EDIT_RESOURCE_MEMBER = SmpConstants.REST_EDIT_RESOURCE + '/' + SmpConstants.PATH_PARAM_ENC_RESOURCE_ID + + '/' + SmpConstants.PATH_RESOURCE_TYPE_MEMBER ; + public static readonly REST_EDIT_RESOURCE_MEMBER_PUT = SmpConstants.REST_EDIT_RESOURCE_MEMBER + '/' + SmpConstants.PATH_ACTION_PUT; + public static readonly REST_EDIT_RESOURCE_MEMBER_DELETE = SmpConstants.REST_EDIT_RESOURCE_MEMBER + '/' + SmpConstants.PATH_PARAM_ENC_MEMBER_ID + + '/' + SmpConstants.PATH_ACTION_DELETE; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceMemberToMemberROConverter.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceMemberToMemberROConverter.java new file mode 100644 index 0000000000000000000000000000000000000000..53724c3676709973dbf6c9f22b30430193d3caee --- /dev/null +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/conversion/DBResourceMemberToMemberROConverter.java @@ -0,0 +1,26 @@ +package eu.europa.ec.edelivery.smp.conversion; + +import eu.europa.ec.edelivery.smp.data.model.user.DBResourceMember; +import eu.europa.ec.edelivery.smp.data.ui.MemberRO; +import eu.europa.ec.edelivery.smp.utils.SessionSecurityUtils; +import org.springframework.core.convert.converter.Converter; +import org.springframework.stereotype.Component; + + +/** + * + */ +@Component +public class DBResourceMemberToMemberROConverter implements Converter<DBResourceMember, MemberRO> { + + @Override + public MemberRO convert(DBResourceMember source) { + MemberRO target = new MemberRO(); + target.setMemberOf("RESOURCE"); + target.setUsername(source.getUser().getUsername()); + target.setFullName(source.getUser().getFullName()); + target.setRoleType(source.getRole()); + target.setMemberId(SessionSecurityUtils.encryptedEntityId(source.getId())); + return target; + } +} diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java index c29053731d1ab0a4a6a5e5ae2fcd72693add76d4..99ffa95e72641ede1efd01a6a6da209e6829cc95 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainDao.java @@ -142,6 +142,23 @@ public class DomainDao extends BaseDao<DBDomain> { query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes)); return query.getResultList(); } + + public Long getDomainsByUserIdAndResourceRolesCount(Long userId, MembershipRoleType ... roleTypes) { + + TypedQuery<Long> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_RESOURCE_ROLES_COUNT, Long.class); + query.setParameter(PARAM_USER_ID, userId); + query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes)); + return query.getSingleResult(); + } + + public List<DBDomain> getDomainsByUserIdAndResourceRoles(Long userId, MembershipRoleType ... roleTypes) { + + TypedQuery<DBDomain> query = memEManager.createNamedQuery(QUERY_DOMAIN_BY_USER_RESOURCE_ROLES, DBDomain.class); + query.setParameter(PARAM_USER_ID, userId); + query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes)); + return query.getResultList(); + } + public List<MembershipRoleType> toList(MembershipRoleType ... roleTypes){ return Arrays.asList(roleTypes ==null || roleTypes.length==0 ?MembershipRoleType.values(): roleTypes); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java index 8d712f356914141e531576b375047a55ee9a9e5c..10d33b66845bf8e38223b6441520d2eaa33ba650 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/DomainMemberDao.java @@ -71,7 +71,7 @@ public class DomainMemberDao extends BaseDao<DBDomainMember> { } public boolean isUserResourceAdministrator(Long userId){ - return false; + return domainDao.getDomainsByUserIdAndResourceRolesCount(userId, MembershipRoleType.ADMIN)>0; } public List<DBDomainMember> getDomainMembers(Long domainId, int iPage, int iPageSize, String filter) { diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java index 2d92c61c4ed89494674e53dc55ed88e25fc4832c..d8a761ae8900f124da8a8cf191e510d188e9a422 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupDao.java @@ -135,20 +135,30 @@ public class GroupDao extends BaseDao<DBGroup> { } public List<DBGroup> getGroupsByUserIdAndRoles(Long userId, MembershipRoleType... roleTypes) { - TypedQuery<DBGroup> query = memEManager.createNamedQuery(QUERY_GROUP_BY_USER_ROLES, DBGroup.class); + TypedQuery<DBGroup> query = memEManager.createNamedQuery(QUERY_GROUP_BY_USER_GROUP_ROLES, DBGroup.class); query.setParameter(PARAM_USER_ID, userId); query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes)); return query.getResultList(); } - public List<DBGroup> getGroupsByDomainUserIdAndRoles(Long domainId, Long userId, MembershipRoleType... roleTypes) { + public List<DBGroup> getGroupsByDomainUserIdAndGroupRoles(Long domainId, Long userId, MembershipRoleType... roleTypes) { - TypedQuery<DBGroup> query = memEManager.createNamedQuery(QUERY_GROUP_BY_DOMAIN_USER_ROLES, DBGroup.class); + TypedQuery<DBGroup> query = memEManager.createNamedQuery(QUERY_GROUP_BY_DOMAIN_USER_GROUP_ROLES, DBGroup.class); query.setParameter(PARAM_DOMAIN_ID, domainId); query.setParameter(PARAM_USER_ID, userId); query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes)); return query.getResultList(); } + + public List<DBGroup> getGroupsByDomainUserIdAndResourceRoles(Long domainId, Long userId, MembershipRoleType... roleTypes) { + + TypedQuery<DBGroup> query = memEManager.createNamedQuery(QUERY_GROUP_BY_DOMAIN_USER_RESOURCE_ROLES, DBGroup.class); + query.setParameter(PARAM_DOMAIN_ID, domainId); + query.setParameter(PARAM_USER_ID, userId); + query.setParameter(PARAM_MEMBERSHIP_ROLES, toList(roleTypes)); + return query.getResultList(); + } + /** * Removes Entity by given domain code * diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java index ba610172fd5f100282c38b92fdb93056760533ca..42afeb4242d9b62405a5c51f6e152f1bd7b4ff9f 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/GroupMemberDao.java @@ -122,7 +122,7 @@ public class GroupMemberDao extends BaseDao<DBGroupMember> { } - public DBGroupMember addMemberToDomain(DBGroup group, DBUser user, MembershipRoleType role) { + public DBGroupMember addMemberToGroup(DBGroup group, DBUser user, MembershipRoleType role) { DBGroupMember groupMember = new DBGroupMember(); groupMember.setRole(role); groupMember.setUser(user); diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java index 5c5dd1069921fa55c838aa8575d9559d89aa926f..ff1b663dfe1ead9cb97580517d8037f1536f1457 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/QueryNames.java @@ -19,6 +19,9 @@ public class QueryNames { public static final String QUERY_DOMAIN_BY_USER_GROUP_ROLES_COUNT = "DBDomain.getByUserAndGroupRolesCount"; public static final String QUERY_DOMAIN_BY_USER_GROUP_ROLES = "DBDomain.getByUserAndGroupRoles"; + + public static final String QUERY_DOMAIN_BY_USER_RESOURCE_ROLES_COUNT = "DBDomain.getByUserAndResourceRolesCount"; + public static final String QUERY_DOMAIN_BY_USER_RESOURCE_ROLES = "DBDomain.getByUserAndResourceRoles"; public static final String QUERY_EXTENSION_ALL = "DBExtension.getAll"; public static final String QUERY_EXTENSION_BY_IDENTIFIER = "DBExtension.getByIdentifier"; @@ -27,13 +30,15 @@ public class QueryNames { public static final String QUERY_GROUP_BY_NAME_DOMAIN = "DBGroup.getByNameDomain"; public static final String QUERY_GROUP_BY_NAME_DOMAIN_CODE = "DBGroup.getByNameDomainCode"; - public static final String QUERY_GROUP_BY_USER_ROLES = "DBGroup.getByUserAndRoles"; - public static final String QUERY_GROUP_BY_DOMAIN_USER_ROLES = "DBGroup.getByDomainAndUserAndRoles"; - public static final String QUERY_GROUP_BY_USER_ROLES_COUNT = "DBGroup.getByUserAndRolesCount"; - public static final String QUERY_GROUP_MEMBERS_COUNT = "DBGroup.getByGroupCount"; - public static final String QUERY_GROUP_MEMBERS_FILTER_COUNT = "DBGroup.getByGroupFilterCount"; - public static final String QUERY_GROUP_MEMBERS = "DBGroup.getByGroup"; - public static final String QUERY_GROUP_MEMBERS_FILTER = "DBGroup.getByGroupFilter"; + public static final String QUERY_GROUP_BY_USER_GROUP_ROLES = "DBGroup.getByUserAndRoles"; + public static final String QUERY_GROUP_BY_DOMAIN_USER_GROUP_ROLES = "DBGroup.getByDomainAndUserAndGroupRoles"; + + public static final String QUERY_GROUP_BY_DOMAIN_USER_RESOURCE_ROLES = "DBGroup.getByDomainAndUserAndResourceRoles"; + public static final String QUERY_GROUP_BY_USER_ROLES_COUNT = "DBGroup.getByUserAndGrouRolesCount"; + public static final String QUERY_GROUP_MEMBERS_COUNT = "DBGroupMember.getByGroupCount"; + public static final String QUERY_GROUP_MEMBERS_FILTER_COUNT = "DBGroupMember.getByGroupFilterCount"; + public static final String QUERY_GROUP_MEMBERS = "DBGroupMember.getByGroup"; + public static final String QUERY_GROUP_MEMBERS_FILTER = "DBGroupMember.getByGroupFilter"; public static final String QUERY_DOMAIN_MEMBER_ALL = "DBDomainMember.getAll"; public static final String QUERY_DOMAIN_MEMBER_BY_USER_DOMAINS_COUNT = "DBDomainMember.getByUserAndDomainsCount"; @@ -66,6 +71,11 @@ public class QueryNames { public static final String QUERY_RESOURCE_MEMBER_BY_USER_DOMAIN_RESOURCE_ROLE_COUNT = "DBResourceMember.getByUserAndDomainRoleResourceCount"; public static final String QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_ROLE_COUNT = "DBResourceMember.getByUserAndGroupsResourcesAndRoleCount"; + public static final String QUERY_RESOURCE_MEMBERS_COUNT = "DBResourceMember.getByResourceCount"; + public static final String QUERY_RESOURCE_MEMBERS_FILTER_COUNT = "DBResourceMember.getByResourceFilterCount"; + public static final String QUERY_RESOURCE_MEMBERS = "DBResourceMember.getByResource"; + public static final String QUERY_RESOURCE_MEMBERS_FILTER = "DBResourceMember.getByResourceFilter"; + public static final String QUERY_RESOURCE_MEMBER_BY_USER_RESOURCE= "DBResourceMember.getByUserAndResource"; public static final String QUERY_SUBRESOURCE_BY_IDENTIFIER_RESOURCE_SUBRESDEF = "DBSubresource.getByIdentifierAndResourceAndSubresourceDef"; @@ -93,6 +103,8 @@ public class QueryNames { public static final String QUERY_GROUP_MEMBER_BY_USER_GROUPS_COUNT = "DBGroupMember.getByUserAndGroupsCount"; public static final String QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_COUNT = "DBGroupMember.getByUserAndDomainGroupsCount"; public static final String QUERY_GROUP_MEMBER_BY_USER_GROUPS = "DBGroupMember.getByUserAndGroups"; + + public static final String QUERY_RESOURCE_MEMBER_BY_USER_RESOURCES = "DBResourceMember.getByUserAndResources"; public static final String QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_ROLE_COUNT = "DBGroupMember.getByUserAndDomainGroupsAndRoleCount"; public static final String QUERY_USER_BY_CI_USERNAME = "DBUser.getUserByUsernameInsensitive"; @@ -122,6 +134,7 @@ public class QueryNames { public static final String PARAM_CERTIFICATE_IDENTIFIER = "certificate_identifier"; public static final String PARAM_RESOURCE_ID = "resource_id"; + public static final String PARAM_RESOURCE_IDS = "resource_ids"; public static final String PARAM_SUBRESOURCE_ID = "subresource_id"; // resource identifier value public static final String PARAM_RESOURCE_IDENTIFIER = "resource_identifier"; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java index 73f95e564f9d324fcbb3499a12ed3cb2519074b7..76c9267fbe648f88fd6fdd861f405160f355eba6 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ResourceMemberDao.java @@ -15,11 +15,14 @@ package eu.europa.ec.edelivery.smp.data.dao; import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType; import eu.europa.ec.edelivery.smp.data.model.DBDomain; +import eu.europa.ec.edelivery.smp.data.model.DBGroup; import eu.europa.ec.edelivery.smp.data.model.doc.DBResource; +import eu.europa.ec.edelivery.smp.data.model.user.DBGroupMember; import eu.europa.ec.edelivery.smp.data.model.user.DBResourceMember; import eu.europa.ec.edelivery.smp.data.model.user.DBUser; import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Repository; import javax.persistence.TypedQuery; @@ -105,4 +108,43 @@ public class ResourceMemberDao extends BaseDao<DBResourceMember> { } + public List<DBResourceMember> getResourceMembers(Long resourceId, int iPage, int iPageSize, String filter) { + boolean hasFilter = StringUtils.isNotBlank(filter); + TypedQuery<DBResourceMember> query = memEManager.createNamedQuery(hasFilter ? + QUERY_RESOURCE_MEMBERS_FILTER : QUERY_RESOURCE_MEMBERS, DBResourceMember.class); + + if (iPageSize > -1 && iPage > -1) { + query.setFirstResult(iPage * iPageSize); + } + if (iPageSize > 0) { + query.setMaxResults(iPageSize); + } + query.setParameter(PARAM_RESOURCE_ID, resourceId); + if (hasFilter) { + query.setParameter(PARAM_USER_FILTER, StringUtils.wrapIfMissing(StringUtils.trim(filter),"%" )); + } + return query.getResultList(); + } + + public Long getResourceMemberCount(Long groupId, String filter) { + boolean hasFilter = StringUtils.isNotBlank(filter); + TypedQuery<Long> query = memEManager.createNamedQuery(hasFilter ? QUERY_RESOURCE_MEMBERS_FILTER_COUNT : QUERY_RESOURCE_MEMBERS_COUNT, Long.class); + query.setParameter(PARAM_RESOURCE_ID, groupId); + if (hasFilter) { + query.setParameter(PARAM_USER_FILTER, StringUtils.wrapIfMissing(StringUtils.trim(filter),"%" )); + } + return query.getSingleResult(); + } + + + public DBResourceMember addMemberToResource(DBResource resource, DBUser user, MembershipRoleType role) { + DBResourceMember resourceMember = new DBResourceMember(); + resourceMember.setRole(role); + resourceMember.setUser(user); + resourceMember.setResource(resource); + resourceMember = merge(resourceMember); + return resourceMember; + } + + } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java index dce74527cbdcbf191c569e318a3295f48f49549f..fb791616ff095fb7aa8948ff90d06f1599c2b302 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBDomain.java @@ -58,6 +58,19 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; " JOIN DBGroupMember gm ON g.id = gm.group.id " + " WHERE gm.role in (:membership_roles) and gm.user.id= :user_id") +@NamedQuery(name = QUERY_DOMAIN_BY_USER_RESOURCE_ROLES_COUNT, query = "SELECT count(d) FROM DBDomain d " + + " JOIN DBGroup g ON d.id = g.domain.id " + + " JOIN DBResource r ON g.id = r.group.id " + + " JOIN DBResourceMember rm ON r.id = rm.resource.id " + + " WHERE rm.role in (:membership_roles) and rm.user.id= :user_id") + + +@NamedQuery(name = QUERY_DOMAIN_BY_USER_RESOURCE_ROLES, query = "SELECT d FROM DBDomain d " + + " JOIN DBGroup g ON d.id = g.domain.id " + + " JOIN DBResource r ON g.id = r.group.id " + + " JOIN DBResourceMember rm ON r.id = rm.resource.id " + + " WHERE rm.role in (:membership_roles) and rm.user.id= :user_id") + @org.hibernate.annotations.Table(appliesTo = "SMP_DOMAIN", comment = "SMP can handle multiple domains. This table contains domain specific data") public class DBDomain extends BaseEntity { diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java index ccd8cfd81239c49efb7f93a272d70f7f13714f11..321728bc8571a780c4750b301ef6fa6ffa546f21 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/DBGroup.java @@ -45,10 +45,15 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; @NamedQuery(name = QUERY_GROUP_BY_USER_ROLES_COUNT, query = "SELECT count(c) FROM DBGroup c JOIN DBGroupMember dm ON c.id = dm.group.id " + " WHERE dm.role in (:membership_roles) and dm.user.id= :user_id") -@NamedQuery(name = QUERY_GROUP_BY_USER_ROLES, query = "SELECT c FROM DBGroup c JOIN DBGroupMember dm ON c.id = dm.group.id " + - " WHERE dm.role in (:membership_roles) and dm.user.id= :user_id") -@NamedQuery(name = QUERY_GROUP_BY_DOMAIN_USER_ROLES, query = "SELECT c FROM DBGroup c JOIN DBGroupMember dm ON c.id = dm.group.id " + +@NamedQuery(name = QUERY_GROUP_BY_USER_GROUP_ROLES, query = "SELECT c FROM DBGroup c JOIN DBGroupMember gm ON c.id = gm.group.id " + + " WHERE gm.role in (:membership_roles) and gm.user.id= :user_id") +@NamedQuery(name = QUERY_GROUP_BY_DOMAIN_USER_GROUP_ROLES, query = "SELECT c FROM DBGroup c JOIN DBGroupMember dm ON c.id = dm.group.id " + " WHERE c.domain.id = :domain_id AND dm.role in (:membership_roles) and dm.user.id= :user_id") +@NamedQuery(name = QUERY_GROUP_BY_DOMAIN_USER_RESOURCE_ROLES, query = "SELECT c FROM DBGroup c " + + " JOIN DBResource r ON c.id = r.group.id " + + " JOIN DBResourceMember rm on r.id = rm.resource.id" + + " WHERE c.domain.id = :domain_id AND rm.role in (:membership_roles) and rm.user.id= :user_id") + public class DBGroup extends BaseEntity { @Id diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java index bf89df0aa72db7791290f339f70821f362e68fea..1db9cd3b9178e0af60f64ed732dc2b2e21310274 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBGroupMember.java @@ -40,8 +40,6 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; " WHERE c.group.id = :group_id AND (lower(c.user.fullName) like lower(:user_filter) OR lower(c.user.username) like lower(:user_filter))") @NamedQuery(name = QUERY_GROUP_MEMBERS_FILTER, query = "SELECT c FROM DBGroupMember c " + " WHERE c.group.id = :group_id AND (lower(c.user.fullName) like lower(:user_filter) OR lower(c.user.username) like lower(:user_filter)) order by c.user.username") - - @NamedQuery(name = QUERY_GROUP_MEMBER_BY_USER_DOMAIN_GROUPS_ROLE_COUNT, query = "SELECT count(c) FROM DBGroupMember c " + " WHERE c.user.id = :user_id AND c.group.domain.id = :domain_id AND c.role= :membership_role ") diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java index 35f42b7d9177f58d083a046eaa29533e5c7cc4d6..c34140f9f150b3a8dab599ee41ef25ff0b424b92 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/model/user/DBResourceMember.java @@ -34,6 +34,14 @@ import static eu.europa.ec.edelivery.smp.data.dao.QueryNames.*; @NamedQuery(name = QUERY_RESOURCE_MEMBER_BY_USER_GROUP_RESOURCES_ROLE_COUNT, query = "SELECT count(c) FROM DBResourceMember c " + " WHERE c.user.id = :user_id AND c.resource.group.id = :group_id AND c.role= :membership_role ") +@NamedQuery(name = QUERY_RESOURCE_MEMBERS_COUNT, query = "SELECT count(c) FROM DBResourceMember c " + + " WHERE c.resource.id = :resource_id") +@NamedQuery(name = QUERY_RESOURCE_MEMBERS, query = "SELECT c FROM DBResourceMember c " + + " WHERE c.resource.id = :resource_id order by c.user.username") +@NamedQuery(name = QUERY_RESOURCE_MEMBERS_FILTER_COUNT, query = "SELECT count(c) FROM DBResourceMember c " + + " WHERE c.resource.id = :resource_id AND (lower(c.user.fullName) like lower(:user_filter) OR lower(c.user.username) like lower(:user_filter))") +@NamedQuery(name = QUERY_RESOURCE_MEMBERS_FILTER, query = "SELECT c FROM DBResourceMember c " + + " WHERE c.resource.id = :resource_id AND (lower(c.user.fullName) like lower(:user_filter) OR lower(c.user.username) like lower(:user_filter)) order by c.user.username") public class DBResourceMember extends BaseEntity { @Id diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java index 70aea05dff5e4607967fd39ded4a3aeaddbd8181..ad78a9ac6498de4891aa38f38bd820454b5f4715 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIDomainPublicService.java @@ -85,6 +85,13 @@ public class UIDomainPublicService extends UIServiceBase<DBDomain, DomainPublicR .collect(Collectors.toList()); } + @Transactional + public List<DomainRO> getAllDomainsForResourceAdminUser(Long userId) { + List<DBDomain> domains = domainDao.getDomainsByUserIdAndResourceRoles(userId, MembershipRoleType.ADMIN); + return domains.stream().map(domain -> conversionService.convert(domain, DomainRO.class)) + .collect(Collectors.toList()); + } + @Transactional public ServiceResult<MemberRO> getDomainMembers(Long domainId, int page, int pageSize, String filter) { diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java index e9137971f7cb56ed4878c314c036d1f1b533526a..53c37efd16691d7a324a905613e7e2cb5f69ad91 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIGroupPublicService.java @@ -86,17 +86,16 @@ public class UIGroupPublicService extends UIServiceBase<DBGroup, GroupRO> { } @Transactional - public List<GroupRO> getAllGroupsForDomainAndUserAndRole(Long domainId, Long userId, MembershipRoleType role) { - List<DBGroup> domainGroups = groupDao.getGroupsByDomainUserIdAndRoles(domainId, userId, role); + public List<GroupRO> getAllGroupsForDomainAndUserAndGroupRole(Long domainId, Long userId, MembershipRoleType role) { + List<DBGroup> domainGroups = groupDao.getGroupsByDomainUserIdAndGroupRoles(domainId, userId, role); return domainGroups.stream().map(domain -> conversionService.convert(domain, GroupRO.class)) .collect(Collectors.toList()); } @Transactional - public List<GroupRO> getAllGroupsForUser(Long userId, MembershipRoleType role) { - List<DBGroup> domainGroups = groupDao.getGroupsByUserIdAndRoles(userId, role); - + public List<GroupRO> getAllGroupsForDomainAndUserAndResourceRole(Long domainId, Long userId, MembershipRoleType role) { + List<DBGroup> domainGroups = groupDao.getGroupsByDomainUserIdAndResourceRoles(domainId, userId, role); return domainGroups.stream().map(domain -> conversionService.convert(domain, GroupRO.class)) .collect(Collectors.toList()); } @@ -199,7 +198,7 @@ public class UIGroupPublicService extends UIServiceBase<DBGroup, GroupRO> { if (groupMemberDao.isUserGroupMember(user, Collections.singletonList(group))) { throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Add membership", "User [" + memberRO.getUsername() + "] is already a member!"); } - member = groupMemberDao.addMemberToDomain(group, user, memberRO.getRoleType()); + member = groupMemberDao.addMemberToGroup(group, user, memberRO.getRoleType()); } return conversionService.convert(member, MemberRO.class); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java index ae8367b9ec02f0c2db147104733155d54e9f51c7..e5e05492f1401172203d6b2f0cf6cb40fda84e9d 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIResourceService.java @@ -1,15 +1,17 @@ package eu.europa.ec.edelivery.smp.services.ui; -import eu.europa.ec.edelivery.smp.data.dao.DomainResourceDefDao; -import eu.europa.ec.edelivery.smp.data.dao.GroupDao; -import eu.europa.ec.edelivery.smp.data.dao.ResourceDao; -import eu.europa.ec.edelivery.smp.data.dao.ResourceDefDao; +import eu.europa.ec.edelivery.smp.data.dao.*; +import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType; import eu.europa.ec.edelivery.smp.data.model.DBDomainResourceDef; import eu.europa.ec.edelivery.smp.data.model.DBGroup; import eu.europa.ec.edelivery.smp.data.model.doc.DBDocument; import eu.europa.ec.edelivery.smp.data.model.doc.DBResource; import eu.europa.ec.edelivery.smp.data.model.doc.DBResourceFilter; import eu.europa.ec.edelivery.smp.data.model.ext.DBResourceDef; +import eu.europa.ec.edelivery.smp.data.model.user.DBGroupMember; +import eu.europa.ec.edelivery.smp.data.model.user.DBResourceMember; +import eu.europa.ec.edelivery.smp.data.model.user.DBUser; +import eu.europa.ec.edelivery.smp.data.ui.MemberRO; import eu.europa.ec.edelivery.smp.data.ui.ResourceRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; import eu.europa.ec.edelivery.smp.exceptions.ErrorCode; @@ -22,6 +24,7 @@ import org.springframework.core.convert.ConversionService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -44,16 +47,20 @@ public class UIResourceService { private final ResourceDao resourceDao; private final GroupDao groupDao; + private final ResourceMemberDao resourceMemberDao; + private final UserDao userDao; private final ResourceDefDao resourceDefDao; private final DomainResourceDefDao domainResourceDefDao; private final ConversionService conversionService; private final SmlConnector smlConnector; - public UIResourceService(ResourceDao resourceDao, ResourceDefDao resourceDefDao, DomainResourceDefDao domainResourceDefDao, GroupDao groupDao, ConversionService conversionService, SmlConnector smlConnector) { + public UIResourceService(ResourceDao resourceDao, ResourceMemberDao resourceMemberDao, ResourceDefDao resourceDefDao, DomainResourceDefDao domainResourceDefDao, UserDao userDao, GroupDao groupDao, ConversionService conversionService, SmlConnector smlConnector) { this.resourceDao = resourceDao; + this.resourceMemberDao = resourceMemberDao; this.resourceDefDao = resourceDefDao; this.domainResourceDefDao = domainResourceDefDao; this.groupDao = groupDao; + this.userDao = userDao; this.conversionService = conversionService; this.smlConnector = smlConnector; } @@ -89,6 +96,43 @@ public class UIResourceService { return result; } + + @Transactional + public ServiceResult<ResourceRO> getResourcesForUserAndGroup(Long userId, MembershipRoleType role, Long groupId, int page, int pageSize, String filterValue) { + + DBGroup group = groupDao.find(groupId); + if (group == null) { + throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_LIST, "Group does not exist!"); + } + DBUser user = userDao.find(userId); + if (user == null) { + throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, ACTION_RESOURCE_LIST, "User does not exist!"); + } + + DBResourceFilter filter = DBResourceFilter.createBuilder() + .user(user) + .membershipRoleType(role) + .group(group) + .identifierFilter(StringUtils.trimToNull(filterValue)) + .build(); + + Long count = resourceDao.getResourcesForFilterCount(filter); + + ServiceResult<ResourceRO> result = new ServiceResult<>(); + result.setPage(page); + result.setPageSize(pageSize); + if (count < 1) { + result.setCount(0L); + return result; + } + result.setCount(count); + List<DBResource> resources = resourceDao.getResourcesForFilter(page, pageSize, filter); + List<ResourceRO> resourceROS = resources.stream().map(resource -> conversionService.convert(resource, ResourceRO.class)).collect(Collectors.toList()); + resourceDao.getResourcesForFilter(page, pageSize, filter); + result.getServiceEntities().addAll(resourceROS); + return result; + } + @Transactional public ResourceRO deleteResourceFromGroup(Long resourceId, Long groupId, Long domainId) { DBResource resource = resourceDao.find(resourceId); @@ -172,6 +216,61 @@ public class UIResourceService { return conversionService.convert(resource, ResourceRO.class); } + @Transactional + public ServiceResult<MemberRO> getResourceMembers(Long resourceId, int page, int pageSize, + String filter) { + Long count = resourceMemberDao.getResourceMemberCount(resourceId, filter); + ServiceResult<MemberRO> result = new ServiceResult<>(); + result.setPage(page); + result.setPageSize(pageSize); + if (count < 1) { + result.setCount(0L); + return result; + } + result.setCount(count); + List<DBResourceMember> memberROS = resourceMemberDao.getResourceMembers(resourceId, page, pageSize, filter); + List<MemberRO> memberList = memberROS.stream().map(member -> conversionService.convert(member, MemberRO.class)).collect(Collectors.toList()); + + result.getServiceEntities().addAll(memberList); + return result; + } + + @Transactional + public MemberRO addMemberToResource(Long resourceId, MemberRO memberRO, Long memberId) { + LOG.info("Add member [{}] to resource [{}]", memberRO.getUsername(), resourceId); + DBUser user = userDao.findUserByUsername(memberRO.getUsername()) + .orElseThrow(() -> new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Add/edit membership", "User [" + memberRO.getUsername() + "] does not exists!")); + + DBResourceMember member; + if (memberId != null) { + member = resourceMemberDao.find(memberId); + member.setRole(memberRO.getRoleType()); + } else { + DBResource resource = resourceDao.find(resourceId); + if (resourceMemberDao.isUserResourceMember(user, resource)) { + throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Add membership", "User [" + memberRO.getUsername() + "] is already a member!"); + } + member = resourceMemberDao.addMemberToResource(resource, user, memberRO.getRoleType()); + } + return conversionService.convert(member, MemberRO.class); + } + + @Transactional + public MemberRO deleteMemberFromResource(Long resourceId, Long memberId) { + LOG.info("Delete member [{}] from resource [{}]", memberId, resourceId); + DBResourceMember resourceMember = resourceMemberDao.find(memberId); + if (resourceMember == null) { + throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Membership", "Membership does not exists!"); + } + if (!Objects.equals(resourceMember.getResource().getId(), resourceId)) { + throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Membership", "Membership does not belong to resource!"); + } + + resourceMemberDao.remove(resourceMember); + return conversionService.convert(resourceMember, MemberRO.class); + } + + public DBDocument createDocumentForResourceDef(DBResourceDef resourceDef) { DBDocument document = new DBDocument(); document.setCurrentVersion(1); diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoTest.java index b1fa8c48f4580f6820ef60f7b4596a13ff79842b..9d433f3f1021763a127838d97595192c86391e76 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/DomainDaoTest.java @@ -28,6 +28,7 @@ public class DomainDaoTest extends AbstractBaseDao { testUtilsDao.clearData(); testUtilsDao.creatDomainMemberships(); testUtilsDao.createGroupMemberships(); + testUtilsDao.createResourceMemberships(); } @Test @@ -111,4 +112,44 @@ public class DomainDaoTest extends AbstractBaseDao { result = testInstance.getDomainsByUserIdAndGroupRoles(testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER, MembershipRoleType.ADMIN); assertEquals(2, result.size()); } + + @Test + public void getDomainsByUserIdAndResourceRolesCount() { + // one for domain 1 + Long cnt = testInstance.getDomainsByUserIdAndResourceRolesCount(testUtilsDao.getUser1().getId(), MembershipRoleType.ADMIN); + assertEquals(1, cnt.intValue()); + + // one for domain 2 + cnt = testInstance.getDomainsByUserIdAndResourceRolesCount(testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER); + assertEquals(1, cnt.intValue()); + + // all + cnt = testInstance.getDomainsByUserIdAndResourceRolesCount(testUtilsDao.getUser1().getId()); + assertEquals(2, cnt.intValue()); + + // all + cnt = testInstance.getDomainsByUserIdAndResourceRolesCount(testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER, MembershipRoleType.ADMIN); + assertEquals(2, cnt.intValue()); + } + @Test + public void getDomainsByUserIdAndResourceRoles() { + // one for domain 1 + List<DBDomain> result = testInstance.getDomainsByUserIdAndResourceRoles(testUtilsDao.getUser1().getId(), MembershipRoleType.ADMIN); + assertEquals(1, result.size()); + assertEquals(testUtilsDao.getD1(), result.get(0)); + + // one for domain 2 + result = testInstance.getDomainsByUserIdAndResourceRoles(testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER); + assertEquals(1, result.size()); + assertEquals(testUtilsDao.getD2(), result.get(0)); + + result = testInstance.getDomainsByUserIdAndResourceRoles(testUtilsDao.getUser2().getId(), MembershipRoleType.VIEWER); + assertEquals(0, result.size()); + + result = testInstance.getDomainsByUserIdAndResourceRoles(testUtilsDao.getUser1().getId()); + assertEquals(2, result.size()); + + result = testInstance.getDomainsByUserIdAndResourceRoles(testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER, MembershipRoleType.ADMIN); + assertEquals(2, result.size()); + } } diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupDaoTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupDaoTest.java index 0f6c6cd950b0bf74aa8b74e3fb46da3caba0e7c4..6eeb204429c196fb0ee0804c51d2b6d324cf0fae 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupDaoTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/GroupDaoTest.java @@ -29,6 +29,7 @@ public class GroupDaoTest extends AbstractBaseDao { // setup initial data! testUtilsDao.clearData(); testUtilsDao.createGroupMemberships(); + testUtilsDao.createResourceMemberships(); testInstance.clearPersistenceContext(); } @@ -97,30 +98,30 @@ public class GroupDaoTest extends AbstractBaseDao { } @Test - public void getGroupsByDomainUserIdAndRolesExists() { + public void getGroupsByDomainUserIdAndGroupRolesExists() { - List<DBGroup> groups = testInstance.getGroupsByDomainUserIdAndRoles( + List<DBGroup> groups = testInstance.getGroupsByDomainUserIdAndGroupRoles( testUtilsDao.getD1().getId(), testUtilsDao.getUser1().getId(), MembershipRoleType.ADMIN); assertEquals(1, groups.size()); - groups = testInstance.getGroupsByDomainUserIdAndRoles( + groups = testInstance.getGroupsByDomainUserIdAndGroupRoles( testUtilsDao.getD1().getId(), testUtilsDao.getUser2().getId(), MembershipRoleType.ADMIN); assertEquals(0, groups.size()); - groups = testInstance.getGroupsByDomainUserIdAndRoles( + groups = testInstance.getGroupsByDomainUserIdAndGroupRoles( testUtilsDao.getD1().getId(), testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER); assertEquals(0, groups.size()); - groups = testInstance.getGroupsByDomainUserIdAndRoles( + groups = testInstance.getGroupsByDomainUserIdAndGroupRoles( testUtilsDao.getD2().getId(), testUtilsDao.getUser1().getId(), MembershipRoleType.VIEWER); @@ -128,5 +129,35 @@ public class GroupDaoTest extends AbstractBaseDao { assertEquals(1, groups.size()); } + @Test + public void getGroupsByDomainUserIdAndResourceRoles() { + + List<DBGroup> groups = testInstance.getGroupsByDomainUserIdAndResourceRoles( + testUtilsDao.getD1().getId(), + testUtilsDao.getUser1().getId(), + MembershipRoleType.ADMIN); + + assertEquals(1, groups.size()); + + groups = testInstance.getGroupsByDomainUserIdAndResourceRoles( + testUtilsDao.getD1().getId(), + testUtilsDao.getUser2().getId(), + MembershipRoleType.ADMIN); + + assertEquals(0, groups.size()); + groups = testInstance.getGroupsByDomainUserIdAndResourceRoles( + testUtilsDao.getD1().getId(), + testUtilsDao.getUser1().getId(), + MembershipRoleType.VIEWER); + + assertEquals(0, groups.size()); + + groups = testInstance.getGroupsByDomainUserIdAndResourceRoles( + testUtilsDao.getD2().getId(), + testUtilsDao.getUser1().getId(), + MembershipRoleType.VIEWER); + + assertEquals(1, groups.size()); + } } diff --git a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql index 159a3053e4fa47e3f27d81d05d3ca7b4ae0a3d14..6236e0929b308b7325657304f5489205d603dacc 100644 --- a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql +++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql @@ -95,7 +95,12 @@ insert into SMP_SUBRESOURCE (ID, FK_RESOURCE_ID,FK_SUREDEF_ID, FK_DOCUMENT_ID, I (2, 1, 1, 2, 'service-value2', 'service-schema2', NOW(), NOW()); insert into SMP_RESOURCE_MEMBER (ID, FK_RESOURCE_ID, FK_USER_ID, MEMBERSHIP_ROLE, CREATED_ON, LAST_UPDATED_ON) values -(1, 1, 2, 'ADMIN', NOW(), NOW()); +(1, 1, 2, 'ADMIN', NOW(), NOW()), +(2, 2, 1, 'ADMIN', NOW(), NOW()), +(3, 3, 2, 'ADMIN', NOW(), NOW()), +(4, 4, 2, 'ADMIN', NOW(), NOW()), +(5, 5, 2, 'ADMIN', NOW(), NOW()) +; insert into SMP_GROUP_MEMBER (ID, FK_GROUP_ID, FK_USER_ID, MEMBERSHIP_ROLE, CREATED_ON, LAST_UPDATED_ON) values (1, 1, 2, 'ADMIN', NOW(), NOW()), @@ -105,3 +110,4 @@ insert into SMP_GROUP_MEMBER (ID, FK_GROUP_ID, FK_USER_ID, MEMBERSHIP_ROLE, CREA insert into SMP_DOMAIN_MEMBER (ID, FK_DOMAIN_ID, FK_USER_ID, MEMBERSHIP_ROLE, CREATED_ON, LAST_UPDATED_ON) values (1, 1, 1, 'ADMIN', NOW(), NOW()), (2, 1, 2, 'VIEWER', NOW(), NOW()); + diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java index 45853178cae264205f33be64e368be092a03753a..4f149a260c754d40ab7257e6929f759f74bf4d5e 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java @@ -88,6 +88,12 @@ public class SMPAuthorizationService { return groupMemberDao.isUserGroupMemberWithRole(userDetails.getUser().getId(), Collections.singletonList(groupId), MembershipRoleType.ADMIN); } + public boolean isResourceAdministrator(String resourceEncId) { + SMPUserDetails userDetails = getAndValidateUserDetails(); + Long resourceId = getIdFromEncryptedString(resourceEncId, false); + return resourceMemberDao.isUserResourceMemberWithRole(userDetails.getUser().getId(), resourceId, MembershipRoleType.ADMIN); + } + public boolean isAnyDomainAdministrator() { SMPUserDetails userDetails = getAndValidateUserDetails(); return domainMemberDao.isUserAnyDomainAdministrator(userDetails.getUser().getId()); diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java index 50acffc305147231af1b8b8da8d9d3aff25606ce..68e7a50d2d1e3c6c42e7efdb9432518d7c63b469 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/ResourceConstants.java @@ -76,14 +76,17 @@ public class ResourceConstants { + "{" + PATH_PARAM_ENC_MEMBER_ID + "}" + "/" + PATH_ACTION_DELETE; public static final String CONTEXT_PATH_EDIT_RESOURCE = CONTEXT_PATH_EDIT_GROUP + "/" + "{" + PATH_PARAM_ENC_GROUP_ID + "}" + "/"+ PATH_RESOURCE_TYPE_RESOURCE; - public static final String SUB_CONTEXT_PATH_EDIT_RESOURCE_CREATE = PATH_ACTION_CREATE; - public static final String SUB_CONTEXT_PATH_EDIT_RESOURCE_DELETE = "{" + PATH_PARAM_ENC_RESOURCE_ID + "}" + "/"+ PATH_ACTION_DELETE; public static final String SUB_CONTEXT_PATH_EDIT_RESOURCE_UPDATE = "{" + PATH_PARAM_ENC_RESOURCE_ID + "}" + "/"+ PATH_ACTION_UPDATE; + public static final String SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER = "{" + PATH_PARAM_ENC_RESOURCE_ID + "}" + "/" + PATH_RESOURCE_TYPE_MEMBER; + public static final String SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER_PUT = SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER+ "/" + PATH_ACTION_PUT; + public static final String SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER_DELETE = SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER + "/" + + "{" + PATH_PARAM_ENC_MEMBER_ID + "}" + "/" + PATH_ACTION_DELETE; + // public public static final String CONTEXT_PATH_PUBLIC_SEARCH_PARTICIPANT = CONTEXT_PATH_PUBLIC + "search"; public static final String CONTEXT_PATH_PUBLIC_DOMAIN = CONTEXT_PATH_PUBLIC + "domain"; diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java index c5d6303b041e0d8375e8132b5b26d2c442842b94..b14900c435710a7fa17b2ee3c29d69a52a60a46d 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/DomainEditController.java @@ -57,7 +57,9 @@ public class DomainEditController { if (StringUtils.equals(forRole, "group-admin")) { return uiDomainService.getAllDomainsForGroupAdminUser(userId); } - + if (StringUtils.equals(forRole, "resource-admin")) { + return uiDomainService.getAllDomainsForResourceAdminUser(userId); + } if (StringUtils.isBlank(forRole) || StringUtils.equals(forRole, "domain-admin")) { return uiDomainService.getAllDomainsForDomainAdminUser(userId); } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/GroupEditController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/GroupEditController.java index e2d8af16c4133cb361592946667769ecb9e44d19..94d03743f4b3b7d025c420ec18d473bd3c173e9a 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/GroupEditController.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/GroupEditController.java @@ -66,13 +66,18 @@ public class GroupEditController { return uiGroupPublicService.getAllGroupsForDomain(domainId); } if (StringUtils.equalsIgnoreCase("group-admin", forRole)) { - return uiGroupPublicService.getAllGroupsForDomainAndUserAndRole(domainId, userId, MembershipRoleType.ADMIN); + return uiGroupPublicService.getAllGroupsForDomainAndUserAndGroupRole(domainId, userId, MembershipRoleType.ADMIN); } + + if (StringUtils.equalsIgnoreCase("resource-admin", forRole)) { + return uiGroupPublicService.getAllGroupsForDomainAndUserAndResourceRole(domainId, userId, MembershipRoleType.ADMIN); + } + if (StringUtils.equalsIgnoreCase("group-viewer", forRole)) { - return uiGroupPublicService.getAllGroupsForDomainAndUserAndRole(domainId, userId, MembershipRoleType.VIEWER); + return uiGroupPublicService.getAllGroupsForDomainAndUserAndGroupRole(domainId, userId, MembershipRoleType.VIEWER); } if (StringUtils.equalsIgnoreCase("all-roles", forRole)) { - return uiGroupPublicService.getAllGroupsForDomainAndUserAndRole(domainId, userId, null); + return uiGroupPublicService.getAllGroupsForDomainAndUserAndGroupRole(domainId, userId, null); } throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "getGroupsForDomain", "Unknown parameter type [" + forRole + "]!"); } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ResourceEditController.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ResourceEditController.java index 5071a29f6513b6bf1385802b650ea754b99806bd..e458933621b927a907e9ce676a8e963a72492913 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ResourceEditController.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/edit/ResourceEditController.java @@ -1,6 +1,8 @@ package eu.europa.ec.edelivery.smp.ui.edit; +import eu.europa.ec.edelivery.smp.data.enums.MembershipRoleType; +import eu.europa.ec.edelivery.smp.data.ui.MemberRO; import eu.europa.ec.edelivery.smp.data.ui.ResourceRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; import eu.europa.ec.edelivery.smp.exceptions.ErrorCode; @@ -59,20 +61,20 @@ public class ResourceEditController { @RequestParam(value = PARAM_PAGINATION_FILTER, defaultValue = "", required = false) String filter) { logAdminAccess("getResourcesForGroup and type: " + forRole); Long groupId = SessionSecurityUtils.decryptEntityId(groupEncId); + Long userId = SessionSecurityUtils.decryptEntityId(userEncId); if (StringUtils.isBlank(forRole)) { return uiResourceService.getGroupResources(groupId, page, pageSize, filter); } - if (StringUtils.equalsIgnoreCase("resource-admin", forRole)) { + if (StringUtils.equalsIgnoreCase("group-admin", forRole)) { return uiResourceService.getGroupResources(groupId, page, pageSize, filter); - } /* - if (StringUtils.equalsIgnoreCase("resource-viewer", forRole)) { - return uiGroupPublicService.getAllGroupsForDomainAndUserAndRole(domainId, userId, MembershipRoleType.VIEWER); } - if (StringUtils.equalsIgnoreCase("all-roles", forRole)) { - return uiGroupPublicService.getAllGroupsForDomainAndUserAndRole(domainId, userId, null); - }*/ + + if (StringUtils.equalsIgnoreCase("resource-admin", forRole)) { + return uiResourceService.getResourcesForUserAndGroup(userId, MembershipRoleType.ADMIN, groupId, page, pageSize, filter); + } + throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "ResourcesForGroups", "Unknown parameter type [" + forRole + "]!"); } @@ -115,6 +117,61 @@ public class ResourceEditController { return uiResourceService.updateResourceForGroup(resourceRO, resourceId, groupId, domainId); } + + @GetMapping(path = SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and" + + " (@smpAuthorizationService.isGroupAdministrator(#groupEncId) or @smpAuthorizationService.isResourceAdministrator(#resourceEncId))") + public ServiceResult<MemberRO> getGroupMemberList(@PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId, + @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId, + @PathVariable(PATH_PARAM_ENC_GROUP_ID) String groupEncId, + @PathVariable(PATH_PARAM_ENC_RESOURCE_ID) String resourceEncId, + @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page, + @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize, + @RequestParam(value = PARAM_PAGINATION_FILTER, defaultValue = "", required = false) String filter) { + + LOG.info("Search for group members with filter [{}], paging: [{}/{}], user: {}", filter, page, pageSize, userEncId); + Long groupId = SessionSecurityUtils.decryptEntityId(groupEncId); + Long resourceId = SessionSecurityUtils.decryptEntityId(resourceEncId); + return uiResourceService.getResourceMembers(resourceId, page, pageSize, filter); + } + + @PutMapping(path = SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER_PUT, produces = MimeTypeUtils.APPLICATION_JSON_VALUE, consumes = MimeTypeUtils.APPLICATION_JSON_VALUE) + @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isGroupAdministrator(#groupEncId)") + public MemberRO putGroupMember(@PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId, + @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId, + @PathVariable(PATH_PARAM_ENC_GROUP_ID) String groupEncId, + @PathVariable(PATH_PARAM_ENC_RESOURCE_ID) String resourceEncId, + @RequestBody MemberRO memberRO) { + + LOG.info("add member to group"); + Long groupId = SessionSecurityUtils.decryptEntityId(groupEncId); + Long resourceId = SessionSecurityUtils.decryptEntityId(resourceEncId); + Long memberId = memberRO.getMemberId() == null ? null : SessionSecurityUtils.decryptEntityId(memberRO.getMemberId()); + if (memberRO.getRoleType() == null) { + memberRO.setRoleType(MembershipRoleType.VIEWER); + } + // is user domain admin or system admin + return uiResourceService.addMemberToResource(resourceId, memberRO, memberId); + } + + @DeleteMapping(value = SUB_CONTEXT_PATH_EDIT_RESOURCE_MEMBER_DELETE) + @PreAuthorize("@smpAuthorizationService.isCurrentlyLoggedIn(#userEncId) and @smpAuthorizationService.isGroupAdministrator(#groupEncId)") + public MemberRO deleteDomainMember( + @PathVariable(PATH_PARAM_ENC_USER_ID) String userEncId, + @PathVariable(PATH_PARAM_ENC_DOMAIN_ID) String domainEncId, + @PathVariable(PATH_PARAM_ENC_GROUP_ID) String groupEncId, + @PathVariable(PATH_PARAM_ENC_RESOURCE_ID) String resourceEncId, + @PathVariable(PATH_PARAM_ENC_MEMBER_ID) String memberEncId + ) { + LOG.info("Delete member from group"); + Long groupId = SessionSecurityUtils.decryptEntityId(groupEncId); + Long memberId = SessionSecurityUtils.decryptEntityId(memberEncId); + Long resourceId = SessionSecurityUtils.decryptEntityId(resourceEncId); + + // is user domain admin or system admin + return uiResourceService.deleteMemberFromResource(resourceId, memberId); + } + protected void logAdminAccess(String action) { LOG.info(SMPLogger.SECURITY_MARKER, "Admin Domain action [{}] by user [{}], ", action, SessionSecurityUtils.getSessionUserDetails()); }