mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-25 03:06:31 -05:00
Add relation between User and Group
This represents the users which are members of this group Signed-off-by: Yannick Bungers <git@innay.de>
This commit is contained in:
parent
8a33f75cf9
commit
68cbb5a9c2
12 changed files with 103 additions and 16 deletions
|
@ -119,6 +119,11 @@ entity "note_group_permission" {
|
|||
*canEdit : boolean
|
||||
}
|
||||
|
||||
entity "group_members_user" {
|
||||
*group : number <<FK group>>
|
||||
*member : uuid <<FK user>>
|
||||
}
|
||||
|
||||
entity "tag" {
|
||||
*id: number <<generated>>
|
||||
*name: text
|
||||
|
@ -144,16 +149,16 @@ entity "history_entry" {
|
|||
|
||||
user "1" -- "0..*" note: owner
|
||||
user "1" -u- "1..*" identity
|
||||
user "1" - "1..*" auth_token: authTokens
|
||||
user "1" -l- "1..*" session
|
||||
user "1" - "0..*" media_upload
|
||||
user "1" -l- "1..*" auth_token: authTokens
|
||||
user "1" -r- "1..*" session
|
||||
user "1" -- "0..*" media_upload
|
||||
user "1" - "0..*" history_entry
|
||||
user "0..*" -- "0..*" note
|
||||
user "1" - "0..*" authorship
|
||||
user "1" -- "0..*" authorship
|
||||
|
||||
(user, note) . author_colors
|
||||
|
||||
revision "0..*" - "0..*" authorship
|
||||
revision "0..*" -- "0..*" authorship
|
||||
(revision, authorship) .. revision_authorship
|
||||
|
||||
media_upload "0..*" -- "1" note
|
||||
|
@ -161,9 +166,11 @@ note "1" - "1..*" revision
|
|||
note "1" - "0..*" history_entry
|
||||
note "0..*" -l- "0..*" tag
|
||||
note "0..*" -- "0..*" group
|
||||
user "1..*" -- "0..*" group
|
||||
|
||||
user "0..*" -- "0..*" note
|
||||
(user, note) . note_user_permission
|
||||
(note, group) . note_group_permission
|
||||
(user, group) . group_members_user
|
||||
|
||||
@enduml
|
||||
|
|
|
@ -20,6 +20,8 @@ import { User } from '../../../users/user.entity';
|
|||
import { UsersModule } from '../../../users/users.module';
|
||||
import { MeController } from './me.controller';
|
||||
import { HistoryEntry } from '../../../history/history-entry.entity';
|
||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
|
||||
|
||||
describe('Me Controller', () => {
|
||||
let controller: MeController;
|
||||
|
@ -47,6 +49,10 @@ describe('Me Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(HistoryEntry))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MeController>(MeController);
|
||||
|
|
|
@ -22,6 +22,8 @@ import { AuthToken } from '../../../auth/auth-token.entity';
|
|||
import { Identity } from '../../../users/identity.entity';
|
||||
import { User } from '../../../users/user.entity';
|
||||
import { MediaController } from './media.controller';
|
||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
|
||||
|
||||
describe('Media Controller', () => {
|
||||
let controller: MediaController;
|
||||
|
@ -57,6 +59,10 @@ describe('Media Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MediaController>(MediaController);
|
||||
|
|
|
@ -19,8 +19,11 @@ import { Identity } from '../../../users/identity.entity';
|
|||
import { User } from '../../../users/user.entity';
|
||||
import { UsersModule } from '../../../users/users.module';
|
||||
import { NotesController } from './notes.controller';
|
||||
import { PermissionsModule } from '../../../permissions/permissions.module';
|
||||
import { HistoryModule } from '../../../history/history.module';
|
||||
import { HistoryEntry } from '../../../history/history-entry.entity';
|
||||
import { NoteGroupPermission } from '../../../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../../../permissions/note-user-permission.entity';
|
||||
|
||||
describe('Notes Controller', () => {
|
||||
let controller: NotesController;
|
||||
|
@ -39,7 +42,13 @@ describe('Notes Controller', () => {
|
|||
useValue: {},
|
||||
},
|
||||
],
|
||||
imports: [RevisionsModule, UsersModule, LoggerModule, HistoryModule],
|
||||
imports: [
|
||||
RevisionsModule,
|
||||
UsersModule,
|
||||
LoggerModule,
|
||||
PermissionsModule,
|
||||
HistoryModule,
|
||||
],
|
||||
})
|
||||
.overrideProvider(getRepositoryToken(Note))
|
||||
.useValue({})
|
||||
|
@ -61,6 +70,10 @@ describe('Notes Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(HistoryEntry))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<NotesController>(NotesController);
|
||||
|
|
|
@ -4,7 +4,14 @@
|
|||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
} from 'typeorm';
|
||||
import { User } from '../users/user.entity';
|
||||
|
||||
@Entity()
|
||||
export class Group {
|
||||
|
@ -26,4 +33,11 @@ export class Group {
|
|||
*/
|
||||
@Column()
|
||||
special: boolean;
|
||||
|
||||
@ManyToMany((_) => User, (user) => user.groups, {
|
||||
eager: true,
|
||||
cascade: true,
|
||||
})
|
||||
@JoinTable()
|
||||
members: User[];
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ import { AuthToken } from '../auth/auth-token.entity';
|
|||
import { Revision } from '../revisions/revision.entity';
|
||||
import { Repository } from 'typeorm';
|
||||
import { NotInDBError } from '../errors/errors';
|
||||
import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||
|
||||
describe('HistoryService', () => {
|
||||
let service: HistoryService;
|
||||
|
@ -54,6 +56,10 @@ describe('HistoryService', () => {
|
|||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<HistoryService>(HistoryService);
|
||||
|
@ -99,7 +105,7 @@ describe('HistoryService', () => {
|
|||
describe('createOrUpdateHistoryEntry', () => {
|
||||
describe('works', () => {
|
||||
it('without an preexisting entry', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
jest.spyOn(historyRepo, 'findOne').mockResolvedValueOnce(undefined);
|
||||
jest
|
||||
|
@ -118,7 +124,7 @@ describe('HistoryService', () => {
|
|||
});
|
||||
|
||||
it('with an preexisting entry', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
const historyEntry = HistoryEntry.create(
|
||||
user,
|
||||
|
@ -148,7 +154,7 @@ describe('HistoryService', () => {
|
|||
describe('updateHistoryEntry', () => {
|
||||
describe('works', () => {
|
||||
it('with an entry', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
const note = Note.create(user, alias);
|
||||
const historyEntry = HistoryEntry.create(user, note);
|
||||
|
@ -173,7 +179,7 @@ describe('HistoryService', () => {
|
|||
});
|
||||
|
||||
it('without an entry', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
const note = Note.create(user, alias);
|
||||
jest.spyOn(historyRepo, 'findOne').mockResolvedValueOnce(undefined);
|
||||
|
@ -192,7 +198,7 @@ describe('HistoryService', () => {
|
|||
describe('deleteHistoryEntry', () => {
|
||||
describe('works', () => {
|
||||
it('with an entry', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
const note = Note.create(user, alias);
|
||||
const historyEntry = HistoryEntry.create(user, note);
|
||||
|
@ -208,7 +214,7 @@ describe('HistoryService', () => {
|
|||
});
|
||||
|
||||
it('without an entry', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
const note = Note.create(user, alias);
|
||||
jest.spyOn(historyRepo, 'findOne').mockResolvedValueOnce(undefined);
|
||||
|
@ -225,7 +231,7 @@ describe('HistoryService', () => {
|
|||
describe('toHistoryEntryDto', () => {
|
||||
describe('works', () => {
|
||||
it('with aliased note', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const alias = 'alias';
|
||||
const title = 'title';
|
||||
const tags = ['tag1', 'tag2'];
|
||||
|
@ -247,7 +253,7 @@ describe('HistoryService', () => {
|
|||
});
|
||||
|
||||
it('with regular note', async () => {
|
||||
const user = new User();
|
||||
const user = {} as User;
|
||||
const title = 'title';
|
||||
const id = 'id';
|
||||
const tags = ['tag1', 'tag2'];
|
||||
|
|
|
@ -25,6 +25,8 @@ import { MediaService } from './media.service';
|
|||
import { Repository } from 'typeorm';
|
||||
import { promises as fs } from 'fs';
|
||||
import { ClientError, NotInDBError, PermissionError } from '../errors/errors';
|
||||
import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||
|
||||
describe('MediaService', () => {
|
||||
let service: MediaService;
|
||||
|
@ -70,6 +72,10 @@ describe('MediaService', () => {
|
|||
.useClass(Repository)
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(MediaUpload))
|
||||
.useClass(Repository)
|
||||
.compile();
|
||||
|
|
|
@ -13,10 +13,18 @@ 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';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Note, AuthorColor, Tag]),
|
||||
TypeOrmModule.forFeature([
|
||||
Note,
|
||||
AuthorColor,
|
||||
Tag,
|
||||
NoteGroupPermission,
|
||||
NoteUserPermission,
|
||||
]),
|
||||
forwardRef(() => RevisionsModule),
|
||||
UsersModule,
|
||||
LoggerModule,
|
||||
|
|
|
@ -18,6 +18,8 @@ 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';
|
||||
|
||||
describe('NotesService', () => {
|
||||
let service: NotesService;
|
||||
|
@ -53,6 +55,10 @@ describe('NotesService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
service = module.get<NotesService>(NotesService);
|
||||
});
|
||||
|
|
|
@ -159,6 +159,7 @@ export class NotesService {
|
|||
historyEntries: [],
|
||||
updatedAt: new Date(),
|
||||
userName: 'Testy',
|
||||
groups: [],
|
||||
},
|
||||
description: 'Very descriptive text.',
|
||||
userPermissions: [],
|
||||
|
|
|
@ -17,6 +17,8 @@ import { Authorship } from './authorship.entity';
|
|||
import { Revision } from './revision.entity';
|
||||
import { RevisionsService } from './revisions.service';
|
||||
import { Tag } from '../notes/tag.entity';
|
||||
import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
|
||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
||||
|
||||
describe('RevisionsService', () => {
|
||||
let service: RevisionsService;
|
||||
|
@ -48,6 +50,10 @@ describe('RevisionsService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<RevisionsService>(RevisionsService);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
import {
|
||||
CreateDateColumn,
|
||||
Entity,
|
||||
ManyToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
UpdateDateColumn,
|
||||
} from 'typeorm';
|
||||
|
@ -14,6 +15,7 @@ import { Column, OneToMany } from 'typeorm';
|
|||
import { Note } from '../notes/note.entity';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Identity } from './identity.entity';
|
||||
import { Group } from '../groups/group.entity';
|
||||
import { HistoryEntry } from '../history/history-entry.entity';
|
||||
|
||||
@Entity()
|
||||
|
@ -52,9 +54,15 @@ export class User {
|
|||
@OneToMany((_) => Identity, (identity) => identity.user)
|
||||
identities: Identity[];
|
||||
|
||||
@ManyToMany((_) => Group, (group) => group.members)
|
||||
groups: Group[];
|
||||
|
||||
@OneToMany((_) => HistoryEntry, (historyEntry) => historyEntry.user)
|
||||
historyEntries: HistoryEntry[];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
public static create(
|
||||
userName: string,
|
||||
displayName: string,
|
||||
|
|
Loading…
Reference in a new issue