From 73d9c3231b0a7756d53fbacdaf20329c291d533d Mon Sep 17 00:00:00 2001 From: Erik Michelson Date: Sun, 1 Sep 2024 14:57:25 +0200 Subject: [PATCH] refactor(backend): rename auth to public-auth-token Signed-off-by: Yannick Bungers Signed-off-by: Erik Michelson --- REUSE.toml | 6 + backend/src/api/private/private-api.module.ts | 8 +- ...oller.ts => publicAuthTokensController.ts} | 36 +++--- .../src/api/public/alias/alias.controller.ts | 4 +- backend/src/api/public/me/me.controller.ts | 4 +- .../src/api/public/media/media.controller.ts | 4 +- .../monitoring/monitoring.controller.ts | 4 +- .../src/api/public/notes/notes.controller.ts | 4 +- backend/src/app.module.ts | 4 +- backend/src/auth/auth.module.ts | 27 ---- backend/src/history/history.service.spec.ts | 4 +- backend/src/media/media.service.spec.ts | 4 +- ...-init.ts => mariadb-1725204784823-init.ts} | 83 ++++++------ ...init.ts => postgres-1725203299761-init.ts} | 73 +++++------ ...7-init.ts => sqlite-1725204990810-init.ts} | 121 +++++++++--------- backend/src/notes/alias.service.spec.ts | 4 +- backend/src/notes/notes.service.spec.ts | 4 +- .../permissions/permissions.service.spec.ts | 4 +- .../mock-public-auth-token-guard.service.ts} | 2 +- .../public-auth-token.dto.ts} | 6 +- .../public-auth-token.entity.ts} | 16 +-- .../public-auth-token.module.ts | 35 +++++ .../public-auth-token.service.spec.ts} | 68 +++++----- .../public-auth-token.service.ts} | 79 ++++++------ .../public-auth-token.strategy.ts} | 13 +- .../websocket/websocket.gateway.spec.ts | 4 +- .../src/revisions/revisions.service.spec.ts | 4 +- backend/src/seed.ts | 4 +- backend/src/users/user.entity.ts | 8 +- backend/test/test-setup.ts | 28 ++-- 30 files changed, 338 insertions(+), 327 deletions(-) rename backend/src/api/private/tokens/{tokens.controller.ts => publicAuthTokensController.ts} (58%) delete mode 100644 backend/src/auth/auth.module.ts rename backend/src/migrations/{mariadb-1696756465867-init.ts => mariadb-1725204784823-init.ts} (93%) rename backend/src/migrations/{postgres-1696756465867-init.ts => postgres-1725203299761-init.ts} (93%) rename backend/src/migrations/{sqlite-1696756465867-init.ts => sqlite-1725204990810-init.ts} (92%) rename backend/src/{auth/mock-auth.guard.ts => public-auth-token/mock-public-auth-token-guard.service.ts} (96%) rename backend/src/{auth/auth-token.dto.ts => public-auth-token/public-auth-token.dto.ts} (80%) rename backend/src/{auth/auth-token.entity.ts => public-auth-token/public-auth-token.entity.ts} (68%) create mode 100644 backend/src/public-auth-token/public-auth-token.module.ts rename backend/src/{auth/auth.service.spec.ts => public-auth-token/public-auth-token.service.spec.ts} (87%) rename backend/src/{auth/auth.service.ts => public-auth-token/public-auth-token.service.ts} (78%) rename backend/src/{auth/token.strategy.ts => public-auth-token/public-auth-token.strategy.ts} (68%) diff --git a/REUSE.toml b/REUSE.toml index 5e30a9a16..ce262fb27 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -198,3 +198,9 @@ path = "backend/**/__snapshots__/**.snap" precedence = "aggregate" SPDX-FileCopyrightText = "2024 The HedgeDoc developers (see AUTHORS file)" SPDX-License-Identifier = "AGPL-3.0-only" + +[[annotations]] +path = "backend/src/migrations/*" +precedence = "aggregate" +SPDX-FileCopyrightText = "2024 The HedgeDoc developers (see AUTHORS file)" +SPDX-License-Identifier = "AGPL-3.0-only" \ No newline at end of file diff --git a/backend/src/api/private/private-api.module.ts b/backend/src/api/private/private-api.module.ts index 448d41713..9b0fc97d7 100644 --- a/backend/src/api/private/private-api.module.ts +++ b/backend/src/api/private/private-api.module.ts @@ -5,7 +5,6 @@ */ import { Module } from '@nestjs/common'; -import { AuthModule } from '../../auth/auth.module'; import { FrontendConfigModule } from '../../frontend-config/frontend-config.module'; import { GroupsModule } from '../../groups/groups.module'; import { HistoryModule } from '../../history/history.module'; @@ -14,6 +13,7 @@ import { LoggerModule } from '../../logger/logger.module'; import { MediaModule } from '../../media/media.module'; import { NotesModule } from '../../notes/notes.module'; import { PermissionsModule } from '../../permissions/permissions.module'; +import { PublicAuthTokenModule } from '../../public-auth-token/public-auth-token.module'; import { RevisionsModule } from '../../revisions/revisions.module'; import { UsersModule } from '../../users/users.module'; import { AliasController } from './alias/alias.controller'; @@ -24,14 +24,14 @@ import { HistoryController } from './me/history/history.controller'; import { MeController } from './me/me.controller'; import { MediaController } from './media/media.controller'; import { NotesController } from './notes/notes.controller'; -import { TokensController } from './tokens/tokens.controller'; +import { PublicAuthTokensController } from './tokens/publicAuthTokensController'; import { UsersController } from './users/users.controller'; @Module({ imports: [ LoggerModule, UsersModule, - AuthModule, + PublicAuthTokenModule, FrontendConfigModule, HistoryModule, PermissionsModule, @@ -42,7 +42,7 @@ import { UsersController } from './users/users.controller'; GroupsModule, ], controllers: [ - TokensController, + PublicAuthTokensController, ConfigController, MediaController, HistoryController, diff --git a/backend/src/api/private/tokens/tokens.controller.ts b/backend/src/api/private/tokens/publicAuthTokensController.ts similarity index 58% rename from backend/src/api/private/tokens/tokens.controller.ts rename to backend/src/api/private/tokens/publicAuthTokensController.ts index ffb4403ef..7de4b05b0 100644 --- a/backend/src/api/private/tokens/tokens.controller.ts +++ b/backend/src/api/private/tokens/publicAuthTokensController.ts @@ -15,14 +15,14 @@ import { } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { - AuthTokenCreateDto, - AuthTokenDto, - AuthTokenWithSecretDto, -} from '../../../auth/auth-token.dto'; -import { AuthService } from '../../../auth/auth.service'; import { SessionGuard } from '../../../identity/session.guard'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; +import { + PublicAuthTokenCreateDto, + PublicAuthTokenDto, + PublicAuthTokenWithSecretDto, +} from '../../../public-auth-token/public-auth-token.dto'; +import { PublicAuthTokenService } from '../../../public-auth-token/public-auth-token.service'; import { User } from '../../../users/user.entity'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; @@ -31,29 +31,31 @@ import { RequestUser } from '../../utils/request-user.decorator'; @OpenApi(401) @ApiTags('tokens') @Controller('tokens') -export class TokensController { +export class PublicAuthTokensController { constructor( private readonly logger: ConsoleLoggerService, - private authService: AuthService, + private publicAuthTokenService: PublicAuthTokenService, ) { - this.logger.setContext(TokensController.name); + this.logger.setContext(PublicAuthTokensController.name); } @Get() @OpenApi(200) - async getUserTokens(@RequestUser() user: User): Promise { - return (await this.authService.getTokensByUser(user)).map((token) => - this.authService.toAuthTokenDto(token), + async getUserTokens( + @RequestUser() user: User, + ): Promise { + return (await this.publicAuthTokenService.getTokensByUser(user)).map( + (token) => this.publicAuthTokenService.toAuthTokenDto(token), ); } @Post() @OpenApi(201) async postTokenRequest( - @Body() createDto: AuthTokenCreateDto, + @Body() createDto: PublicAuthTokenCreateDto, @RequestUser() user: User, - ): Promise { - return await this.authService.addToken( + ): Promise { + return await this.publicAuthTokenService.addToken( user, createDto.label, createDto.validUntil, @@ -66,10 +68,10 @@ export class TokensController { @RequestUser() user: User, @Param('keyId') keyId: string, ): Promise { - const tokens = await this.authService.getTokensByUser(user); + const tokens = await this.publicAuthTokenService.getTokensByUser(user); for (const token of tokens) { if (token.keyId == keyId) { - return await this.authService.removeToken(keyId); + return await this.publicAuthTokenService.removeToken(keyId); } } throw new UnauthorizedException( diff --git a/backend/src/api/public/alias/alias.controller.ts b/backend/src/api/public/alias/alias.controller.ts index a16f5a1cc..ebc482e63 100644 --- a/backend/src/api/public/alias/alias.controller.ts +++ b/backend/src/api/public/alias/alias.controller.ts @@ -16,7 +16,6 @@ import { } from '@nestjs/common'; import { ApiSecurity, ApiTags } from '@nestjs/swagger'; -import { TokenAuthGuard } from '../../../auth/token.strategy'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { AliasCreateDto } from '../../../notes/alias-create.dto'; import { AliasUpdateDto } from '../../../notes/alias-update.dto'; @@ -24,11 +23,12 @@ import { AliasDto } from '../../../notes/alias.dto'; import { AliasService } from '../../../notes/alias.service'; import { NotesService } from '../../../notes/notes.service'; import { PermissionsService } from '../../../permissions/permissions.service'; +import { PublicAuthTokenGuard } from '../../../public-auth-token/public-auth-token.strategy'; import { User } from '../../../users/user.entity'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; -@UseGuards(TokenAuthGuard) +@UseGuards(PublicAuthTokenGuard) @OpenApi(401) @ApiTags('alias') @ApiSecurity('token') diff --git a/backend/src/api/public/me/me.controller.ts b/backend/src/api/public/me/me.controller.ts index 3bf2d253c..d8eca753c 100644 --- a/backend/src/api/public/me/me.controller.ts +++ b/backend/src/api/public/me/me.controller.ts @@ -14,7 +14,6 @@ import { } from '@nestjs/common'; import { ApiSecurity, ApiTags } from '@nestjs/swagger'; -import { TokenAuthGuard } from '../../../auth/token.strategy'; import { HistoryEntryUpdateDto } from '../../../history/history-entry-update.dto'; import { HistoryEntryDto } from '../../../history/history-entry.dto'; import { HistoryService } from '../../../history/history.service'; @@ -24,6 +23,7 @@ import { MediaService } from '../../../media/media.service'; import { NoteMetadataDto } from '../../../notes/note-metadata.dto'; import { Note } from '../../../notes/note.entity'; import { NotesService } from '../../../notes/notes.service'; +import { PublicAuthTokenGuard } from '../../../public-auth-token/public-auth-token.strategy'; import { FullUserInfoDto } from '../../../users/user-info.dto'; import { User } from '../../../users/user.entity'; import { UsersService } from '../../../users/users.service'; @@ -32,7 +32,7 @@ import { OpenApi } from '../../utils/openapi.decorator'; import { RequestNote } from '../../utils/request-note.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; -@UseGuards(TokenAuthGuard) +@UseGuards(PublicAuthTokenGuard) @OpenApi(401) @ApiTags('me') @ApiSecurity('token') diff --git a/backend/src/api/public/media/media.controller.ts b/backend/src/api/public/media/media.controller.ts index 71d169047..f552942ef 100644 --- a/backend/src/api/public/media/media.controller.ts +++ b/backend/src/api/public/media/media.controller.ts @@ -25,7 +25,6 @@ import { } from '@nestjs/swagger'; import { Response } from 'express'; -import { TokenAuthGuard } from '../../../auth/token.strategy'; import { PermissionError } from '../../../errors/errors'; import { ConsoleLoggerService } from '../../../logger/console-logger.service'; import { MediaUploadDto } from '../../../media/media-upload.dto'; @@ -36,13 +35,14 @@ import { PermissionsGuard } from '../../../permissions/permissions.guard'; import { PermissionsService } from '../../../permissions/permissions.service'; import { RequirePermission } from '../../../permissions/require-permission.decorator'; import { RequiredPermission } from '../../../permissions/required-permission.enum'; +import { PublicAuthTokenGuard } from '../../../public-auth-token/public-auth-token.strategy'; import { User } from '../../../users/user.entity'; import { NoteHeaderInterceptor } from '../../utils/note-header.interceptor'; import { OpenApi } from '../../utils/openapi.decorator'; import { RequestNote } from '../../utils/request-note.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; -@UseGuards(TokenAuthGuard) +@UseGuards(PublicAuthTokenGuard) @OpenApi(401) @ApiTags('media') @ApiSecurity('token') diff --git a/backend/src/api/public/monitoring/monitoring.controller.ts b/backend/src/api/public/monitoring/monitoring.controller.ts index cf6299d72..0d086b4c5 100644 --- a/backend/src/api/public/monitoring/monitoring.controller.ts +++ b/backend/src/api/public/monitoring/monitoring.controller.ts @@ -6,12 +6,12 @@ import { Controller, Get, UseGuards } from '@nestjs/common'; import { ApiSecurity, ApiTags } from '@nestjs/swagger'; -import { TokenAuthGuard } from '../../../auth/token.strategy'; import { MonitoringService } from '../../../monitoring/monitoring.service'; import { ServerStatusDto } from '../../../monitoring/server-status.dto'; +import { PublicAuthTokenGuard } from '../../../public-auth-token/public-auth-token.strategy'; import { OpenApi } from '../../utils/openapi.decorator'; -@UseGuards(TokenAuthGuard) +@UseGuards(PublicAuthTokenGuard) @OpenApi(401) @ApiTags('monitoring') @ApiSecurity('token') diff --git a/backend/src/api/public/notes/notes.controller.ts b/backend/src/api/public/notes/notes.controller.ts index b2aab7bee..4c454e60a 100644 --- a/backend/src/api/public/notes/notes.controller.ts +++ b/backend/src/api/public/notes/notes.controller.ts @@ -17,7 +17,6 @@ import { } from '@nestjs/common'; import { ApiSecurity, ApiTags } from '@nestjs/swagger'; -import { TokenAuthGuard } from '../../../auth/token.strategy'; import { NotInDBError } from '../../../errors/errors'; import { GroupsService } from '../../../groups/groups.service'; import { HistoryService } from '../../../history/history.service'; @@ -37,6 +36,7 @@ import { PermissionsGuard } from '../../../permissions/permissions.guard'; import { PermissionsService } from '../../../permissions/permissions.service'; import { RequirePermission } from '../../../permissions/require-permission.decorator'; import { RequiredPermission } from '../../../permissions/required-permission.enum'; +import { PublicAuthTokenGuard } from '../../../public-auth-token/public-auth-token.strategy'; import { RevisionMetadataDto } from '../../../revisions/revision-metadata.dto'; import { RevisionDto } from '../../../revisions/revision.dto'; import { RevisionsService } from '../../../revisions/revisions.service'; @@ -49,7 +49,7 @@ import { OpenApi } from '../../utils/openapi.decorator'; import { RequestNote } from '../../utils/request-note.decorator'; import { RequestUser } from '../../utils/request-user.decorator'; -@UseGuards(TokenAuthGuard, PermissionsGuard) +@UseGuards(PublicAuthTokenGuard, PermissionsGuard) @OpenApi(401) @ApiTags('notes') @ApiSecurity('token') diff --git a/backend/src/app.module.ts b/backend/src/app.module.ts index 170d2a012..207154c73 100644 --- a/backend/src/app.module.ts +++ b/backend/src/app.module.ts @@ -12,7 +12,6 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { PrivateApiModule } from './api/private/private-api.module'; import { PublicApiModule } from './api/public/public-api.module'; -import { AuthModule } from './auth/auth.module'; import { AuthorsModule } from './authors/authors.module'; import appConfig from './config/app.config'; import authConfig from './config/auth.config'; @@ -34,6 +33,7 @@ import { MediaModule } from './media/media.module'; import { MonitoringModule } from './monitoring/monitoring.module'; import { NotesModule } from './notes/notes.module'; import { PermissionsModule } from './permissions/permissions.module'; +import { PublicAuthTokenModule } from './public-auth-token/public-auth-token.module'; import { WebsocketModule } from './realtime/websocket/websocket.module'; import { RevisionsModule } from './revisions/revisions.module'; import { SessionModule } from './sessions/session.module'; @@ -107,7 +107,7 @@ const routes: Routes = [ GroupsModule, LoggerModule, MediaModule, - AuthModule, + PublicAuthTokenModule, FrontendConfigModule, WebsocketModule, IdentityModule, diff --git a/backend/src/auth/auth.module.ts b/backend/src/auth/auth.module.ts deleted file mode 100644 index 874805b5a..000000000 --- a/backend/src/auth/auth.module.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ -import { Module } from '@nestjs/common'; -import { PassportModule } from '@nestjs/passport'; -import { TypeOrmModule } from '@nestjs/typeorm'; - -import { LoggerModule } from '../logger/logger.module'; -import { UsersModule } from '../users/users.module'; -import { AuthToken } from './auth-token.entity'; -import { AuthService } from './auth.service'; -import { MockAuthGuard } from './mock-auth.guard'; -import { TokenAuthGuard, TokenStrategy } from './token.strategy'; - -@Module({ - imports: [ - UsersModule, - PassportModule, - LoggerModule, - TypeOrmModule.forFeature([AuthToken]), - ], - providers: [AuthService, TokenStrategy, MockAuthGuard, TokenAuthGuard], - exports: [AuthService], -}) -export class AuthModule {} diff --git a/backend/src/history/history.service.spec.ts b/backend/src/history/history.service.spec.ts index 1c4121507..b8a1ce8db 100644 --- a/backend/src/history/history.service.spec.ts +++ b/backend/src/history/history.service.spec.ts @@ -11,7 +11,6 @@ import assert from 'assert'; import { Mock } from 'ts-mockery'; import { DataSource, EntityManager, Repository } from 'typeorm'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; @@ -28,6 +27,7 @@ import { NotesModule } from '../notes/notes.module'; import { Tag } from '../notes/tag.entity'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; import { RevisionsModule } from '../revisions/revisions.module'; @@ -112,7 +112,7 @@ describe('HistoryService', () => { }) .overrideProvider(getRepositoryToken(User)) .useValue({}) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/media/media.service.spec.ts b/backend/src/media/media.service.spec.ts index ee7810cdf..f2b8bde46 100644 --- a/backend/src/media/media.service.spec.ts +++ b/backend/src/media/media.service.spec.ts @@ -11,7 +11,6 @@ import { promises as fs } from 'fs'; import { Repository } from 'typeorm'; import appConfigMock from '../../src/config/mock/app.config.mock'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import authConfigMock from '../config/mock/auth.config.mock'; import databaseConfigMock from '../config/mock/database.config.mock'; @@ -28,6 +27,7 @@ import { NotesModule } from '../notes/notes.module'; import { Tag } from '../notes/tag.entity'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; import { Session } from '../sessions/session.entity'; @@ -84,7 +84,7 @@ describe('MediaService', () => { }) .overrideProvider(getRepositoryToken(Edit)) .useValue({}) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/migrations/mariadb-1696756465867-init.ts b/backend/src/migrations/mariadb-1725204784823-init.ts similarity index 93% rename from backend/src/migrations/mariadb-1696756465867-init.ts rename to backend/src/migrations/mariadb-1725204784823-init.ts index 5cf3a3ed9..df1fcd636 100644 --- a/backend/src/migrations/mariadb-1696756465867-init.ts +++ b/backend/src/migrations/mariadb-1725204784823-init.ts @@ -1,26 +1,15 @@ -/* - * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class Init1696756465867 implements MigrationInterface { - name = 'Init1696756465867'; +export class MariadbInit1725204784823 implements MigrationInterface { + name = 'MariadbInit1725204784823'; public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE \`auth_token\` (\`id\` int NOT NULL AUTO_INCREMENT, \`keyId\` varchar(255) NOT NULL, \`label\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`accessTokenHash\` varchar(255) NOT NULL, \`validUntil\` datetime NOT NULL, \`lastUsedAt\` date NULL, \`userId\` int NULL, UNIQUE INDEX \`IDX_9d2cf0a2cc3df58b87cbbc43e4\` (\`keyId\`), UNIQUE INDEX \`IDX_15b2228d06b08bb4cc98876c65\` (\`accessTokenHash\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); await queryRunner.query( `CREATE TABLE \`history_entry\` (\`id\` int NOT NULL AUTO_INCREMENT, \`pinStatus\` tinyint NOT NULL, \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`userId\` int NULL, \`noteId\` int NULL, UNIQUE INDEX \`IDX_928dd947355b0837366470a916\` (\`noteId\`, \`userId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, ); await queryRunner.query( `CREATE TABLE \`media_upload\` (\`id\` varchar(255) NOT NULL, \`backendType\` varchar(255) NOT NULL, \`fileUrl\` varchar(255) NOT NULL, \`backendData\` text NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`noteId\` int NULL, \`userId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, ); - await queryRunner.query( - `CREATE TABLE \`group\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(255) NOT NULL, \`displayName\` varchar(255) NOT NULL, \`special\` tinyint NOT NULL, UNIQUE INDEX \`IDX_8a45300fd825918f3b40195fbd\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); await queryRunner.query( `CREATE TABLE \`note_group_permission\` (\`id\` int NOT NULL AUTO_INCREMENT, \`canEdit\` tinyint NOT NULL, \`groupId\` int NULL, \`noteId\` int NULL, UNIQUE INDEX \`IDX_ee1744842a9ef3ffbc05a7016a\` (\`groupId\`, \`noteId\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, ); @@ -48,14 +37,17 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE TABLE \`author\` (\`id\` int NOT NULL AUTO_INCREMENT, \`color\` int NOT NULL, \`userId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, ); - await queryRunner.query( - `CREATE TABLE \`user\` (\`id\` int NOT NULL AUTO_INCREMENT, \`username\` varchar(255) NOT NULL, \`displayName\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`photo\` text NULL, \`email\` text NULL, UNIQUE INDEX \`IDX_78a916df40e02a9deb1c4b75ed\` (\`username\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, - ); await queryRunner.query( `CREATE TABLE \`identity\` (\`id\` int NOT NULL AUTO_INCREMENT, \`providerType\` varchar(255) NOT NULL, \`providerName\` text NULL, \`syncSource\` tinyint NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`providerUserId\` text NULL, \`oAuthAccessToken\` text NULL, \`passwordHash\` text NULL, \`userId\` int NULL, PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, ); await queryRunner.query( - `CREATE TABLE \`group_members_user\` (\`groupId\` int NOT NULL, \`userId\` int NOT NULL, INDEX \`IDX_bfa303089d367a2e3c02b002b8\` (\`groupId\`), INDEX \`IDX_427107c650638bcb2f1e167d2e\` (\`userId\`), PRIMARY KEY (\`groupId\`, \`userId\`)) ENGINE=InnoDB`, + `CREATE TABLE \`public_auth_token\` (\`id\` int NOT NULL AUTO_INCREMENT, \`keyId\` varchar(255) NOT NULL, \`label\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`hash\` varchar(255) NOT NULL, \`validUntil\` datetime NOT NULL, \`lastUsedAt\` date NULL, \`userId\` int NULL, UNIQUE INDEX \`IDX_b4c4b9179f72ef63c32248e83a\` (\`keyId\`), UNIQUE INDEX \`IDX_6450514886fa4182c889c076df\` (\`hash\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`user\` (\`id\` int NOT NULL AUTO_INCREMENT, \`username\` varchar(255) NOT NULL, \`displayName\` varchar(255) NOT NULL, \`createdAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), \`updatedAt\` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`photo\` text NULL, \`email\` text NULL, UNIQUE INDEX \`IDX_78a916df40e02a9deb1c4b75ed\` (\`username\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, + ); + await queryRunner.query( + `CREATE TABLE \`group\` (\`id\` int NOT NULL AUTO_INCREMENT, \`name\` varchar(255) NOT NULL, \`displayName\` varchar(255) NOT NULL, \`special\` tinyint NOT NULL, UNIQUE INDEX \`IDX_8a45300fd825918f3b40195fbd\` (\`name\`), PRIMARY KEY (\`id\`)) ENGINE=InnoDB`, ); await queryRunner.query( `CREATE TABLE \`revision_tags_tag\` (\`revisionId\` int NOT NULL, \`tagId\` int NOT NULL, INDEX \`IDX_3382f45eefeb40f91e45cfd418\` (\`revisionId\`), INDEX \`IDX_19dbafe2a8b456c0ef40858d49\` (\`tagId\`), PRIMARY KEY (\`revisionId\`, \`tagId\`)) ENGINE=InnoDB`, @@ -64,7 +56,7 @@ export class Init1696756465867 implements MigrationInterface { `CREATE TABLE \`revision_edits_edit\` (\`revisionId\` int NOT NULL, \`editId\` int NOT NULL, INDEX \`IDX_52c6a61e1a646768391c7854fe\` (\`revisionId\`), INDEX \`IDX_470886feb50e30114e39c42698\` (\`editId\`), PRIMARY KEY (\`revisionId\`, \`editId\`)) ENGINE=InnoDB`, ); await queryRunner.query( - `ALTER TABLE \`auth_token\` ADD CONSTRAINT \`FK_5a326267f11b44c0d62526bc718\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, + `CREATE TABLE \`group_members_user\` (\`groupId\` int NOT NULL, \`userId\` int NOT NULL, INDEX \`IDX_bfa303089d367a2e3c02b002b8\` (\`groupId\`), INDEX \`IDX_427107c650638bcb2f1e167d2e\` (\`userId\`), PRIMARY KEY (\`groupId\`, \`userId\`)) ENGINE=InnoDB`, ); await queryRunner.query( `ALTER TABLE \`history_entry\` ADD CONSTRAINT \`FK_42b8ae461cb58747a24340e6c64\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, @@ -112,10 +104,7 @@ export class Init1696756465867 implements MigrationInterface { `ALTER TABLE \`identity\` ADD CONSTRAINT \`FK_12915039d2868ab654567bf5181\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( - `ALTER TABLE \`group_members_user\` ADD CONSTRAINT \`FK_bfa303089d367a2e3c02b002b8f\` FOREIGN KEY (\`groupId\`) REFERENCES \`group\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE \`group_members_user\` ADD CONSTRAINT \`FK_427107c650638bcb2f1e167d2e5\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, + `ALTER TABLE \`public_auth_token\` ADD CONSTRAINT \`FK_b7b4f28eb8b4a0fc443448b9054\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( `ALTER TABLE \`revision_tags_tag\` ADD CONSTRAINT \`FK_3382f45eefeb40f91e45cfd4180\` FOREIGN KEY (\`revisionId\`) REFERENCES \`revision\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, @@ -129,9 +118,21 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `ALTER TABLE \`revision_edits_edit\` ADD CONSTRAINT \`FK_470886feb50e30114e39c426987\` FOREIGN KEY (\`editId\`) REFERENCES \`edit\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, ); + await queryRunner.query( + `ALTER TABLE \`group_members_user\` ADD CONSTRAINT \`FK_bfa303089d367a2e3c02b002b8f\` FOREIGN KEY (\`groupId\`) REFERENCES \`group\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`, + ); + await queryRunner.query( + `ALTER TABLE \`group_members_user\` ADD CONSTRAINT \`FK_427107c650638bcb2f1e167d2e5\` FOREIGN KEY (\`userId\`) REFERENCES \`user\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); } public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE \`group_members_user\` DROP FOREIGN KEY \`FK_427107c650638bcb2f1e167d2e5\``, + ); + await queryRunner.query( + `ALTER TABLE \`group_members_user\` DROP FOREIGN KEY \`FK_bfa303089d367a2e3c02b002b8f\``, + ); await queryRunner.query( `ALTER TABLE \`revision_edits_edit\` DROP FOREIGN KEY \`FK_470886feb50e30114e39c426987\``, ); @@ -145,10 +146,7 @@ export class Init1696756465867 implements MigrationInterface { `ALTER TABLE \`revision_tags_tag\` DROP FOREIGN KEY \`FK_3382f45eefeb40f91e45cfd4180\``, ); await queryRunner.query( - `ALTER TABLE \`group_members_user\` DROP FOREIGN KEY \`FK_427107c650638bcb2f1e167d2e5\``, - ); - await queryRunner.query( - `ALTER TABLE \`group_members_user\` DROP FOREIGN KEY \`FK_bfa303089d367a2e3c02b002b8f\``, + `ALTER TABLE \`public_auth_token\` DROP FOREIGN KEY \`FK_b7b4f28eb8b4a0fc443448b9054\``, ); await queryRunner.query( `ALTER TABLE \`identity\` DROP FOREIGN KEY \`FK_12915039d2868ab654567bf5181\``, @@ -196,8 +194,12 @@ export class Init1696756465867 implements MigrationInterface { `ALTER TABLE \`history_entry\` DROP FOREIGN KEY \`FK_42b8ae461cb58747a24340e6c64\``, ); await queryRunner.query( - `ALTER TABLE \`auth_token\` DROP FOREIGN KEY \`FK_5a326267f11b44c0d62526bc718\``, + `DROP INDEX \`IDX_427107c650638bcb2f1e167d2e\` ON \`group_members_user\``, ); + await queryRunner.query( + `DROP INDEX \`IDX_bfa303089d367a2e3c02b002b8\` ON \`group_members_user\``, + ); + await queryRunner.query(`DROP TABLE \`group_members_user\``); await queryRunner.query( `DROP INDEX \`IDX_470886feb50e30114e39c42698\` ON \`revision_edits_edit\``, ); @@ -213,17 +215,21 @@ export class Init1696756465867 implements MigrationInterface { ); await queryRunner.query(`DROP TABLE \`revision_tags_tag\``); await queryRunner.query( - `DROP INDEX \`IDX_427107c650638bcb2f1e167d2e\` ON \`group_members_user\``, + `DROP INDEX \`IDX_8a45300fd825918f3b40195fbd\` ON \`group\``, ); - await queryRunner.query( - `DROP INDEX \`IDX_bfa303089d367a2e3c02b002b8\` ON \`group_members_user\``, - ); - await queryRunner.query(`DROP TABLE \`group_members_user\``); - await queryRunner.query(`DROP TABLE \`identity\``); + await queryRunner.query(`DROP TABLE \`group\``); await queryRunner.query( `DROP INDEX \`IDX_78a916df40e02a9deb1c4b75ed\` ON \`user\``, ); await queryRunner.query(`DROP TABLE \`user\``); + await queryRunner.query( + `DROP INDEX \`IDX_6450514886fa4182c889c076df\` ON \`public_auth_token\``, + ); + await queryRunner.query( + `DROP INDEX \`IDX_b4c4b9179f72ef63c32248e83a\` ON \`public_auth_token\``, + ); + await queryRunner.query(`DROP TABLE \`public_auth_token\``); + await queryRunner.query(`DROP TABLE \`identity\``); await queryRunner.query(`DROP TABLE \`author\``); await queryRunner.query( `DROP INDEX \`IDX_28c5d1d16da7908c97c9bc2f74\` ON \`session\``, @@ -248,21 +254,10 @@ export class Init1696756465867 implements MigrationInterface { `DROP INDEX \`IDX_ee1744842a9ef3ffbc05a7016a\` ON \`note_group_permission\``, ); await queryRunner.query(`DROP TABLE \`note_group_permission\``); - await queryRunner.query( - `DROP INDEX \`IDX_8a45300fd825918f3b40195fbd\` ON \`group\``, - ); - await queryRunner.query(`DROP TABLE \`group\``); await queryRunner.query(`DROP TABLE \`media_upload\``); await queryRunner.query( `DROP INDEX \`IDX_928dd947355b0837366470a916\` ON \`history_entry\``, ); await queryRunner.query(`DROP TABLE \`history_entry\``); - await queryRunner.query( - `DROP INDEX \`IDX_15b2228d06b08bb4cc98876c65\` ON \`auth_token\``, - ); - await queryRunner.query( - `DROP INDEX \`IDX_9d2cf0a2cc3df58b87cbbc43e4\` ON \`auth_token\``, - ); - await queryRunner.query(`DROP TABLE \`auth_token\``); } } diff --git a/backend/src/migrations/postgres-1696756465867-init.ts b/backend/src/migrations/postgres-1725203299761-init.ts similarity index 93% rename from backend/src/migrations/postgres-1696756465867-init.ts rename to backend/src/migrations/postgres-1725203299761-init.ts index aa45f25d4..6f278eaed 100644 --- a/backend/src/migrations/postgres-1696756465867-init.ts +++ b/backend/src/migrations/postgres-1725203299761-init.ts @@ -1,17 +1,9 @@ -/* - * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class Init1696756465867 implements MigrationInterface { - name = 'Init1696756465867'; +export class Init1725203299761 implements MigrationInterface { + name = 'Init1725203299761'; public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "auth_token" ("id" SERIAL NOT NULL, "keyId" character varying NOT NULL, "label" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "accessTokenHash" character varying NOT NULL, "validUntil" TIMESTAMP NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_9d2cf0a2cc3df58b87cbbc43e48" UNIQUE ("keyId"), CONSTRAINT "UQ_15b2228d06b08bb4cc98876c651" UNIQUE ("accessTokenHash"), CONSTRAINT "PK_4572ff5d1264c4a523f01aa86a0" PRIMARY KEY ("id"))`, - ); await queryRunner.query( `CREATE TABLE "history_entry" ("id" SERIAL NOT NULL, "pinStatus" boolean NOT NULL, "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "userId" integer, "noteId" integer, CONSTRAINT "PK_b65bd95b0d2929668589d57b97a" PRIMARY KEY ("id"))`, ); @@ -21,9 +13,6 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE TABLE "media_upload" ("id" character varying NOT NULL, "backendType" character varying NOT NULL, "fileUrl" character varying NOT NULL, "backendData" text, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "noteId" integer, "userId" integer, CONSTRAINT "PK_b406d9cee56e253dfd3b3d52706" PRIMARY KEY ("id"))`, ); - await queryRunner.query( - `CREATE TABLE "group" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, "displayName" character varying NOT NULL, "special" boolean NOT NULL, CONSTRAINT "UQ_8a45300fd825918f3b40195fbdc" UNIQUE ("name"), CONSTRAINT "PK_256aa0fda9b1de1a73ee0b7106b" PRIMARY KEY ("id"))`, - ); await queryRunner.query( `CREATE TABLE "note_group_permission" ("id" SERIAL NOT NULL, "canEdit" boolean NOT NULL, "groupId" integer, "noteId" integer, CONSTRAINT "PK_6327989190949e6a55d02a080c3" PRIMARY KEY ("id"))`, ); @@ -60,20 +49,17 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE TABLE "author" ("id" SERIAL NOT NULL, "color" integer NOT NULL, "userId" integer, CONSTRAINT "PK_5a0e79799d372fe56f2f3fa6871" PRIMARY KEY ("id"))`, ); - await queryRunner.query( - `CREATE TABLE "user" ("id" SERIAL NOT NULL, "username" character varying NOT NULL, "displayName" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "photo" text, "email" text, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`, - ); await queryRunner.query( `CREATE TABLE "identity" ("id" SERIAL NOT NULL, "providerType" character varying NOT NULL, "providerName" text, "syncSource" boolean NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "providerUserId" text, "oAuthAccessToken" text, "passwordHash" text, "userId" integer, CONSTRAINT "PK_ff16a44186b286d5e626178f726" PRIMARY KEY ("id"))`, ); await queryRunner.query( - `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "PK_7170c9a27e7b823d391d9e11f2e" PRIMARY KEY ("groupId", "userId"))`, + `CREATE TABLE "public_auth_token" ("id" SERIAL NOT NULL, "keyId" character varying NOT NULL, "label" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "hash" character varying NOT NULL, "validUntil" TIMESTAMP NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_b4c4b9179f72ef63c32248e83ab" UNIQUE ("keyId"), CONSTRAINT "UQ_6450514886fa4182c889c076df6" UNIQUE ("hash"), CONSTRAINT "PK_1bdb7c2d237fb02d84fa75f48a5" PRIMARY KEY ("id"))`, ); await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, + `CREATE TABLE "user" ("id" SERIAL NOT NULL, "username" character varying NOT NULL, "displayName" character varying NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP NOT NULL DEFAULT now(), "photo" text, "email" text, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"), CONSTRAINT "PK_cace4a159ff9f2512dd42373760" PRIMARY KEY ("id"))`, ); await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, + `CREATE TABLE "group" ("id" SERIAL NOT NULL, "name" character varying NOT NULL, "displayName" character varying NOT NULL, "special" boolean NOT NULL, CONSTRAINT "UQ_8a45300fd825918f3b40195fbdc" UNIQUE ("name"), CONSTRAINT "PK_256aa0fda9b1de1a73ee0b7106b" PRIMARY KEY ("id"))`, ); await queryRunner.query( `CREATE TABLE "revision_tags_tag" ("revisionId" integer NOT NULL, "tagId" integer NOT NULL, CONSTRAINT "PK_006354d3ecad6cb1e606320647b" PRIMARY KEY ("revisionId", "tagId"))`, @@ -94,7 +80,13 @@ export class Init1696756465867 implements MigrationInterface { `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, ); await queryRunner.query( - `ALTER TABLE "auth_token" ADD CONSTRAINT "FK_5a326267f11b44c0d62526bc718" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "PK_7170c9a27e7b823d391d9e11f2e" PRIMARY KEY ("groupId", "userId"))`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, ); await queryRunner.query( `ALTER TABLE "history_entry" ADD CONSTRAINT "FK_42b8ae461cb58747a24340e6c64" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, @@ -142,10 +134,7 @@ export class Init1696756465867 implements MigrationInterface { `ALTER TABLE "identity" ADD CONSTRAINT "FK_12915039d2868ab654567bf5181" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( - `ALTER TABLE "group_members_user" ADD CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f" FOREIGN KEY ("groupId") REFERENCES "group"("id") ON DELETE CASCADE ON UPDATE CASCADE`, - ); - await queryRunner.query( - `ALTER TABLE "group_members_user" ADD CONSTRAINT "FK_427107c650638bcb2f1e167d2e5" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + `ALTER TABLE "public_auth_token" ADD CONSTRAINT "FK_b7b4f28eb8b4a0fc443448b9054" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, ); await queryRunner.query( `ALTER TABLE "revision_tags_tag" ADD CONSTRAINT "FK_3382f45eefeb40f91e45cfd4180" FOREIGN KEY ("revisionId") REFERENCES "revision"("id") ON DELETE CASCADE ON UPDATE CASCADE`, @@ -159,9 +148,21 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `ALTER TABLE "revision_edits_edit" ADD CONSTRAINT "FK_470886feb50e30114e39c426987" FOREIGN KEY ("editId") REFERENCES "edit"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, ); + await queryRunner.query( + `ALTER TABLE "group_members_user" ADD CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f" FOREIGN KEY ("groupId") REFERENCES "group"("id") ON DELETE CASCADE ON UPDATE CASCADE`, + ); + await queryRunner.query( + `ALTER TABLE "group_members_user" ADD CONSTRAINT "FK_427107c650638bcb2f1e167d2e5" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE NO ACTION ON UPDATE NO ACTION`, + ); } public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "group_members_user" DROP CONSTRAINT "FK_427107c650638bcb2f1e167d2e5"`, + ); + await queryRunner.query( + `ALTER TABLE "group_members_user" DROP CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f"`, + ); await queryRunner.query( `ALTER TABLE "revision_edits_edit" DROP CONSTRAINT "FK_470886feb50e30114e39c426987"`, ); @@ -175,10 +176,7 @@ export class Init1696756465867 implements MigrationInterface { `ALTER TABLE "revision_tags_tag" DROP CONSTRAINT "FK_3382f45eefeb40f91e45cfd4180"`, ); await queryRunner.query( - `ALTER TABLE "group_members_user" DROP CONSTRAINT "FK_427107c650638bcb2f1e167d2e5"`, - ); - await queryRunner.query( - `ALTER TABLE "group_members_user" DROP CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f"`, + `ALTER TABLE "public_auth_token" DROP CONSTRAINT "FK_b7b4f28eb8b4a0fc443448b9054"`, ); await queryRunner.query( `ALTER TABLE "identity" DROP CONSTRAINT "FK_12915039d2868ab654567bf5181"`, @@ -226,8 +224,12 @@ export class Init1696756465867 implements MigrationInterface { `ALTER TABLE "history_entry" DROP CONSTRAINT "FK_42b8ae461cb58747a24340e6c64"`, ); await queryRunner.query( - `ALTER TABLE "auth_token" DROP CONSTRAINT "FK_5a326267f11b44c0d62526bc718"`, + `DROP INDEX "public"."IDX_427107c650638bcb2f1e167d2e"`, ); + await queryRunner.query( + `DROP INDEX "public"."IDX_bfa303089d367a2e3c02b002b8"`, + ); + await queryRunner.query(`DROP TABLE "group_members_user"`); await queryRunner.query( `DROP INDEX "public"."IDX_470886feb50e30114e39c42698"`, ); @@ -242,15 +244,10 @@ export class Init1696756465867 implements MigrationInterface { `DROP INDEX "public"."IDX_3382f45eefeb40f91e45cfd418"`, ); await queryRunner.query(`DROP TABLE "revision_tags_tag"`); - await queryRunner.query( - `DROP INDEX "public"."IDX_427107c650638bcb2f1e167d2e"`, - ); - await queryRunner.query( - `DROP INDEX "public"."IDX_bfa303089d367a2e3c02b002b8"`, - ); - await queryRunner.query(`DROP TABLE "group_members_user"`); - await queryRunner.query(`DROP TABLE "identity"`); + await queryRunner.query(`DROP TABLE "group"`); await queryRunner.query(`DROP TABLE "user"`); + await queryRunner.query(`DROP TABLE "public_auth_token"`); + await queryRunner.query(`DROP TABLE "identity"`); await queryRunner.query(`DROP TABLE "author"`); await queryRunner.query( `DROP INDEX "public"."IDX_28c5d1d16da7908c97c9bc2f74"`, @@ -269,12 +266,10 @@ export class Init1696756465867 implements MigrationInterface { `DROP INDEX "public"."IDX_ee1744842a9ef3ffbc05a7016a"`, ); await queryRunner.query(`DROP TABLE "note_group_permission"`); - await queryRunner.query(`DROP TABLE "group"`); await queryRunner.query(`DROP TABLE "media_upload"`); await queryRunner.query( `DROP INDEX "public"."IDX_928dd947355b0837366470a916"`, ); await queryRunner.query(`DROP TABLE "history_entry"`); - await queryRunner.query(`DROP TABLE "auth_token"`); } } diff --git a/backend/src/migrations/sqlite-1696756465867-init.ts b/backend/src/migrations/sqlite-1725204990810-init.ts similarity index 92% rename from backend/src/migrations/sqlite-1696756465867-init.ts rename to backend/src/migrations/sqlite-1725204990810-init.ts index 195cd9001..9631b32de 100644 --- a/backend/src/migrations/sqlite-1696756465867-init.ts +++ b/backend/src/migrations/sqlite-1725204990810-init.ts @@ -1,17 +1,9 @@ -/* - * SPDX-FileCopyrightText: 2023 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ import { MigrationInterface, QueryRunner } from 'typeorm'; -export class Init1696756465867 implements MigrationInterface { - name = 'Init1696756465867'; +export class SqliteInit1725204990810 implements MigrationInterface { + name = 'SqliteInit1725204990810'; public async up(queryRunner: QueryRunner): Promise { - await queryRunner.query( - `CREATE TABLE "auth_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "accessTokenHash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_9d2cf0a2cc3df58b87cbbc43e48" UNIQUE ("keyId"), CONSTRAINT "UQ_15b2228d06b08bb4cc98876c651" UNIQUE ("accessTokenHash"))`, - ); await queryRunner.query( `CREATE TABLE "history_entry" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "pinStatus" boolean NOT NULL, "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "userId" integer, "noteId" integer)`, ); @@ -21,9 +13,6 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE TABLE "media_upload" ("id" varchar PRIMARY KEY NOT NULL, "backendType" varchar NOT NULL, "fileUrl" varchar NOT NULL, "backendData" text, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "noteId" integer, "userId" integer)`, ); - await queryRunner.query( - `CREATE TABLE "group" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "displayName" varchar NOT NULL, "special" boolean NOT NULL, CONSTRAINT "UQ_8a45300fd825918f3b40195fbdc" UNIQUE ("name"))`, - ); await queryRunner.query( `CREATE TABLE "note_group_permission" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "canEdit" boolean NOT NULL, "groupId" integer, "noteId" integer)`, ); @@ -60,20 +49,17 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE TABLE "author" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "color" integer NOT NULL, "userId" integer)`, ); - await queryRunner.query( - `CREATE TABLE "user" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "username" varchar NOT NULL, "displayName" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "photo" text, "email" text, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"))`, - ); await queryRunner.query( `CREATE TABLE "identity" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "providerType" varchar NOT NULL, "providerName" text, "syncSource" boolean NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "providerUserId" text, "oAuthAccessToken" text, "passwordHash" text, "userId" integer)`, ); await queryRunner.query( - `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, PRIMARY KEY ("groupId", "userId"))`, + `CREATE TABLE "public_auth_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "hash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_b4c4b9179f72ef63c32248e83ab" UNIQUE ("keyId"), CONSTRAINT "UQ_6450514886fa4182c889c076df6" UNIQUE ("hash"))`, ); await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, + `CREATE TABLE "user" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "username" varchar NOT NULL, "displayName" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "updatedAt" datetime NOT NULL DEFAULT (datetime('now')), "photo" text, "email" text, CONSTRAINT "UQ_78a916df40e02a9deb1c4b75edb" UNIQUE ("username"))`, ); await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, + `CREATE TABLE "group" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar NOT NULL, "displayName" varchar NOT NULL, "special" boolean NOT NULL, CONSTRAINT "UQ_8a45300fd825918f3b40195fbdc" UNIQUE ("name"))`, ); await queryRunner.query( `CREATE TABLE "revision_tags_tag" ("revisionId" integer NOT NULL, "tagId" integer NOT NULL, PRIMARY KEY ("revisionId", "tagId"))`, @@ -94,14 +80,13 @@ export class Init1696756465867 implements MigrationInterface { `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, ); await queryRunner.query( - `CREATE TABLE "temporary_auth_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "accessTokenHash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_9d2cf0a2cc3df58b87cbbc43e48" UNIQUE ("keyId"), CONSTRAINT "UQ_15b2228d06b08bb4cc98876c651" UNIQUE ("accessTokenHash"), CONSTRAINT "FK_5a326267f11b44c0d62526bc718" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, + `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, PRIMARY KEY ("groupId", "userId"))`, ); await queryRunner.query( - `INSERT INTO "temporary_auth_token"("id", "keyId", "label", "createdAt", "accessTokenHash", "validUntil", "lastUsedAt", "userId") SELECT "id", "keyId", "label", "createdAt", "accessTokenHash", "validUntil", "lastUsedAt", "userId" FROM "auth_token"`, + `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, ); - await queryRunner.query(`DROP TABLE "auth_token"`); await queryRunner.query( - `ALTER TABLE "temporary_auth_token" RENAME TO "auth_token"`, + `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, ); await queryRunner.query(`DROP INDEX "IDX_928dd947355b0837366470a916"`); await queryRunner.query( @@ -223,23 +208,15 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `ALTER TABLE "temporary_identity" RENAME TO "identity"`, ); - await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); - await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); await queryRunner.query( - `CREATE TABLE "temporary_group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f" FOREIGN KEY ("groupId") REFERENCES "group" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_427107c650638bcb2f1e167d2e5" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, PRIMARY KEY ("groupId", "userId"))`, + `CREATE TABLE "temporary_public_auth_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "hash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_b4c4b9179f72ef63c32248e83ab" UNIQUE ("keyId"), CONSTRAINT "UQ_6450514886fa4182c889c076df6" UNIQUE ("hash"), CONSTRAINT "FK_b7b4f28eb8b4a0fc443448b9054" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE CASCADE ON UPDATE NO ACTION)`, ); await queryRunner.query( - `INSERT INTO "temporary_group_members_user"("groupId", "userId") SELECT "groupId", "userId" FROM "group_members_user"`, + `INSERT INTO "temporary_public_auth_token"("id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId") SELECT "id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId" FROM "public_auth_token"`, ); - await queryRunner.query(`DROP TABLE "group_members_user"`); + await queryRunner.query(`DROP TABLE "public_auth_token"`); await queryRunner.query( - `ALTER TABLE "temporary_group_members_user" RENAME TO "group_members_user"`, - ); - await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, + `ALTER TABLE "temporary_public_auth_token" RENAME TO "public_auth_token"`, ); await queryRunner.query(`DROP INDEX "IDX_3382f45eefeb40f91e45cfd418"`); await queryRunner.query(`DROP INDEX "IDX_19dbafe2a8b456c0ef40858d49"`); @@ -277,9 +254,45 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE INDEX "IDX_470886feb50e30114e39c42698" ON "revision_edits_edit" ("editId") `, ); + await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); + await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); + await queryRunner.query( + `CREATE TABLE "temporary_group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, CONSTRAINT "FK_bfa303089d367a2e3c02b002b8f" FOREIGN KEY ("groupId") REFERENCES "group" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "FK_427107c650638bcb2f1e167d2e5" FOREIGN KEY ("userId") REFERENCES "user" ("id") ON DELETE NO ACTION ON UPDATE NO ACTION, PRIMARY KEY ("groupId", "userId"))`, + ); + await queryRunner.query( + `INSERT INTO "temporary_group_members_user"("groupId", "userId") SELECT "groupId", "userId" FROM "group_members_user"`, + ); + await queryRunner.query(`DROP TABLE "group_members_user"`); + await queryRunner.query( + `ALTER TABLE "temporary_group_members_user" RENAME TO "group_members_user"`, + ); + await queryRunner.query( + `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, + ); } public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); + await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); + await queryRunner.query( + `ALTER TABLE "group_members_user" RENAME TO "temporary_group_members_user"`, + ); + await queryRunner.query( + `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, PRIMARY KEY ("groupId", "userId"))`, + ); + await queryRunner.query( + `INSERT INTO "group_members_user"("groupId", "userId") SELECT "groupId", "userId" FROM "temporary_group_members_user"`, + ); + await queryRunner.query(`DROP TABLE "temporary_group_members_user"`); + await queryRunner.query( + `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, + ); + await queryRunner.query( + `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, + ); await queryRunner.query(`DROP INDEX "IDX_470886feb50e30114e39c42698"`); await queryRunner.query(`DROP INDEX "IDX_52c6a61e1a646768391c7854fe"`); await queryRunner.query( @@ -316,24 +329,16 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE INDEX "IDX_3382f45eefeb40f91e45cfd418" ON "revision_tags_tag" ("revisionId") `, ); - await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); - await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); await queryRunner.query( - `ALTER TABLE "group_members_user" RENAME TO "temporary_group_members_user"`, + `ALTER TABLE "public_auth_token" RENAME TO "temporary_public_auth_token"`, ); await queryRunner.query( - `CREATE TABLE "group_members_user" ("groupId" integer NOT NULL, "userId" integer NOT NULL, PRIMARY KEY ("groupId", "userId"))`, + `CREATE TABLE "public_auth_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "hash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_b4c4b9179f72ef63c32248e83ab" UNIQUE ("keyId"), CONSTRAINT "UQ_6450514886fa4182c889c076df6" UNIQUE ("hash"))`, ); await queryRunner.query( - `INSERT INTO "group_members_user"("groupId", "userId") SELECT "groupId", "userId" FROM "temporary_group_members_user"`, - ); - await queryRunner.query(`DROP TABLE "temporary_group_members_user"`); - await queryRunner.query( - `CREATE INDEX "IDX_427107c650638bcb2f1e167d2e" ON "group_members_user" ("userId") `, - ); - await queryRunner.query( - `CREATE INDEX "IDX_bfa303089d367a2e3c02b002b8" ON "group_members_user" ("groupId") `, + `INSERT INTO "public_auth_token"("id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId") SELECT "id", "keyId", "label", "createdAt", "hash", "validUntil", "lastUsedAt", "userId" FROM "temporary_public_auth_token"`, ); + await queryRunner.query(`DROP TABLE "temporary_public_auth_token"`); await queryRunner.query( `ALTER TABLE "identity" RENAME TO "temporary_identity"`, ); @@ -454,27 +459,19 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query( `CREATE UNIQUE INDEX "IDX_928dd947355b0837366470a916" ON "history_entry" ("noteId", "userId") `, ); - await queryRunner.query( - `ALTER TABLE "auth_token" RENAME TO "temporary_auth_token"`, - ); - await queryRunner.query( - `CREATE TABLE "auth_token" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "keyId" varchar NOT NULL, "label" varchar NOT NULL, "createdAt" datetime NOT NULL DEFAULT (datetime('now')), "accessTokenHash" varchar NOT NULL, "validUntil" datetime NOT NULL, "lastUsedAt" date, "userId" integer, CONSTRAINT "UQ_9d2cf0a2cc3df58b87cbbc43e48" UNIQUE ("keyId"), CONSTRAINT "UQ_15b2228d06b08bb4cc98876c651" UNIQUE ("accessTokenHash"))`, - ); - await queryRunner.query( - `INSERT INTO "auth_token"("id", "keyId", "label", "createdAt", "accessTokenHash", "validUntil", "lastUsedAt", "userId") SELECT "id", "keyId", "label", "createdAt", "accessTokenHash", "validUntil", "lastUsedAt", "userId" FROM "temporary_auth_token"`, - ); - await queryRunner.query(`DROP TABLE "temporary_auth_token"`); + await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); + await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); + await queryRunner.query(`DROP TABLE "group_members_user"`); await queryRunner.query(`DROP INDEX "IDX_470886feb50e30114e39c42698"`); await queryRunner.query(`DROP INDEX "IDX_52c6a61e1a646768391c7854fe"`); await queryRunner.query(`DROP TABLE "revision_edits_edit"`); await queryRunner.query(`DROP INDEX "IDX_19dbafe2a8b456c0ef40858d49"`); await queryRunner.query(`DROP INDEX "IDX_3382f45eefeb40f91e45cfd418"`); await queryRunner.query(`DROP TABLE "revision_tags_tag"`); - await queryRunner.query(`DROP INDEX "IDX_427107c650638bcb2f1e167d2e"`); - await queryRunner.query(`DROP INDEX "IDX_bfa303089d367a2e3c02b002b8"`); - await queryRunner.query(`DROP TABLE "group_members_user"`); - await queryRunner.query(`DROP TABLE "identity"`); + await queryRunner.query(`DROP TABLE "group"`); await queryRunner.query(`DROP TABLE "user"`); + await queryRunner.query(`DROP TABLE "public_auth_token"`); + await queryRunner.query(`DROP TABLE "identity"`); await queryRunner.query(`DROP TABLE "author"`); await queryRunner.query(`DROP INDEX "IDX_28c5d1d16da7908c97c9bc2f74"`); await queryRunner.query(`DROP TABLE "session"`); @@ -487,10 +484,8 @@ export class Init1696756465867 implements MigrationInterface { await queryRunner.query(`DROP TABLE "note_user_permission"`); await queryRunner.query(`DROP INDEX "IDX_ee1744842a9ef3ffbc05a7016a"`); await queryRunner.query(`DROP TABLE "note_group_permission"`); - await queryRunner.query(`DROP TABLE "group"`); await queryRunner.query(`DROP TABLE "media_upload"`); await queryRunner.query(`DROP INDEX "IDX_928dd947355b0837366470a916"`); await queryRunner.query(`DROP TABLE "history_entry"`); - await queryRunner.query(`DROP TABLE "auth_token"`); } } diff --git a/backend/src/notes/alias.service.spec.ts b/backend/src/notes/alias.service.spec.ts index 876990a8f..6f65861e1 100644 --- a/backend/src/notes/alias.service.spec.ts +++ b/backend/src/notes/alias.service.spec.ts @@ -10,7 +10,6 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Mock } from 'ts-mockery'; import { DataSource, EntityManager, Repository } from 'typeorm'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; @@ -29,6 +28,7 @@ import { Identity } from '../identity/identity.entity'; import { LoggerModule } from '../logger/logger.module'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { RealtimeNoteModule } from '../realtime/realtime-note/realtime-note.module'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; @@ -118,7 +118,7 @@ describe('AliasService', () => { .useValue(aliasRepo) .overrideProvider(getRepositoryToken(User)) .useClass(Repository) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/notes/notes.service.spec.ts b/backend/src/notes/notes.service.spec.ts index e10d126a8..04ea08a9a 100644 --- a/backend/src/notes/notes.service.spec.ts +++ b/backend/src/notes/notes.service.spec.ts @@ -15,7 +15,6 @@ import { Repository, } from 'typeorm'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import { DefaultAccessLevel } from '../config/default-access-level.enum'; import appConfigMock from '../config/mock/app.config.mock'; @@ -40,6 +39,7 @@ import { Identity } from '../identity/identity.entity'; import { LoggerModule } from '../logger/logger.module'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { RealtimeNoteModule } from '../realtime/realtime-note/realtime-note.module'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; @@ -194,7 +194,7 @@ describe('NotesService', () => { .useValue(aliasRepo) .overrideProvider(getRepositoryToken(User)) .useValue(userRepo) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/permissions/permissions.service.spec.ts b/backend/src/permissions/permissions.service.spec.ts index 320c97b4f..f1a78e7a6 100644 --- a/backend/src/permissions/permissions.service.spec.ts +++ b/backend/src/permissions/permissions.service.spec.ts @@ -10,7 +10,6 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Mock } from 'ts-mockery'; import { DataSource, EntityManager, Repository } from 'typeorm'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import { DefaultAccessLevel } from '../config/default-access-level.enum'; import { GuestAccess } from '../config/guest_access.enum'; @@ -38,6 +37,7 @@ import { import { Note } from '../notes/note.entity'; import { NotesModule } from '../notes/notes.module'; import { Tag } from '../notes/tag.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { Edit } from '../revisions/edit.entity'; import { Revision } from '../revisions/revision.entity'; import { Session } from '../sessions/session.entity'; @@ -162,7 +162,7 @@ describe('PermissionsService', () => { }) .overrideProvider(getRepositoryToken(User)) .useValue(userRepo) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/auth/mock-auth.guard.ts b/backend/src/public-auth-token/mock-public-auth-token-guard.service.ts similarity index 96% rename from backend/src/auth/mock-auth.guard.ts rename to backend/src/public-auth-token/mock-public-auth-token-guard.service.ts index 289ebc5b5..4834e7ac4 100644 --- a/backend/src/auth/mock-auth.guard.ts +++ b/backend/src/public-auth-token/mock-public-auth-token-guard.service.ts @@ -10,7 +10,7 @@ import { User } from '../users/user.entity'; import { UsersService } from '../users/users.service'; @Injectable() -export class MockAuthGuard { +export class MockPublicAuthTokenGuard { private user: User; constructor(private usersService: UsersService) {} diff --git a/backend/src/auth/auth-token.dto.ts b/backend/src/public-auth-token/public-auth-token.dto.ts similarity index 80% rename from backend/src/auth/auth-token.dto.ts rename to backend/src/public-auth-token/public-auth-token.dto.ts index d86d31ad6..c55b64bb6 100644 --- a/backend/src/auth/auth-token.dto.ts +++ b/backend/src/public-auth-token/public-auth-token.dto.ts @@ -9,7 +9,7 @@ import { IsDate, IsNumber, IsOptional, IsString } from 'class-validator'; import { BaseDto } from '../utils/base.dto.'; import { TimestampMillis } from '../utils/timestamp'; -export class AuthTokenDto extends BaseDto { +export class PublicAuthTokenDto extends BaseDto { @IsString() label: string; @@ -30,12 +30,12 @@ export class AuthTokenDto extends BaseDto { lastUsedAt: Date | null; } -export class AuthTokenWithSecretDto extends AuthTokenDto { +export class PublicAuthTokenWithSecretDto extends PublicAuthTokenDto { @IsString() secret: string; } -export class AuthTokenCreateDto extends BaseDto { +export class PublicAuthTokenCreateDto extends BaseDto { @IsString() label: string; diff --git a/backend/src/auth/auth-token.entity.ts b/backend/src/public-auth-token/public-auth-token.entity.ts similarity index 68% rename from backend/src/auth/auth-token.entity.ts rename to backend/src/public-auth-token/public-auth-token.entity.ts index bb3207be2..5c662646e 100644 --- a/backend/src/auth/auth-token.entity.ts +++ b/backend/src/public-auth-token/public-auth-token.entity.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -14,15 +14,15 @@ import { import { User } from '../users/user.entity'; @Entity() -export class AuthToken { +export class PublicAuthToken { @PrimaryGeneratedColumn() id: number; @Column({ unique: true }) keyId: string; - @ManyToOne((_) => User, (user) => user.authTokens, { - onDelete: 'CASCADE', // This deletes the AuthToken, when the associated User is deleted + @ManyToOne((_) => User, (user) => user.publicAuthTokens, { + onDelete: 'CASCADE', // This deletes the PublicAuthToken, when the associated User is deleted }) user: Promise; @@ -33,7 +33,7 @@ export class AuthToken { createdAt: Date; @Column({ unique: true }) - accessTokenHash: string; + hash: string; @Column() validUntil: Date; @@ -50,12 +50,12 @@ export class AuthToken { label: string, tokenString: string, validUntil: Date, - ): Omit { - const token = new AuthToken(); + ): Omit { + const token = new PublicAuthToken(); token.keyId = keyId; token.user = Promise.resolve(user); token.label = label; - token.accessTokenHash = tokenString; + token.hash = tokenString; token.validUntil = validUntil; token.lastUsedAt = null; return token; diff --git a/backend/src/public-auth-token/public-auth-token.module.ts b/backend/src/public-auth-token/public-auth-token.module.ts new file mode 100644 index 000000000..15c114906 --- /dev/null +++ b/backend/src/public-auth-token/public-auth-token.module.ts @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ +import { Module } from '@nestjs/common'; +import { PassportModule } from '@nestjs/passport'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +import { LoggerModule } from '../logger/logger.module'; +import { UsersModule } from '../users/users.module'; +import { MockPublicAuthTokenGuard } from './mock-public-auth-token-guard.service'; +import { PublicAuthToken } from './public-auth-token.entity'; +import { PublicAuthTokenService } from './public-auth-token.service'; +import { + PublicAuthTokenGuard, + PublicAuthTokenStrategy, +} from './public-auth-token.strategy'; + +@Module({ + imports: [ + UsersModule, + PassportModule, + LoggerModule, + TypeOrmModule.forFeature([PublicAuthToken]), + ], + providers: [ + PublicAuthTokenService, + PublicAuthTokenStrategy, + MockPublicAuthTokenGuard, + PublicAuthTokenGuard, + ], + exports: [PublicAuthTokenService], +}) +export class PublicAuthTokenModule {} diff --git a/backend/src/auth/auth.service.spec.ts b/backend/src/public-auth-token/public-auth-token.service.spec.ts similarity index 87% rename from backend/src/auth/auth.service.spec.ts rename to backend/src/public-auth-token/public-auth-token.service.spec.ts index 17c9297b6..6dd735137 100644 --- a/backend/src/auth/auth.service.spec.ts +++ b/backend/src/public-auth-token/public-auth-token.service.spec.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -21,23 +21,23 @@ import { LoggerModule } from '../logger/logger.module'; import { Session } from '../sessions/session.entity'; import { User } from '../users/user.entity'; import { UsersModule } from '../users/users.module'; -import { AuthToken } from './auth-token.entity'; -import { AuthService } from './auth.service'; +import { PublicAuthToken } from './public-auth-token.entity'; +import { PublicAuthTokenService } from './public-auth-token.service'; describe('AuthService', () => { - let service: AuthService; + let service: PublicAuthTokenService; let user: User; - let authToken: AuthToken; + let authToken: PublicAuthToken; let userRepo: Repository; - let authTokenRepo: Repository; + let authTokenRepo: Repository; class CreateQueryBuilderClass { leftJoinAndSelect: () => CreateQueryBuilderClass; where: () => CreateQueryBuilderClass; orWhere: () => CreateQueryBuilderClass; setParameter: () => CreateQueryBuilderClass; - getOne: () => AuthToken; - getMany: () => AuthToken[]; + getOne: () => PublicAuthToken; + getMany: () => PublicAuthToken[]; } let createQueryBuilderFunc: CreateQueryBuilderClass; @@ -45,9 +45,9 @@ describe('AuthService', () => { beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ - AuthService, + PublicAuthTokenService, { - provide: getRepositoryToken(AuthToken), + provide: getRepositoryToken(PublicAuthToken), useClass: Repository, }, ], @@ -69,20 +69,20 @@ describe('AuthService', () => { .useValue({}) .compile(); - service = module.get(AuthService); + service = module.get(PublicAuthTokenService); userRepo = module.get>(getRepositoryToken(User)); - authTokenRepo = module.get>( - getRepositoryToken(AuthToken), + authTokenRepo = module.get>( + getRepositoryToken(PublicAuthToken), ); user = User.create('hardcoded', 'Testy') as User; - authToken = AuthToken.create( + authToken = PublicAuthToken.create( 'testKeyId', user, 'testToken', 'abc', new Date(new Date().getTime() + 60000), // make this AuthToken valid for 1min - ) as AuthToken; + ) as PublicAuthToken; const createQueryBuilder = { leftJoinAndSelect: () => createQueryBuilder, @@ -133,13 +133,13 @@ describe('AuthService', () => { jest.spyOn(authTokenRepo, 'findOne').mockResolvedValueOnce({ ...authToken, user: Promise.resolve(user), - accessTokenHash: accessTokenHash, + hash: accessTokenHash, }); const authTokenFromCall = await service.getAuthToken(authToken.keyId); expect(authTokenFromCall).toEqual({ ...authToken, user: Promise.resolve(user), - accessTokenHash: accessTokenHash, + hash: accessTokenHash, }); }); describe('fails:', () => { @@ -160,13 +160,13 @@ describe('AuthService', () => { ); expect(() => - service.checkToken(secret, accessToken as AuthToken), + service.checkToken(secret, accessToken as PublicAuthToken), ).not.toThrow(); }); it('AuthToken has wrong hash', () => { const [accessToken] = service.createToken(user, 'TestToken', undefined); expect(() => - service.checkToken('secret', accessToken as AuthToken), + service.checkToken('secret', accessToken as PublicAuthToken), ).toThrow(TokenNotValidError); }); it('AuthToken has wrong validUntil Date', () => { @@ -176,7 +176,7 @@ describe('AuthService', () => { 1549312452000, ); expect(() => - service.checkToken(secret, accessToken as AuthToken), + service.checkToken(secret, accessToken as PublicAuthToken), ).toThrow(TokenNotValidError); }); }); @@ -191,7 +191,7 @@ describe('AuthService', () => { jest .spyOn(authTokenRepo, 'save') .mockImplementationOnce( - async (authTokenSaved, _): Promise => { + async (authTokenSaved, _): Promise => { expect(authTokenSaved.keyId).toEqual(authToken.keyId); expect(authTokenSaved.lastUsedAt).not.toEqual(1549312452000); return authToken; @@ -217,16 +217,16 @@ describe('AuthService', () => { .digest('hex'); jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce({ ...user, - authTokens: Promise.resolve([authToken]), + publicAuthTokens: Promise.resolve([authToken]), }); jest.spyOn(authTokenRepo, 'findOne').mockResolvedValue({ ...authToken, user: Promise.resolve(user), - accessTokenHash: accessTokenHash, + hash: accessTokenHash, }); jest .spyOn(authTokenRepo, 'save') - .mockImplementationOnce(async (_, __): Promise => { + .mockImplementationOnce(async (_, __): Promise => { return authToken; }); const userByToken = await service.validateToken( @@ -234,7 +234,7 @@ describe('AuthService', () => { ); expect(userByToken).toEqual({ ...user, - authTokens: Promise.resolve([authToken]), + publicAuthTokens: Promise.resolve([authToken]), }); }); describe('fails:', () => { @@ -276,7 +276,7 @@ describe('AuthService', () => { }); jest .spyOn(authTokenRepo, 'remove') - .mockImplementationOnce(async (token, __): Promise => { + .mockImplementationOnce(async (token, __): Promise => { expect(token).toEqual({ ...authToken, user: Promise.resolve(user), @@ -301,7 +301,10 @@ describe('AuthService', () => { jest .spyOn(authTokenRepo, 'save') .mockImplementationOnce( - async (authTokenSaved: AuthToken, _): Promise => { + async ( + authTokenSaved: PublicAuthToken, + _, + ): Promise => { expect(authTokenSaved.lastUsedAt).toBeNull(); return authTokenSaved; }, @@ -320,7 +323,10 @@ describe('AuthService', () => { jest .spyOn(authTokenRepo, 'save') .mockImplementationOnce( - async (authTokenSaved: AuthToken, _): Promise => { + async ( + authTokenSaved: PublicAuthToken, + _, + ): Promise => { expect(authTokenSaved.lastUsedAt).toBeNull(); return authTokenSaved; }, @@ -335,7 +341,7 @@ describe('AuthService', () => { it('should throw TooManyTokensError when number of tokens >= 200', async () => { jest .spyOn(authTokenRepo, 'find') - .mockImplementationOnce(async (): Promise => { + .mockImplementationOnce(async (): Promise => { const inValidToken = [authToken]; inValidToken.length = 201; return inValidToken; @@ -361,7 +367,7 @@ describe('AuthService', () => { .mockResolvedValueOnce([expiredToken, authToken]); jest .spyOn(authTokenRepo, 'remove') - .mockImplementationOnce(async (token): Promise => { + .mockImplementationOnce(async (token): Promise => { expect(token).toEqual(expiredToken); expect(token).not.toBe(authToken); return authToken; @@ -388,7 +394,7 @@ describe('AuthService', () => { }); describe('toAuthTokenDto', () => { - const authToken = new AuthToken(); + const authToken = new PublicAuthToken(); authToken.keyId = 'testKeyId'; authToken.label = 'testLabel'; const date = new Date(); diff --git a/backend/src/auth/auth.service.ts b/backend/src/public-auth-token/public-auth-token.service.ts similarity index 78% rename from backend/src/auth/auth.service.ts rename to backend/src/public-auth-token/public-auth-token.service.ts index 135ee116e..10790aeb8 100644 --- a/backend/src/auth/auth.service.ts +++ b/backend/src/public-auth-token/public-auth-token.service.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -18,19 +18,22 @@ import { ConsoleLoggerService } from '../logger/console-logger.service'; import { User } from '../users/user.entity'; import { bufferToBase64Url } from '../utils/password'; import { TimestampMillis } from '../utils/timestamp'; -import { AuthTokenDto, AuthTokenWithSecretDto } from './auth-token.dto'; -import { AuthToken } from './auth-token.entity'; +import { + PublicAuthTokenDto, + PublicAuthTokenWithSecretDto, +} from './public-auth-token.dto'; +import { PublicAuthToken } from './public-auth-token.entity'; export const AUTH_TOKEN_PREFIX = 'hd2'; @Injectable() -export class AuthService { +export class PublicAuthTokenService { constructor( private readonly logger: ConsoleLoggerService, - @InjectRepository(AuthToken) - private authTokenRepository: Repository, + @InjectRepository(PublicAuthToken) + private authTokenRepository: Repository, ) { - this.logger.setContext(AuthService.name); + this.logger.setContext(PublicAuthTokenService.name); } async validateToken(tokenString: string): Promise { @@ -54,8 +57,8 @@ export class AuthService { createToken( user: User, identifier: string, - validUntil: TimestampMillis | undefined, - ): [Omit, string] { + userDefinedValidUntil: TimestampMillis | undefined, + ): [Omit, string] { const secret = bufferToBase64Url(randomBytes(64)); const keyId = bufferToBase64Url(randomBytes(8)); // More about the choice of SHA-512 in the dev docs @@ -63,27 +66,23 @@ export class AuthService { .createHash('sha512') .update(secret) .digest('hex'); - let token; // Tokens can only be valid for a maximum of 2 years const maximumTokenValidity = new Date().getTime() + 2 * 365 * 24 * 60 * 60 * 1000; - if (!validUntil || validUntil === 0 || validUntil > maximumTokenValidity) { - token = AuthToken.create( - keyId, - user, - identifier, - accessTokenHash, - new Date(maximumTokenValidity), - ); - } else { - token = AuthToken.create( - keyId, - user, - identifier, - accessTokenHash, - new Date(validUntil), - ); - } + const isTokenLimitedToMaximumValidity = + !userDefinedValidUntil || + userDefinedValidUntil === 0 || + userDefinedValidUntil > maximumTokenValidity; + const validUntil = isTokenLimitedToMaximumValidity + ? maximumTokenValidity + : userDefinedValidUntil; + const token = PublicAuthToken.create( + keyId, + user, + identifier, + accessTokenHash, + new Date(validUntil), + ); return [token, secret]; } @@ -91,10 +90,10 @@ export class AuthService { user: User, identifier: string, validUntil: TimestampMillis | undefined, - ): Promise { - user.authTokens = this.getTokensByUser(user); + ): Promise { + user.publicAuthTokens = this.getTokensByUser(user); - if ((await user.authTokens).length >= 200) { + if ((await user.publicAuthTokens).length >= 200) { // This is a very high ceiling unlikely to hinder legitimate usage, // but should prevent possible attack vectors throw new TooManyTokensError( @@ -104,7 +103,7 @@ export class AuthService { const [token, secret] = this.createToken(user, identifier, validUntil); const createdToken = (await this.authTokenRepository.save( token, - )) as AuthToken; + )) as PublicAuthToken; return this.toAuthTokenWithSecretDto( createdToken, `${AUTH_TOKEN_PREFIX}.${createdToken.keyId}.${secret}`, @@ -122,7 +121,7 @@ export class AuthService { await this.authTokenRepository.save(token); } - async getAuthToken(keyId: string): Promise { + async getAuthToken(keyId: string): Promise { const token = await this.authTokenRepository.findOne({ where: { keyId: keyId }, relations: ['user'], @@ -133,11 +132,11 @@ export class AuthService { return token; } - checkToken(secret: string, token: AuthToken): void { + checkToken(secret: string, token: PublicAuthToken): void { const userHash = Buffer.from( crypto.createHash('sha512').update(secret).digest('hex'), ); - const dbHash = Buffer.from(token.accessTokenHash); + const dbHash = Buffer.from(token.hash); if ( // Normally, both hashes have the same length, as they are both SHA512 // This is only defense-in-depth, as timingSafeEqual throws if the buffers are not of the same length @@ -159,7 +158,7 @@ export class AuthService { } } - async getTokensByUser(user: User): Promise { + async getTokensByUser(user: User): Promise { const tokens = await this.authTokenRepository.find({ where: { user: { id: user.id } }, }); @@ -179,8 +178,8 @@ export class AuthService { await this.authTokenRepository.remove(token); } - toAuthTokenDto(authToken: AuthToken): AuthTokenDto { - const tokenDto: AuthTokenDto = { + toAuthTokenDto(authToken: PublicAuthToken): PublicAuthTokenDto { + const tokenDto: PublicAuthTokenDto = { label: authToken.label, keyId: authToken.keyId, createdAt: authToken.createdAt, @@ -196,9 +195,9 @@ export class AuthService { } toAuthTokenWithSecretDto( - authToken: AuthToken, + authToken: PublicAuthToken, secret: string, - ): AuthTokenWithSecretDto { + ): PublicAuthTokenWithSecretDto { const tokenDto = this.toAuthTokenDto(authToken); return { ...tokenDto, @@ -220,7 +219,7 @@ export class AuthService { async removeInvalidTokens(): Promise { const currentTime = new Date().getTime(); - const tokens: AuthToken[] = await this.authTokenRepository.find(); + const tokens: PublicAuthToken[] = await this.authTokenRepository.find(); let removedTokens = 0; for (const token of tokens) { if (token.validUntil && token.validUntil.getTime() <= currentTime) { diff --git a/backend/src/auth/token.strategy.ts b/backend/src/public-auth-token/public-auth-token.strategy.ts similarity index 68% rename from backend/src/auth/token.strategy.ts rename to backend/src/public-auth-token/public-auth-token.strategy.ts index 1a6010eab..36ee05f61 100644 --- a/backend/src/auth/token.strategy.ts +++ b/backend/src/public-auth-token/public-auth-token.strategy.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * SPDX-FileCopyrightText: 2024 The HedgeDoc developers (see AUTHORS file) * * SPDX-License-Identifier: AGPL-3.0-only */ @@ -9,14 +9,17 @@ import { Strategy } from 'passport-http-bearer'; import { NotInDBError, TokenNotValidError } from '../errors/errors'; import { User } from '../users/user.entity'; -import { AuthService } from './auth.service'; +import { PublicAuthTokenService } from './public-auth-token.service'; @Injectable() -export class TokenAuthGuard extends AuthGuard('token') {} +export class PublicAuthTokenGuard extends AuthGuard('token') {} @Injectable() -export class TokenStrategy extends PassportStrategy(Strategy, 'token') { - constructor(private authService: AuthService) { +export class PublicAuthTokenStrategy extends PassportStrategy( + Strategy, + 'token', +) { + constructor(private authService: PublicAuthTokenService) { super(); } diff --git a/backend/src/realtime/websocket/websocket.gateway.spec.ts b/backend/src/realtime/websocket/websocket.gateway.spec.ts index 16ff225da..df5e6f795 100644 --- a/backend/src/realtime/websocket/websocket.gateway.spec.ts +++ b/backend/src/realtime/websocket/websocket.gateway.spec.ts @@ -13,7 +13,6 @@ import { Mock } from 'ts-mockery'; import { Repository } from 'typeorm'; import WebSocket from 'ws'; -import { AuthToken } from '../../auth/auth-token.entity'; import { Author } from '../../authors/author.entity'; import appConfigMock from '../../config/mock/app.config.mock'; import authConfigMock from '../../config/mock/auth.config.mock'; @@ -33,6 +32,7 @@ import { NotePermission } from '../../permissions/note-permission.enum'; import { NoteUserPermission } from '../../permissions/note-user-permission.entity'; import { PermissionsModule } from '../../permissions/permissions.module'; import { PermissionsService } from '../../permissions/permissions.service'; +import { PublicAuthToken } from '../../public-auth-token/public-auth-token.entity'; import { Edit } from '../../revisions/edit.entity'; import { Revision } from '../../revisions/revision.entity'; import { Session } from '../../sessions/session.entity'; @@ -122,7 +122,7 @@ describe('Websocket gateway', () => { }) .overrideProvider(getRepositoryToken(User)) .useClass(Repository) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/revisions/revisions.service.spec.ts b/backend/src/revisions/revisions.service.spec.ts index 4bd588b56..2bc460ada 100644 --- a/backend/src/revisions/revisions.service.spec.ts +++ b/backend/src/revisions/revisions.service.spec.ts @@ -10,7 +10,6 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { Mock } from 'ts-mockery'; import { Repository } from 'typeorm'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import appConfigMock from '../config/mock/app.config.mock'; import authConfigMock from '../config/mock/auth.config.mock'; @@ -27,6 +26,7 @@ import { NotesModule } from '../notes/notes.module'; import { Tag } from '../notes/tag.entity'; import { NoteGroupPermission } from '../permissions/note-group-permission.entity'; import { NoteUserPermission } from '../permissions/note-user-permission.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { Session } from '../sessions/session.entity'; import { User } from '../users/user.entity'; import { Edit } from './edit.entity'; @@ -67,7 +67,7 @@ describe('RevisionsService', () => { .useValue({}) .overrideProvider(getRepositoryToken(User)) .useValue({}) - .overrideProvider(getRepositoryToken(AuthToken)) + .overrideProvider(getRepositoryToken(PublicAuthToken)) .useValue({}) .overrideProvider(getRepositoryToken(Identity)) .useValue({}) diff --git a/backend/src/seed.ts b/backend/src/seed.ts index 956599450..e6b21b0a3 100644 --- a/backend/src/seed.ts +++ b/backend/src/seed.ts @@ -5,7 +5,6 @@ */ import { DataSource } from 'typeorm'; -import { AuthToken } from './auth/auth-token.entity'; import { Author } from './authors/author.entity'; import { Group } from './groups/group.entity'; import { HistoryEntry } from './history/history-entry.entity'; @@ -17,6 +16,7 @@ import { Note } from './notes/note.entity'; import { Tag } from './notes/tag.entity'; import { NoteGroupPermission } from './permissions/note-group-permission.entity'; import { NoteUserPermission } from './permissions/note-user-permission.entity'; +import { PublicAuthToken } from './public-auth-token/public-auth-token.entity'; import { Edit } from './revisions/edit.entity'; import { Revision } from './revisions/revision.entity'; import { Session } from './sessions/session.entity'; @@ -40,7 +40,7 @@ const dataSource = new DataSource({ HistoryEntry, MediaUpload, Tag, - AuthToken, + PublicAuthToken, Identity, Author, Session, diff --git a/backend/src/users/user.entity.ts b/backend/src/users/user.entity.ts index 85a2d15c3..25567b547 100644 --- a/backend/src/users/user.entity.ts +++ b/backend/src/users/user.entity.ts @@ -13,13 +13,13 @@ import { UpdateDateColumn, } from 'typeorm'; -import { AuthToken } from '../auth/auth-token.entity'; import { Author } from '../authors/author.entity'; import { Group } from '../groups/group.entity'; import { HistoryEntry } from '../history/history-entry.entity'; import { Identity } from '../identity/identity.entity'; import { MediaUpload } from '../media/media-upload.entity'; import { Note } from '../notes/note.entity'; +import { PublicAuthToken } from '../public-auth-token/public-auth-token.entity'; import { Username } from '../utils/username'; @Entity() @@ -56,8 +56,8 @@ export class User { @OneToMany((_) => Note, (note) => note.owner) ownedNotes: Promise; - @OneToMany((_) => AuthToken, (authToken) => authToken.user) - authTokens: Promise; + @OneToMany((_) => PublicAuthToken, (authToken) => authToken.user) + publicAuthTokens: Promise; @OneToMany((_) => Identity, (identity) => identity.user) identities: Promise; @@ -87,7 +87,7 @@ export class User { newUser.photo = null; newUser.email = null; newUser.ownedNotes = Promise.resolve([]); - newUser.authTokens = Promise.resolve([]); + newUser.publicAuthTokens = Promise.resolve([]); newUser.identities = Promise.resolve([]); newUser.groups = Promise.resolve([]); newUser.historyEntries = Promise.resolve([]); diff --git a/backend/test/test-setup.ts b/backend/test/test-setup.ts index adabfbcfd..d97e9c183 100644 --- a/backend/test/test-setup.ts +++ b/backend/test/test-setup.ts @@ -14,11 +14,6 @@ import { Connection, createConnection } from 'typeorm'; import { PrivateApiModule } from '../src/api/private/private-api.module'; import { PublicApiModule } from '../src/api/public/public-api.module'; import { setupApp } from '../src/app-init'; -import { AuthTokenWithSecretDto } from '../src/auth/auth-token.dto'; -import { AuthModule } from '../src/auth/auth.module'; -import { AuthService } from '../src/auth/auth.service'; -import { MockAuthGuard } from '../src/auth/mock-auth.guard'; -import { TokenAuthGuard } from '../src/auth/token.strategy'; import { AuthorsModule } from '../src/authors/authors.module'; import { AppConfig } from '../src/config/app.config'; import { AuthConfig } from '../src/config/auth.config'; @@ -75,6 +70,11 @@ import { NotesModule } from '../src/notes/notes.module'; import { NotesService } from '../src/notes/notes.service'; import { PermissionsModule } from '../src/permissions/permissions.module'; import { PermissionsService } from '../src/permissions/permissions.service'; +import { MockPublicAuthTokenGuard } from '../src/public-auth-token/mock-public-auth-token-guard.service'; +import { PublicAuthTokenWithSecretDto } from '../src/public-auth-token/public-auth-token.dto'; +import { PublicAuthTokenModule } from '../src/public-auth-token/public-auth-token.module'; +import { PublicAuthTokenService } from '../src/public-auth-token/public-auth-token.service'; +import { PublicAuthTokenGuard } from '../src/public-auth-token/public-auth-token.strategy'; import { RevisionsModule } from '../src/revisions/revisions.module'; import { RevisionsService } from '../src/revisions/revisions.service'; import { SessionModule } from '../src/sessions/session.module'; @@ -105,12 +105,12 @@ export class TestSetup { mediaService: MediaService; historyService: HistoryService; aliasService: AliasService; - authService: AuthService; + publicAuthTokenService: PublicAuthTokenService; sessionService: SessionService; revisionsService: RevisionsService; users: User[] = []; - authTokens: AuthTokenWithSecretDto[] = []; + authTokens: PublicAuthTokenWithSecretDto[] = []; anonymousNotes: Note[] = []; ownedNotes: Note[] = []; permissionsService: PermissionsService; @@ -288,7 +288,7 @@ export class TestSetupBuilder { GroupsModule, LoggerModule, MediaModule, - AuthModule, + PublicAuthTokenModule, FrontendConfigModule, IdentityModule, SessionModule, @@ -332,8 +332,10 @@ export class TestSetupBuilder { this.testSetup.moduleRef.get(HistoryService); this.testSetup.aliasService = this.testSetup.moduleRef.get(AliasService); - this.testSetup.authService = - this.testSetup.moduleRef.get(AuthService); + this.testSetup.publicAuthTokenService = + this.testSetup.moduleRef.get( + PublicAuthTokenService, + ); this.testSetup.permissionsService = this.testSetup.moduleRef.get(PermissionsService); this.testSetup.sessionService = @@ -363,8 +365,8 @@ export class TestSetupBuilder { public withMockAuth() { this.setupPreCompile.push(async () => { this.testingModuleBuilder - .overrideGuard(TokenAuthGuard) - .useClass(MockAuthGuard); + .overrideGuard(PublicAuthTokenGuard) + .useClass(MockPublicAuthTokenGuard); return await Promise.resolve(); }); return this; @@ -403,7 +405,7 @@ export class TestSetupBuilder { // create auth tokens this.testSetup.authTokens = await Promise.all( this.testSetup.users.map(async (user) => { - return await this.testSetup.authService.addToken( + return await this.testSetup.publicAuthTokenService.addToken( user, 'test', new Date().getTime() + 60 * 60 * 1000,