From 4161cb56932690ace3fec39c79e3700ebba9ef60 Mon Sep 17 00:00:00 2001 From: Renaud Michotte Date: Mon, 15 Jun 2020 14:04:29 +0200 Subject: [PATCH] authorization: limit fields on Patron form This commit restricts the role management for patrons using the role management API. Depending of the API result, some roles could be disabled into the role field into the Patron form. If the current user has only the librarian role, then the library field from the patron form editor will be disabled and set by default to the current library from the current logged user. - Closes rero/rero-ils#930 Co-authored_by: Renaud Michotte --- .../admin/src/app/routes/patrons-route.ts | 49 +++++++++++++++++++ .../src/app/routes/route-tool.service.ts | 7 +++ .../app/service/record-permission.service.ts | 11 +++++ 3 files changed, 67 insertions(+) diff --git a/projects/admin/src/app/routes/patrons-route.ts b/projects/admin/src/app/routes/patrons-route.ts index 295838fc1..b71216580 100644 --- a/projects/admin/src/app/routes/patrons-route.ts +++ b/projects/admin/src/app/routes/patrons-route.ts @@ -14,7 +14,10 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ +import { FormlyFieldConfig } from '@ngx-formly/core'; import { DetailComponent, EditorComponent, RecordSearchComponent, RouteInterface } from '@rero/ng-core'; +import { JSONSchema7 } from 'json-schema'; +import { map } from 'rxjs/operators'; import { CanUpdateGuard } from '../guard/can-update.guard'; import { PatronsBriefViewComponent } from '../record/brief-view/patrons-brief-view.component'; import { PatronDetailViewComponent } from '../record/detail-view/patron-detail-view/patron-detail-view.component'; @@ -58,6 +61,9 @@ export class PatronsRoute extends BaseRoute implements RouteInterface { } return record; }, + formFieldMap: (field: FormlyFieldConfig, jsonSchema: JSONSchema7): FormlyFieldConfig => { + return this._limitUserFormField(field, jsonSchema); + }, // use simple query for UI search preFilters: { simple: 1 @@ -68,4 +74,47 @@ export class PatronsRoute extends BaseRoute implements RouteInterface { } }; } + + /** Limit some field from user editor. + * + * @param field - FormlyFieldConfig + * @param jsonSchema - JSONSchema7 + * @return FormlyFieldConfig + */ + private _limitUserFormField(field: FormlyFieldConfig, jsonSchema: JSONSchema7): FormlyFieldConfig { + const formOptions = jsonSchema.form; + // ROLES FIELD MANAGEMENT --------------------------------- + // Depending of current user, the roles user can managed could be restricted. + // Call the 'role_management' API filter allowed roles. If user cannot manage a role, then this role + // will be disabled. We can't hide the restricted role because if the edited user has already this role + // this information will be lost on save ! + if (formOptions && formOptions.fieldMap === 'roles') { + const values = Object.assign([], field.templateOptions.options); // create a clone of original values + field.templateOptions.options = this._routeToolService.recordPermissionService.getRolesManagementPermissions().pipe( + map(results => { + values.forEach((role: any) => role.disabled = !results.allowed_roles.includes(role.value)); + return values; + }) + ); + } + + // LIBRARY MANAGEMENT ------------------------------------- + // If current logged user doesn't have the 'system_librarian' role, then the only library available + // should be the current_user.current_library. Set default value for library select the current_library URI + // and disable the field (so the user can't change/manage other libraries) + if (formOptions && formOptions.fieldMap === 'library') { + if (!this._routeToolService.userService.hasRole('system_librarian')) { + if (!field.hasOwnProperty('templateOptions')) { + field.templateOptions = {}; + } + const currentLibraryEndpoint = this._routeToolService.apiService.getRefEndpoint( + 'libraries', + this._routeToolService.userService.getCurrentUser().getCurrentLibrary() + ); + field.templateOptions.disabled = true; + field.fieldGroup[0].defaultValue = currentLibraryEndpoint; + } + } + return field; + } } diff --git a/projects/admin/src/app/routes/route-tool.service.ts b/projects/admin/src/app/routes/route-tool.service.ts index 8f777794b..0e2ee1039 100644 --- a/projects/admin/src/app/routes/route-tool.service.ts +++ b/projects/admin/src/app/routes/route-tool.service.ts @@ -63,6 +63,13 @@ export class RouteToolService { return this._recordService; } + /** + * @return recordPermissionService + */ + get recordPermissionService() { + return this._recordPermissionService; + } + /** * @return datePipe */ diff --git a/projects/admin/src/app/service/record-permission.service.ts b/projects/admin/src/app/service/record-permission.service.ts index 3aae5f204..66c1f20af 100644 --- a/projects/admin/src/app/service/record-permission.service.ts +++ b/projects/admin/src/app/service/record-permission.service.ts @@ -18,6 +18,8 @@ import { I18nPluralPipe, NgLocaleLocalization } from '@angular/common'; import { HttpClient, HttpHeaders } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators'; @Injectable({ providedIn: 'root' @@ -54,6 +56,15 @@ export class RecordPermissionService { return this._httpClient.get(url, this._httpOptions); } + + /** + * Get roles that the current user can manage + * @return an observable on allowed roles management + */ + getRolesManagementPermissions(): Observable { + return this._httpClient.get('api/patrons/roles_management_permissions', this._httpOptions); + } + /** * Generate tooltip messages * @param reasons - Object with reasons to insert into the tooltip