Browse Source

Introduce permissions in access

pull/2870/head
x1c0 2 years ago
committed by Thomas Kaul
parent
commit
de08ddf867
  1. 1
      CHANGELOG.md
  2. 4
      apps/api/src/app/access/create-access.dto.ts
  3. 4
      apps/api/src/app/user/user.service.ts
  4. 2
      apps/api/src/interceptors/redact-values-in-response.interceptor.ts
  5. 2
      apps/client/src/app/components/access-table/access-table.component.html
  6. 15
      apps/client/src/app/components/access-table/access-table.component.ts
  7. 11
      apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts
  8. 15
      apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html
  9. 1
      libs/common/src/lib/interfaces/access.interface.ts

1
CHANGELOG.md

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added support to grant private access with permissions
- Added `permissions` to the `Access` model
### Changed

4
apps/api/src/app/access/create-access.dto.ts

@ -12,4 +12,8 @@ export class CreateAccessDto {
@IsOptional()
@IsString()
type?: 'PUBLIC';
@IsOptional()
@IsString()
permission?: string;
}

4
apps/api/src/app/user/user.service.ts

@ -109,6 +109,10 @@ export class UserService {
return aUser.Settings.settings.isRestrictedView ?? false;
}
public hasReadRestrictedPermission(user: UserWithSettings): boolean {
return user.permissions.includes('READ_RESTRICTED');
}
public async user(
userWhereUniqueInput: Prisma.UserWhereUniqueInput
): Promise<UserWithSettings | null> {

2
apps/api/src/interceptors/redact-values-in-response.interceptor.ts

@ -28,7 +28,7 @@ export class RedactValuesInResponseInterceptor<T>
if (
hasImpersonationId ||
this.userService.isRestrictedView(request.user)
this.userService.hasReadRestrictedPermission(request.user)
) {
data = redactAttributes({
object: data,

2
apps/client/src/app/components/access-table/access-table.component.html

@ -18,7 +18,7 @@
<td *matCellDef="let element" class="px-1 text-nowrap" mat-cell>
<div class="align-items-center d-flex">
<ion-icon class="mr-1" name="lock-closed-outline" />
<ng-container i18n>Restricted View</ng-container>
{{ getDisplayName(element.type) }}
</div>
</td>
</ng-container>

15
apps/client/src/app/components/access-table/access-table.component.ts

@ -44,6 +44,21 @@ export class AccessTableComponent implements OnChanges, OnInit {
}
}
public getDisplayName(
type: 'PRIVATE' | 'PUBLIC' | 'RESTRICTED_VIEW' | 'VIEW'
): string {
switch (type) {
case 'PUBLIC':
return $localize`Public`;
case 'RESTRICTED_VIEW':
return $localize`Restricted View`;
case 'VIEW':
return $localize`View`;
default:
return $localize`Unknown`;
}
}
public onDeleteAccess(aId: string) {
const confirmation = confirm(
$localize`Do you really want to revoke this granted access?`

11
apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts

@ -38,19 +38,23 @@ export class CreateOrUpdateAccessDialog implements OnDestroy {
this.accessForm = this.formBuilder.group({
alias: [this.data.access.alias],
type: [this.data.access.type, Validators.required],
userId: [this.data.access.grantee, Validators.required]
userId: [this.data.access.grantee, Validators.required],
permission: [this.data.access.permission, Validators.required]
});
this.accessForm.get('type').valueChanges.subscribe((value) => {
const userIdControl = this.accessForm.get('userId');
const permissionControl = this.accessForm.get('permission');
if (value === 'PRIVATE') {
userIdControl.setValidators(Validators.required);
permissionControl.setValidators(Validators.required);
} else {
userIdControl.clearValidators();
}
userIdControl.updateValueAndValidity();
permissionControl.updateValueAndValidity();
this.changeDetectorRef.markForCheck();
});
@ -64,9 +68,10 @@ export class CreateOrUpdateAccessDialog implements OnDestroy {
const access: CreateAccessDto = {
alias: this.accessForm.controls['alias'].value,
granteeUserId: this.accessForm.controls['userId'].value,
type: this.accessForm.controls['type'].value
type: this.accessForm.controls['type'].value,
permission: this.accessForm.controls['permission'].value
};
this.dataService
.postAccess(access)
.pipe(

15
apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html

@ -30,9 +30,9 @@
@if (accessForm.controls['type'].value === 'PRIVATE') {
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label
>Ghostfolio <ng-container i18n>User ID</ng-container></mat-label
>
<mat-label>
Ghostfolio <ng-container i18n>User ID</ng-container>
</mat-label>
<input
formControlName="userId"
matInput
@ -41,6 +41,15 @@
/>
</mat-form-field>
</div>
<div>
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>Permission</mat-label>
<mat-select formControlName="permission">
<mat-option i18n value="READ_RESTRICTED">Restricted view</mat-option>
<mat-option i18n value="READ">View</mat-option>
</mat-select>
</mat-form-field>
</div>
}
</div>
<div class="justify-content-end" mat-dialog-actions>

1
libs/common/src/lib/interfaces/access.interface.ts

@ -3,4 +3,5 @@ export interface Access {
grantee?: string;
id: string;
type: 'PRIVATE' | 'PUBLIC' | 'RESTRICTED_VIEW';
permission: 'READ' | 'READ_RESTRICTED';
}

Loading…
Cancel
Save