mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-07-28 18:24:38 -05:00
frontend permissions dialogs
This commit is contained in:
@@ -163,7 +163,7 @@
|
||||
</svg><span> <ng-container i18n>File Tasks<span *ngIf="tasksService.failedFileTasks.length > 0"><span class="badge bg-danger ms-2">{{tasksService.failedFileTasks.length}}</span></span></ng-container></span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" *ifPermissions="{ action: PermissionAction.View, type: PermissionType.Log }">
|
||||
<li class="nav-item" *ifPermissions="{ action: PermissionAction.View, type: PermissionType.Admin }">
|
||||
<a class="nav-link" routerLink="logs" routerLinkActive="active" (click)="closeMenu()" ngbPopover="Logs" i18n-ngbPopover [disablePopover]="!slimSidebarEnabled" placement="end" container="body" triggers="mouseenter:mouseleave" popoverClass="popover-slim">
|
||||
<svg class="sidebaricon" fill="currentColor">
|
||||
<use xlink:href="assets/bootstrap-icons.svg#text-left"/>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<app-input-text i18n-title title="Name" formControlName="name" [error]="error?.name"></app-input-text>
|
||||
<app-permissions-select i18n-title title="Permissions" formControlName="permissions"></app-permissions-select>
|
||||
<app-permissions-select i18n-title title="Permissions" formControlName="permissions" [error]="error?.permissions"></app-permissions-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -26,7 +26,7 @@ export class GroupEditDialogComponent extends EditDialogComponent<PaperlessGroup
|
||||
getForm(): FormGroup {
|
||||
return new FormGroup({
|
||||
name: new FormControl(''),
|
||||
permissions: new FormControl(''),
|
||||
permissions: new FormControl(null),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -11,19 +11,21 @@
|
||||
<app-input-text i18n-title title="First name" formControlName="first_name" [error]="error?.first_name"></app-input-text>
|
||||
<app-input-text i18n-title title="Last name" formControlName="last_name" [error]="error?.first_name"></app-input-text>
|
||||
|
||||
<div class="form-check form-switch">
|
||||
<input type="checkbox" class="form-check-input" id="is_active" formControlName="is_active">
|
||||
<label class="form-check-label" for="is_active" i18n>Active</label>
|
||||
<div class="mb-2">
|
||||
<div class="form-check form-switch form-check-inline">
|
||||
<input type="checkbox" class="form-check-input" id="is_active" formControlName="is_active">
|
||||
<label class="form-check-label" for="is_active" i18n>Active</label>
|
||||
</div>
|
||||
<div class="form-check form-switch form-check-inline">
|
||||
<input type="checkbox" class="form-check-input" id="is_superuser" formControlName="is_superuser">
|
||||
<label class="form-check-label" for="is_superuser" i18n>Superuser</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-check form-switch">
|
||||
<input type="checkbox" class="form-check-input" id="is_superuser" formControlName="is_superuser">
|
||||
<label class="form-check-label" for="is_superuser" i18n>Superuser</label>
|
||||
</div>
|
||||
<app-input-select i18n-title title="Groups" [items]="groups" multiple="true" formControlName="groups"></app-input-select>
|
||||
</div>
|
||||
<div class="col">
|
||||
<app-input-select i18n-title title="Groups" [items]="groups" multiple="true" formControlName="groups"></app-input-select>
|
||||
<app-permissions-select i18n-title title="Permissions" formControlName="permissions"></app-permissions-select>
|
||||
<app-permissions-select i18n-title title="Permissions" formControlName="user_permissions" [error]="error?.user_permissions"></app-permissions-select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -42,10 +42,10 @@ export class UserEditDialogComponent extends EditDialogComponent<PaperlessUser>
|
||||
username: new FormControl(''),
|
||||
first_name: new FormControl(''),
|
||||
last_name: new FormControl(''),
|
||||
is_active: new FormControl(''),
|
||||
is_superuser: new FormControl(''),
|
||||
groups: new FormControl(''),
|
||||
permissions: new FormControl(''),
|
||||
is_active: new FormControl(null),
|
||||
is_superuser: new FormControl(null),
|
||||
groups: new FormControl(null),
|
||||
user_permissions: new FormControl(null),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +1,27 @@
|
||||
<form [formGroup]="form">
|
||||
<label>{{title}}</label>
|
||||
<label class="form-label">{{title}}</label>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item" *ngFor="let type of PermissionType | keyvalue" [formGroupName]="type.key">
|
||||
{{type.key}}:
|
||||
<li class="list-group-item d-flex">
|
||||
<div class="col-3" i18n>Type</div>
|
||||
<div class="col" i18n>All</div>
|
||||
<div class="col" i18n>Add</div>
|
||||
<div class="col" i18n>Change</div>
|
||||
<div class="col" i18n>Delete</div>
|
||||
<div class="col" i18n>View</div>
|
||||
</li>
|
||||
<li class="list-group-item d-flex" *ngFor="let type of PermissionType | keyvalue" [formGroupName]="type.key">
|
||||
<div class="col-3">{{type.key}}:</div>
|
||||
|
||||
<div class="form-check form-check-inline form-switch">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_all" formControlName="all">
|
||||
<label class="form-check-label" for="{{type.key}}_all" i18n>All</label>
|
||||
<div class="col form-check form-check-inline form-switch">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_all" (change)="toggleAll($event, type.key)" [checked]="typesWithAllActions.has(type.key)">
|
||||
<label class="form-check-label visually-hidden" for="{{type.key}}_all" i18n>All</label>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let action of PermissionAction | keyvalue" class="form-check form-check-inline" [disabled]="isAll(type.key)">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_{{action.key}}" formControlName="{{action.key}}">
|
||||
<label class="form-check-label" for="{{type.key}}_{{action.key}}" i18n>{{action.key}}</label>
|
||||
<div *ngFor="let action of PermissionAction | keyvalue" class="col form-check form-check-inline">
|
||||
<input type="checkbox" class="form-check-input" id="{{type.key}}_{{action.key}}" formControlName="{{action.key}}" [attr.disabled]="typesWithAllActions.has(type.key) ? true : null">
|
||||
<label class="form-check-label visually-hidden" for="{{type.key}}_{{action.key}}" i18n>{{action.key}}</label>
|
||||
</div>
|
||||
</li>
|
||||
<div *ngIf="error" class="invalid-feedback d-block">{{error}}</div>
|
||||
</ul>
|
||||
</form>
|
||||
|
@@ -10,7 +10,6 @@ import {
|
||||
PermissionsService,
|
||||
PermissionType,
|
||||
} from 'src/app/services/permissions.service'
|
||||
import { AbstractInputComponent } from '../input/abstract-input'
|
||||
|
||||
@Component({
|
||||
providers: [
|
||||
@@ -33,14 +32,18 @@ export class PermissionsSelectComponent
|
||||
@Input()
|
||||
title: string = 'Permissions'
|
||||
|
||||
@Input()
|
||||
error: string
|
||||
|
||||
permissions: string[]
|
||||
|
||||
form = new FormGroup({})
|
||||
|
||||
typesWithAllActions: Set<string> = new Set()
|
||||
|
||||
constructor(private readonly permissionsService: PermissionsService) {
|
||||
for (const type in PermissionType) {
|
||||
const control = new FormGroup({})
|
||||
control.addControl('all', new FormControl(null))
|
||||
for (const action in PermissionAction) {
|
||||
control.addControl(action, new FormControl(null))
|
||||
}
|
||||
@@ -50,7 +53,7 @@ export class PermissionsSelectComponent
|
||||
|
||||
writeValue(permissions: string[]): void {
|
||||
this.permissions = permissions
|
||||
this.permissions.forEach((permissionStr) => {
|
||||
this.permissions?.forEach((permissionStr) => {
|
||||
const { actionKey, typeKey } =
|
||||
this.permissionsService.getPermissionKeys(permissionStr)
|
||||
|
||||
@@ -60,20 +63,70 @@ export class PermissionsSelectComponent
|
||||
}
|
||||
}
|
||||
})
|
||||
Object.keys(PermissionType).forEach((type) => {
|
||||
if (Object.values(this.form.get(type).value).every((val) => val)) {
|
||||
this.typesWithAllActions.add(type)
|
||||
} else {
|
||||
this.typesWithAllActions.delete(type)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onChange = (newValue: string[]) => {}
|
||||
|
||||
onTouched = () => {}
|
||||
|
||||
disabled: boolean = false
|
||||
|
||||
registerOnChange(fn: any): void {
|
||||
throw new Error('Method not implemented.')
|
||||
this.onChange = fn
|
||||
}
|
||||
|
||||
registerOnTouched(fn: any): void {
|
||||
throw new Error('Method not implemented.')
|
||||
this.onTouched = fn
|
||||
}
|
||||
|
||||
setDisabledState?(isDisabled: boolean): void {
|
||||
throw new Error('Method not implemented.')
|
||||
this.disabled = isDisabled
|
||||
}
|
||||
|
||||
ngOnInit(): void {}
|
||||
ngOnInit(): void {
|
||||
this.form.valueChanges.subscribe((newValue) => {
|
||||
let permissions = []
|
||||
Object.entries(newValue).forEach(([typeKey, typeValue]) => {
|
||||
// e.g. [Document, { Add: true, View: true ... }]
|
||||
const selectedActions = Object.entries(typeValue).filter(
|
||||
([actionKey, actionValue]) => actionValue
|
||||
)
|
||||
|
||||
isAll(key: string): boolean {
|
||||
return this.form.get(key).get('all').value == true
|
||||
selectedActions.forEach(([actionKey, actionValue]) => {
|
||||
permissions.push(
|
||||
(PermissionType[typeKey] as string).replace(
|
||||
'%s',
|
||||
PermissionAction[actionKey]
|
||||
)
|
||||
)
|
||||
})
|
||||
|
||||
if (selectedActions.length == Object.entries(typeValue).length) {
|
||||
this.typesWithAllActions.add(typeKey)
|
||||
} else {
|
||||
this.typesWithAllActions.delete(typeKey)
|
||||
}
|
||||
})
|
||||
this.onChange(permissions)
|
||||
})
|
||||
}
|
||||
|
||||
toggleAll(event, type) {
|
||||
const typeGroup = this.form.get(type)
|
||||
if (event.target.checked) {
|
||||
Object.keys(PermissionAction).forEach((action) => {
|
||||
typeGroup.get(action).patchValue(true)
|
||||
})
|
||||
this.typesWithAllActions.add(type)
|
||||
} else {
|
||||
this.typesWithAllActions.delete(type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -245,7 +245,7 @@ export class SettingsComponent
|
||||
is_active: user.is_active,
|
||||
is_superuser: user.is_superuser,
|
||||
groups: user.groups,
|
||||
permissions: user.permissions,
|
||||
user_permissions: user.user_permissions,
|
||||
}
|
||||
this.usersGroup.addControl(
|
||||
user.id.toString(),
|
||||
@@ -257,7 +257,7 @@ export class SettingsComponent
|
||||
is_active: new FormControl(null),
|
||||
is_superuser: new FormControl(null),
|
||||
groups: new FormControl(null),
|
||||
permissions: new FormControl(null),
|
||||
user_permissions: new FormControl(null),
|
||||
})
|
||||
)
|
||||
}
|
||||
@@ -514,7 +514,21 @@ export class SettingsComponent
|
||||
modal.componentInstance.btnCaption = $localize`Proceed`
|
||||
modal.componentInstance.confirmClicked.subscribe(() => {
|
||||
modal.componentInstance.buttonsEnabled = false
|
||||
this.usersService.delete(user)
|
||||
this.usersService.delete(user).subscribe({
|
||||
next: () => {
|
||||
modal.close()
|
||||
this.toastService.showInfo($localize`Deleted user`)
|
||||
this.usersService.listAll().subscribe((r) => {
|
||||
this.users = r.results
|
||||
this.initialize()
|
||||
})
|
||||
},
|
||||
error: (e) => {
|
||||
this.toastService.showError(
|
||||
$localize`Error deleting user: ${e.toString()}.`
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
@@ -554,7 +568,21 @@ export class SettingsComponent
|
||||
modal.componentInstance.btnCaption = $localize`Proceed`
|
||||
modal.componentInstance.confirmClicked.subscribe(() => {
|
||||
modal.componentInstance.buttonsEnabled = false
|
||||
this.groupsService.delete(group)
|
||||
this.groupsService.delete(group).subscribe({
|
||||
next: () => {
|
||||
modal.close()
|
||||
this.toastService.showInfo($localize`Deleted group`)
|
||||
this.groupsService.listAll().subscribe((r) => {
|
||||
this.groups = r.results
|
||||
this.initialize()
|
||||
})
|
||||
},
|
||||
error: (e) => {
|
||||
this.toastService.showError(
|
||||
$localize`Error deleting group: ${e.toString()}.`
|
||||
)
|
||||
},
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user