mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-04-14 12:05:10 +00:00
Merge pull request #1266 from hedgedoc/feature/anonymous_user_colors
This commit is contained in:
commit
2b0fa17d03
26 changed files with 288 additions and 136 deletions
|
@ -74,7 +74,7 @@ entity "revision" {
|
|||
entity "authorship" {
|
||||
*id : uuid <<generated>>
|
||||
--
|
||||
*userId : uuid <FK user>>
|
||||
*authorId : uuid <FK user>>
|
||||
*startPos : number
|
||||
*endPos : number
|
||||
*createdAt : date
|
||||
|
@ -86,11 +86,12 @@ entity "revision_authorship" {
|
|||
*authorshipId : uuid <<FK authorship>>
|
||||
}
|
||||
|
||||
entity "author_colors" {
|
||||
*noteId : uuid <<FK note>>
|
||||
*userId : uuid <<FK user>>
|
||||
entity "author" {
|
||||
*id : number <<generated>>
|
||||
--
|
||||
*color : text
|
||||
sessionID : text <<FK session>>
|
||||
userId : uuid <<FK user>>
|
||||
}
|
||||
|
||||
|
||||
|
@ -148,22 +149,23 @@ entity "history_entry" {
|
|||
*updatedAt: date
|
||||
}
|
||||
|
||||
user "1" -- "0..*" note: owner
|
||||
user "0..1" -- "0..*" note: owner
|
||||
user "1" -u- "1..*" identity
|
||||
user "1" -l- "1..*" auth_token: authTokens
|
||||
user "1" -r- "1..*" session
|
||||
user "1" -- "0..*" media_upload
|
||||
user "1" - "0..*" history_entry
|
||||
user "1" -- "0..*" history_entry
|
||||
user "0..*" -- "0..*" note
|
||||
user "1" -- "0..*" authorship
|
||||
user "0..1" -- "0..*" author
|
||||
|
||||
(user, note) . author_colors
|
||||
author "1" -- "0..*" authorship
|
||||
author "1" -u- "0..*" session
|
||||
|
||||
revision "0..*" -- "0..*" authorship
|
||||
(revision, authorship) .. revision_authorship
|
||||
|
||||
media_upload "0..*" -- "1" note
|
||||
note "1" - "1..*" revision
|
||||
note "1" -d- "1..*" revision
|
||||
note "1" - "0..*" history_entry
|
||||
note "0..*" -l- "0..*" tag
|
||||
note "0..*" -- "0..*" group
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Author } from '../../../../authors/author.entity';
|
||||
import { Session } from '../../../../users/session.entity';
|
||||
import { HistoryController } from './history.controller';
|
||||
import { LoggerModule } from '../../../../logger/logger.module';
|
||||
import { UsersModule } from '../../../../users/users.module';
|
||||
|
@ -19,7 +21,6 @@ import { User } from '../../../../users/user.entity';
|
|||
import { Note } from '../../../../notes/note.entity';
|
||||
import { AuthToken } from '../../../../auth/auth-token.entity';
|
||||
import { Identity } from '../../../../users/identity.entity';
|
||||
import { AuthorColor } from '../../../../notes/author-color.entity';
|
||||
import { Authorship } from '../../../../revisions/authorship.entity';
|
||||
import { Revision } from '../../../../revisions/revision.entity';
|
||||
import { Tag } from '../../../../notes/tag.entity';
|
||||
|
@ -58,8 +59,6 @@ describe('HistoryController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Identity))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
|
@ -74,6 +73,10 @@ describe('HistoryController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<HistoryController>(HistoryController);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Author } from '../../../authors/author.entity';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { MeController } from './me.controller';
|
||||
import { UsersModule } from '../../../users/users.module';
|
||||
import { LoggerModule } from '../../../logger/logger.module';
|
||||
|
@ -12,7 +14,6 @@ import { getRepositoryToken } from '@nestjs/typeorm';
|
|||
import { User } from '../../../users/user.entity';
|
||||
import { Identity } from '../../../users/identity.entity';
|
||||
import { MediaModule } from '../../../media/media.module';
|
||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
|
||||
import { Authorship } from '../../../revisions/authorship.entity';
|
||||
|
@ -62,8 +63,6 @@ describe('MeController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
|
@ -72,6 +71,10 @@ describe('MeController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MeController>(MeController);
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Author } from '../../../authors/author.entity';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { UsersModule } from '../../../users/users.module';
|
||||
import { MediaController } from './media.controller';
|
||||
import { LoggerModule } from '../../../logger/logger.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
@ -16,7 +19,6 @@ import externalConfigMock from '../../../config/mock/external-services.config.mo
|
|||
import { MediaModule } from '../../../media/media.module';
|
||||
import { NotesModule } from '../../../notes/notes.module';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
||||
import { Authorship } from '../../../revisions/authorship.entity';
|
||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||
import { Identity } from '../../../users/identity.entity';
|
||||
|
@ -48,11 +50,10 @@ describe('MediaController', () => {
|
|||
externalConfigMock,
|
||||
],
|
||||
}),
|
||||
UsersModule,
|
||||
],
|
||||
controllers: [MediaController],
|
||||
})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
|
@ -75,6 +76,10 @@ describe('MediaController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MediaController>(MediaController);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Author } from '../../../authors/author.entity';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { NotesController } from './notes.controller';
|
||||
import { NotesService } from '../../../notes/notes.service';
|
||||
import {
|
||||
|
@ -26,7 +28,6 @@ import appConfigMock from '../../../config/mock/app.config.mock';
|
|||
import mediaConfigMock from '../../../config/mock/media.config.mock';
|
||||
import { Revision } from '../../../revisions/revision.entity';
|
||||
import { Authorship } from '../../../revisions/authorship.entity';
|
||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
||||
import { User } from '../../../users/user.entity';
|
||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||
import { Identity } from '../../../users/identity.entity';
|
||||
|
@ -52,6 +53,10 @@ describe('NotesController', () => {
|
|||
provide: getRepositoryToken(Tag),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(User),
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
imports: [
|
||||
RevisionsModule,
|
||||
|
@ -74,8 +79,6 @@ describe('NotesController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
|
@ -96,6 +99,10 @@ describe('NotesController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<NotesController>(NotesController);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { TokensController } from './tokens.controller';
|
||||
import { LoggerModule } from '../../../logger/logger.module';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
@ -36,6 +37,8 @@ describe('TokensController', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Identity))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<TokensController>(TokensController);
|
||||
|
|
|
@ -10,9 +10,9 @@ import {
|
|||
getRepositoryToken,
|
||||
TypeOrmModule,
|
||||
} from '@nestjs/typeorm';
|
||||
import { Author } from '../../../authors/author.entity';
|
||||
import { HistoryModule } from '../../../history/history.module';
|
||||
import { LoggerModule } from '../../../logger/logger.module';
|
||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
||||
import { Note } from '../../../notes/note.entity';
|
||||
import { NotesModule } from '../../../notes/notes.module';
|
||||
import { Tag } from '../../../notes/tag.entity';
|
||||
|
@ -20,6 +20,7 @@ import { Authorship } from '../../../revisions/authorship.entity';
|
|||
import { Revision } from '../../../revisions/revision.entity';
|
||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||
import { Identity } from '../../../users/identity.entity';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { User } from '../../../users/user.entity';
|
||||
import { UsersModule } from '../../../users/users.module';
|
||||
import { MeController } from './me.controller';
|
||||
|
@ -62,8 +63,6 @@ describe('Me Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Identity))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
|
@ -80,6 +79,10 @@ describe('Me Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MeController>(MeController);
|
||||
|
|
|
@ -7,12 +7,12 @@
|
|||
import { ConfigModule } from '@nestjs/config';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Author } from '../../../authors/author.entity';
|
||||
import appConfigMock from '../../../config/mock/app.config.mock';
|
||||
import mediaConfigMock from '../../../config/mock/media.config.mock';
|
||||
import { LoggerModule } from '../../../logger/logger.module';
|
||||
import { MediaUpload } from '../../../media/media-upload.entity';
|
||||
import { MediaModule } from '../../../media/media.module';
|
||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
||||
import { Note } from '../../../notes/note.entity';
|
||||
import { NotesModule } from '../../../notes/notes.module';
|
||||
import { Tag } from '../../../notes/tag.entity';
|
||||
|
@ -20,6 +20,7 @@ import { Authorship } from '../../../revisions/authorship.entity';
|
|||
import { Revision } from '../../../revisions/revision.entity';
|
||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||
import { Identity } from '../../../users/identity.entity';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { User } from '../../../users/user.entity';
|
||||
import { MediaController } from './media.controller';
|
||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||
|
@ -42,8 +43,6 @@ describe('Media Controller', () => {
|
|||
NotesModule,
|
||||
],
|
||||
})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
|
@ -66,6 +65,10 @@ describe('Media Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MediaController>(MediaController);
|
||||
|
|
|
@ -10,8 +10,8 @@ import {
|
|||
getRepositoryToken,
|
||||
TypeOrmModule,
|
||||
} from '@nestjs/typeorm';
|
||||
import { Author } from '../../../authors/author.entity';
|
||||
import { LoggerModule } from '../../../logger/logger.module';
|
||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
||||
import { Note } from '../../../notes/note.entity';
|
||||
import { NotesService } from '../../../notes/notes.service';
|
||||
import { Tag } from '../../../notes/tag.entity';
|
||||
|
@ -20,6 +20,7 @@ import { Revision } from '../../../revisions/revision.entity';
|
|||
import { RevisionsModule } from '../../../revisions/revisions.module';
|
||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||
import { Identity } from '../../../users/identity.entity';
|
||||
import { Session } from '../../../users/session.entity';
|
||||
import { User } from '../../../users/user.entity';
|
||||
import { UsersModule } from '../../../users/users.module';
|
||||
import { NotesController } from './notes.controller';
|
||||
|
@ -52,6 +53,10 @@ describe('Notes Controller', () => {
|
|||
provide: getRepositoryToken(Tag),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(User),
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
imports: [
|
||||
RevisionsModule,
|
||||
|
@ -76,8 +81,6 @@ describe('Notes Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
|
@ -98,6 +101,10 @@ describe('Notes Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<NotesController>(NotesController);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { AuthService } from './auth.service';
|
||||
import { PassportModule } from '@nestjs/passport';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
|
@ -49,6 +50,8 @@ describe('AuthService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<AuthService>(AuthService);
|
||||
|
|
|
@ -4,14 +4,68 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
import { Authorship } from '../revisions/authorship.entity';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
|
||||
export type AuthorColor = number;
|
||||
|
||||
/**
|
||||
* The author represents a single user editing a note.
|
||||
* A 'user' can either be a registered and logged-in user or a browser session identified by its cookie.
|
||||
* All edits (aka authorships) of one user in a note must belong to the same author, so that the same color can be displayed.
|
||||
*/
|
||||
@Entity()
|
||||
export class Author {
|
||||
//TODO: Still missing many properties
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
note: Note;
|
||||
/**
|
||||
* The id of the color of this author
|
||||
* The application maps the id to an actual color
|
||||
*/
|
||||
@Column({ type: 'int' })
|
||||
color: AuthorColor;
|
||||
|
||||
/**
|
||||
* A list of (browser) sessions this author has
|
||||
* Only contains sessions for anonymous users, which don't have a user set
|
||||
*/
|
||||
@OneToMany(() => Session, (session) => session.author)
|
||||
sessions: Session[];
|
||||
|
||||
/**
|
||||
* User that this author corresponds to
|
||||
* Only set when the user was identified (by a browser session) as a registered user at edit-time
|
||||
*/
|
||||
@ManyToOne(() => User, (user) => user.authors, { nullable: true })
|
||||
user: User | null;
|
||||
|
||||
/**
|
||||
* List of authorships that this author created
|
||||
* All authorships must belong to the same note
|
||||
*/
|
||||
@OneToMany(() => Authorship, (authorship) => authorship.author)
|
||||
authorships: Authorship[];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
public static create(
|
||||
color: number,
|
||||
): Pick<Author, 'color' | 'sessions' | 'user' | 'authorships'> {
|
||||
const newAuthor = new Author();
|
||||
newAuthor.color = color;
|
||||
newAuthor.sessions = [];
|
||||
newAuthor.user = null;
|
||||
newAuthor.authorships = [];
|
||||
return newAuthor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,15 @@
|
|||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { HistoryService } from './history.service';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { getConnectionToken, getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Identity } from '../users/identity.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
import { AuthorColor } from '../notes/author-color.entity';
|
||||
import { Authorship } from '../revisions/authorship.entity';
|
||||
import { HistoryEntry } from './history-entry.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
|
@ -75,8 +76,6 @@ describe('HistoryService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Note))
|
||||
|
@ -89,6 +88,10 @@ describe('HistoryService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<HistoryService>(HistoryService);
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
import { ConfigModule } from '@nestjs/config';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import mediaConfigMock from '../config/mock/media.config.mock';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { AuthorColor } from '../notes/author-color.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { Tag } from '../notes/tag.entity';
|
||||
|
@ -17,6 +17,7 @@ import { Authorship } from '../revisions/authorship.entity';
|
|||
import { Revision } from '../revisions/revision.entity';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Identity } from '../users/identity.entity';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { FilesystemBackend } from './backends/filesystem-backend';
|
||||
|
@ -56,8 +57,6 @@ describe('MediaService', () => {
|
|||
UsersModule,
|
||||
],
|
||||
})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
|
@ -80,6 +79,10 @@ describe('MediaService', () => {
|
|||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<MediaService>(MediaService);
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Column, Entity, ManyToOne } from 'typeorm';
|
||||
import { User } from '../users/user.entity';
|
||||
import { Note } from './note.entity';
|
||||
|
||||
@Entity()
|
||||
export class AuthorColor {
|
||||
@ManyToOne((_) => Note, (note) => note.authorColors, {
|
||||
primary: true,
|
||||
})
|
||||
note: Note;
|
||||
|
||||
@ManyToOne((_) => User, {
|
||||
primary: true,
|
||||
})
|
||||
user: User;
|
||||
|
||||
@Column()
|
||||
color: string;
|
||||
}
|
|
@ -17,7 +17,6 @@ import { NoteGroupPermission } from '../permissions/note-group-permission.entity
|
|||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||
import { Revision } from '../revisions/revision.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
import { AuthorColor } from './author-color.entity';
|
||||
import { Tag } from './tag.entity';
|
||||
import { HistoryEntry } from '../history/history-entry.entity';
|
||||
import { MediaUpload } from '../media/media-upload.entity';
|
||||
|
@ -59,8 +58,6 @@ export class Note {
|
|||
owner: User | null;
|
||||
@OneToMany((_) => Revision, (revision) => revision.note, { cascade: true })
|
||||
revisions: Promise<Revision[]>;
|
||||
@OneToMany((_) => AuthorColor, (authorColor) => authorColor.note)
|
||||
authorColors: AuthorColor[];
|
||||
@OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user)
|
||||
historyEntries: HistoryEntry[];
|
||||
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note)
|
||||
|
@ -90,7 +87,6 @@ export class Note {
|
|||
newNote.alias = alias ?? null;
|
||||
newNote.viewCount = 0;
|
||||
newNote.owner = owner ?? null;
|
||||
newNote.authorColors = [];
|
||||
newNote.userPermissions = [];
|
||||
newNote.groupPermissions = [];
|
||||
newNote.revisions = Promise.resolve([]) as Promise<Revision[]>;
|
||||
|
|
|
@ -5,27 +5,27 @@
|
|||
*/
|
||||
|
||||
import { forwardRef, Module } from '@nestjs/common';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { GroupsModule } from '../groups/groups.module';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||
import { RevisionsModule } from '../revisions/revisions.module';
|
||||
import { User } from '../users/user.entity';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { AuthorColor } from './author-color.entity';
|
||||
import { Note } from './note.entity';
|
||||
import { NotesService } from './notes.service';
|
||||
import { Tag } from './tag.entity';
|
||||
import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||
import { GroupsModule } from '../groups/groups.module';
|
||||
import { ConfigModule } from '@nestjs/config';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([
|
||||
Note,
|
||||
AuthorColor,
|
||||
Tag,
|
||||
NoteGroupPermission,
|
||||
NoteUserPermission,
|
||||
User,
|
||||
]),
|
||||
forwardRef(() => RevisionsModule),
|
||||
UsersModule,
|
||||
|
|
|
@ -6,15 +6,16 @@
|
|||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { Authorship } from '../revisions/authorship.entity';
|
||||
import { Revision } from '../revisions/revision.entity';
|
||||
import { RevisionsModule } from '../revisions/revisions.module';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Identity } from '../users/identity.entity';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { AuthorColor } from './author-color.entity';
|
||||
import { Note } from './note.entity';
|
||||
import { NotesService } from './notes.service';
|
||||
import { Repository } from 'typeorm';
|
||||
|
@ -45,6 +46,12 @@ describe('NotesService', () => {
|
|||
let forbiddenNoteId: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
/**
|
||||
* We need to have *one* userRepo for both the providers array and
|
||||
* the overrideProvider call, as otherwise we have two instances
|
||||
* and the mock of createQueryBuilder replaces the wrong one
|
||||
* **/
|
||||
userRepo = new Repository<User>();
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
NotesService,
|
||||
|
@ -56,6 +63,10 @@ describe('NotesService', () => {
|
|||
provide: getRepositoryToken(Tag),
|
||||
useClass: Repository,
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(User),
|
||||
useValue: userRepo,
|
||||
},
|
||||
],
|
||||
imports: [
|
||||
ConfigModule.forRoot({
|
||||
|
@ -73,15 +84,13 @@ describe('NotesService', () => {
|
|||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useClass(Repository)
|
||||
.useValue(userRepo)
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Identity))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
|
@ -90,6 +99,10 @@ describe('NotesService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
const config = module.get<ConfigService>(ConfigService);
|
||||
|
@ -658,7 +671,8 @@ describe('NotesService', () => {
|
|||
describe('toNoteMetadataDto', () => {
|
||||
it('works', async () => {
|
||||
const user = User.create('hardcoded', 'Testy') as User;
|
||||
const otherUser = User.create('other hardcoded', 'Testy2') as User;
|
||||
const author = Author.create(1);
|
||||
author.user = user;
|
||||
const group = Group.create('testGroup', 'testGroup');
|
||||
const content = 'testContent';
|
||||
jest
|
||||
|
@ -668,33 +682,36 @@ describe('NotesService', () => {
|
|||
const revisions = await note.revisions;
|
||||
revisions[0].authorships = [
|
||||
{
|
||||
user: otherUser,
|
||||
revisions: revisions,
|
||||
startPos: 0,
|
||||
endPos: 1,
|
||||
updatedAt: new Date(1549312452000),
|
||||
author: author,
|
||||
} as Authorship,
|
||||
{
|
||||
user: user,
|
||||
revisions: revisions,
|
||||
startPos: 0,
|
||||
endPos: 1,
|
||||
updatedAt: new Date(1549312452001),
|
||||
author: author,
|
||||
} as Authorship,
|
||||
];
|
||||
revisions[0].createdAt = new Date(1549312452000);
|
||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValue(revisions[0]);
|
||||
const createQueryBuilder = {
|
||||
innerJoin: () => createQueryBuilder,
|
||||
where: () => createQueryBuilder,
|
||||
getMany: () => [user],
|
||||
};
|
||||
jest
|
||||
.spyOn(userRepo, 'createQueryBuilder')
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
.mockImplementation(() => createQueryBuilder);
|
||||
note.publicId = 'testId';
|
||||
note.alias = 'testAlias';
|
||||
note.title = 'testTitle';
|
||||
note.description = 'testDescription';
|
||||
note.authorColors = [
|
||||
{
|
||||
note: note,
|
||||
user: user,
|
||||
color: 'red',
|
||||
} as AuthorColor,
|
||||
];
|
||||
note.owner = user;
|
||||
note.userPermissions = [
|
||||
{
|
||||
|
@ -748,6 +765,8 @@ describe('NotesService', () => {
|
|||
describe('toNoteDto', () => {
|
||||
it('works', async () => {
|
||||
const user = User.create('hardcoded', 'Testy') as User;
|
||||
const author = Author.create(1);
|
||||
author.user = user;
|
||||
const otherUser = User.create('other hardcoded', 'Testy2') as User;
|
||||
otherUser.userName = 'other hardcoded user';
|
||||
const group = Group.create('testGroup', 'testGroup');
|
||||
|
@ -759,18 +778,18 @@ describe('NotesService', () => {
|
|||
const revisions = await note.revisions;
|
||||
revisions[0].authorships = [
|
||||
{
|
||||
user: otherUser,
|
||||
revisions: revisions,
|
||||
startPos: 0,
|
||||
endPos: 1,
|
||||
updatedAt: new Date(1549312452000),
|
||||
author: author,
|
||||
} as Authorship,
|
||||
{
|
||||
user: user,
|
||||
revisions: revisions,
|
||||
startPos: 0,
|
||||
endPos: 1,
|
||||
updatedAt: new Date(1549312452001),
|
||||
author: author,
|
||||
} as Authorship,
|
||||
];
|
||||
revisions[0].createdAt = new Date(1549312452000);
|
||||
|
@ -778,17 +797,20 @@ describe('NotesService', () => {
|
|||
.spyOn(revisionRepo, 'findOne')
|
||||
.mockResolvedValue(revisions[0])
|
||||
.mockResolvedValue(revisions[0]);
|
||||
const createQueryBuilder = {
|
||||
innerJoin: () => createQueryBuilder,
|
||||
where: () => createQueryBuilder,
|
||||
getMany: () => [user],
|
||||
};
|
||||
jest
|
||||
.spyOn(userRepo, 'createQueryBuilder')
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
.mockImplementation(() => createQueryBuilder);
|
||||
note.publicId = 'testId';
|
||||
note.alias = 'testAlias';
|
||||
note.title = 'testTitle';
|
||||
note.description = 'testDescription';
|
||||
note.authorColors = [
|
||||
{
|
||||
note: note,
|
||||
user: user,
|
||||
color: 'red',
|
||||
} as AuthorColor,
|
||||
];
|
||||
note.owner = user;
|
||||
note.userPermissions = [
|
||||
{
|
||||
|
|
|
@ -41,6 +41,7 @@ export class NotesService {
|
|||
private readonly logger: ConsoleLoggerService,
|
||||
@InjectRepository(Note) private noteRepository: Repository<Note>,
|
||||
@InjectRepository(Tag) private tagRepository: Repository<Tag>,
|
||||
@InjectRepository(User) private userRepository: Repository<User>,
|
||||
@Inject(UsersService) private usersService: UsersService,
|
||||
@Inject(GroupsService) private groupsService: GroupsService,
|
||||
@Inject(forwardRef(() => RevisionsService))
|
||||
|
@ -60,13 +61,7 @@ export class NotesService {
|
|||
async getUserNotes(user: User): Promise<Note[]> {
|
||||
const notes = await this.noteRepository.find({
|
||||
where: { owner: user },
|
||||
relations: [
|
||||
'owner',
|
||||
'userPermissions',
|
||||
'groupPermissions',
|
||||
'authorColors',
|
||||
'tags',
|
||||
],
|
||||
relations: ['owner', 'userPermissions', 'groupPermissions', 'tags'],
|
||||
});
|
||||
if (notes === undefined) {
|
||||
return [];
|
||||
|
@ -173,7 +168,6 @@ export class NotesService {
|
|||
},
|
||||
],
|
||||
relations: [
|
||||
'authorColors',
|
||||
'owner',
|
||||
'groupPermissions',
|
||||
'groupPermissions.group',
|
||||
|
@ -195,6 +189,22 @@ export class NotesService {
|
|||
return note;
|
||||
}
|
||||
|
||||
/**
|
||||
* @async
|
||||
* Get all users that ever appeared as an author for the given note
|
||||
* @param note The note to search authors for
|
||||
*/
|
||||
async getAuthorUsers(note: Note): Promise<User[]> {
|
||||
return await this.userRepository
|
||||
.createQueryBuilder('user')
|
||||
.innerJoin('user.authors', 'author')
|
||||
.innerJoin('author.authorships', 'authorship')
|
||||
.innerJoin('authorship.revisions', 'revision')
|
||||
.innerJoin('revision.note', 'note')
|
||||
.where('note.id = :id', { id: note.id })
|
||||
.getMany();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided note id or alias is not forbidden
|
||||
* @param noteIdOrAlias - the alias or id in question
|
||||
|
@ -317,7 +327,7 @@ export class NotesService {
|
|||
// the user of that Authorship is the updateUser
|
||||
return lastRevision.authorships.sort(
|
||||
(a, b) => b.updatedAt.getTime() - a.updatedAt.getTime(),
|
||||
)[0].user;
|
||||
)[0].author.user;
|
||||
}
|
||||
// If there are no Authorships, the owner is the updateUser
|
||||
return note.owner;
|
||||
|
@ -365,9 +375,7 @@ export class NotesService {
|
|||
title: note.title ?? '',
|
||||
createTime: (await this.getFirstRevision(note)).createdAt,
|
||||
description: note.description ?? '',
|
||||
editedBy: note.authorColors.map(
|
||||
(authorColor) => authorColor.user.userName,
|
||||
),
|
||||
editedBy: (await this.getAuthorUsers(note)).map((user) => user.userName),
|
||||
permissions: this.toNotePermissionsDto(note),
|
||||
tags: this.toTagList(note),
|
||||
updateTime: (await this.getLatestRevision(note)).createdAt,
|
||||
|
|
|
@ -7,15 +7,16 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import { Group } from '../groups/group.entity';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { AuthorColor } from '../notes/author-color.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { Tag } from '../notes/tag.entity';
|
||||
import { Authorship } from '../revisions/authorship.entity';
|
||||
import { Revision } from '../revisions/revision.entity';
|
||||
import { Identity } from '../users/identity.entity';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { NoteGroupPermission } from './note-group-permission.entity';
|
||||
|
@ -50,8 +51,6 @@ describe('PermissionsService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Note))
|
||||
|
@ -64,6 +63,10 @@ describe('PermissionsService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
permissionsService = module.get<PermissionsService>(PermissionsService);
|
||||
});
|
||||
|
|
|
@ -13,11 +13,11 @@ import {
|
|||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { User } from '../users/user.entity';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import { Revision } from './revision.entity';
|
||||
|
||||
/**
|
||||
* This class stores which parts of a revision were edited by a particular user.
|
||||
* The Authorship represents a change in the content of a note by a particular {@link Author}
|
||||
*/
|
||||
@Entity()
|
||||
export class Authorship {
|
||||
|
@ -31,10 +31,10 @@ export class Authorship {
|
|||
revisions: Revision[];
|
||||
|
||||
/**
|
||||
* User this authorship represents
|
||||
* Author that created the change
|
||||
*/
|
||||
@ManyToOne((_) => User)
|
||||
user: User;
|
||||
@ManyToOne(() => Author, (author) => author.authorships)
|
||||
author: Author;
|
||||
|
||||
@Column()
|
||||
startPos: number;
|
||||
|
@ -47,4 +47,15 @@ export class Authorship {
|
|||
|
||||
@UpdateDateColumn()
|
||||
updatedAt: Date;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
public static create(author: Author, startPos: number, endPos: number) {
|
||||
const newAuthorship = new Authorship();
|
||||
newAuthorship.author = author;
|
||||
newAuthorship.startPos = startPos;
|
||||
newAuthorship.endPos = endPos;
|
||||
return newAuthorship;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
import { forwardRef, Module } from '@nestjs/common';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { AuthorsModule } from '../authors/authors.module';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { Authorship } from './authorship.entity';
|
||||
|
@ -19,6 +20,7 @@ import { ConfigModule } from '@nestjs/config';
|
|||
forwardRef(() => NotesModule),
|
||||
LoggerModule,
|
||||
ConfigModule,
|
||||
AuthorsModule,
|
||||
],
|
||||
providers: [RevisionsService],
|
||||
exports: [RevisionsService],
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { Repository } from 'typeorm';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import { AuthorsModule } from '../authors/authors.module';
|
||||
import { NotInDBError } from '../errors/errors';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { AuthorColor } from '../notes/author-color.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Identity } from '../users/identity.entity';
|
||||
import { Session } from '../users/session.entity';
|
||||
import { User } from '../users/user.entity';
|
||||
import { Authorship } from './authorship.entity';
|
||||
import { Revision } from './revision.entity';
|
||||
|
@ -49,8 +51,6 @@ describe('RevisionsService', () => {
|
|||
})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
|
@ -69,6 +69,10 @@ describe('RevisionsService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Group))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Session))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Author))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<RevisionsService>(RevisionsService);
|
||||
|
|
49
src/seed.ts
49
src/seed.ts
|
@ -5,6 +5,8 @@
|
|||
*/
|
||||
|
||||
import { createConnection } from 'typeorm';
|
||||
import { Author } from './authors/author.entity';
|
||||
import { Session } from './users/session.entity';
|
||||
import { User } from './users/user.entity';
|
||||
import { Note } from './notes/note.entity';
|
||||
import { Revision } from './revisions/revision.entity';
|
||||
|
@ -12,7 +14,6 @@ import { Authorship } from './revisions/authorship.entity';
|
|||
import { NoteGroupPermission } from './permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from './permissions/note-user-permission.entity';
|
||||
import { Group } from './groups/group.entity';
|
||||
import { AuthorColor } from './notes/author-color.entity';
|
||||
import { HistoryEntry } from './history/history-entry.entity';
|
||||
import { MediaUpload } from './media/media-upload.entity';
|
||||
import { Tag } from './notes/tag.entity';
|
||||
|
@ -33,28 +34,50 @@ createConnection({
|
|||
NoteGroupPermission,
|
||||
NoteUserPermission,
|
||||
Group,
|
||||
AuthorColor,
|
||||
HistoryEntry,
|
||||
MediaUpload,
|
||||
Tag,
|
||||
AuthToken,
|
||||
Identity,
|
||||
Author,
|
||||
Session,
|
||||
],
|
||||
synchronize: true,
|
||||
logging: false,
|
||||
dropSchema: true,
|
||||
})
|
||||
.then(async (connection) => {
|
||||
const user = User.create('hardcoded', 'Test User');
|
||||
const note = Note.create(undefined, 'test');
|
||||
const revision = Revision.create(
|
||||
'This is a test note',
|
||||
'This is a test note',
|
||||
);
|
||||
note.revisions = Promise.all([revision]);
|
||||
note.userPermissions = [];
|
||||
note.groupPermissions = [];
|
||||
user.ownedNotes = [note];
|
||||
await connection.manager.save([user, note, revision]);
|
||||
const users = [];
|
||||
users.push(User.create('hardcoded', 'Test User 1'));
|
||||
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'));
|
||||
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const author = connection.manager.create(Author, Author.create(1));
|
||||
const user = connection.manager.create(User, users[i]);
|
||||
author.user = user;
|
||||
const revision = Revision.create(
|
||||
'This is a test note',
|
||||
'This is a test note',
|
||||
);
|
||||
const authorship = Authorship.create(author, 1, 42);
|
||||
revision.authorships = [authorship];
|
||||
notes[i].revisions = Promise.all([revision]);
|
||||
notes[i].userPermissions = [];
|
||||
notes[i].groupPermissions = [];
|
||||
user.ownedNotes = [notes[i]];
|
||||
await connection.manager.save([
|
||||
notes[i],
|
||||
user,
|
||||
revision,
|
||||
authorship,
|
||||
author,
|
||||
]);
|
||||
}
|
||||
const foundUser = await connection.manager.findOne(User);
|
||||
if (!foundUser) {
|
||||
throw new Error('Could not find freshly seeded user. Aborting.');
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
*/
|
||||
|
||||
import { ISession } from 'connect-typeorm';
|
||||
import { Column, Entity, Index, PrimaryColumn } from 'typeorm';
|
||||
import { Column, Entity, Index, ManyToOne, PrimaryColumn } from 'typeorm';
|
||||
import { Author } from '../authors/author.entity';
|
||||
|
||||
@Entity()
|
||||
export class Session implements ISession {
|
||||
|
@ -18,4 +19,7 @@ export class Session implements ISession {
|
|||
|
||||
@Column('text')
|
||||
public json = '';
|
||||
|
||||
@ManyToOne(() => Author, (author) => author.sessions)
|
||||
author: Author;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
import { Column, OneToMany } from 'typeorm';
|
||||
import { Author } from '../authors/author.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Identity } from './identity.entity';
|
||||
|
@ -68,6 +69,9 @@ export class User {
|
|||
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.user)
|
||||
mediaUploads: MediaUpload[];
|
||||
|
||||
@OneToMany(() => Author, (author) => author.user)
|
||||
authors: Author[];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
|
|
|
@ -8,11 +8,12 @@ import { Module } from '@nestjs/common';
|
|||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { Identity } from './identity.entity';
|
||||
import { Session } from './session.entity';
|
||||
import { User } from './user.entity';
|
||||
import { UsersService } from './users.service';
|
||||
|
||||
@Module({
|
||||
imports: [TypeOrmModule.forFeature([User, Identity]), LoggerModule],
|
||||
imports: [TypeOrmModule.forFeature([User, Identity, Session]), LoggerModule],
|
||||
providers: [UsersService],
|
||||
exports: [UsersService],
|
||||
})
|
||||
|
|
Loading…
Add table
Reference in a new issue