mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-20 10:15:17 -04:00
Merge branch 'develop' into public-api-uploads
This commit is contained in:
commit
8a6e81e1c8
20 changed files with 919 additions and 683 deletions
|
@ -1,17 +1,16 @@
|
|||
@startuml
|
||||
' hide the spot
|
||||
hide circle
|
||||
|
||||
' avoid problems with angled crows feet
|
||||
skinparam linetype ortho
|
||||
skinparam nodesep 60
|
||||
|
||||
entity "Note" {
|
||||
*id : uuid <<generated>>
|
||||
--
|
||||
*shortid : text
|
||||
*alias : text
|
||||
alias : text
|
||||
*viewcount : number
|
||||
*ownerId : uuid <<FK User>>
|
||||
description: text
|
||||
title: text
|
||||
}
|
||||
|
||||
entity "User" {
|
||||
|
@ -49,7 +48,7 @@ entity "Identity" {
|
|||
passwordHash : text
|
||||
}
|
||||
|
||||
entity "Session" as seesion {
|
||||
entity "Session" {
|
||||
*id : text
|
||||
--
|
||||
*expiredAt : number
|
||||
|
@ -115,6 +114,11 @@ entity "Group" {
|
|||
*canEdit : boolean
|
||||
}
|
||||
|
||||
entity "Tag" {
|
||||
*id: number <<generated>>
|
||||
*name: text
|
||||
}
|
||||
|
||||
entity "MediaUpload" {
|
||||
*id : text <<unique>>
|
||||
--
|
||||
|
@ -125,20 +129,26 @@ entity "MediaUpload" {
|
|||
*createdAt : date
|
||||
}
|
||||
|
||||
Note "1" - "1..*" Revision
|
||||
User "1" -- "0..*" Note: owner
|
||||
User "1" -u- "1..*" Identity
|
||||
User "1" - "1..*" authToken
|
||||
User "1" -l- "1..*" Session
|
||||
User "1" - "0..*" MediaUpload
|
||||
User "0..*" -- "0..*" Note
|
||||
User "1" - "0..*" Authorship
|
||||
|
||||
(User, Note) . AuthorColors
|
||||
|
||||
Revision "0..*" - "0..*" Authorship
|
||||
(Revision, Authorship) .. RevisionAuthorship
|
||||
Authorship "0..*" -- "1" User
|
||||
Note "0..*" -- "1" User : owner
|
||||
Note "1" -- "0..*" NoteUserPermission
|
||||
NoteUserPermission "1" -- "1" User
|
||||
Note "1" -- "0..*" NoteGroupPermission
|
||||
NoteGroupPermission "0..*" -- "1" Group
|
||||
Identity "1..*" -- "1" User
|
||||
authToken "1..*" -- "1" User
|
||||
seesion "1..*" -- "1" User
|
||||
Note "0..*" -- "0..*" User : color
|
||||
(Note, User) .. AuthorColors
|
||||
|
||||
MediaUpload "0..*" -- "1" Note
|
||||
MediaUpload "0..*" -- "1" User
|
||||
Note "1" - "1..*" Revision
|
||||
Note "0..*" -l- "0..*" Tag
|
||||
Note "0..*" -- "0..*" Group
|
||||
|
||||
User "0..*" -- "0..*" Note
|
||||
(User, Note) . NoteUserPermission
|
||||
(Note, Group) . NoteGroupPermission
|
||||
|
||||
@enduml
|
||||
|
|
|
@ -47,6 +47,8 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/History"
|
||||
'401':
|
||||
"$ref": "#/components/responses/UnauthorizedError"
|
||||
|
@ -60,11 +62,11 @@ paths:
|
|||
description: JSON Object which contains id, title, tags, last visit time and pinned status
|
||||
responses:
|
||||
'200':
|
||||
description: The list of recently viewed notes and pinned notes.
|
||||
description: Information about the history entry
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/HistoryObject"
|
||||
"$ref": "#/components/schemas/History"
|
||||
'401':
|
||||
"$ref": "#/components/responses/UnauthorizedError"
|
||||
'404':
|
||||
|
@ -88,14 +90,14 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/HistoryObject"
|
||||
"$ref": "#/components/schemas/HistoryUpdate"
|
||||
responses:
|
||||
'200':
|
||||
description: The new history.
|
||||
description: The new history object.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/HistoryObject"
|
||||
"$ref": "#/components/schemas/History"
|
||||
'401':
|
||||
"$ref": "#/components/responses/UnauthorizedError"
|
||||
'404':
|
||||
|
@ -183,7 +185,7 @@ paths:
|
|||
markdownExample:
|
||||
"$ref": '#/components/examples/markdownExample'
|
||||
responses:
|
||||
'200':
|
||||
'201':
|
||||
description: Get information about the newly created note.
|
||||
content:
|
||||
application/json:
|
||||
|
@ -226,7 +228,7 @@ paths:
|
|||
- note
|
||||
summary: Imports some markdown data into a new note with a given alias
|
||||
operationId: createNoteWithAlias
|
||||
description: This endpoint equals to the above one except that the alias from the url will be assigned to the note if [FreeURL-mode](https://github.com/codimd/server/tree/master/docs/configuration-env-vars.md#users-and-privileges) is enabled.
|
||||
description: This endpoint creates a new note with the content of the HTTP request body and the alias from the URL parameter.
|
||||
requestBody:
|
||||
required: true
|
||||
description: The content of the note to be imported as markdown.
|
||||
|
@ -238,7 +240,7 @@ paths:
|
|||
markdownExample:
|
||||
"$ref": '#/components/examples/markdownExample'
|
||||
responses:
|
||||
'200':
|
||||
'201':
|
||||
description: Get information about the newly created note.
|
||||
content:
|
||||
application/json:
|
||||
|
@ -285,7 +287,7 @@ paths:
|
|||
- note
|
||||
summary: Imports some markdown data into an existing note, creating a new revision
|
||||
operationId: createNewRevisionForNote
|
||||
description: This endpoint equals to the above one except that the alias from the url will be assigned to the note if [FreeURL-mode](https://github.com/codimd/server/tree/master/docs/configuration-env-vars.md#users-and-privileges) is enabled.
|
||||
description: This endpoint updates the note content of an existing note. The old content is completely replaced and a new revision is created.
|
||||
requestBody:
|
||||
required: true
|
||||
description: The content of the note to be imported as markdown.
|
||||
|
@ -318,20 +320,14 @@ paths:
|
|||
text/plain:
|
||||
example: my-note
|
||||
/notes/{note}/metadata:
|
||||
put:
|
||||
get:
|
||||
tags:
|
||||
- note
|
||||
summary: Set the permissions of a note
|
||||
operationId: updateNoteMetadata
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/NoteMetadata"
|
||||
summary: Get the metadata of a note
|
||||
operationId: getNoteMetadata
|
||||
responses:
|
||||
'200':
|
||||
description: The updated permissions of the note.
|
||||
description: The metadata of the note.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
|
@ -350,18 +346,24 @@ paths:
|
|||
content:
|
||||
text/plain:
|
||||
example: my-note
|
||||
get:
|
||||
tags:
|
||||
- note
|
||||
summary: Get the permissions of a note
|
||||
operationId: getNoteMetadata
|
||||
responses:
|
||||
'200':
|
||||
description: The permissions of the note.
|
||||
/notes/{note}/permissions:
|
||||
put:
|
||||
tags: [ note ]
|
||||
summary: Set permissions of a note
|
||||
operationId: updateNotePermissions
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/NoteMetadata"
|
||||
"$ref": "#/components/schemas/NotePermissionsUpdate"
|
||||
responses:
|
||||
'200':
|
||||
description: The updated permissions of the note.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/NotePermissions"
|
||||
'401':
|
||||
"$ref": "#/components/responses/UnauthorizedError"
|
||||
'403':
|
||||
|
@ -389,6 +391,8 @@ paths:
|
|||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/NoteRevisionsMetadata"
|
||||
'401':
|
||||
"$ref": "#/components/responses/UnauthorizedError"
|
||||
|
@ -552,7 +556,7 @@ paths:
|
|||
required: true
|
||||
description: ID or alias of the parent note
|
||||
responses:
|
||||
'200':
|
||||
'201':
|
||||
description: The file was uploaded successfully.
|
||||
content:
|
||||
application/json:
|
||||
|
@ -642,6 +646,15 @@ components:
|
|||
properties:
|
||||
password:
|
||||
type: string
|
||||
GroupInfo:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
displayName:
|
||||
type: string
|
||||
special:
|
||||
type: boolean
|
||||
ImageProxyRequest:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -713,9 +726,32 @@ components:
|
|||
type: object
|
||||
properties:
|
||||
owner:
|
||||
type: string
|
||||
description: Username of the owner of the note
|
||||
sharedTo:
|
||||
$ref: "#/components/schemas/UserInfo"
|
||||
sharedToUsers:
|
||||
type: array
|
||||
description: Contains all users that can read the note and a boolean that denotes if they can also edit.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
user:
|
||||
$ref: "#/components/schemas/UserInfo"
|
||||
canEdit:
|
||||
type: boolean
|
||||
sharedToGroups:
|
||||
type: array
|
||||
description: Contains all groups that can read the note and a boolean that denotes if they can also edit.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
group:
|
||||
$ref: "#/components/schemas/GroupInfo"
|
||||
canEdit:
|
||||
type: boolean
|
||||
NotePermissionsUpdate:
|
||||
type: object
|
||||
description: Contains only title, description and tags of a note.
|
||||
properties:
|
||||
sharedToUsers:
|
||||
type: array
|
||||
description: Contains all usernames that can read the note and a boolean that denotes if they can also edit.
|
||||
items:
|
||||
|
@ -725,10 +761,17 @@ components:
|
|||
type: string
|
||||
canEdit:
|
||||
type: boolean
|
||||
|
||||
NoteRevisionsMetadata:
|
||||
sharedToGroups:
|
||||
type: array
|
||||
description: Contains all groups that can read the note and a boolean that denotes if they can also edit.
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
groupname:
|
||||
type: string
|
||||
canEdit:
|
||||
type: boolean
|
||||
NoteRevisionsMetadata:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
|
@ -840,7 +883,7 @@ components:
|
|||
type: boolean
|
||||
disconnectSocketQueueLength:
|
||||
type: integer
|
||||
HistoryObject:
|
||||
History:
|
||||
type: object
|
||||
properties:
|
||||
metadata:
|
||||
|
@ -848,14 +891,12 @@ components:
|
|||
pinned:
|
||||
type: boolean
|
||||
description: Whether the user has pinned this note.
|
||||
History:
|
||||
HistoryUpdate:
|
||||
type: object
|
||||
properties:
|
||||
history:
|
||||
type: array
|
||||
description: The array that contains history objects.
|
||||
items:
|
||||
"$ref": "#/components/schemas/HistoryObject"
|
||||
pinned:
|
||||
type: boolean
|
||||
description: Whether the user has pinned this note.
|
||||
MediaUpload:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
@ -5,6 +5,7 @@ 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 { AuthToken } from '../../../users/auth-token.entity';
|
||||
|
@ -35,6 +36,8 @@ describe('Me Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MeController>(MeController);
|
||||
|
|
|
@ -6,6 +6,7 @@ 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';
|
||||
import { Authorship } from '../../../revisions/authorship.entity';
|
||||
import { Revision } from '../../../revisions/revision.entity';
|
||||
import { AuthToken } from '../../../users/auth-token.entity';
|
||||
|
@ -37,6 +38,8 @@ describe('Media Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<MediaController>(MediaController);
|
||||
|
|
|
@ -4,6 +4,7 @@ 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';
|
||||
import { Authorship } from '../../../revisions/authorship.entity';
|
||||
import { Revision } from '../../../revisions/revision.entity';
|
||||
import { RevisionsModule } from '../../../revisions/revisions.module';
|
||||
|
@ -25,6 +26,10 @@ describe('Notes Controller', () => {
|
|||
provide: getRepositoryToken(Note),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(Tag),
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
imports: [RevisionsModule, UsersModule, LoggerModule],
|
||||
})
|
||||
|
@ -44,6 +49,8 @@ describe('Notes Controller', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Note))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
controller = module.get<NotesController>(NotesController);
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
Put,
|
||||
} from '@nestjs/common';
|
||||
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
|
||||
import { NoteMetadataUpdateDto } from '../../../notes/note-metadata.dto';
|
||||
import { NotePermissionsUpdateDto } from '../../../notes/note-permissions.dto';
|
||||
import { NotesService } from '../../../notes/notes.service';
|
||||
import { RevisionsService } from '../../../revisions/revisions.service';
|
||||
|
|
|
@ -20,7 +20,7 @@ export class HistoryService {
|
|||
description: 'Very descriptive text.',
|
||||
editedBy: [],
|
||||
id: 'foobar-barfoo',
|
||||
permission: {
|
||||
permissions: {
|
||||
owner: {
|
||||
displayName: 'foo',
|
||||
userName: 'fooUser',
|
||||
|
@ -59,7 +59,7 @@ export class HistoryService {
|
|||
description: 'Very descriptive text.',
|
||||
editedBy: [],
|
||||
id: 'foobar-barfoo',
|
||||
permission: {
|
||||
permissions: {
|
||||
owner: {
|
||||
displayName: 'foo',
|
||||
userName: 'fooUser',
|
||||
|
|
|
@ -4,6 +4,7 @@ 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 { AuthToken } from '../users/auth-token.entity';
|
||||
|
@ -43,6 +44,8 @@ describe('MediaService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<MediaService>(MediaService);
|
||||
|
|
|
@ -32,5 +32,15 @@ export class NoteMetadataDto {
|
|||
@ValidateNested()
|
||||
editedBy: UserInfoDto['userName'][];
|
||||
@ValidateNested()
|
||||
permission: NotePermissionsDto;
|
||||
permissions: NotePermissionsDto;
|
||||
}
|
||||
|
||||
export class NoteMetadataUpdateDto {
|
||||
@IsString()
|
||||
title: string;
|
||||
@IsString()
|
||||
description: string;
|
||||
@IsArray()
|
||||
@IsString({ each: true })
|
||||
tags: string[];
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ export class NoteUserPermissionEntryDto {
|
|||
canEdit: boolean;
|
||||
}
|
||||
|
||||
export class NotePermissionEntryUpdateDto {
|
||||
export class NoteUserPermissionUpdateDto {
|
||||
@IsString()
|
||||
username: string;
|
||||
@IsBoolean()
|
||||
|
@ -31,6 +31,13 @@ export class NoteGroupPermissionEntryDto {
|
|||
canEdit: boolean;
|
||||
}
|
||||
|
||||
export class NoteGroupPermissionUpdateDto {
|
||||
@IsString()
|
||||
groupname: string;
|
||||
@IsBoolean()
|
||||
canEdit: boolean;
|
||||
}
|
||||
|
||||
export class NotePermissionsDto {
|
||||
@ValidateNested()
|
||||
owner: UserInfoDto;
|
||||
|
@ -45,5 +52,8 @@ export class NotePermissionsDto {
|
|||
export class NotePermissionsUpdateDto {
|
||||
@IsArray()
|
||||
@ValidateNested()
|
||||
sharedTo: NotePermissionEntryUpdateDto[];
|
||||
sharedToUsers: NoteUserPermissionUpdateDto[];
|
||||
@IsArray()
|
||||
@ValidateNested()
|
||||
sharedToGroups: NoteGroupPermissionUpdateDto[];
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ import { generate as shortIdGenerate } from 'shortid';
|
|||
import {
|
||||
Column,
|
||||
Entity,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
OneToMany,
|
||||
PrimaryGeneratedColumn,
|
||||
|
@ -11,6 +13,7 @@ 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';
|
||||
|
||||
@Entity('Notes')
|
||||
export class Note {
|
||||
|
@ -25,7 +28,7 @@ export class Note {
|
|||
unique: true,
|
||||
nullable: true,
|
||||
})
|
||||
alias: string;
|
||||
alias?: string;
|
||||
@OneToMany(
|
||||
_ => NoteGroupPermission,
|
||||
groupPermission => groupPermission.note,
|
||||
|
@ -59,10 +62,27 @@ export class Note {
|
|||
)
|
||||
authorColors: AuthorColor[];
|
||||
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
description?: string;
|
||||
@Column({
|
||||
nullable: true,
|
||||
})
|
||||
title?: string;
|
||||
|
||||
@ManyToMany(
|
||||
_ => Tag,
|
||||
tag => tag.notes,
|
||||
{ eager: true, cascade: true },
|
||||
)
|
||||
@JoinTable()
|
||||
tags: Tag[];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
private constructor() {}
|
||||
|
||||
public static create(owner?: User, alias?: string, shortid?: string) {
|
||||
public static create(owner?: User, alias?: string, shortid?: string): Note {
|
||||
if (!shortid) {
|
||||
shortid = shortIdGenerate();
|
||||
}
|
||||
|
@ -74,6 +94,10 @@ export class Note {
|
|||
newNote.authorColors = [];
|
||||
newNote.userPermissions = [];
|
||||
newNote.groupPermissions = [];
|
||||
newNote.revisions = Promise.resolve([]);
|
||||
newNote.description = null;
|
||||
newNote.title = null;
|
||||
newNote.tags = [];
|
||||
return newNote;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
import { Note } from './note.entity';
|
||||
|
||||
export class NoteUtils {
|
||||
public static parseTitle(note: Note): string {
|
||||
// TODO: Implement method
|
||||
return 'Hardcoded note title';
|
||||
}
|
||||
|
||||
public static parseDescription(note: Note): string {
|
||||
// TODO: Implement method
|
||||
return 'Hardcoded note description';
|
||||
}
|
||||
|
||||
public static parseTags(note: Note): string[] {
|
||||
// TODO: Implement method
|
||||
return ['Hardcoded note tag'];
|
||||
}
|
||||
}
|
|
@ -6,10 +6,11 @@ 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';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
TypeOrmModule.forFeature([Note, AuthorColor]),
|
||||
TypeOrmModule.forFeature([Note, AuthorColor, Tag]),
|
||||
forwardRef(() => RevisionsModule),
|
||||
UsersModule,
|
||||
LoggerModule,
|
||||
|
|
|
@ -11,6 +11,7 @@ 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';
|
||||
|
||||
describe('NotesService', () => {
|
||||
let service: NotesService;
|
||||
|
@ -23,6 +24,10 @@ describe('NotesService', () => {
|
|||
provide: getRepositoryToken(Note),
|
||||
useValue: {},
|
||||
},
|
||||
{
|
||||
provide: getRepositoryToken(Tag),
|
||||
useValue: {},
|
||||
},
|
||||
],
|
||||
imports: [UsersModule, RevisionsModule, LoggerModule],
|
||||
})
|
||||
|
@ -40,6 +45,8 @@ describe('NotesService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Note))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.compile();
|
||||
service = module.get<NotesService>(NotesService);
|
||||
});
|
||||
|
|
|
@ -7,20 +7,21 @@ import { Revision } from '../revisions/revision.entity';
|
|||
import { RevisionsService } from '../revisions/revisions.service';
|
||||
import { User } from '../users/user.entity';
|
||||
import { UsersService } from '../users/users.service';
|
||||
import { NoteMetadataDto } from './note-metadata.dto';
|
||||
import { NoteMetadataDto, NoteMetadataUpdateDto } from './note-metadata.dto';
|
||||
import {
|
||||
NotePermissionsDto,
|
||||
NotePermissionsUpdateDto,
|
||||
} from './note-permissions.dto';
|
||||
import { NoteDto } from './note.dto';
|
||||
import { Note } from './note.entity';
|
||||
import { NoteUtils } from './note.utils';
|
||||
import { Tag } from './tag.entity';
|
||||
|
||||
@Injectable()
|
||||
export class NotesService {
|
||||
constructor(
|
||||
private readonly logger: ConsoleLoggerService,
|
||||
@InjectRepository(Note) private noteRepository: Repository<Note>,
|
||||
@InjectRepository(Tag) private tagRepository: Repository<Tag>,
|
||||
@Inject(UsersService) private usersService: UsersService,
|
||||
@Inject(forwardRef(() => RevisionsService))
|
||||
private revisionsService: RevisionsService,
|
||||
|
@ -37,7 +38,7 @@ export class NotesService {
|
|||
description: 'Very descriptive text.',
|
||||
editedBy: [],
|
||||
id: 'foobar-barfoo',
|
||||
permission: {
|
||||
permissions: {
|
||||
owner: {
|
||||
displayName: 'foo',
|
||||
userName: 'fooUser',
|
||||
|
@ -102,13 +103,13 @@ export class NotesService {
|
|||
// TODO: Convert DB UUID to base64
|
||||
id: note.id,
|
||||
alias: note.alias,
|
||||
title: NoteUtils.parseTitle(note),
|
||||
title: note.title,
|
||||
// TODO: Get actual createTime
|
||||
createTime: new Date(),
|
||||
description: NoteUtils.parseDescription(note),
|
||||
description: note.description,
|
||||
editedBy: note.authorColors.map(authorColor => authorColor.user.userName),
|
||||
// TODO: Extract into method
|
||||
permission: {
|
||||
permissions: {
|
||||
owner: this.usersService.toUserDto(note.owner),
|
||||
sharedToUsers: note.userPermissions.map(noteUserPermission => ({
|
||||
user: this.usersService.toUserDto(noteUserPermission.user),
|
||||
|
@ -119,7 +120,7 @@ export class NotesService {
|
|||
canEdit: noteGroupPermission.canEdit,
|
||||
})),
|
||||
},
|
||||
tags: NoteUtils.parseTags(note),
|
||||
tags: note.tags.map(tag => tag.name),
|
||||
updateTime: (await this.getLastRevision(note)).createdAt,
|
||||
// TODO: Get actual updateUser
|
||||
updateUser: {
|
||||
|
|
19
src/notes/tag.entity.ts
Normal file
19
src/notes/tag.entity.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';
|
||||
import { Note } from './note.entity';
|
||||
|
||||
@Entity()
|
||||
export class Tag {
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column({
|
||||
nullable: false,
|
||||
})
|
||||
name: string;
|
||||
|
||||
@ManyToMany(
|
||||
_ => Note,
|
||||
note => note.tags,
|
||||
)
|
||||
notes: Note[];
|
||||
}
|
|
@ -10,6 +10,7 @@ import { User } from '../users/user.entity';
|
|||
import { Authorship } from './authorship.entity';
|
||||
import { Revision } from './revision.entity';
|
||||
import { RevisionsService } from './revisions.service';
|
||||
import { Tag } from '../notes/tag.entity';
|
||||
|
||||
describe('RevisionsService', () => {
|
||||
let service: RevisionsService;
|
||||
|
@ -39,6 +40,8 @@ describe('RevisionsService', () => {
|
|||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.compile();
|
||||
|
||||
service = module.get<RevisionsService>(RevisionsService);
|
||||
|
|
|
@ -76,6 +76,7 @@ export class RevisionsService {
|
|||
createRevision(content: string) {
|
||||
// TODO: Add previous revision
|
||||
// TODO: Calculate patch
|
||||
// TODO: Save metadata
|
||||
return this.revisionRepository.create({
|
||||
content: content,
|
||||
length: content.length,
|
||||
|
|
|
@ -98,20 +98,28 @@ describe('Notes', () => {
|
|||
).toEqual('New note text');
|
||||
});
|
||||
|
||||
it.skip(`PUT /notes/{note}/metadata`, () => {
|
||||
// TODO
|
||||
return request(app.getHttpServer())
|
||||
.post('/notes/test5/metadata')
|
||||
.set('Content-Type', 'text/markdown')
|
||||
.expect(200);
|
||||
});
|
||||
|
||||
it.skip(`GET /notes/{note}/metadata`, () => {
|
||||
notesService.createNote('This is a test note.', 'test6');
|
||||
return request(app.getHttpServer())
|
||||
it(`GET /notes/{note}/metadata`, async () => {
|
||||
await notesService.createNote('This is a test note.', 'test6');
|
||||
const metadata = await request(app.getHttpServer())
|
||||
.get('/notes/test6/metadata')
|
||||
.expect(200);
|
||||
// TODO: Find out how to check the structure of the returned JSON
|
||||
expect(typeof metadata.body.id).toEqual('string');
|
||||
expect(metadata.body.alias).toEqual('test6');
|
||||
expect(metadata.body.title).toBeNull();
|
||||
expect(metadata.body.description).toBeNull();
|
||||
expect(typeof metadata.body.createTime).toEqual('string');
|
||||
expect(metadata.body.editedBy).toEqual([]);
|
||||
expect(metadata.body.permissions.owner).toBeNull();
|
||||
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
|
||||
expect(metadata.body.permissions.sharedToUsers).toEqual([]);
|
||||
expect(metadata.body.tags).toEqual([]);
|
||||
expect(typeof metadata.body.updateTime).toEqual('string');
|
||||
expect(typeof metadata.body.updateUser.displayName).toEqual('string');
|
||||
expect(typeof metadata.body.updateUser.userName).toEqual('string');
|
||||
expect(typeof metadata.body.updateUser.email).toEqual('string');
|
||||
expect(typeof metadata.body.updateUser.photo).toEqual('string');
|
||||
expect(typeof metadata.body.viewCount).toEqual('number');
|
||||
expect(metadata.body.editedBy).toEqual([]);
|
||||
});
|
||||
|
||||
it(`GET /notes/{note}/revisions`, async () => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue