Browse Source

#2820 Grant private access

pull/2822/head
x1c0 2 years ago
parent
commit
d541318a05
  1. 1
      CHANGELOG.md
  2. 21
      apps/api/src/app/access/access.controller.ts
  3. 21
      apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.component.ts
  4. 12
      apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html
  5. 22
      apps/client/src/app/components/user-account-access/user-account-access.component.ts
  6. 4
      libs/common/src/lib/interfaces/access.interface.ts

1
CHANGELOG.md

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Improved the user interface of the access table to share the portfolio
- Grant private access
## 2.34.0 - 2024-01-02

21
apps/api/src/app/access/access.controller.ts

@ -65,13 +65,20 @@ export class AccessController {
public async createAccess(
@Body() data: CreateAccessDto
): Promise<AccessModel> {
return this.accessService.createAccess({
alias: data.alias || undefined,
GranteeUser: data.granteeUserId
? { connect: { id: data.granteeUserId } }
: undefined,
User: { connect: { id: this.request.user.id } }
});
try {
return await this.accessService.createAccess({
alias: data.alias || undefined,
GranteeUser: data.granteeUserId
? { connect: { id: data.granteeUserId } }
: undefined,
User: { connect: { id: this.request.user.id } }
});
} catch {
throw new HttpException(
getReasonPhrase(StatusCodes.BAD_REQUEST),
StatusCodes.BAD_REQUEST
);
}
}
@Delete(':id')

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

@ -7,6 +7,7 @@ import {
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto';
import { DataService } from '@ghostfolio/client/services/data.service';
import { Subject } from 'rxjs';
import { CreateOrUpdateAccessDialogParams } from './interfaces/interfaces';
@ -26,13 +27,15 @@ export class CreateOrUpdateAccessDialog implements OnDestroy {
public constructor(
@Inject(MAT_DIALOG_DATA) public data: CreateOrUpdateAccessDialogParams,
public dialogRef: MatDialogRef<CreateOrUpdateAccessDialog>,
private formBuilder: FormBuilder
private formBuilder: FormBuilder,
private dataService: DataService
) {}
ngOnInit() {
this.accessForm = this.formBuilder.group({
alias: [this.data.access.alias],
type: [this.data.access.type, Validators.required]
type: [this.data.access.type, Validators.required],
userId: [this.data.access.grantee, Validators.required]
});
}
@ -43,10 +46,20 @@ export class CreateOrUpdateAccessDialog implements OnDestroy {
public onSubmit() {
const access: CreateAccessDto = {
alias: this.accessForm.controls['alias'].value,
type: this.accessForm.controls['type'].value
type: this.accessForm.controls['type'].value,
granteeUserId: this.accessForm.controls['userId'].value
};
this.dialogRef.close({ access });
this.dataService.postAccess(access).subscribe({
next: () => {
this.dialogRef.close();
},
error: (error) => {
if (error.status === 400) {
alert('It was not possible to grant access, please try again later.');
}
}
});
}
public ngOnDestroy() {

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

@ -22,9 +22,21 @@
<mat-label i18n>Type</mat-label>
<mat-select formControlName="type">
<mat-option i18n value="PUBLIC">Public</mat-option>
<mat-option i18n value="PRIVATE">Private</mat-option>
</mat-select>
</mat-form-field>
</div>
<div *ngIf="accessForm.controls['type'].value === 'PRIVATE' ">
<mat-form-field appearance="outline" class="w-100">
<mat-label i18n>User ID</mat-label>
<input
formControlName="userId"
matInput
type="text"
(keydown.enter)="$event.stopPropagation()"
/>
</mat-form-field>
</div>
</div>
<div class="justify-content-end" mat-dialog-actions>
<button i18n mat-button type="button" (click)="onCancel()">Cancel</button>

22
apps/client/src/app/components/user-account-access/user-account-access.component.ts

@ -112,25 +112,9 @@ export class UserAccountAccessComponent implements OnDestroy, OnInit {
width: this.deviceType === 'mobile' ? '100vw' : '50rem'
});
dialogRef
.afterClosed()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe((data: any) => {
const access: CreateAccessDto = data?.access;
if (access) {
this.dataService
.postAccess({ alias: access.alias })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe({
next: () => {
this.update();
}
});
}
this.router.navigate(['.'], { relativeTo: this.route });
});
dialogRef.afterClosed().subscribe(() => {
this.router.navigate(['.'], { relativeTo: this.route });
});
}
private update() {

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

@ -1,6 +1,6 @@
export interface Access {
alias?: string;
grantee: string;
grantee?: string;
id: string;
type: 'PUBLIC' | 'RESTRICTED_VIEW';
type: 'PUBLIC' | 'PRIVATE' | 'RESTRICTED_VIEW';
}

Loading…
Cancel
Save