refactor: replace TypeORM with knex.js

Co-authored-by: Philip Molares <philip.molares@udo.edu>
Signed-off-by: Philip Molares <philip.molares@udo.edu>
Signed-off-by: Erik Michelson <github@erik.michelson.eu>
This commit is contained in:
Erik Michelson 2025-03-14 23:33:29 +01:00
parent 6e151c8a1b
commit 4bd49085c6
No known key found for this signature in database
GPG key ID: DB99ADDDC5C0AF82
241 changed files with 4577 additions and 6636 deletions

View file

@ -6,8 +6,9 @@
import { AliasCreateDto, AliasUpdateDto } from '@hedgedoc/commons';
import request from 'supertest';
import { AliasCreateDto } from '../../src/alias/alias-create.dto';
import { AliasUpdateDto } from '../../src/alias/alias-update.dto';
import { User } from '../../src/database/user.entity';
import { Note } from '../../src/notes/note.entity';
import {
password1,
password2,
@ -55,7 +56,7 @@ describe('Alias', () => {
describe('POST /alias', () => {
const testAlias = 'aliasTest';
const newAliasDto: AliasCreateDto = {
noteIdOrAlias: testAlias,
alias: testAlias,
newAlias: '',
};
let publicId = '';
@ -87,7 +88,7 @@ describe('Alias', () => {
primaryAlias: false,
noteId: publicId,
});
expect(note.body.metadata.primaryAddress).toEqual(testAlias);
expect(note.body.metadata.primaryAlias).toEqual(testAlias);
expect(note.body.metadata.id).toEqual(publicId);
});
@ -158,7 +159,7 @@ describe('Alias', () => {
primaryAlias: true,
noteId: publicId,
});
expect(note.body.metadata.primaryAddress).toEqual(newAlias);
expect(note.body.metadata.primaryAlias).toEqual(newAlias);
expect(note.body.metadata.id).toEqual(publicId);
});

View file

@ -53,9 +53,10 @@ describe('Auth', () => {
.set('Content-Type', 'application/json')
.send(JSON.stringify(registrationDto))
.expect(201);
const newUser = await testSetup.userService.getUserByUsername(username, [
UserRelationEnum.IDENTITIES,
]);
const newUser = await testSetup.userService.getUserDtoByUsername(
username,
[UserRelationEnum.IDENTITIES],
);
expect(newUser.displayName).toEqual(displayName);
await expect(newUser.identities).resolves.toHaveLength(1);
await expect(
@ -115,7 +116,7 @@ describe('Auth', () => {
.expect(400);
expect(response.text).toContain('PasswordTooWeakError');
await expect(() =>
testSetup.userService.getUserByUsername(username, [
testSetup.userService.getUserDtoByUsername(username, [
UserRelationEnum.IDENTITIES,
]),
).rejects.toThrow(NotInDBError);

View file

@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { GuestAccess, LoginDto } from '@hedgedoc/commons';
import { LoginDto, PermissionLevel } from '@hedgedoc/commons';
import request from 'supertest';
import { createDefaultMockNoteConfig } from '../../src/config/mock/note.config.mock';
@ -66,7 +66,7 @@ describe('Groups', () => {
describe('API requires authentication', () => {
beforeAll(() => {
noteConfigMock.guestAccess = GuestAccess.DENY;
noteConfigMock.guestAccess = PermissionLevel.DENY;
});
test('get group', async () => {
const response = await request(testSetup.app.getHttpServer()).get(

View file

@ -11,7 +11,7 @@ import { HistoryEntryImportDto } from '../../src/history/history-entry-import.dt
import { HistoryEntry } from '../../src/history/history-entry.entity';
import { HistoryService } from '../../src/history/history.service';
import { Note } from '../../src/notes/note.entity';
import { NotesService } from '../../src/notes/notes.service';
import { NoteService } from '../../src/notes/note.service';
import { UsersService } from '../../src/users/users.service';
import { TestSetup, TestSetupBuilder } from '../test-setup';
@ -43,7 +43,7 @@ describe('History', () => {
localIdentityService = moduleRef.get(LocalService);
user = await userService.createUser(username, 'Testy', null, null);
await localIdentityService.createLocalIdentity(user, password);
const notesService = moduleRef.get(NotesService);
const notesService = moduleRef.get(NoteService);
note = await notesService.createNote(content, user, 'note');
note2 = await notesService.createNote(content, user, 'note2');
agent = request.agent(testSetup.app.getHttpServer());

View file

@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { LoginUserInfoDto, ProviderType } from '@hedgedoc/commons';
import { AuthProviderType, LoginUserInfoDto } from '@hedgedoc/commons';
import { promises as fs } from 'fs';
import request from 'supertest';
@ -58,7 +58,7 @@ describe('Me', () => {
it('GET /me', async () => {
const userInfo = testSetup.userService.toLoginUserInfoDto(
user,
ProviderType.LOCAL,
AuthProviderType.LOCAL,
);
const response = await agent
.get('/api/private/me')
@ -127,7 +127,8 @@ describe('Me', () => {
expect(imageIds).toContain(response.body[1].uuid);
expect(imageIds).toContain(response.body[2].uuid);
expect(imageIds).toContain(response.body[3].uuid);
const mediaUploads = await testSetup.mediaService.listUploadsByUser(user);
const mediaUploads =
await testSetup.mediaService.getMediaUploadUuidsByUserId(user);
for (const upload of mediaUploads) {
await testSetup.mediaService.deleteFile(upload);
}
@ -143,7 +144,8 @@ describe('Me', () => {
displayName: newDisplayName,
})
.expect(200);
const dbUser = await testSetup.userService.getUserByUsername('hardcoded');
const dbUser =
await testSetup.userService.getUserDtoByUsername('hardcoded');
expect(dbUser.displayName).toEqual(newDisplayName);
});
@ -155,17 +157,19 @@ describe('Me', () => {
user,
note1,
);
const dbUser = await testSetup.userService.getUserByUsername('hardcoded');
const dbUser =
await testSetup.userService.getUserDtoByUsername('hardcoded');
expect(dbUser).toBeInstanceOf(User);
const mediaUploads = await testSetup.mediaService.listUploadsByUser(dbUser);
const mediaUploads =
await testSetup.mediaService.getMediaUploadUuidsByUserId(dbUser);
expect(mediaUploads).toHaveLength(1);
expect(mediaUploads[0].uuid).toEqual(upload.uuid);
await agent.delete('/api/private/me').expect(204);
await expect(
testSetup.userService.getUserByUsername('hardcoded'),
testSetup.userService.getUserDtoByUsername('hardcoded'),
).rejects.toThrow(NotInDBError);
const mediaUploadsAfter =
await testSetup.mediaService.listUploadsByNote(note1);
await testSetup.mediaService.getMediaUploadUuidsByNoteId(note1);
expect(mediaUploadsAfter).toHaveLength(0);
});
});

View file

@ -187,7 +187,7 @@ describe('Media', () => {
// upload a file with the default test user
const testNote = await testSetup.notesService.createNote(
'test content',
await testSetup.userService.getUserByUsername(username2),
await testSetup.userService.getUserDtoByUsername(username2),
'test_delete_media_note',
);
const testImage = await fs.readFile('test/private-api/fixtures/test.png');

View file

@ -81,7 +81,7 @@ describe('Notes', () => {
expect(response.body.metadata?.id).toBeDefined();
expect(
await testSetup.notesService.getNoteContent(
await testSetup.notesService.getNoteByIdOrAlias(
await testSetup.notesService.getNoteIdByAlias(
response.body.metadata.id,
),
),
@ -108,7 +108,7 @@ describe('Notes', () => {
});
describe('POST /notes/{note}', () => {
it('works with a non-existing alias', async () => {
it('works with a non-existing aliases', async () => {
const response = await agent
.post('/api/private/notes/test2')
.set('Content-Type', 'text/markdown')
@ -118,14 +118,14 @@ describe('Notes', () => {
expect(response.body.metadata?.id).toBeDefined();
return expect(
await testSetup.notesService.getNoteContent(
await testSetup.notesService.getNoteByIdOrAlias(
await testSetup.notesService.getNoteIdByAlias(
response.body.metadata?.id,
),
),
).toEqual(content);
});
it('fails with a forbidden alias', async () => {
it('fails with a forbidden aliases', async () => {
await agent
.post(`/api/private/notes/${forbiddenNoteId}`)
.set('Content-Type', 'text/markdown')
@ -134,7 +134,7 @@ describe('Notes', () => {
.expect(400);
});
it('fails with a existing alias', async () => {
it('fails with a existing aliases', async () => {
await agent
.post('/api/private/notes/test2')
.set('Content-Type', 'text/markdown')
@ -156,7 +156,7 @@ describe('Notes', () => {
.expect(413);
});
it('cannot create an alias equal to a note publicId', async () => {
it('cannot create an aliases equal to a note publicId', async () => {
await agent
.post(`/api/private/notes/${testSetup.anonymousNotes[0].publicId}`)
.set('Content-Type', 'text/markdown')
@ -168,7 +168,7 @@ describe('Notes', () => {
describe('DELETE /notes/{note}', () => {
describe('works', () => {
it('with an existing alias and keepMedia false', async () => {
it('with an existing aliases and keepMedia false', async () => {
const noteId = 'test3';
const note = await testSetup.notesService.createNote(
content,
@ -189,16 +189,16 @@ describe('Notes', () => {
})
.expect(204);
await expect(
testSetup.notesService.getNoteByIdOrAlias(noteId),
testSetup.notesService.getNoteIdByAlias(noteId),
).rejects.toEqual(
new NotInDBError(`Note with id/alias '${noteId}' not found.`),
);
expect(
await testSetup.mediaService.listUploadsByUser(user1),
await testSetup.mediaService.getMediaUploadUuidsByUserId(user1),
).toHaveLength(0);
await fs.rmdir(uploadPath);
});
it('with an existing alias and keepMedia true', async () => {
it('with an existing aliases and keepMedia true', async () => {
const noteId = 'test3a';
const note = await testSetup.notesService.createNote(
content,
@ -219,22 +219,22 @@ describe('Notes', () => {
})
.expect(204);
await expect(
testSetup.notesService.getNoteByIdOrAlias(noteId),
testSetup.notesService.getNoteIdByAlias(noteId),
).rejects.toEqual(
new NotInDBError(`Note with id/alias '${noteId}' not found.`),
);
expect(
await testSetup.mediaService.listUploadsByUser(user1),
await testSetup.mediaService.getMediaUploadUuidsByUserId(user1),
).toHaveLength(1);
// delete the file afterwards
await fs.unlink(join(uploadPath, upload.uuid + '.png'));
await fs.rmdir(uploadPath);
});
});
it('fails with a forbidden alias', async () => {
it('fails with a forbidden aliases', async () => {
await agent.delete(`/api/private/notes/${forbiddenNoteId}`).expect(400);
});
it('fails with a non-existing alias', async () => {
it('fails with a non-existing aliases', async () => {
await agent.delete('/api/private/notes/i_dont_exist').expect(404);
});
});
@ -249,7 +249,7 @@ describe('Notes', () => {
.expect(200);
expect(typeof metadata.body.id).toEqual('string');
expect(metadata.body.aliases[0].name).toEqual(noteAlias);
expect(metadata.body.primaryAddress).toEqual(noteAlias);
expect(metadata.body.primaryAlias).toEqual(noteAlias);
expect(metadata.body.title).toEqual('');
expect(metadata.body.description).toEqual('');
expect(typeof metadata.body.createdAt).toEqual('string');
@ -259,19 +259,19 @@ describe('Notes', () => {
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
expect(metadata.body.tags).toEqual([]);
expect(typeof metadata.body.updatedAt).toEqual('string');
expect(typeof metadata.body.updateUsername).toEqual('string');
expect(typeof metadata.body.lastUpdatedBy).toEqual('string');
expect(typeof metadata.body.viewCount).toEqual('number');
expect(metadata.body.editedBy).toEqual([]);
});
it('fails with a forbidden alias', async () => {
it('fails with a forbidden aliases', async () => {
await agent
.get(`/api/private/notes/${forbiddenNoteId}/metadata`)
.expect('Content-Type', /json/)
.expect(400);
});
it('fails with non-existing alias', async () => {
it('fails with non-existing aliases', async () => {
// check if a missing note correctly returns 404
await agent
.get('/api/private/notes/i_dont_exist/metadata')
@ -305,7 +305,7 @@ describe('Notes', () => {
});
describe('GET /notes/{note}/revisions', () => {
it('works with existing alias', async () => {
it('works with existing aliases', async () => {
await testSetup.notesService.createNote(content, user1, 'test4');
// create a second note to check for a regression, where typeorm always returned
// all revisions in the database
@ -317,13 +317,13 @@ describe('Notes', () => {
expect(response.body).toHaveLength(1);
});
it('fails with a forbidden alias', async () => {
it('fails with a forbidden aliases', async () => {
await agent
.get(`/api/private/notes/${forbiddenNoteId}/revisions`)
.expect(400);
});
it('fails with non-existing alias', async () => {
it('fails with non-existing aliases', async () => {
// check if a missing note correctly returns 404
await agent
.get('/api/private/notes/i_dont_exist/revisions')
@ -333,7 +333,7 @@ describe('Notes', () => {
});
describe('DELETE /notes/{note}/revisions', () => {
it('works with an existing alias', async () => {
it('works with an existing aliases', async () => {
const noteId = 'test8';
const note = await testSetup.notesService.createNote(
content,
@ -356,12 +356,12 @@ describe('Notes', () => {
.expect(200);
expect(responseAfterDeleting.body).toHaveLength(1);
});
it('fails with a forbidden alias', async () => {
it('fails with a forbidden aliases', async () => {
await agent
.delete(`/api/private/notes/${forbiddenNoteId}/revisions`)
.expect(400);
});
it('fails with non-existing alias', async () => {
it('fails with non-existing aliases', async () => {
// check if a missing note correctly returns 404
await agent
.delete('/api/private/notes/i_dont_exist/revisions')
@ -371,7 +371,7 @@ describe('Notes', () => {
});
describe('GET /notes/{note}/revisions/{revision-id}', () => {
it('works with an existing alias', async () => {
it('works with an existing aliases', async () => {
const note = await testSetup.notesService.createNote(
content,
user1,
@ -384,12 +384,12 @@ describe('Notes', () => {
.expect(200);
expect(response.body.content).toEqual(content);
});
it('fails with a forbidden alias', async () => {
it('fails with a forbidden aliases', async () => {
await agent
.get(`/api/private/notes/${forbiddenNoteId}/revisions/1`)
.expect(400);
});
it('fails with non-existing alias', async () => {
it('fails with non-existing aliases', async () => {
// check if a missing note correctly returns 404
await agent
.get('/api/private/notes/i_dont_exist/revisions/1')
@ -459,7 +459,7 @@ describe('Notes', () => {
alias,
);
// Redact default read permissions
const note = await testSetup.notesService.getNoteByIdOrAlias(alias);
const note = await testSetup.notesService.getNoteIdByAlias(alias);
const everyone = await testSetup.groupService.getEveryoneGroup();
const loggedin = await testSetup.groupService.getLoggedInGroup();
await testSetup.permissionsService.removeGroupPermission(note, everyone);
@ -510,7 +510,7 @@ describe('Notes', () => {
it("doesn't do anything if the user is the owner", async () => {
const note =
await testSetup.notesService.getNoteByIdOrAlias(user1NoteAlias);
await testSetup.notesService.getNoteIdByAlias(user1NoteAlias);
await testSetup.permissionsService.removeUserPermission(note, user2);
const response = await agent
@ -557,7 +557,7 @@ describe('Notes', () => {
it('works', async () => {
const note =
await testSetup.notesService.getNoteByIdOrAlias(user1NoteAlias);
await testSetup.notesService.getNoteIdByAlias(user1NoteAlias);
await testSetup.permissionsService.setUserPermission(
note,
user2,
@ -630,7 +630,7 @@ describe('Notes', () => {
it('works', async () => {
const note =
await testSetup.notesService.getNoteByIdOrAlias(user1NoteAlias);
await testSetup.notesService.getNoteIdByAlias(user1NoteAlias);
await testSetup.permissionsService.setGroupPermission(
note,
group1,