mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-26 11:43:59 -05:00
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 <philip.molares@udo.edu>
This commit is contained in:
parent
bb7561b9ad
commit
b896f954b9
14 changed files with 89 additions and 40 deletions
|
@ -45,21 +45,17 @@ export class AuthToken {
|
||||||
lastUsed: Date | null;
|
lastUsed: Date | null;
|
||||||
|
|
||||||
public static create(
|
public static create(
|
||||||
|
keyId: string,
|
||||||
user: User,
|
user: User,
|
||||||
label: string,
|
label: string,
|
||||||
keyId: string,
|
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
validUntil: Date,
|
validUntil: Date,
|
||||||
): Pick<
|
): Omit<AuthToken, 'id' | 'createdAt'> {
|
||||||
AuthToken,
|
|
||||||
'user' | 'label' | 'keyId' | 'accessTokenHash' | 'createdAt' | 'validUntil'
|
|
||||||
> {
|
|
||||||
const newToken = new AuthToken();
|
const newToken = new AuthToken();
|
||||||
|
newToken.keyId = keyId;
|
||||||
newToken.user = user;
|
newToken.user = user;
|
||||||
newToken.label = label;
|
newToken.label = label;
|
||||||
newToken.keyId = keyId;
|
|
||||||
newToken.accessTokenHash = accessToken;
|
newToken.accessTokenHash = accessToken;
|
||||||
newToken.createdAt = new Date();
|
|
||||||
newToken.validUntil = validUntil;
|
newToken.validUntil = validUntil;
|
||||||
newToken.lastUsed = null;
|
newToken.lastUsed = null;
|
||||||
return newToken;
|
return newToken;
|
||||||
|
|
|
@ -58,9 +58,7 @@ export class Author {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(
|
public static create(color: number): Omit<Author, 'id'> {
|
||||||
color: number,
|
|
||||||
): Pick<Author, 'color' | 'sessions' | 'user' | 'edits'> {
|
|
||||||
const newAuthor = new Author();
|
const newAuthor = new Author();
|
||||||
newAuthor.color = color;
|
newAuthor.color = color;
|
||||||
newAuthor.sessions = [];
|
newAuthor.sessions = [];
|
||||||
|
|
|
@ -43,11 +43,12 @@ export class Group {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(name: string, displayName: string): Group {
|
public static create(name: string, displayName: string): Omit<Group, 'id'> {
|
||||||
const newGroup = new Group();
|
const newGroup = new Group();
|
||||||
newGroup.special = false; // this attribute should only be true for the two special groups
|
|
||||||
newGroup.name = name;
|
newGroup.name = name;
|
||||||
newGroup.displayName = displayName;
|
newGroup.displayName = displayName;
|
||||||
|
newGroup.special = false; // this attribute should only be true for the two special groups
|
||||||
|
newGroup.members = [];
|
||||||
return newGroup;
|
return newGroup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,15 +28,21 @@ export class HistoryEntry {
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
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.
|
* Create a history entry
|
||||||
public static create(user: User, note?: Note): HistoryEntry {
|
* @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<HistoryEntry, 'updatedAt'> {
|
||||||
const newHistoryEntry = new HistoryEntry();
|
const newHistoryEntry = new HistoryEntry();
|
||||||
newHistoryEntry.user = user;
|
newHistoryEntry.user = user;
|
||||||
if (note) {
|
newHistoryEntry.note = note;
|
||||||
newHistoryEntry.note = note;
|
newHistoryEntry.pinStatus = pinStatus;
|
||||||
}
|
|
||||||
newHistoryEntry.pinStatus = false;
|
|
||||||
return newHistoryEntry;
|
return newHistoryEntry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,11 +101,15 @@ export class Identity {
|
||||||
user: User,
|
user: User,
|
||||||
providerType: ProviderType,
|
providerType: ProviderType,
|
||||||
syncSource = false,
|
syncSource = false,
|
||||||
): Identity {
|
): Omit<Identity, 'id' | 'createdAt' | 'updatedAt'> {
|
||||||
const newIdentity = new Identity();
|
const newIdentity = new Identity();
|
||||||
newIdentity.user = user;
|
newIdentity.user = user;
|
||||||
newIdentity.providerType = providerType;
|
newIdentity.providerType = providerType;
|
||||||
|
newIdentity.providerName = null;
|
||||||
newIdentity.syncSource = syncSource;
|
newIdentity.syncSource = syncSource;
|
||||||
|
newIdentity.providerUserId = null;
|
||||||
|
newIdentity.oAuthAccessToken = null;
|
||||||
|
newIdentity.passwordHash = null;
|
||||||
return newIdentity;
|
return newIdentity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ export class MediaUpload {
|
||||||
extension: string,
|
extension: string,
|
||||||
backendType: BackendType,
|
backendType: BackendType,
|
||||||
backendData?: string,
|
backendData?: string,
|
||||||
): MediaUpload {
|
): Omit<MediaUpload, 'createdAt'> {
|
||||||
const upload = new MediaUpload();
|
const upload = new MediaUpload();
|
||||||
const randomBytes = crypto.randomBytes(16);
|
const randomBytes = crypto.randomBytes(16);
|
||||||
upload.id = randomBytes.toString('hex') + '.' + extension;
|
upload.id = randomBytes.toString('hex') + '.' + extension;
|
||||||
|
|
|
@ -54,10 +54,11 @@ export class Alias {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
static create(name: string, primary = false): Alias {
|
static create(name: string, note: Note, primary = false): Omit<Alias, 'id'> {
|
||||||
const alias = new Alias();
|
const alias = new Alias();
|
||||||
alias.name = name;
|
alias.name = name;
|
||||||
alias.primary = primary;
|
alias.primary = primary;
|
||||||
|
alias.note = note;
|
||||||
return alias;
|
return alias;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,40 +27,49 @@ import { generatePublicId } from './utils';
|
||||||
export class Note {
|
export class Note {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
@Column({ type: 'text' })
|
@Column({ type: 'text' })
|
||||||
publicId: string;
|
publicId: string;
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
(_) => Alias,
|
(_) => Alias,
|
||||||
(alias) => alias.note,
|
(alias) => alias.note,
|
||||||
{ cascade: true }, // This ensures that embedded Aliases are automatically saved to the database
|
{ cascade: true }, // This ensures that embedded Aliases are automatically saved to the database
|
||||||
)
|
)
|
||||||
aliases: Alias[];
|
aliases: Alias[];
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
(_) => NoteGroupPermission,
|
(_) => NoteGroupPermission,
|
||||||
(groupPermission) => groupPermission.note,
|
(groupPermission) => groupPermission.note,
|
||||||
{ cascade: true }, // This ensures that embedded NoteGroupPermissions are automatically saved to the database
|
{ cascade: true }, // This ensures that embedded NoteGroupPermissions are automatically saved to the database
|
||||||
)
|
)
|
||||||
groupPermissions: NoteGroupPermission[];
|
groupPermissions: NoteGroupPermission[];
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
(_) => NoteUserPermission,
|
(_) => NoteUserPermission,
|
||||||
(userPermission) => userPermission.note,
|
(userPermission) => userPermission.note,
|
||||||
{ cascade: true }, // This ensures that embedded NoteUserPermission are automatically saved to the database
|
{ cascade: true }, // This ensures that embedded NoteUserPermission are automatically saved to the database
|
||||||
)
|
)
|
||||||
userPermissions: NoteUserPermission[];
|
userPermissions: NoteUserPermission[];
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
nullable: false,
|
nullable: false,
|
||||||
default: 0,
|
default: 0,
|
||||||
})
|
})
|
||||||
viewCount: number;
|
viewCount: number;
|
||||||
|
|
||||||
@ManyToOne((_) => User, (user) => user.ownedNotes, {
|
@ManyToOne((_) => User, (user) => user.ownedNotes, {
|
||||||
onDelete: 'CASCADE', // This deletes the Note, when the associated User is deleted
|
onDelete: 'CASCADE', // This deletes the Note, when the associated User is deleted
|
||||||
nullable: true,
|
nullable: true,
|
||||||
})
|
})
|
||||||
owner: User | null;
|
owner: User | null;
|
||||||
|
|
||||||
@OneToMany((_) => Revision, (revision) => revision.note, { cascade: true })
|
@OneToMany((_) => Revision, (revision) => revision.note, { cascade: true })
|
||||||
revisions: Promise<Revision[]>;
|
revisions: Promise<Revision[]>;
|
||||||
|
|
||||||
@OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user)
|
@OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user)
|
||||||
historyEntries: HistoryEntry[];
|
historyEntries: HistoryEntry[];
|
||||||
|
|
||||||
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note)
|
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note)
|
||||||
mediaUploads: MediaUpload[];
|
mediaUploads: MediaUpload[];
|
||||||
|
|
||||||
|
@ -69,6 +78,7 @@ export class Note {
|
||||||
type: 'text',
|
type: 'text',
|
||||||
})
|
})
|
||||||
description: string | null;
|
description: string | null;
|
||||||
|
|
||||||
@Column({
|
@Column({
|
||||||
nullable: true,
|
nullable: true,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
|
@ -82,15 +92,19 @@ export class Note {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(owner?: User, alias?: string): Note {
|
public static create(owner?: User, alias?: string): Omit<Note, 'id'> {
|
||||||
const newNote = new Note();
|
const newNote = new Note();
|
||||||
newNote.publicId = generatePublicId();
|
newNote.publicId = generatePublicId();
|
||||||
newNote.aliases = alias ? [Alias.create(alias, true)] : [];
|
newNote.aliases = alias
|
||||||
newNote.viewCount = 0;
|
? [Alias.create(alias, newNote, true) as Alias]
|
||||||
newNote.owner = owner ?? null;
|
: [];
|
||||||
newNote.userPermissions = [];
|
newNote.userPermissions = [];
|
||||||
newNote.groupPermissions = [];
|
newNote.groupPermissions = [];
|
||||||
newNote.revisions = Promise.resolve([]) as Promise<Revision[]>;
|
newNote.viewCount = 0;
|
||||||
|
newNote.owner = owner ?? null;
|
||||||
|
newNote.revisions = Promise.resolve([]);
|
||||||
|
newNote.historyEntries = [];
|
||||||
|
newNote.mediaUploads = [];
|
||||||
newNote.description = null;
|
newNote.description = null;
|
||||||
newNote.title = null;
|
newNote.title = null;
|
||||||
newNote.tags = [];
|
newNote.tags = [];
|
||||||
|
|
|
@ -28,9 +28,14 @@ export class NoteGroupPermission {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(group: Group, canEdit: boolean): NoteGroupPermission {
|
public static create(
|
||||||
|
group: Group,
|
||||||
|
note: Note,
|
||||||
|
canEdit: boolean,
|
||||||
|
): NoteGroupPermission {
|
||||||
const groupPermission = new NoteGroupPermission();
|
const groupPermission = new NoteGroupPermission();
|
||||||
groupPermission.group = group;
|
groupPermission.group = group;
|
||||||
|
groupPermission.note = note;
|
||||||
groupPermission.canEdit = canEdit;
|
groupPermission.canEdit = canEdit;
|
||||||
return groupPermission;
|
return groupPermission;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,14 @@ export class NoteUserPermission {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(user: User, canEdit: boolean): NoteUserPermission {
|
public static create(
|
||||||
|
user: User,
|
||||||
|
note: Note,
|
||||||
|
canEdit: boolean,
|
||||||
|
): NoteUserPermission {
|
||||||
const userPermission = new NoteUserPermission();
|
const userPermission = new NoteUserPermission();
|
||||||
userPermission.user = user;
|
userPermission.user = user;
|
||||||
|
userPermission.note = note;
|
||||||
userPermission.canEdit = canEdit;
|
userPermission.canEdit = canEdit;
|
||||||
return userPermission;
|
return userPermission;
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,8 +51,13 @@ export class Edit {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
public static create(author: Author, startPos: number, endPos: number) {
|
public static create(
|
||||||
|
author: Author,
|
||||||
|
startPos: number,
|
||||||
|
endPos: number,
|
||||||
|
): Omit<Edit, 'id' | 'createdAt' | 'updatedAt'> {
|
||||||
const newEdit = new Edit();
|
const newEdit = new Edit();
|
||||||
|
newEdit.revisions = [];
|
||||||
newEdit.author = author;
|
newEdit.author = author;
|
||||||
newEdit.startPos = startPos;
|
newEdit.startPos = startPos;
|
||||||
newEdit.endPos = endPos;
|
newEdit.endPos = endPos;
|
||||||
|
|
|
@ -59,6 +59,7 @@ export class Revision {
|
||||||
*/
|
*/
|
||||||
@ManyToOne((_) => Note, (note) => note.revisions, { onDelete: 'CASCADE' })
|
@ManyToOne((_) => Note, (note) => note.revisions, { onDelete: 'CASCADE' })
|
||||||
note: Note;
|
note: Note;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All edit objects which are used in the revision.
|
* 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
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
static create(content: string, patch: string): Revision {
|
static create(
|
||||||
|
content: string,
|
||||||
|
patch: string,
|
||||||
|
note: Note,
|
||||||
|
): Omit<Revision, 'id' | 'createdAt'> {
|
||||||
const newRevision = new Revision();
|
const newRevision = new Revision();
|
||||||
newRevision.patch = patch;
|
newRevision.patch = patch;
|
||||||
newRevision.content = content;
|
newRevision.content = content;
|
||||||
newRevision.length = content.length;
|
newRevision.length = content.length;
|
||||||
|
newRevision.note = note;
|
||||||
|
newRevision.edits = [];
|
||||||
return newRevision;
|
return newRevision;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
11
src/seed.ts
11
src/seed.ts
|
@ -57,9 +57,9 @@ createConnection({
|
||||||
users.push(User.create('hardcoded_2', 'Test User 2'));
|
users.push(User.create('hardcoded_2', 'Test User 2'));
|
||||||
users.push(User.create('hardcoded_3', 'Test User 3'));
|
users.push(User.create('hardcoded_3', 'Test User 3'));
|
||||||
const notes: Note[] = [];
|
const notes: Note[] = [];
|
||||||
notes.push(Note.create(undefined, 'test'));
|
notes.push(Note.create(undefined, 'test') as Note);
|
||||||
notes.push(Note.create(undefined, 'test2'));
|
notes.push(Note.create(undefined, 'test2') as Note);
|
||||||
notes.push(Note.create(undefined, 'test3'));
|
notes.push(Note.create(undefined, 'test3') as Note);
|
||||||
|
|
||||||
for (let i = 0; i < 3; i++) {
|
for (let i = 0; i < 3; i++) {
|
||||||
const author = connection.manager.create(Author, Author.create(1));
|
const author = connection.manager.create(Author, Author.create(1));
|
||||||
|
@ -71,8 +71,9 @@ createConnection({
|
||||||
const revision = Revision.create(
|
const revision = Revision.create(
|
||||||
'This is a test note',
|
'This is a test note',
|
||||||
'This is a test note',
|
'This is a test note',
|
||||||
);
|
notes[i],
|
||||||
const edit = Edit.create(author, 1, 42);
|
) as Revision;
|
||||||
|
const edit = Edit.create(author, 1, 42) as Edit;
|
||||||
revision.edits = [edit];
|
revision.edits = [edit];
|
||||||
notes[i].revisions = Promise.all([revision]);
|
notes[i].revisions = Promise.all([revision]);
|
||||||
notes[i].userPermissions = [];
|
notes[i].userPermissions = [];
|
||||||
|
|
|
@ -79,13 +79,19 @@ export class User {
|
||||||
public static create(
|
public static create(
|
||||||
username: string,
|
username: string,
|
||||||
displayName: string,
|
displayName: string,
|
||||||
): Pick<
|
): Omit<User, 'id' | 'createdAt' | 'updatedAt'> {
|
||||||
User,
|
|
||||||
'username' | 'displayName' | 'ownedNotes' | 'authTokens' | 'identities'
|
|
||||||
> {
|
|
||||||
const newUser = new User();
|
const newUser = new User();
|
||||||
newUser.username = username;
|
newUser.username = username;
|
||||||
newUser.displayName = displayName;
|
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;
|
return newUser;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue