Newer
Older
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { createSelector, select, Store } from '@ngrx/store';
import { distinctUntilChanged, filter, map, switchMap, take, tap } from 'rxjs/operators';
import {
GroupRegistryCancelGroupAction,
GroupRegistryEditGroupAction
} from '../../+admin/admin-access-control/group-registry/group-registry.actions';
import { GroupRegistryState } from '../../+admin/admin-access-control/group-registry/group-registry.reducers';
import { AppState } from '../../app.reducer';
import { hasValue } from '../../shared/empty.util';
import { NotificationsService } from '../../shared/notifications/notifications.service';
import { FollowLinkConfig } from '../../shared/utils/follow-link-config.model';
import { RemoteDataBuildService } from '../cache/builders/remote-data-build.service';
import { SearchParam } from '../cache/models/search-param.model';
import { ObjectCacheService } from '../cache/object-cache.service';
Marie Verdonck
committed
import { RestResponse } from '../cache/response.models';
import { DSOChangeAnalyzer } from '../data/dso-change-analyzer.service';
import { PaginatedList } from '../data/paginated-list';
import { RemoteData } from '../data/remote-data';
import {
CreateRequest,
DeleteRequest,
FindListOptions,
FindListRequest,
PostRequest
} from '../data/request.models';
import { RequestService } from '../data/request.service';
import { HttpOptions } from '../dspace-rest-v2/dspace-rest-v2.service';
import { HALEndpointService } from '../shared/hal-endpoint.service';
import { configureRequest, getResponseFromEntry} from '../shared/operators';
import { EPerson } from './models/eperson.model';
import { Group } from './models/group.model';
import { dataService } from '../cache/builders/build-decorators';
import { GROUP } from './models/group.resource-type';
import { DSONameService } from '../breadcrumbs/dso-name.service';
import { Community } from '../shared/community.model';
import { Collection } from '../shared/collection.model';
import { ComcolRole } from '../../shared/comcol-forms/edit-comcol-page/comcol-role/comcol-role';
const groupRegistryStateSelector = (state: AppState) => state.groupRegistry;
const editGroupSelector = createSelector(groupRegistryStateSelector, (groupRegistryState: GroupRegistryState) => groupRegistryState.editGroup);
* Provides methods to retrieve eperson group resources from the REST API & Group related CRUD actions.
@dataService(GROUP)
export class GroupDataService extends DataService<Group> {
protected linkPath = 'groups';
public ePersonsEndpoint = 'epersons';
public subgroupsEndpoint = 'subgroups';
protected http: HttpClient,
protected notificationsService: NotificationsService,
protected rdbService: RemoteDataBuildService,
protected objectCache: ObjectCacheService,
protected halService: HALEndpointService,
protected nameService: DSONameService,
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/**
* Retrieves all groups
* @param pagination The pagination info used to retrieve the groups
*/
public getGroups(options: FindListOptions = {}, ...linksToFollow: Array<FollowLinkConfig<Group>>): Observable<RemoteData<PaginatedList<Group>>> {
const hrefObs = this.getFindAllHref(options, this.linkPath, ...linksToFollow);
hrefObs.pipe(
filter((href: string) => hasValue(href)),
take(1))
.subscribe((href: string) => {
const request = new FindListRequest(this.requestService.generateRequestId(), href, options);
this.requestService.configure(request);
});
return this.rdbService.buildList<Group>(hrefObs) as Observable<RemoteData<PaginatedList<Group>>>;
}
/**
* Returns a search result list of groups, with certain query (searches in group name and by exact uuid)
* Endpoint used: /eperson/groups/search/byMetadata?query=<:name>
* @param query search query param
* @param options
* @param linksToFollow
*/
public searchGroups(query: string, options?: FindListOptions, ...linksToFollow: Array<FollowLinkConfig<Group>>): Observable<RemoteData<PaginatedList<Group>>> {
const searchParams = [new SearchParam('query', query)];
let findListOptions = new FindListOptions();
if (options) {
findListOptions = Object.assign(new FindListOptions(), options);
}
if (findListOptions.searchParams) {
findListOptions.searchParams = [...findListOptions.searchParams, ...searchParams];
} else {
findListOptions.searchParams = searchParams;
}
return this.searchBy('byMetadata', findListOptions, ...linksToFollow);
}
/**
* Check if the current user is member of to the indicated group
*
* @param groupName
* the group name
* @return boolean
* true if user is member of the indicated group, false otherwise
*/
isMemberOf(groupName: string): Observable<boolean> {
const searchHref = 'isMemberOf';
const options = new FindListOptions();
options.searchParams = [new SearchParam('groupName', groupName)];
return this.searchBy(searchHref, options).pipe(
filter((groups: RemoteData<PaginatedList<Group>>) => !groups.isResponsePending),
take(1),
map((groups: RemoteData<PaginatedList<Group>>) => groups.payload.totalElements > 0)
);
}
/**
* Method to delete a group
* @param id The group id to delete
*/
public deleteGroup(group: Group): Observable<boolean> {
}
/**
* Create or Update a group
* If the group contains an id, it is assumed the eperson already exists and is updated instead
* @param group The group to create or update
*/
public createOrUpdateGroup(group: Group): Observable<RemoteData<Group>> {
const isUpdate = hasValue(group.id);
if (isUpdate) {
return this.updateGroup(group);
} else {
return this.create(group, null);
}
}
/**
* // TODO
* @param {DSpaceObject} ePerson The given object
*/
updateGroup(group: Group): Observable<RemoteData<Group>> {
/**
* Adds given subgroup as a subgroup to the given active group
* @param activeGroup Group we want to add subgroup to
* @param subgroup Group we want to add as subgroup to activeGroup
*/
Marie Verdonck
committed
addSubGroupToGroup(activeGroup: Group, subgroup: Group): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId();
const options: HttpOptions = Object.create({});
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'text/uri-list');
options.headers = headers;
const postRequest = new PostRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint, subgroup.self, options);
this.requestService.configure(postRequest);
Marie Verdonck
committed
return this.fetchResponse(requestId);
}
/**
* Deletes a given subgroup from the subgroups of the given active group
* @param activeGroup Group we want to delete subgroup from
* @param subgroup Subgroup we want to delete from activeGroup
*/
Marie Verdonck
committed
deleteSubGroupFromGroup(activeGroup: Group, subgroup: Group): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId();
const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.subgroupsEndpoint + '/' + subgroup.id);
this.requestService.configure(deleteRequest);
Marie Verdonck
committed
return this.fetchResponse(requestId);
}
/**
* Adds given ePerson as member to given group
* @param activeGroup Group we want to add member to
* @param ePerson EPerson we want to add as member to given activeGroup
*/
Marie Verdonck
committed
addMemberToGroup(activeGroup: Group, ePerson: EPerson): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId();
const options: HttpOptions = Object.create({});
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'text/uri-list');
options.headers = headers;
const postRequest = new PostRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint, ePerson.self, options);
this.requestService.configure(postRequest);
Marie Verdonck
committed
return this.fetchResponse(requestId);
}
/**
* Deletes a given ePerson from the members of the given active group
* @param activeGroup Group we want to delete member from
* @param ePerson EPerson we want to delete from members of given activeGroup
*/
Marie Verdonck
committed
deleteMemberFromGroup(activeGroup: Group, ePerson: EPerson): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId();
const deleteRequest = new DeleteRequest(requestId, activeGroup.self + '/' + this.ePersonsEndpoint + '/' + ePerson.id);
this.requestService.configure(deleteRequest);
Marie Verdonck
committed
return this.fetchResponse(requestId);
}
/**
* Gets the restResponse from the requestService
* @param requestId
*/
protected fetchResponse(requestId: string): Observable<RestResponse> {
return this.requestService.getByUUID(requestId).pipe(
getResponseFromEntry(),
map((response: RestResponse) => {
return response;
})
);
/**
* Method to retrieve the group that is currently being edited
*/
public getActiveGroup(): Observable<Group> {
return this.store.pipe(select(editGroupSelector))
}
/**
* Method to cancel editing a group, dispatches a cancel group action
*/
public cancelEditGroup() {
this.store.dispatch(new GroupRegistryCancelGroupAction());
}
/**
* Method to set the group being edited, dispatches an edit group action
* @param group The group to edit
*/
public editGroup(group: Group) {
this.store.dispatch(new GroupRegistryEditGroupAction(group));
}
/**
* Method that clears a cached groups request
*/
public clearGroupsRequests(): void {
this.getBrowseEndpoint().pipe(take(1)).subscribe((link: string) => {
this.requestService.removeByHrefSubstring(link);
});
/**
* Method that clears a cached get subgroups of certain group request
*/
public clearGroupLinkRequests(href: string): void {
this.requestService.removeByHrefSubstring(href);
}
Marie Verdonck
committed
public getGroupRegistryRouterLink(): string {
return '/admin/access-control/groups';
}
Marie Verdonck
committed
/**
* Change which group is being edited and return the link for the edit page of the new group being edited
* @param newGroup New group to edit
*/
public startEditingNewGroup(newGroup: Group): string {
this.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => {
if (newGroup === activeGroup) {
this.cancelEditGroup()
} else {
this.editGroup(newGroup)
}
});
return this.getGroupEditPageRouterLinkWithID(newGroup.id)
Marie Verdonck
committed
}
/**
* Get Edit page of group
* @param group Group we want edit page for
*/
public getGroupEditPageRouterLink(group: Group): string {
return this.getGroupEditPageRouterLinkWithID(group.id);
}
/**
* Get Edit page of group
* @param groupID Group ID we want edit page for
*/
public getGroupEditPageRouterLinkWithID(groupId: string): string {
return '/admin/access-control/groups/' + groupId;
}
/**
* Extract optional UUID from a string
* @param stringWithUUID String with possible UUID
*/
public getUUIDFromString(stringWithUUID: string): string {
let foundUUID = '';
const uuidMatches = stringWithUUID.match(/[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}/g);
if (uuidMatches != null) {
foundUUID = uuidMatches[0];
}
return foundUUID;
Marie Verdonck
committed
}
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
/**
* Create a group for a given role for a given community or collection.
*
* @param dso The community or collection for which to create a group
* @param comcolRole The role for which to create a group
*/
createComcolGroup(dso: Community|Collection, comcolRole: ComcolRole): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId();
const link = comcolRole.getEndpoint(dso);
const group = Object.assign(new Group(), {
metadata: {
'dc.description': [
{
value: `${this.nameService.getName(dso)} admin group`,
}
],
},
});
return this.halService.getEndpoint(link).pipe(
distinctUntilChanged(),
take(1),
map((endpoint: string) =>
new CreateRequest(
requestId,
endpoint,
JSON.stringify(group),
)
),
configureRequest(this.requestService),
tap(() => this.requestService.removeByHrefSubstring(link)),
switchMap((restRequest) => this.requestService.getByUUID(restRequest.uuid)),
getResponseFromEntry(),
);
}
/**
* Delete the group for a given role for a given community or collection.
*
* @param dso The community or collection for which to delete the group
* @param comcolRole The role for which to delete the group
*/
deleteComcolGroup(dso: Community|Collection, comcolRole: ComcolRole): Observable<RestResponse> {
const requestId = this.requestService.generateRequestId();
const link = comcolRole.getEndpoint(dso);
return this.halService.getEndpoint(link).pipe(
distinctUntilChanged(),
take(1),
map((endpoint: string) =>
new DeleteRequest(
requestId,
endpoint,
)
),
configureRequest(this.requestService),
tap(() => this.requestService.removeByHrefSubstring(link)),
switchMap((restRequest) => this.requestService.getByUUID(restRequest.uuid)),
getResponseFromEntry(),
);
}