Skip to content

Commit

Permalink
Merge pull request #22 from HSG-Library/develop
Browse files Browse the repository at this point in the history
Add the possibilty to customize the set of roles to copy
  • Loading branch information
d22 authored Feb 19, 2024
2 parents 9c9f4cf + 85cb322 commit f2a9174
Show file tree
Hide file tree
Showing 47 changed files with 2,562 additions and 2,379 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/check_and_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Use Node.js 13.x
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: 13.x

Expand Down
36 changes: 18 additions & 18 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"

on:
push:
branches: [main, develop]
branches: ["main", "develop"]
paths:
[
"package.json",
"package-lock.json",
"cloudapp/src/**",
".github/workflows/**",
]
pull_request:
# The branches below must be a subset of the branches above
branches: [main]
branches: ["main"]
paths:
[
"package.json",
"package-lock.json",
"cloudapp/src/**",
".github/workflows/**",
]
schedule:
- cron: "35 10 * * 1"
- cron: "35 10 * * 1" # at 10:53 every Monday

jobs:
analyze:
Expand All @@ -29,13 +32,10 @@ jobs:
fail-fast: false
matrix:
language: ["javascript"]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed

steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v4

# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
Expand Down
21 changes: 18 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<a href="https://developers.exlibrisgroup.com/appcenter/copy-user-roles/">![CloudApp Activations](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapps01.ext.exlibrisgroup.com%2Fappstats.json&query=%24%5B%3F(%40.cloud_app_id%3D%3D'hsg-library%2Falma-copy-user-roles')%5D.user_count&style=flat&label=Cloud%20App%20Activations)</a>
<a href="https://developers.exlibrisgroup.com/appcenter/copy-user-roles/">![Deployed Version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fapps01.ext.exlibrisgroup.com%2Fapps.json&query=%24%5B%3F(%40.id%3D%3D'hsg-library%2Falma-copy-user-roles')%5D.version&label=Deployed%20Version&color=green)</a>

# Copy User Roles
<img align="right" src="./cloudapp/src/assets/app-icon.png" width="100" style="border-radius: 3px">
Expand All @@ -8,7 +10,7 @@ An [ExLibris Alma CloudApp](https://developers.exlibrisgroup.com/cloudapps/), wh
<br>

## How to use
In order to use the CloudApp, one of the following roles is needed:
In order to use the CloudApp, one of the following roles is needed:
* 'User Manager'
* 'User Administrator'
* 'Gerneral System Administrator'
Expand Down Expand Up @@ -52,15 +54,28 @@ If a user is added to the list of allowed users, access is granted regardless of

**Allow by role**

To use the app, the role of 'User Manager', 'User Administrator' or 'Gerneral System Administrator' is needed, anyway. This configuration allows to further restrict to a smaller set of allowed roles. Please note, that as soon as a user is added to the list of allowed users it is not possible to restrict access by role.
To use the app, the role of 'User Manager', 'User Administrator' or 'Gerneral System Administrator' is needed. However, this configuration allows to further restrict to a smaller set of allowed roles. Please note, that as soon as a user is added to the list of allowed users it is not possible to restrict access by role.

<img src="doc/img/allow-by-role.jpg" width=400><br><br><br>

## Select which roles should be copied

By default all roles assinged to the source user are copied to the target user.

<img src="doc/img/selected-roles-01.jpg" width=400><br><br><br>

If only some roles should be copied, there is the possibilty to select a custom set of roles:

<img src="doc/img/selected-roles-02.jpg" width=400><br><br><br>

Please note, that the slection has no effect when using the 'Compare' function.


## Copying roles from users with invalid roles
* When selecting the source user the roles will be validated, if not all roles are valid there will be a dialog with the error message from Alma, which should help to find the role which is not correctly configured
* The dialog offers the possibilty to proceed anyway: in this case, the valid roles will be copied and the invalid roles will be skipped.
* The copy process with invalid roles **takes significantly longer** than with only valid roles
* After copying, a short summary about the valid and invalid roles is displayed
* After copying, a short summary about the valid and invalid roles is displayed

<img src="doc/img/results-copy.jpg" width=400><br><br><br>

Expand Down
5 changes: 3 additions & 2 deletions cloudapp/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const AppConfig = {
pageSize: 30
}
pageSize: 30,
httpHeader: { 'Content-Type': 'application/json', 'Accept': 'application/json' }
}
20 changes: 13 additions & 7 deletions cloudapp/src/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import { NgModule } from '@angular/core'
import { HttpClientModule } from '@angular/common/http'
import { NgModule } from '@angular/core'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'
import { BrowserModule } from '@angular/platform-browser'
import { BrowserAnimationsModule } from '@angular/platform-browser/animations'
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field'
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
import { MaterialModule, CloudAppTranslateModule, AlertModule } from '@exlibris/exl-cloudapp-angular-lib'
import { AlertModule, CloudAppTranslateModule, MaterialModule } from '@exlibris/exl-cloudapp-angular-lib'

import { AppComponent } from './app.component'
import { AppRoutingModule } from './app-routing.module'
import { MainComponent } from './components/main/main.component'
import { ValidationDialog } from './components/validationDialog/validationDialog.component'
import { AppComponent } from './app.component'
import { ConfigurationComponent } from './components/configuration/configuration.component'
import { FindUserComponent } from './components/findUser/findUser.component'
import { LoaderComponent } from './components/loader/loader.component'
import { MainComponent } from './components/main/main.component'
import { RoleSelectComponent } from './components/roleSelect/roleSelect.component'
import { ValidationDialog } from './components/validationDialog/validationDialog.component'
import { ResultComponent } from './components/result/result.component'
import { RoleOutputComponet } from './components/result/role-output.component'

@NgModule({
declarations: [
Expand All @@ -22,6 +25,9 @@ import { LoaderComponent } from './components/loader/loader.component'
ValidationDialog,
FindUserComponent,
LoaderComponent,
RoleSelectComponent,
ResultComponent,
RoleOutputComponet,
],
entryComponents: [
ValidationDialog,
Expand Down
128 changes: 65 additions & 63 deletions cloudapp/src/app/components/configuration/configuration.component.html
Original file line number Diff line number Diff line change
@@ -1,69 +1,71 @@
<!-- action buttons -->
<div class="eca-actions">
<button mat-flat-button color="secondary" (click)="back()">
<mat-icon>arrow_back</mat-icon> {{'config.backButton' | translate }}
</button>
<button mat-flat-button color="primary" (click)="save()" [disabled]="saving || !dirty">{{'config.saveButton' | translate}}</button>
</div>
<!-- /action buttons -->
<mat-card>
<h1 translate>config.allowUsage</h1>
<p translate>config.allowUsageExplanation</p>
<div id="copy-user-roles-config">
<!-- action buttons -->
<div class="eca-actions">
<button mat-flat-button color="secondary" (click)="back()">
<mat-icon>arrow_back</mat-icon> {{'config.backButton' | translate }}
</button>
<button mat-flat-button color="primary" (click)="save()" [disabled]="saving || !dirty">{{'config.saveButton' | translate}}</button>
</div>
<!-- /action buttons -->
<section>
<h1 translate>config.allowUsage</h1>
<p translate>config.allowUsageExplanation</p>

<!-- allow usage for user -->
<mat-card>
<h1 translate>config.allowByUser</h1>
<div *ngIf="allowedUsers.size > 0">
<div class="cur-allowed-users-title-bar">
<p class="bold" translate>
config.allowedUsers
</p>
<button mat-icon-button [disabled]="allowedUsersSelection.length == 0" (click)="removeAllowedUsers()">
<mat-icon>delete</mat-icon>
</button>
<!-- allow usage for user -->
<section>
<h1 translate>config.allowByUser</h1>
<div *ngIf="allowedUsers.size > 0">
<div class="cur-allowed-users-title-bar">
<p class="bold" translate>
config.allowedUsers
</p>
<button mat-icon-button [disabled]="allowedUsersSelection.length == 0" (click)="removeAllowedUsers()">
<mat-icon>delete</mat-icon>
</button>
</div>
<mat-selection-list class="allowed-users-list"
[multiple]=" true"
[(ngModel)]="allowedUsersSelection"
(ngModelChange)="selectAllowedUsers($event)">
<mat-list-option class="list-option"
*ngFor="let allowedUser of allowedUsers"
[value]="allowedUser">
<div matLine>
<span class="uxf-icon uxf-user leading-icon"></span>
{{allowedUser.last_name}}, {{allowedUser.first_name}} - {{allowedUser?.user_group?.desc.trim()}}&nbsp;
[{{allowedUser?.user_group?.value}}]
</div>
</mat-list-option>
</mat-selection-list>
</div>
<mat-selection-list class="allowed-users-list"

<p class="bold" translate>
config.searchForUser
</p>
<app-find-user (selectedUserOutput)="addAllowedUser($event)"></app-find-user>
</section>
<!-- /allow usage for user -->
<!-- allow usage for role -->
<section>
<h1 translate>config.allowByRole</h1>
<p *ngIf="allowedUsers.size > 0"><b translate>config.rolesAndUsersAreExclusive</b></p>
<p translate>config.allowUsersWithRoleText</p>
<mat-selection-list [disabled]="allowedUsers.size > 0"
[multiple]=" true"
[(ngModel)]="allowedUsersSelection"
(ngModelChange)="selectAllowedUsers($event)">
<mat-list-option class="list-option"
*ngFor="let allowedUser of allowedUsers"
[value]="allowedUser">
<div matLine>
<span class="uxf-icon uxf-user leading-icon"></span>
{{allowedUser.last_name}}, {{allowedUser.first_name}} - {{allowedUser?.user_group?.desc.trim()}}&nbsp;
[{{allowedUser?.user_group?.value}}]
</div>
</mat-list-option>
[(ngModel)]="allowedRolesSelection"
(ngModelChange)="selectAllowedRole($event)">
<mat-list-option class="list-option" [value]="0" [disabled]="allowedRolesSelection.length > 0 && !allowedRolesSelection.includes(0)">{{'config.allowAnyRole' | translate }}</mat-list-option>
<mat-list-option class="list-option" [value]="26" [disabled]="allowedRolesSelection.includes(0)">{{'config.allowForGeneralAdministrator' | translate }}</mat-list-option>
<mat-list-option class="list-option" [value]="50" [disabled]="allowedRolesSelection.includes(0)">{{'config.allowForUserAdministrator' | translate }}</mat-list-option>
</mat-selection-list>
</section>
<!-- /allow usage for role -->
<div class="eca-actions">
<button mat-flat-button color="secondary" (click)="removeConfig()">
<mat-icon>delete</mat-icon> {{'config.removeConfig' | translate }}
</button>
</div>

<p class="bold" translate>
config.searchForUser
</p>
<app-find-user (selectedUserOutput)="addAllowedUser($event)"></app-find-user>
</mat-card>
<!-- /allow usage for user -->
<!-- allow usage for role -->
<mat-card>
<h1 translate>config.allowByRole</h1>
<p *ngIf="allowedUsers.size > 0"><b translate>config.rolesAndUsersAreExclusive</b></p>
<p translate>config.allowUsersWithRoleText</p>
<mat-selection-list [disabled]="allowedUsers.size > 0"
[multiple]=" true"
[(ngModel)]="allowedRolesSelection"
(ngModelChange)="selectAllowedRole($event)">
<mat-list-option class="list-option" [value]="0" [disabled]="allowedRolesSelection.length > 0 && !allowedRolesSelection.includes(0)">{{'config.allowAnyRole' | translate }}</mat-list-option>
<mat-list-option class="list-option" [value]="26" [disabled]="allowedRolesSelection.includes(0)">{{'config.allowForGeneralAdministrator' | translate }}</mat-list-option>
<mat-list-option class="list-option" [value]="50" [disabled]="allowedRolesSelection.includes(0)">{{'config.allowForUserAdministrator' | translate }}</mat-list-option>
</mat-selection-list>
</mat-card>
<!-- /allow usage for role -->
<div class="eca-actions">
<button mat-flat-button color="secondary" (click)="removeConfig()">
<mat-icon>delete</mat-icon> {{'config.removeConfig' | translate }}
</button>
</div>

</mat-card>
<app-loader [loading]="loading"></app-loader>
</section>
<app-loader [loading]="loading"></app-loader>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Router } from '@angular/router'
import { AlertService, CloudAppConfigService } from '@exlibris/exl-cloudapp-angular-lib'
import { TranslateService } from '@ngx-translate/core'
import { Configuration } from '../../types/configuration.type'
import { UserSummaryEnriched } from '../../types/userSummaryEnriched.type'
import { UserDetailsChecked } from '../../types/userDetailsChecked'


@Component({
Expand All @@ -18,8 +18,8 @@ export class ConfigurationComponent implements OnInit {
dirty: boolean
config: Configuration

allowedUsers: Set<UserSummaryEnriched> = new Set<UserSummaryEnriched>()
allowedUsersSelection: UserSummaryEnriched[] = []
allowedUsers: Set<UserDetailsChecked> = new Set<UserDetailsChecked>()
allowedUsersSelection: UserDetailsChecked[] = []

allowedRolesSelection: number[] = [0]

Expand All @@ -33,14 +33,14 @@ export class ConfigurationComponent implements OnInit {
ngOnInit(): void {
this.configService.get().subscribe(config => {
this.config = config
this.allowedUsers = new Set<UserSummaryEnriched>(this.config.allowedUsers)
this.allowedUsers = new Set<UserDetailsChecked>(this.config.allowedUsers)
if (this.config.allowedRoles?.length > 0) {
this.allowedRolesSelection = this.config.allowedRoles
}
})
}

addAllowedUser(user: UserSummaryEnriched): void {
addAllowedUser(user: UserDetailsChecked): void {
if (this.isAlreadyAllowed(user)) {
let alertMsg = this.translate.instant('config.userAlreadyInList', {
user: `${user.first_name} ${user.last_name}`
Expand Down Expand Up @@ -78,7 +78,7 @@ export class ConfigurationComponent implements OnInit {
}
}

selectAllowedUsers($event: UserSummaryEnriched[]): void {
selectAllowedUsers($event: UserDetailsChecked[]): void {
this.allowedUsersSelection = $event
}

Expand Down Expand Up @@ -109,7 +109,7 @@ export class ConfigurationComponent implements OnInit {
}
}

private isAlreadyAllowed(user: UserSummaryEnriched): boolean {
private isAlreadyAllowed(user: UserDetailsChecked): boolean {
return Array.from(this.allowedUsers).some((userInList) => userInList.primary_id == user.primary_id)
}
}
3 changes: 1 addition & 2 deletions cloudapp/src/app/components/findUser/findUser.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@
*ngFor="let resultEntity of resultEntites" [value]="resultEntity">
<div>
<span class="uxf-icon uxf-user leading-icon"></span>
{{resultEntity.last_name}}, {{resultEntity.first_name}} - {{resultEntity?.user_group?.desc.trim()}}&nbsp;
[{{resultEntity?.user_group?.value}}] -
{{resultEntity.last_name}}, {{resultEntity.first_name}} - {{resultEntity?.user_group?.desc.trim()}}&nbsp;-
<span *ngIf="resultEntity?.user_role" [ngPlural]="resultEntity?.user_role?.length">
{{resultEntity?.user_role?.length}}&nbsp;
<ng-template ngPluralCase="=1">{{ 'global.role' | translate }}</ng-template>
Expand Down
Loading

0 comments on commit f2a9174

Please sign in to comment.