mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-20 02:05:21 -04: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" {
|
entity "authorship" {
|
||||||
*id : uuid <<generated>>
|
*id : uuid <<generated>>
|
||||||
--
|
--
|
||||||
*userId : uuid <FK user>>
|
*authorId : uuid <FK user>>
|
||||||
*startPos : number
|
*startPos : number
|
||||||
*endPos : number
|
*endPos : number
|
||||||
*createdAt : date
|
*createdAt : date
|
||||||
|
@ -86,11 +86,12 @@ entity "revision_authorship" {
|
||||||
*authorshipId : uuid <<FK authorship>>
|
*authorshipId : uuid <<FK authorship>>
|
||||||
}
|
}
|
||||||
|
|
||||||
entity "author_colors" {
|
entity "author" {
|
||||||
*noteId : uuid <<FK note>>
|
*id : number <<generated>>
|
||||||
*userId : uuid <<FK user>>
|
|
||||||
--
|
--
|
||||||
*color : text
|
*color : text
|
||||||
|
sessionID : text <<FK session>>
|
||||||
|
userId : uuid <<FK user>>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -148,22 +149,23 @@ entity "history_entry" {
|
||||||
*updatedAt: date
|
*updatedAt: date
|
||||||
}
|
}
|
||||||
|
|
||||||
user "1" -- "0..*" note: owner
|
user "0..1" -- "0..*" note: owner
|
||||||
user "1" -u- "1..*" identity
|
user "1" -u- "1..*" identity
|
||||||
user "1" -l- "1..*" auth_token: authTokens
|
user "1" -l- "1..*" auth_token: authTokens
|
||||||
user "1" -r- "1..*" session
|
user "1" -r- "1..*" session
|
||||||
user "1" -- "0..*" media_upload
|
user "1" -- "0..*" media_upload
|
||||||
user "1" - "0..*" history_entry
|
user "1" -- "0..*" history_entry
|
||||||
user "0..*" -- "0..*" note
|
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 "0..*" -- "0..*" authorship
|
||||||
(revision, authorship) .. revision_authorship
|
(revision, authorship) .. revision_authorship
|
||||||
|
|
||||||
media_upload "0..*" -- "1" note
|
media_upload "0..*" -- "1" note
|
||||||
note "1" - "1..*" revision
|
note "1" -d- "1..*" revision
|
||||||
note "1" - "0..*" history_entry
|
note "1" - "0..*" history_entry
|
||||||
note "0..*" -l- "0..*" tag
|
note "0..*" -l- "0..*" tag
|
||||||
note "0..*" -- "0..*" group
|
note "0..*" -- "0..*" group
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { Author } from '../../../../authors/author.entity';
|
||||||
|
import { Session } from '../../../../users/session.entity';
|
||||||
import { HistoryController } from './history.controller';
|
import { HistoryController } from './history.controller';
|
||||||
import { LoggerModule } from '../../../../logger/logger.module';
|
import { LoggerModule } from '../../../../logger/logger.module';
|
||||||
import { UsersModule } from '../../../../users/users.module';
|
import { UsersModule } from '../../../../users/users.module';
|
||||||
|
@ -19,7 +21,6 @@ import { User } from '../../../../users/user.entity';
|
||||||
import { Note } from '../../../../notes/note.entity';
|
import { Note } from '../../../../notes/note.entity';
|
||||||
import { AuthToken } from '../../../../auth/auth-token.entity';
|
import { AuthToken } from '../../../../auth/auth-token.entity';
|
||||||
import { Identity } from '../../../../users/identity.entity';
|
import { Identity } from '../../../../users/identity.entity';
|
||||||
import { AuthorColor } from '../../../../notes/author-color.entity';
|
|
||||||
import { Authorship } from '../../../../revisions/authorship.entity';
|
import { Authorship } from '../../../../revisions/authorship.entity';
|
||||||
import { Revision } from '../../../../revisions/revision.entity';
|
import { Revision } from '../../../../revisions/revision.entity';
|
||||||
import { Tag } from '../../../../notes/tag.entity';
|
import { Tag } from '../../../../notes/tag.entity';
|
||||||
|
@ -58,8 +59,6 @@ describe('HistoryController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Identity))
|
.overrideProvider(getRepositoryToken(Identity))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Revision))
|
.overrideProvider(getRepositoryToken(Revision))
|
||||||
|
@ -74,6 +73,10 @@ describe('HistoryController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<HistoryController>(HistoryController);
|
controller = module.get<HistoryController>(HistoryController);
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { Author } from '../../../authors/author.entity';
|
||||||
|
import { Session } from '../../../users/session.entity';
|
||||||
import { MeController } from './me.controller';
|
import { MeController } from './me.controller';
|
||||||
import { UsersModule } from '../../../users/users.module';
|
import { UsersModule } from '../../../users/users.module';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
|
@ -12,7 +14,6 @@ import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import { User } from '../../../users/user.entity';
|
import { User } from '../../../users/user.entity';
|
||||||
import { Identity } from '../../../users/identity.entity';
|
import { Identity } from '../../../users/identity.entity';
|
||||||
import { MediaModule } from '../../../media/media.module';
|
import { MediaModule } from '../../../media/media.module';
|
||||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
|
||||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||||
import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
|
import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
|
||||||
import { Authorship } from '../../../revisions/authorship.entity';
|
import { Authorship } from '../../../revisions/authorship.entity';
|
||||||
|
@ -62,8 +63,6 @@ describe('MeController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||||
|
@ -72,6 +71,10 @@ describe('MeController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<MeController>(MeController);
|
controller = module.get<MeController>(MeController);
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
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 { MediaController } from './media.controller';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
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 { MediaModule } from '../../../media/media.module';
|
||||||
import { NotesModule } from '../../../notes/notes.module';
|
import { NotesModule } from '../../../notes/notes.module';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
|
||||||
import { Authorship } from '../../../revisions/authorship.entity';
|
import { Authorship } from '../../../revisions/authorship.entity';
|
||||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||||
import { Identity } from '../../../users/identity.entity';
|
import { Identity } from '../../../users/identity.entity';
|
||||||
|
@ -48,11 +50,10 @@ describe('MediaController', () => {
|
||||||
externalConfigMock,
|
externalConfigMock,
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
UsersModule,
|
||||||
],
|
],
|
||||||
controllers: [MediaController],
|
controllers: [MediaController],
|
||||||
})
|
})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
|
@ -75,6 +76,10 @@ describe('MediaController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<MediaController>(MediaController);
|
controller = module.get<MediaController>(MediaController);
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { Author } from '../../../authors/author.entity';
|
||||||
|
import { Session } from '../../../users/session.entity';
|
||||||
import { NotesController } from './notes.controller';
|
import { NotesController } from './notes.controller';
|
||||||
import { NotesService } from '../../../notes/notes.service';
|
import { NotesService } from '../../../notes/notes.service';
|
||||||
import {
|
import {
|
||||||
|
@ -26,7 +28,6 @@ import appConfigMock from '../../../config/mock/app.config.mock';
|
||||||
import mediaConfigMock from '../../../config/mock/media.config.mock';
|
import mediaConfigMock from '../../../config/mock/media.config.mock';
|
||||||
import { Revision } from '../../../revisions/revision.entity';
|
import { Revision } from '../../../revisions/revision.entity';
|
||||||
import { Authorship } from '../../../revisions/authorship.entity';
|
import { Authorship } from '../../../revisions/authorship.entity';
|
||||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
|
||||||
import { User } from '../../../users/user.entity';
|
import { User } from '../../../users/user.entity';
|
||||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||||
import { Identity } from '../../../users/identity.entity';
|
import { Identity } from '../../../users/identity.entity';
|
||||||
|
@ -52,6 +53,10 @@ describe('NotesController', () => {
|
||||||
provide: getRepositoryToken(Tag),
|
provide: getRepositoryToken(Tag),
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(User),
|
||||||
|
useValue: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
RevisionsModule,
|
RevisionsModule,
|
||||||
|
@ -74,8 +79,6 @@ describe('NotesController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(User))
|
.overrideProvider(getRepositoryToken(User))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
|
@ -96,6 +99,10 @@ describe('NotesController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<NotesController>(NotesController);
|
controller = module.get<NotesController>(NotesController);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { Session } from '../../../users/session.entity';
|
||||||
import { TokensController } from './tokens.controller';
|
import { TokensController } from './tokens.controller';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
@ -36,6 +37,8 @@ describe('TokensController', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Identity))
|
.overrideProvider(getRepositoryToken(Identity))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<TokensController>(TokensController);
|
controller = module.get<TokensController>(TokensController);
|
||||||
|
|
|
@ -10,9 +10,9 @@ import {
|
||||||
getRepositoryToken,
|
getRepositoryToken,
|
||||||
TypeOrmModule,
|
TypeOrmModule,
|
||||||
} from '@nestjs/typeorm';
|
} from '@nestjs/typeorm';
|
||||||
|
import { Author } from '../../../authors/author.entity';
|
||||||
import { HistoryModule } from '../../../history/history.module';
|
import { HistoryModule } from '../../../history/history.module';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
|
||||||
import { Note } from '../../../notes/note.entity';
|
import { Note } from '../../../notes/note.entity';
|
||||||
import { NotesModule } from '../../../notes/notes.module';
|
import { NotesModule } from '../../../notes/notes.module';
|
||||||
import { Tag } from '../../../notes/tag.entity';
|
import { Tag } from '../../../notes/tag.entity';
|
||||||
|
@ -20,6 +20,7 @@ import { Authorship } from '../../../revisions/authorship.entity';
|
||||||
import { Revision } from '../../../revisions/revision.entity';
|
import { Revision } from '../../../revisions/revision.entity';
|
||||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||||
import { Identity } from '../../../users/identity.entity';
|
import { Identity } from '../../../users/identity.entity';
|
||||||
|
import { Session } from '../../../users/session.entity';
|
||||||
import { User } from '../../../users/user.entity';
|
import { User } from '../../../users/user.entity';
|
||||||
import { UsersModule } from '../../../users/users.module';
|
import { UsersModule } from '../../../users/users.module';
|
||||||
import { MeController } from './me.controller';
|
import { MeController } from './me.controller';
|
||||||
|
@ -62,8 +63,6 @@ describe('Me Controller', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Identity))
|
.overrideProvider(getRepositoryToken(Identity))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Revision))
|
.overrideProvider(getRepositoryToken(Revision))
|
||||||
|
@ -80,6 +79,10 @@ describe('Me Controller', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<MeController>(MeController);
|
controller = module.get<MeController>(MeController);
|
||||||
|
|
|
@ -7,12 +7,12 @@
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
import { Author } from '../../../authors/author.entity';
|
||||||
import appConfigMock from '../../../config/mock/app.config.mock';
|
import appConfigMock from '../../../config/mock/app.config.mock';
|
||||||
import mediaConfigMock from '../../../config/mock/media.config.mock';
|
import mediaConfigMock from '../../../config/mock/media.config.mock';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
import { MediaUpload } from '../../../media/media-upload.entity';
|
import { MediaUpload } from '../../../media/media-upload.entity';
|
||||||
import { MediaModule } from '../../../media/media.module';
|
import { MediaModule } from '../../../media/media.module';
|
||||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
|
||||||
import { Note } from '../../../notes/note.entity';
|
import { Note } from '../../../notes/note.entity';
|
||||||
import { NotesModule } from '../../../notes/notes.module';
|
import { NotesModule } from '../../../notes/notes.module';
|
||||||
import { Tag } from '../../../notes/tag.entity';
|
import { Tag } from '../../../notes/tag.entity';
|
||||||
|
@ -20,6 +20,7 @@ import { Authorship } from '../../../revisions/authorship.entity';
|
||||||
import { Revision } from '../../../revisions/revision.entity';
|
import { Revision } from '../../../revisions/revision.entity';
|
||||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||||
import { Identity } from '../../../users/identity.entity';
|
import { Identity } from '../../../users/identity.entity';
|
||||||
|
import { Session } from '../../../users/session.entity';
|
||||||
import { User } from '../../../users/user.entity';
|
import { User } from '../../../users/user.entity';
|
||||||
import { MediaController } from './media.controller';
|
import { MediaController } from './media.controller';
|
||||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||||
|
@ -42,8 +43,6 @@ describe('Media Controller', () => {
|
||||||
NotesModule,
|
NotesModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
|
@ -66,6 +65,10 @@ describe('Media Controller', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<MediaController>(MediaController);
|
controller = module.get<MediaController>(MediaController);
|
||||||
|
|
|
@ -10,8 +10,8 @@ import {
|
||||||
getRepositoryToken,
|
getRepositoryToken,
|
||||||
TypeOrmModule,
|
TypeOrmModule,
|
||||||
} from '@nestjs/typeorm';
|
} from '@nestjs/typeorm';
|
||||||
|
import { Author } from '../../../authors/author.entity';
|
||||||
import { LoggerModule } from '../../../logger/logger.module';
|
import { LoggerModule } from '../../../logger/logger.module';
|
||||||
import { AuthorColor } from '../../../notes/author-color.entity';
|
|
||||||
import { Note } from '../../../notes/note.entity';
|
import { Note } from '../../../notes/note.entity';
|
||||||
import { NotesService } from '../../../notes/notes.service';
|
import { NotesService } from '../../../notes/notes.service';
|
||||||
import { Tag } from '../../../notes/tag.entity';
|
import { Tag } from '../../../notes/tag.entity';
|
||||||
|
@ -20,6 +20,7 @@ import { Revision } from '../../../revisions/revision.entity';
|
||||||
import { RevisionsModule } from '../../../revisions/revisions.module';
|
import { RevisionsModule } from '../../../revisions/revisions.module';
|
||||||
import { AuthToken } from '../../../auth/auth-token.entity';
|
import { AuthToken } from '../../../auth/auth-token.entity';
|
||||||
import { Identity } from '../../../users/identity.entity';
|
import { Identity } from '../../../users/identity.entity';
|
||||||
|
import { Session } from '../../../users/session.entity';
|
||||||
import { User } from '../../../users/user.entity';
|
import { User } from '../../../users/user.entity';
|
||||||
import { UsersModule } from '../../../users/users.module';
|
import { UsersModule } from '../../../users/users.module';
|
||||||
import { NotesController } from './notes.controller';
|
import { NotesController } from './notes.controller';
|
||||||
|
@ -52,6 +53,10 @@ describe('Notes Controller', () => {
|
||||||
provide: getRepositoryToken(Tag),
|
provide: getRepositoryToken(Tag),
|
||||||
useValue: {},
|
useValue: {},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(User),
|
||||||
|
useValue: {},
|
||||||
|
},
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
RevisionsModule,
|
RevisionsModule,
|
||||||
|
@ -76,8 +81,6 @@ describe('Notes Controller', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(User))
|
.overrideProvider(getRepositoryToken(User))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
|
@ -98,6 +101,10 @@ describe('Notes Controller', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
controller = module.get<NotesController>(NotesController);
|
controller = module.get<NotesController>(NotesController);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { Session } from '../users/session.entity';
|
||||||
import { AuthService } from './auth.service';
|
import { AuthService } from './auth.service';
|
||||||
import { PassportModule } from '@nestjs/passport';
|
import { PassportModule } from '@nestjs/passport';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
@ -49,6 +50,8 @@ describe('AuthService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(User))
|
.overrideProvider(getRepositoryToken(User))
|
||||||
.useClass(Repository)
|
.useClass(Repository)
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
service = module.get<AuthService>(AuthService);
|
service = module.get<AuthService>(AuthService);
|
||||||
|
|
|
@ -4,14 +4,68 @@
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Entity, PrimaryGeneratedColumn } from 'typeorm';
|
import {
|
||||||
import { Note } from '../notes/note.entity';
|
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()
|
@Entity()
|
||||||
export class Author {
|
export class Author {
|
||||||
//TODO: Still missing many properties
|
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number;
|
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 { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { Author } from '../authors/author.entity';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
|
import { Session } from '../users/session.entity';
|
||||||
import { HistoryService } from './history.service';
|
import { HistoryService } from './history.service';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
import { NotesModule } from '../notes/notes.module';
|
import { NotesModule } from '../notes/notes.module';
|
||||||
import { getConnectionToken, getRepositoryToken } from '@nestjs/typeorm';
|
import { getConnectionToken, getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import { Identity } from '../users/identity.entity';
|
import { Identity } from '../users/identity.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { AuthorColor } from '../notes/author-color.entity';
|
|
||||||
import { Authorship } from '../revisions/authorship.entity';
|
import { Authorship } from '../revisions/authorship.entity';
|
||||||
import { HistoryEntry } from './history-entry.entity';
|
import { HistoryEntry } from './history-entry.entity';
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
|
@ -75,8 +76,6 @@ describe('HistoryService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Revision))
|
.overrideProvider(getRepositoryToken(Revision))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Note))
|
.overrideProvider(getRepositoryToken(Note))
|
||||||
|
@ -89,6 +88,10 @@ describe('HistoryService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
service = module.get<HistoryService>(HistoryService);
|
service = module.get<HistoryService>(HistoryService);
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
import { Author } from '../authors/author.entity';
|
||||||
import mediaConfigMock from '../config/mock/media.config.mock';
|
import mediaConfigMock from '../config/mock/media.config.mock';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { AuthorColor } from '../notes/author-color.entity';
|
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
import { NotesModule } from '../notes/notes.module';
|
import { NotesModule } from '../notes/notes.module';
|
||||||
import { Tag } from '../notes/tag.entity';
|
import { Tag } from '../notes/tag.entity';
|
||||||
|
@ -17,6 +17,7 @@ import { Authorship } from '../revisions/authorship.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
import { Identity } from '../users/identity.entity';
|
import { Identity } from '../users/identity.entity';
|
||||||
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
import { FilesystemBackend } from './backends/filesystem-backend';
|
import { FilesystemBackend } from './backends/filesystem-backend';
|
||||||
|
@ -56,8 +57,6 @@ describe('MediaService', () => {
|
||||||
UsersModule,
|
UsersModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
|
@ -80,6 +79,10 @@ describe('MediaService', () => {
|
||||||
.useClass(Repository)
|
.useClass(Repository)
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
service = module.get<MediaService>(MediaService);
|
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 { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { AuthorColor } from './author-color.entity';
|
|
||||||
import { Tag } from './tag.entity';
|
import { Tag } from './tag.entity';
|
||||||
import { HistoryEntry } from '../history/history-entry.entity';
|
import { HistoryEntry } from '../history/history-entry.entity';
|
||||||
import { MediaUpload } from '../media/media-upload.entity';
|
import { MediaUpload } from '../media/media-upload.entity';
|
||||||
|
@ -59,8 +58,6 @@ export class Note {
|
||||||
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((_) => AuthorColor, (authorColor) => authorColor.note)
|
|
||||||
authorColors: AuthorColor[];
|
|
||||||
@OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user)
|
@OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user)
|
||||||
historyEntries: HistoryEntry[];
|
historyEntries: HistoryEntry[];
|
||||||
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note)
|
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.note)
|
||||||
|
@ -90,7 +87,6 @@ export class Note {
|
||||||
newNote.alias = alias ?? null;
|
newNote.alias = alias ?? null;
|
||||||
newNote.viewCount = 0;
|
newNote.viewCount = 0;
|
||||||
newNote.owner = owner ?? null;
|
newNote.owner = owner ?? null;
|
||||||
newNote.authorColors = [];
|
|
||||||
newNote.userPermissions = [];
|
newNote.userPermissions = [];
|
||||||
newNote.groupPermissions = [];
|
newNote.groupPermissions = [];
|
||||||
newNote.revisions = Promise.resolve([]) as Promise<Revision[]>;
|
newNote.revisions = Promise.resolve([]) as Promise<Revision[]>;
|
||||||
|
|
|
@ -5,27 +5,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { forwardRef, Module } from '@nestjs/common';
|
import { forwardRef, Module } from '@nestjs/common';
|
||||||
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { GroupsModule } from '../groups/groups.module';
|
||||||
import { LoggerModule } from '../logger/logger.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 { RevisionsModule } from '../revisions/revisions.module';
|
||||||
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
import { AuthorColor } from './author-color.entity';
|
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
import { NotesService } from './notes.service';
|
import { NotesService } from './notes.service';
|
||||||
import { Tag } from './tag.entity';
|
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({
|
@Module({
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forFeature([
|
TypeOrmModule.forFeature([
|
||||||
Note,
|
Note,
|
||||||
AuthorColor,
|
|
||||||
Tag,
|
Tag,
|
||||||
NoteGroupPermission,
|
NoteGroupPermission,
|
||||||
NoteUserPermission,
|
NoteUserPermission,
|
||||||
|
User,
|
||||||
]),
|
]),
|
||||||
forwardRef(() => RevisionsModule),
|
forwardRef(() => RevisionsModule),
|
||||||
UsersModule,
|
UsersModule,
|
||||||
|
|
|
@ -6,15 +6,16 @@
|
||||||
|
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
import { Author } from '../authors/author.entity';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { Authorship } from '../revisions/authorship.entity';
|
import { Authorship } from '../revisions/authorship.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { RevisionsModule } from '../revisions/revisions.module';
|
import { RevisionsModule } from '../revisions/revisions.module';
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
import { Identity } from '../users/identity.entity';
|
import { Identity } from '../users/identity.entity';
|
||||||
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
import { AuthorColor } from './author-color.entity';
|
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
import { NotesService } from './notes.service';
|
import { NotesService } from './notes.service';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
@ -45,6 +46,12 @@ describe('NotesService', () => {
|
||||||
let forbiddenNoteId: string;
|
let forbiddenNoteId: string;
|
||||||
|
|
||||||
beforeEach(async () => {
|
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({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
providers: [
|
providers: [
|
||||||
NotesService,
|
NotesService,
|
||||||
|
@ -56,6 +63,10 @@ describe('NotesService', () => {
|
||||||
provide: getRepositoryToken(Tag),
|
provide: getRepositoryToken(Tag),
|
||||||
useClass: Repository,
|
useClass: Repository,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(User),
|
||||||
|
useValue: userRepo,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
|
@ -73,15 +84,13 @@ describe('NotesService', () => {
|
||||||
.overrideProvider(getRepositoryToken(Tag))
|
.overrideProvider(getRepositoryToken(Tag))
|
||||||
.useClass(Repository)
|
.useClass(Repository)
|
||||||
.overrideProvider(getRepositoryToken(User))
|
.overrideProvider(getRepositoryToken(User))
|
||||||
.useClass(Repository)
|
.useValue(userRepo)
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Identity))
|
.overrideProvider(getRepositoryToken(Identity))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Revision))
|
.overrideProvider(getRepositoryToken(Revision))
|
||||||
.useClass(Repository)
|
.useClass(Repository)
|
||||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||||
|
@ -90,6 +99,10 @@ describe('NotesService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useClass(Repository)
|
.useClass(Repository)
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
const config = module.get<ConfigService>(ConfigService);
|
const config = module.get<ConfigService>(ConfigService);
|
||||||
|
@ -658,7 +671,8 @@ describe('NotesService', () => {
|
||||||
describe('toNoteMetadataDto', () => {
|
describe('toNoteMetadataDto', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const user = User.create('hardcoded', 'Testy') as User;
|
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 group = Group.create('testGroup', 'testGroup');
|
||||||
const content = 'testContent';
|
const content = 'testContent';
|
||||||
jest
|
jest
|
||||||
|
@ -668,33 +682,36 @@ describe('NotesService', () => {
|
||||||
const revisions = await note.revisions;
|
const revisions = await note.revisions;
|
||||||
revisions[0].authorships = [
|
revisions[0].authorships = [
|
||||||
{
|
{
|
||||||
user: otherUser,
|
|
||||||
revisions: revisions,
|
revisions: revisions,
|
||||||
startPos: 0,
|
startPos: 0,
|
||||||
endPos: 1,
|
endPos: 1,
|
||||||
updatedAt: new Date(1549312452000),
|
updatedAt: new Date(1549312452000),
|
||||||
|
author: author,
|
||||||
} as Authorship,
|
} as Authorship,
|
||||||
{
|
{
|
||||||
user: user,
|
|
||||||
revisions: revisions,
|
revisions: revisions,
|
||||||
startPos: 0,
|
startPos: 0,
|
||||||
endPos: 1,
|
endPos: 1,
|
||||||
updatedAt: new Date(1549312452001),
|
updatedAt: new Date(1549312452001),
|
||||||
|
author: author,
|
||||||
} as Authorship,
|
} as Authorship,
|
||||||
];
|
];
|
||||||
revisions[0].createdAt = new Date(1549312452000);
|
revisions[0].createdAt = new Date(1549312452000);
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValue(revisions[0]);
|
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.publicId = 'testId';
|
||||||
note.alias = 'testAlias';
|
note.alias = 'testAlias';
|
||||||
note.title = 'testTitle';
|
note.title = 'testTitle';
|
||||||
note.description = 'testDescription';
|
note.description = 'testDescription';
|
||||||
note.authorColors = [
|
|
||||||
{
|
|
||||||
note: note,
|
|
||||||
user: user,
|
|
||||||
color: 'red',
|
|
||||||
} as AuthorColor,
|
|
||||||
];
|
|
||||||
note.owner = user;
|
note.owner = user;
|
||||||
note.userPermissions = [
|
note.userPermissions = [
|
||||||
{
|
{
|
||||||
|
@ -748,6 +765,8 @@ describe('NotesService', () => {
|
||||||
describe('toNoteDto', () => {
|
describe('toNoteDto', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const user = User.create('hardcoded', 'Testy') as User;
|
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;
|
const otherUser = User.create('other hardcoded', 'Testy2') as User;
|
||||||
otherUser.userName = 'other hardcoded user';
|
otherUser.userName = 'other hardcoded user';
|
||||||
const group = Group.create('testGroup', 'testGroup');
|
const group = Group.create('testGroup', 'testGroup');
|
||||||
|
@ -759,18 +778,18 @@ describe('NotesService', () => {
|
||||||
const revisions = await note.revisions;
|
const revisions = await note.revisions;
|
||||||
revisions[0].authorships = [
|
revisions[0].authorships = [
|
||||||
{
|
{
|
||||||
user: otherUser,
|
|
||||||
revisions: revisions,
|
revisions: revisions,
|
||||||
startPos: 0,
|
startPos: 0,
|
||||||
endPos: 1,
|
endPos: 1,
|
||||||
updatedAt: new Date(1549312452000),
|
updatedAt: new Date(1549312452000),
|
||||||
|
author: author,
|
||||||
} as Authorship,
|
} as Authorship,
|
||||||
{
|
{
|
||||||
user: user,
|
|
||||||
revisions: revisions,
|
revisions: revisions,
|
||||||
startPos: 0,
|
startPos: 0,
|
||||||
endPos: 1,
|
endPos: 1,
|
||||||
updatedAt: new Date(1549312452001),
|
updatedAt: new Date(1549312452001),
|
||||||
|
author: author,
|
||||||
} as Authorship,
|
} as Authorship,
|
||||||
];
|
];
|
||||||
revisions[0].createdAt = new Date(1549312452000);
|
revisions[0].createdAt = new Date(1549312452000);
|
||||||
|
@ -778,17 +797,20 @@ describe('NotesService', () => {
|
||||||
.spyOn(revisionRepo, 'findOne')
|
.spyOn(revisionRepo, 'findOne')
|
||||||
.mockResolvedValue(revisions[0])
|
.mockResolvedValue(revisions[0])
|
||||||
.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.publicId = 'testId';
|
||||||
note.alias = 'testAlias';
|
note.alias = 'testAlias';
|
||||||
note.title = 'testTitle';
|
note.title = 'testTitle';
|
||||||
note.description = 'testDescription';
|
note.description = 'testDescription';
|
||||||
note.authorColors = [
|
|
||||||
{
|
|
||||||
note: note,
|
|
||||||
user: user,
|
|
||||||
color: 'red',
|
|
||||||
} as AuthorColor,
|
|
||||||
];
|
|
||||||
note.owner = user;
|
note.owner = user;
|
||||||
note.userPermissions = [
|
note.userPermissions = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -41,6 +41,7 @@ export class NotesService {
|
||||||
private readonly logger: ConsoleLoggerService,
|
private readonly logger: ConsoleLoggerService,
|
||||||
@InjectRepository(Note) private noteRepository: Repository<Note>,
|
@InjectRepository(Note) private noteRepository: Repository<Note>,
|
||||||
@InjectRepository(Tag) private tagRepository: Repository<Tag>,
|
@InjectRepository(Tag) private tagRepository: Repository<Tag>,
|
||||||
|
@InjectRepository(User) private userRepository: Repository<User>,
|
||||||
@Inject(UsersService) private usersService: UsersService,
|
@Inject(UsersService) private usersService: UsersService,
|
||||||
@Inject(GroupsService) private groupsService: GroupsService,
|
@Inject(GroupsService) private groupsService: GroupsService,
|
||||||
@Inject(forwardRef(() => RevisionsService))
|
@Inject(forwardRef(() => RevisionsService))
|
||||||
|
@ -60,13 +61,7 @@ export class NotesService {
|
||||||
async getUserNotes(user: User): Promise<Note[]> {
|
async getUserNotes(user: User): Promise<Note[]> {
|
||||||
const notes = await this.noteRepository.find({
|
const notes = await this.noteRepository.find({
|
||||||
where: { owner: user },
|
where: { owner: user },
|
||||||
relations: [
|
relations: ['owner', 'userPermissions', 'groupPermissions', 'tags'],
|
||||||
'owner',
|
|
||||||
'userPermissions',
|
|
||||||
'groupPermissions',
|
|
||||||
'authorColors',
|
|
||||||
'tags',
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
if (notes === undefined) {
|
if (notes === undefined) {
|
||||||
return [];
|
return [];
|
||||||
|
@ -173,7 +168,6 @@ export class NotesService {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
relations: [
|
relations: [
|
||||||
'authorColors',
|
|
||||||
'owner',
|
'owner',
|
||||||
'groupPermissions',
|
'groupPermissions',
|
||||||
'groupPermissions.group',
|
'groupPermissions.group',
|
||||||
|
@ -195,6 +189,22 @@ export class NotesService {
|
||||||
return note;
|
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
|
* Check if the provided note id or alias is not forbidden
|
||||||
* @param noteIdOrAlias - the alias or id in question
|
* @param noteIdOrAlias - the alias or id in question
|
||||||
|
@ -317,7 +327,7 @@ export class NotesService {
|
||||||
// the user of that Authorship is the updateUser
|
// the user of that Authorship is the updateUser
|
||||||
return lastRevision.authorships.sort(
|
return lastRevision.authorships.sort(
|
||||||
(a, b) => b.updatedAt.getTime() - a.updatedAt.getTime(),
|
(a, b) => b.updatedAt.getTime() - a.updatedAt.getTime(),
|
||||||
)[0].user;
|
)[0].author.user;
|
||||||
}
|
}
|
||||||
// If there are no Authorships, the owner is the updateUser
|
// If there are no Authorships, the owner is the updateUser
|
||||||
return note.owner;
|
return note.owner;
|
||||||
|
@ -365,9 +375,7 @@ export class NotesService {
|
||||||
title: note.title ?? '',
|
title: note.title ?? '',
|
||||||
createTime: (await this.getFirstRevision(note)).createdAt,
|
createTime: (await this.getFirstRevision(note)).createdAt,
|
||||||
description: note.description ?? '',
|
description: note.description ?? '',
|
||||||
editedBy: note.authorColors.map(
|
editedBy: (await this.getAuthorUsers(note)).map((user) => user.userName),
|
||||||
(authorColor) => authorColor.user.userName,
|
|
||||||
),
|
|
||||||
permissions: this.toNotePermissionsDto(note),
|
permissions: this.toNotePermissionsDto(note),
|
||||||
tags: this.toTagList(note),
|
tags: this.toTagList(note),
|
||||||
updateTime: (await this.getLatestRevision(note)).createdAt,
|
updateTime: (await this.getLatestRevision(note)).createdAt,
|
||||||
|
|
|
@ -7,15 +7,16 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
|
import { Author } from '../authors/author.entity';
|
||||||
import { Group } from '../groups/group.entity';
|
import { Group } from '../groups/group.entity';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { AuthorColor } from '../notes/author-color.entity';
|
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
import { NotesModule } from '../notes/notes.module';
|
import { NotesModule } from '../notes/notes.module';
|
||||||
import { Tag } from '../notes/tag.entity';
|
import { Tag } from '../notes/tag.entity';
|
||||||
import { Authorship } from '../revisions/authorship.entity';
|
import { Authorship } from '../revisions/authorship.entity';
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { Identity } from '../users/identity.entity';
|
import { Identity } from '../users/identity.entity';
|
||||||
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
import { NoteGroupPermission } from './note-group-permission.entity';
|
import { NoteGroupPermission } from './note-group-permission.entity';
|
||||||
|
@ -50,8 +51,6 @@ describe('PermissionsService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(Revision))
|
.overrideProvider(getRepositoryToken(Revision))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Note))
|
.overrideProvider(getRepositoryToken(Note))
|
||||||
|
@ -64,6 +63,10 @@ describe('PermissionsService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
permissionsService = module.get<PermissionsService>(PermissionsService);
|
permissionsService = module.get<PermissionsService>(PermissionsService);
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,11 +13,11 @@ import {
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { User } from '../users/user.entity';
|
import { Author } from '../authors/author.entity';
|
||||||
import { Revision } from './revision.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()
|
@Entity()
|
||||||
export class Authorship {
|
export class Authorship {
|
||||||
|
@ -31,10 +31,10 @@ export class Authorship {
|
||||||
revisions: Revision[];
|
revisions: Revision[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* User this authorship represents
|
* Author that created the change
|
||||||
*/
|
*/
|
||||||
@ManyToOne((_) => User)
|
@ManyToOne(() => Author, (author) => author.authorships)
|
||||||
user: User;
|
author: Author;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
startPos: number;
|
startPos: number;
|
||||||
|
@ -47,4 +47,15 @@ export class Authorship {
|
||||||
|
|
||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
updatedAt: Date;
|
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 { forwardRef, Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { AuthorsModule } from '../authors/authors.module';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { NotesModule } from '../notes/notes.module';
|
import { NotesModule } from '../notes/notes.module';
|
||||||
import { Authorship } from './authorship.entity';
|
import { Authorship } from './authorship.entity';
|
||||||
|
@ -19,6 +20,7 @@ import { ConfigModule } from '@nestjs/config';
|
||||||
forwardRef(() => NotesModule),
|
forwardRef(() => NotesModule),
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
|
AuthorsModule,
|
||||||
],
|
],
|
||||||
providers: [RevisionsService],
|
providers: [RevisionsService],
|
||||||
exports: [RevisionsService],
|
exports: [RevisionsService],
|
||||||
|
|
|
@ -7,13 +7,15 @@
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
|
import { Author } from '../authors/author.entity';
|
||||||
|
import { AuthorsModule } from '../authors/authors.module';
|
||||||
import { NotInDBError } from '../errors/errors';
|
import { NotInDBError } from '../errors/errors';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { AuthorColor } from '../notes/author-color.entity';
|
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
import { NotesModule } from '../notes/notes.module';
|
import { NotesModule } from '../notes/notes.module';
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
import { Identity } from '../users/identity.entity';
|
import { Identity } from '../users/identity.entity';
|
||||||
|
import { Session } from '../users/session.entity';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { Authorship } from './authorship.entity';
|
import { Authorship } from './authorship.entity';
|
||||||
import { Revision } from './revision.entity';
|
import { Revision } from './revision.entity';
|
||||||
|
@ -49,8 +51,6 @@ describe('RevisionsService', () => {
|
||||||
})
|
})
|
||||||
.overrideProvider(getRepositoryToken(Authorship))
|
.overrideProvider(getRepositoryToken(Authorship))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
|
||||||
.useValue({})
|
|
||||||
.overrideProvider(getRepositoryToken(User))
|
.overrideProvider(getRepositoryToken(User))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
|
@ -69,6 +69,10 @@ describe('RevisionsService', () => {
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
|
.useValue({})
|
||||||
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
|
|
||||||
service = module.get<RevisionsService>(RevisionsService);
|
service = module.get<RevisionsService>(RevisionsService);
|
||||||
|
|
49
src/seed.ts
49
src/seed.ts
|
@ -5,6 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { createConnection } from 'typeorm';
|
import { createConnection } from 'typeorm';
|
||||||
|
import { Author } from './authors/author.entity';
|
||||||
|
import { Session } from './users/session.entity';
|
||||||
import { User } from './users/user.entity';
|
import { User } from './users/user.entity';
|
||||||
import { Note } from './notes/note.entity';
|
import { Note } from './notes/note.entity';
|
||||||
import { Revision } from './revisions/revision.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 { NoteGroupPermission } from './permissions/note-group-permission.entity';
|
||||||
import { NoteUserPermission } from './permissions/note-user-permission.entity';
|
import { NoteUserPermission } from './permissions/note-user-permission.entity';
|
||||||
import { Group } from './groups/group.entity';
|
import { Group } from './groups/group.entity';
|
||||||
import { AuthorColor } from './notes/author-color.entity';
|
|
||||||
import { HistoryEntry } from './history/history-entry.entity';
|
import { HistoryEntry } from './history/history-entry.entity';
|
||||||
import { MediaUpload } from './media/media-upload.entity';
|
import { MediaUpload } from './media/media-upload.entity';
|
||||||
import { Tag } from './notes/tag.entity';
|
import { Tag } from './notes/tag.entity';
|
||||||
|
@ -33,28 +34,50 @@ createConnection({
|
||||||
NoteGroupPermission,
|
NoteGroupPermission,
|
||||||
NoteUserPermission,
|
NoteUserPermission,
|
||||||
Group,
|
Group,
|
||||||
AuthorColor,
|
|
||||||
HistoryEntry,
|
HistoryEntry,
|
||||||
MediaUpload,
|
MediaUpload,
|
||||||
Tag,
|
Tag,
|
||||||
AuthToken,
|
AuthToken,
|
||||||
Identity,
|
Identity,
|
||||||
|
Author,
|
||||||
|
Session,
|
||||||
],
|
],
|
||||||
synchronize: true,
|
synchronize: true,
|
||||||
logging: false,
|
logging: false,
|
||||||
|
dropSchema: true,
|
||||||
})
|
})
|
||||||
.then(async (connection) => {
|
.then(async (connection) => {
|
||||||
const user = User.create('hardcoded', 'Test User');
|
const users = [];
|
||||||
const note = Note.create(undefined, 'test');
|
users.push(User.create('hardcoded', 'Test User 1'));
|
||||||
const revision = Revision.create(
|
users.push(User.create('hardcoded_2', 'Test User 2'));
|
||||||
'This is a test note',
|
users.push(User.create('hardcoded_3', 'Test User 3'));
|
||||||
'This is a test note',
|
const notes: Note[] = [];
|
||||||
);
|
notes.push(Note.create(undefined, 'test'));
|
||||||
note.revisions = Promise.all([revision]);
|
notes.push(Note.create(undefined, 'test2'));
|
||||||
note.userPermissions = [];
|
notes.push(Note.create(undefined, 'test3'));
|
||||||
note.groupPermissions = [];
|
|
||||||
user.ownedNotes = [note];
|
for (let i = 0; i < 3; i++) {
|
||||||
await connection.manager.save([user, note, revision]);
|
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);
|
const foundUser = await connection.manager.findOne(User);
|
||||||
if (!foundUser) {
|
if (!foundUser) {
|
||||||
throw new Error('Could not find freshly seeded user. Aborting.');
|
throw new Error('Could not find freshly seeded user. Aborting.');
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ISession } from 'connect-typeorm';
|
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()
|
@Entity()
|
||||||
export class Session implements ISession {
|
export class Session implements ISession {
|
||||||
|
@ -18,4 +19,7 @@ export class Session implements ISession {
|
||||||
|
|
||||||
@Column('text')
|
@Column('text')
|
||||||
public json = '';
|
public json = '';
|
||||||
|
|
||||||
|
@ManyToOne(() => Author, (author) => author.sessions)
|
||||||
|
author: Author;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import {
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
import { Column, OneToMany } from 'typeorm';
|
import { Column, OneToMany } from 'typeorm';
|
||||||
|
import { Author } from '../authors/author.entity';
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
import { Identity } from './identity.entity';
|
import { Identity } from './identity.entity';
|
||||||
|
@ -68,6 +69,9 @@ export class User {
|
||||||
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.user)
|
@OneToMany((_) => MediaUpload, (mediaUpload) => mediaUpload.user)
|
||||||
mediaUploads: MediaUpload[];
|
mediaUploads: MediaUpload[];
|
||||||
|
|
||||||
|
@OneToMany(() => Author, (author) => author.user)
|
||||||
|
authors: Author[];
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||||
private constructor() {}
|
private constructor() {}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,12 @@ import { Module } from '@nestjs/common';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { Identity } from './identity.entity';
|
import { Identity } from './identity.entity';
|
||||||
|
import { Session } from './session.entity';
|
||||||
import { User } from './user.entity';
|
import { User } from './user.entity';
|
||||||
import { UsersService } from './users.service';
|
import { UsersService } from './users.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [TypeOrmModule.forFeature([User, Identity]), LoggerModule],
|
imports: [TypeOrmModule.forFeature([User, Identity, Session]), LoggerModule],
|
||||||
providers: [UsersService],
|
providers: [UsersService],
|
||||||
exports: [UsersService],
|
exports: [UsersService],
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue