Browse Source

refactoring

pull/3444/head
José Marinho 1 year ago
parent
commit
f8cbb4195f
  1. 6
      apps/api/src/app/user/delete-own-user.dto.ts
  2. 49
      apps/api/src/app/user/user.controller.ts
  3. 50
      apps/client/src/app/components/user-account-settings/user-account-settings.component.ts
  4. 3
      apps/client/src/app/components/user-account-settings/user-account-settings.html
  5. 5
      apps/client/src/app/services/data.service.ts
  6. 4
      libs/common/src/lib/permissions.ts

6
apps/api/src/app/user/delete-own-user.dto.ts

@ -0,0 +1,6 @@
import { IsString } from 'class-validator';
export class DeleteOwnUserDto {
@IsString()
accessToken: string;
}

49
apps/api/src/app/user/user.controller.ts

@ -26,6 +26,7 @@ import { User as UserModel } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { StatusCodes, getReasonPhrase } from 'http-status-codes';
import { size } from 'lodash'; import { size } from 'lodash';
import { DeleteOwnUserDto } from './delete-own-user.dto';
import { UserItem } from './interfaces/user-item.interface'; import { UserItem } from './interfaces/user-item.interface';
import { UpdateUserSettingDto } from './update-user-setting.dto'; import { UpdateUserSettingDto } from './update-user-setting.dto';
import { UserService } from './user.service'; import { UserService } from './user.service';
@ -40,47 +41,47 @@ export class UserController {
private readonly userService: UserService private readonly userService: UserService
) {} ) {}
@Delete(':id') @Delete()
@HasPermission(permissions.deleteUser)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async deleteUser(@Param('id') id: string): Promise<UserModel> {
if (id === this.request.user.id) {
throw new HttpException(
getReasonPhrase(StatusCodes.FORBIDDEN),
StatusCodes.FORBIDDEN
);
}
return this.userService.deleteUser({
id
});
}
@Delete('self/:accessToken')
@HasPermission(permissions.deleteOwnUser) @HasPermission(permissions.deleteOwnUser)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard) @UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async deleteOwnUser( public async deleteOwnUser(
@Param('accessToken') accessToken: string @Body() data: DeleteOwnUserDto
): Promise<UserModel> { ): Promise<UserModel> {
const hashedAccessToken = this.userService.createAccessToken( const hashedAccessToken = this.userService.createAccessToken(
accessToken, data.accessToken,
this.configurationService.get('ACCESS_TOKEN_SALT') this.configurationService.get('ACCESS_TOKEN_SALT')
); );
const [user] = await this.userService.users({ const [user] = await this.userService.users({
where: { accessToken: hashedAccessToken } where: { accessToken: hashedAccessToken, id: this.request.user.id }
}); });
if (!user) { if (!user) {
throw new HttpException( throw new HttpException(
getReasonPhrase(StatusCodes.NOT_FOUND), getReasonPhrase(StatusCodes.FORBIDDEN),
StatusCodes.NOT_FOUND StatusCodes.FORBIDDEN
); );
} }
return this.userService.deleteUser({ return this.userService.deleteUser({
id: user.id, accessToken: hashedAccessToken,
accessToken: hashedAccessToken id: user.id
});
}
@Delete(':id')
@HasPermission(permissions.deleteUser)
@UseGuards(AuthGuard('jwt'), HasPermissionGuard)
public async deleteUser(@Param('id') id: string): Promise<UserModel> {
if (id === this.request.user.id) {
throw new HttpException(
getReasonPhrase(StatusCodes.FORBIDDEN),
StatusCodes.FORBIDDEN
);
}
return this.userService.deleteUser({
id
}); });
} }

50
apps/client/src/app/components/user-account-settings/user-account-settings.component.ts

@ -113,31 +113,6 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit {
return !(this.language === 'de' || this.language === 'en'); return !(this.language === 'de' || this.language === 'en');
} }
public onCloseAccount() {
const confirmation = confirm(
$localize`Do you really want to close your account?`
);
const accessToken = this.deleteOwnUserForm.get('accessToken').value;
if (confirmation) {
this.dataService
.deleteOwnUser(accessToken)
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe({
next: () => {
this.tokenStorageService.signOut();
this.userService.remove();
document.location.href = `/${document.documentElement.lang}`;
},
error: () => {
alert($localize`Oops! Incorrect Security Token.`);
}
});
}
}
public onChangeUserSetting(aKey: string, aValue: string) { public onChangeUserSetting(aKey: string, aValue: string) {
this.dataService this.dataService
.putUserSetting({ [aKey]: aValue }) .putUserSetting({ [aKey]: aValue })
@ -164,6 +139,31 @@ export class UserAccountSettingsComponent implements OnDestroy, OnInit {
}); });
} }
public onCloseAccount() {
const confirmation = confirm(
$localize`Do you really want to close your account?`
);
const accessToken = this.deleteOwnUserForm.get('accessToken').value;
if (confirmation) {
this.dataService
.deleteOwnUser({ accessToken })
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe({
next: () => {
this.tokenStorageService.signOut();
this.userService.remove();
document.location.href = `/${document.documentElement.lang}`;
},
error: () => {
alert($localize`Oops! Incorrect Security Token.`);
}
});
}
}
public onExperimentalFeaturesChange(aEvent: MatSlideToggleChange) { public onExperimentalFeaturesChange(aEvent: MatSlideToggleChange) {
this.dataService this.dataService
.putUserSetting({ isExperimentalFeatures: aEvent.checked }) .putUserSetting({ isExperimentalFeatures: aEvent.checked })

3
apps/client/src/app/components/user-account-settings/user-account-settings.html

@ -247,6 +247,7 @@
appearance="outline" appearance="outline"
class="without-hint w-100" class="without-hint w-100"
color="warn" color="warn"
[hideRequiredMarker]="true"
> >
<mat-label class="danger-zone-text" i18n <mat-label class="danger-zone-text" i18n
>Security Token</mat-label >Security Token</mat-label
@ -274,7 +275,7 @@
<div class="align-items-center d-flex py-1"> <div class="align-items-center d-flex py-1">
<div class="pr-1 w-50"></div> <div class="pr-1 w-50"></div>
<div class="pl-1 text-monospace w-50"> <div class="pl-1 w-50">
<button <button
color="warn" color="warn"
mat-flat-button mat-flat-button

5
apps/client/src/app/services/data.service.ts

@ -9,6 +9,7 @@ import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
import { PortfolioHoldingDetail } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-holding-detail.interface'; import { PortfolioHoldingDetail } from '@ghostfolio/api/app/portfolio/interfaces/portfolio-holding-detail.interface';
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface'; import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface'; import { SymbolItem } from '@ghostfolio/api/app/symbol/interfaces/symbol-item.interface';
import { DeleteOwnUserDto } from '@ghostfolio/api/app/user/delete-own-user.dto';
import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface'; import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interface';
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { IDataProviderHistoricalResponse } from '@ghostfolio/api/services/interfaces/interfaces'; import { IDataProviderHistoricalResponse } from '@ghostfolio/api/services/interfaces/interfaces';
@ -271,8 +272,8 @@ export class DataService {
return this.http.delete<any>(`/api/v1/benchmark/${dataSource}/${symbol}`); return this.http.delete<any>(`/api/v1/benchmark/${dataSource}/${symbol}`);
} }
public deleteOwnUser(accessToken: string) { public deleteOwnUser(aData: DeleteOwnUserDto) {
return this.http.delete<any>(`/api/v1/user/self/${accessToken}`); return this.http.delete<any>(`/api/v1/user`, { body: aData });
} }
public deleteUser(aId: string) { public deleteUser(aId: string) {

4
libs/common/src/lib/permissions.ts

@ -57,11 +57,11 @@ export function getPermissions(aRole: Role): string[] {
permissions.deleteAccess, permissions.deleteAccess,
permissions.deleteAccount, permissions.deleteAccount,
permissions.deleteAuthDevice, permissions.deleteAuthDevice,
permissions.deleteOwnUser,
permissions.deleteOrder, permissions.deleteOrder,
permissions.deletePlatform, permissions.deletePlatform,
permissions.deleteTag, permissions.deleteTag,
permissions.deleteUser, permissions.deleteUser,
permissions.deleteOwnUser,
permissions.updateAccount, permissions.updateAccount,
permissions.updateAuthDevice, permissions.updateAuthDevice,
permissions.updateOrder, permissions.updateOrder,
@ -81,12 +81,12 @@ export function getPermissions(aRole: Role): string[] {
permissions.createAccount, permissions.createAccount,
permissions.createAccountBalance, permissions.createAccountBalance,
permissions.createOrder, permissions.createOrder,
permissions.deleteOwnUser,
permissions.deleteAccess, permissions.deleteAccess,
permissions.deleteAccount, permissions.deleteAccount,
permissions.deleteAccountBalance, permissions.deleteAccountBalance,
permissions.deleteAuthDevice, permissions.deleteAuthDevice,
permissions.deleteOrder, permissions.deleteOrder,
permissions.deleteOwnUser,
permissions.updateAccount, permissions.updateAccount,
permissions.updateAuthDevice, permissions.updateAuthDevice,
permissions.updateOrder, permissions.updateOrder,

Loading…
Cancel
Save