From b896f954b92f8ed18e51431cca412438917a7a25 Mon Sep 17 00:00:00 2001 From: Philip Molares Date: Sat, 25 Sep 2021 11:50:28 +0200 Subject: [PATCH] feat: consolidate entities create This was done to give better typings to the function signatures of entities `create` methods. It also ensures that each field that should be set to `null` is set to `null` and doesn't leave that up to the typeorm handlers. See: #1641 Signed-off-by: Philip Molares --- src/auth/auth-token.entity.ts | 10 +++----- src/authors/author.entity.ts | 4 +--- src/groups/group.entity.ts | 5 ++-- src/history/history-entry.entity.ts | 20 ++++++++++------ src/identity/identity.entity.ts | 6 ++++- src/media/media-upload.entity.ts | 2 +- src/notes/alias.entity.ts | 3 ++- src/notes/note.entity.ts | 24 +++++++++++++++---- .../note-group-permission.entity.ts | 7 +++++- .../note-user-permission.entity.ts | 7 +++++- src/revisions/edit.entity.ts | 7 +++++- src/revisions/revision.entity.ts | 9 ++++++- src/seed.ts | 11 +++++---- src/users/user.entity.ts | 14 +++++++---- 14 files changed, 89 insertions(+), 40 deletions(-) diff --git a/src/auth/auth-token.entity.ts b/src/auth/auth-token.entity.ts index dc0e66aad..80d9da025 100644 --- a/src/auth/auth-token.entity.ts +++ b/src/auth/auth-token.entity.ts @@ -45,21 +45,17 @@ export class AuthToken { lastUsed: Date | null; public static create( + keyId: string, user: User, label: string, - keyId: string, accessToken: string, validUntil: Date, - ): Pick< - AuthToken, - 'user' | 'label' | 'keyId' | 'accessTokenHash' | 'createdAt' | 'validUntil' - > { + ): Omit { const newToken = new AuthToken(); + newToken.keyId = keyId; newToken.user = user; newToken.label = label; - newToken.keyId = keyId; newToken.accessTokenHash = accessToken; - newToken.createdAt = new Date(); newToken.validUntil = validUntil; newToken.lastUsed = null; return newToken; diff --git a/src/authors/author.entity.ts b/src/authors/author.entity.ts index 94e1cab5f..bc24af958 100644 --- a/src/authors/author.entity.ts +++ b/src/authors/author.entity.ts @@ -58,9 +58,7 @@ export class Author { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - public static create( - color: number, - ): Pick { + public static create(color: number): Omit { const newAuthor = new Author(); newAuthor.color = color; newAuthor.sessions = []; diff --git a/src/groups/group.entity.ts b/src/groups/group.entity.ts index 1a63224c1..083b4fb9e 100644 --- a/src/groups/group.entity.ts +++ b/src/groups/group.entity.ts @@ -43,11 +43,12 @@ export class Group { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - public static create(name: string, displayName: string): Group { + public static create(name: string, displayName: string): Omit { const newGroup = new Group(); - newGroup.special = false; // this attribute should only be true for the two special groups newGroup.name = name; newGroup.displayName = displayName; + newGroup.special = false; // this attribute should only be true for the two special groups + newGroup.members = []; return newGroup; } } diff --git a/src/history/history-entry.entity.ts b/src/history/history-entry.entity.ts index b7ab7b54b..053822312 100644 --- a/src/history/history-entry.entity.ts +++ b/src/history/history-entry.entity.ts @@ -28,15 +28,21 @@ export class HistoryEntry { @UpdateDateColumn() updatedAt: Date; - // The optional note parameter is necessary for the createNote method in the NotesService, - // as we create the note then and don't need to add it to the HistoryEntry. - public static create(user: User, note?: Note): HistoryEntry { + /** + * Create a history entry + * @param user the user the history entry is associated with + * @param note the note the history entry is associated with + * @param [pinStatus=false] if the history entry should be pinned + */ + public static create( + user: User, + note: Note, + pinStatus = false, + ): Omit { const newHistoryEntry = new HistoryEntry(); newHistoryEntry.user = user; - if (note) { - newHistoryEntry.note = note; - } - newHistoryEntry.pinStatus = false; + newHistoryEntry.note = note; + newHistoryEntry.pinStatus = pinStatus; return newHistoryEntry; } } diff --git a/src/identity/identity.entity.ts b/src/identity/identity.entity.ts index bc36e6f10..512070d3b 100644 --- a/src/identity/identity.entity.ts +++ b/src/identity/identity.entity.ts @@ -101,11 +101,15 @@ export class Identity { user: User, providerType: ProviderType, syncSource = false, - ): Identity { + ): Omit { const newIdentity = new Identity(); newIdentity.user = user; newIdentity.providerType = providerType; + newIdentity.providerName = null; newIdentity.syncSource = syncSource; + newIdentity.providerUserId = null; + newIdentity.oAuthAccessToken = null; + newIdentity.passwordHash = null; return newIdentity; } } diff --git a/src/media/media-upload.entity.ts b/src/media/media-upload.entity.ts index 7bc0bbe62..c7259335b 100644 --- a/src/media/media-upload.entity.ts +++ b/src/media/media-upload.entity.ts @@ -59,7 +59,7 @@ export class MediaUpload { extension: string, backendType: BackendType, backendData?: string, - ): MediaUpload { + ): Omit { const upload = new MediaUpload(); const randomBytes = crypto.randomBytes(16); upload.id = randomBytes.toString('hex') + '.' + extension; diff --git a/src/notes/alias.entity.ts b/src/notes/alias.entity.ts index eb7e746ce..0be2a7d89 100644 --- a/src/notes/alias.entity.ts +++ b/src/notes/alias.entity.ts @@ -54,10 +54,11 @@ export class Alias { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - static create(name: string, primary = false): Alias { + static create(name: string, note: Note, primary = false): Omit { const alias = new Alias(); alias.name = name; alias.primary = primary; + alias.note = note; return alias; } } diff --git a/src/notes/note.entity.ts b/src/notes/note.entity.ts index 23c964e78..505db302f 100644 --- a/src/notes/note.entity.ts +++ b/src/notes/note.entity.ts @@ -27,40 +27,49 @@ import { generatePublicId } from './utils'; export class Note { @PrimaryGeneratedColumn('uuid') id: string; + @Column({ type: 'text' }) publicId: string; + @OneToMany( (_) => Alias, (alias) => alias.note, { cascade: true }, // This ensures that embedded Aliases are automatically saved to the database ) aliases: Alias[]; + @OneToMany( (_) => NoteGroupPermission, (groupPermission) => groupPermission.note, { cascade: true }, // This ensures that embedded NoteGroupPermissions are automatically saved to the database ) groupPermissions: NoteGroupPermission[]; + @OneToMany( (_) => NoteUserPermission, (userPermission) => userPermission.note, { cascade: true }, // This ensures that embedded NoteUserPermission are automatically saved to the database ) userPermissions: NoteUserPermission[]; + @Column({ nullable: false, default: 0, }) viewCount: number; + @ManyToOne((_) => User, (user) => user.ownedNotes, { onDelete: 'CASCADE', // This deletes the Note, when the associated User is deleted nullable: true, }) owner: User | null; + @OneToMany((_) => Revision, (revision) => revision.note, { cascade: true }) revisions: Promise; + @OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user) historyEntries: HistoryEntry[]; + @OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note) mediaUploads: MediaUpload[]; @@ -69,6 +78,7 @@ export class Note { type: 'text', }) description: string | null; + @Column({ nullable: true, type: 'text', @@ -82,15 +92,19 @@ export class Note { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - public static create(owner?: User, alias?: string): Note { + public static create(owner?: User, alias?: string): Omit { const newNote = new Note(); newNote.publicId = generatePublicId(); - newNote.aliases = alias ? [Alias.create(alias, true)] : []; - newNote.viewCount = 0; - newNote.owner = owner ?? null; + newNote.aliases = alias + ? [Alias.create(alias, newNote, true) as Alias] + : []; newNote.userPermissions = []; newNote.groupPermissions = []; - newNote.revisions = Promise.resolve([]) as Promise; + newNote.viewCount = 0; + newNote.owner = owner ?? null; + newNote.revisions = Promise.resolve([]); + newNote.historyEntries = []; + newNote.mediaUploads = []; newNote.description = null; newNote.title = null; newNote.tags = []; diff --git a/src/permissions/note-group-permission.entity.ts b/src/permissions/note-group-permission.entity.ts index 9fda06d27..2c0eb779b 100644 --- a/src/permissions/note-group-permission.entity.ts +++ b/src/permissions/note-group-permission.entity.ts @@ -28,9 +28,14 @@ export class NoteGroupPermission { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - public static create(group: Group, canEdit: boolean): NoteGroupPermission { + public static create( + group: Group, + note: Note, + canEdit: boolean, + ): NoteGroupPermission { const groupPermission = new NoteGroupPermission(); groupPermission.group = group; + groupPermission.note = note; groupPermission.canEdit = canEdit; return groupPermission; } diff --git a/src/permissions/note-user-permission.entity.ts b/src/permissions/note-user-permission.entity.ts index 6d3a637a5..c0e128f9f 100644 --- a/src/permissions/note-user-permission.entity.ts +++ b/src/permissions/note-user-permission.entity.ts @@ -28,9 +28,14 @@ export class NoteUserPermission { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - public static create(user: User, canEdit: boolean): NoteUserPermission { + public static create( + user: User, + note: Note, + canEdit: boolean, + ): NoteUserPermission { const userPermission = new NoteUserPermission(); userPermission.user = user; + userPermission.note = note; userPermission.canEdit = canEdit; return userPermission; } diff --git a/src/revisions/edit.entity.ts b/src/revisions/edit.entity.ts index 138339923..ac2a188fe 100644 --- a/src/revisions/edit.entity.ts +++ b/src/revisions/edit.entity.ts @@ -51,8 +51,13 @@ export class Edit { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - public static create(author: Author, startPos: number, endPos: number) { + public static create( + author: Author, + startPos: number, + endPos: number, + ): Omit { const newEdit = new Edit(); + newEdit.revisions = []; newEdit.author = author; newEdit.startPos = startPos; newEdit.endPos = endPos; diff --git a/src/revisions/revision.entity.ts b/src/revisions/revision.entity.ts index 3684d0e80..749a6e494 100644 --- a/src/revisions/revision.entity.ts +++ b/src/revisions/revision.entity.ts @@ -59,6 +59,7 @@ export class Revision { */ @ManyToOne((_) => Note, (note) => note.revisions, { onDelete: 'CASCADE' }) note: Note; + /** * All edit objects which are used in the revision. */ @@ -69,11 +70,17 @@ export class Revision { // eslint-disable-next-line @typescript-eslint/no-empty-function private constructor() {} - static create(content: string, patch: string): Revision { + static create( + content: string, + patch: string, + note: Note, + ): Omit { const newRevision = new Revision(); newRevision.patch = patch; newRevision.content = content; newRevision.length = content.length; + newRevision.note = note; + newRevision.edits = []; return newRevision; } } diff --git a/src/seed.ts b/src/seed.ts index 25ea740c1..b66300909 100644 --- a/src/seed.ts +++ b/src/seed.ts @@ -57,9 +57,9 @@ createConnection({ users.push(User.create('hardcoded_2', 'Test User 2')); users.push(User.create('hardcoded_3', 'Test User 3')); const notes: Note[] = []; - notes.push(Note.create(undefined, 'test')); - notes.push(Note.create(undefined, 'test2')); - notes.push(Note.create(undefined, 'test3')); + notes.push(Note.create(undefined, 'test') as Note); + notes.push(Note.create(undefined, 'test2') as Note); + notes.push(Note.create(undefined, 'test3') as Note); for (let i = 0; i < 3; i++) { const author = connection.manager.create(Author, Author.create(1)); @@ -71,8 +71,9 @@ createConnection({ const revision = Revision.create( 'This is a test note', 'This is a test note', - ); - const edit = Edit.create(author, 1, 42); + notes[i], + ) as Revision; + const edit = Edit.create(author, 1, 42) as Edit; revision.edits = [edit]; notes[i].revisions = Promise.all([revision]); notes[i].userPermissions = []; diff --git a/src/users/user.entity.ts b/src/users/user.entity.ts index 54df92695..e965d63fb 100644 --- a/src/users/user.entity.ts +++ b/src/users/user.entity.ts @@ -79,13 +79,19 @@ export class User { public static create( username: string, displayName: string, - ): Pick< - User, - 'username' | 'displayName' | 'ownedNotes' | 'authTokens' | 'identities' - > { + ): Omit { const newUser = new User(); newUser.username = username; newUser.displayName = displayName; + newUser.photo = null; + newUser.email = null; + newUser.ownedNotes = []; + newUser.authTokens = []; + newUser.identities = Promise.resolve([]); + newUser.groups = []; + newUser.historyEntries = []; + newUser.mediaUploads = []; + newUser.authors = []; return newUser; } }