diff --git a/src/api/private/me/me.controller.spec.ts b/src/api/private/me/me.controller.spec.ts new file mode 100644 index 000000000..55a5e81d9 --- /dev/null +++ b/src/api/private/me/me.controller.spec.ts @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Test, TestingModule } from '@nestjs/testing'; +import { MeController } from './me.controller'; +import { UsersModule } from '../../../users/users.module'; +import { LoggerModule } from '../../../logger/logger.module'; +import { getRepositoryToken } from '@nestjs/typeorm'; +import { User } from '../../../users/user.entity'; +import { Identity } from '../../../users/identity.entity'; +import { MediaModule } from '../../../media/media.module'; +import { AuthorColor } from '../../../notes/author-color.entity'; +import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity'; +import { NoteUserPermission } from '../../../permissions/note-user-permission.entity'; +import { Authorship } from '../../../revisions/authorship.entity'; +import { ConfigModule } from '@nestjs/config'; +import appConfigMock from '../../../config/mock/app.config.mock'; +import authConfigMock from '../../../config/mock/auth.config.mock'; +import mediaConfigMock from '../../../config/mock/media.config.mock'; +import customizationConfigMock from '../../../config/mock/customization.config.mock'; +import externalServicesConfigMock from '../../../config/mock/external-services.config.mock'; +import { MediaUpload } from '../../../media/media-upload.entity'; +import { Note } from '../../../notes/note.entity'; +import { Tag } from '../../../notes/tag.entity'; +import { Revision } from '../../../revisions/revision.entity'; +import { Group } from '../../../groups/group.entity'; + +describe('MeController', () => { + let controller: MeController; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + controllers: [MeController], + imports: [ + UsersModule, + LoggerModule, + MediaModule, + ConfigModule.forRoot({ + isGlobal: true, + load: [ + appConfigMock, + authConfigMock, + mediaConfigMock, + customizationConfigMock, + externalServicesConfigMock, + ], + }), + ], + }) + .overrideProvider(getRepositoryToken(User)) + .useValue({}) + .overrideProvider(getRepositoryToken(Identity)) + .useValue({}) + .overrideProvider(getRepositoryToken(Note)) + .useValue({}) + .overrideProvider(getRepositoryToken(Tag)) + .useValue({}) + .overrideProvider(getRepositoryToken(Revision)) + .useValue({}) + .overrideProvider(getRepositoryToken(Group)) + .useValue({}) + .overrideProvider(getRepositoryToken(AuthorColor)) + .useValue({}) + .overrideProvider(getRepositoryToken(NoteGroupPermission)) + .useValue({}) + .overrideProvider(getRepositoryToken(NoteUserPermission)) + .useValue({}) + .overrideProvider(getRepositoryToken(Authorship)) + .useValue({}) + .overrideProvider(getRepositoryToken(MediaUpload)) + .useValue({}) + .compile(); + + controller = module.get(MeController); + }); + + it('should be defined', () => { + expect(controller).toBeDefined(); + }); +}); diff --git a/src/api/private/me/me.controller.ts b/src/api/private/me/me.controller.ts new file mode 100644 index 000000000..3151a4fd7 --- /dev/null +++ b/src/api/private/me/me.controller.ts @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Body, Controller, Delete, Get, HttpCode, Post } from '@nestjs/common'; +import { UserInfoDto } from '../../../users/user-info.dto'; +import { ConsoleLoggerService } from '../../../logger/console-logger.service'; +import { UsersService } from '../../../users/users.service'; +import { MediaService } from '../../../media/media.service'; +import { MediaUploadDto } from '../../../media/media-upload.dto'; + +@Controller('me') +export class MeController { + constructor( + private readonly logger: ConsoleLoggerService, + private userService: UsersService, + private mediaService: MediaService, + ) { + this.logger.setContext(MeController.name); + } + + @Get() + async getMe(): Promise { + // ToDo: use actual user here + const user = await this.userService.getUserByUsername('hardcoded'); + return this.userService.toUserDto(user); + } + + @Get('media') + async getMyMedia(): Promise { + // ToDo: use actual user here + const user = await this.userService.getUserByUsername('hardcoded'); + const media = await this.mediaService.listUploadsByUser(user); + return media.map((media) => this.mediaService.toMediaUploadDto(media)); + } + + @Delete() + @HttpCode(204) + async deleteUser(): Promise { + // ToDo: use actual user here + const user = await this.userService.getUserByUsername('hardcoded'); + const mediaUploads = await this.mediaService.listUploadsByUser(user); + for (const mediaUpload of mediaUploads) { + await this.mediaService.deleteFile(mediaUpload); + } + this.logger.debug(`Deleted all media uploads of ${user.userName}`); + await this.userService.deleteUser(user); + this.logger.debug(`Deleted ${user.userName}`); + } + + @Post('profile') + @HttpCode(200) + async updateDisplayName(@Body('name') newDisplayName: string): Promise { + // ToDo: use actual user here + const user = await this.userService.getUserByUsername('hardcoded'); + await this.userService.changeDisplayName(user, newDisplayName); + } +} diff --git a/src/api/private/private-api.module.ts b/src/api/private/private-api.module.ts index 729c65306..913920e81 100644 --- a/src/api/private/private-api.module.ts +++ b/src/api/private/private-api.module.ts @@ -9,6 +9,7 @@ import { TokensController } from './tokens/tokens.controller'; import { LoggerModule } from '../../logger/logger.module'; import { UsersModule } from '../../users/users.module'; import { AuthModule } from '../../auth/auth.module'; +import { MeController } from './me/me.controller'; import { ConfigController } from './config/config.controller'; import { FrontendConfigModule } from '../../frontend-config/frontend-config.module'; import { HistoryController } from './me/history/history.controller'; @@ -27,8 +28,8 @@ import { RevisionsModule } from '../../revisions/revisions.module'; AuthModule, FrontendConfigModule, HistoryModule, - NotesModule, PermissionsModule, + NotesModule, MediaModule, RevisionsModule, ], @@ -37,6 +38,7 @@ import { RevisionsModule } from '../../revisions/revisions.module'; ConfigController, MediaController, HistoryController, + MeController, NotesController, ], })