diff --git a/apps/api/src/app/user/delete-own-user.dto.ts b/apps/api/src/app/user/delete-own-user.dto.ts new file mode 100644 index 000000000..1e3f940cb --- /dev/null +++ b/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; +} diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts index 05642119e..7cd2002bd 100644 --- a/apps/api/src/app/user/user.controller.ts +++ b/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 { size } from 'lodash'; +import { DeleteOwnUserDto } from './delete-own-user.dto'; import { UserItem } from './interfaces/user-item.interface'; import { UpdateUserSettingDto } from './update-user-setting.dto'; import { UserService } from './user.service'; @@ -40,47 +41,47 @@ export class UserController { private readonly userService: UserService ) {} - @Delete(':id') - @HasPermission(permissions.deleteUser) - @UseGuards(AuthGuard('jwt'), HasPermissionGuard) - public async deleteUser(@Param('id') id: string): Promise { - if (id === this.request.user.id) { - throw new HttpException( - getReasonPhrase(StatusCodes.FORBIDDEN), - StatusCodes.FORBIDDEN - ); - } - - return this.userService.deleteUser({ - id - }); - } - - @Delete('self/:accessToken') + @Delete() @HasPermission(permissions.deleteOwnUser) @UseGuards(AuthGuard('jwt'), HasPermissionGuard) public async deleteOwnUser( - @Param('accessToken') accessToken: string + @Body() data: DeleteOwnUserDto ): Promise { const hashedAccessToken = this.userService.createAccessToken( - accessToken, + data.accessToken, this.configurationService.get('ACCESS_TOKEN_SALT') ); const [user] = await this.userService.users({ - where: { accessToken: hashedAccessToken } + where: { accessToken: hashedAccessToken, id: this.request.user.id } }); if (!user) { throw new HttpException( - getReasonPhrase(StatusCodes.NOT_FOUND), - StatusCodes.NOT_FOUND + getReasonPhrase(StatusCodes.FORBIDDEN), + StatusCodes.FORBIDDEN ); } 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 { + if (id === this.request.user.id) { + throw new HttpException( + getReasonPhrase(StatusCodes.FORBIDDEN), + StatusCodes.FORBIDDEN + ); + } + + return this.userService.deleteUser({ + id }); } diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts b/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts index 0eda31586..c65bb7d11 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.component.ts +++ b/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'); } - 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) { this.dataService .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) { this.dataService .putUserSetting({ isExperimentalFeatures: aEvent.checked }) diff --git a/apps/client/src/app/components/user-account-settings/user-account-settings.html b/apps/client/src/app/components/user-account-settings/user-account-settings.html index 1bc9f05af..17b13cf94 100644 --- a/apps/client/src/app/components/user-account-settings/user-account-settings.html +++ b/apps/client/src/app/components/user-account-settings/user-account-settings.html @@ -247,6 +247,7 @@ appearance="outline" class="without-hint w-100" color="warn" + [hideRequiredMarker]="true" > Security Token
-
+