Fix CommentRoutes

This commit is contained in:
Jerko Steiner 2019-01-22 13:06:01 +01:00
parent 8865b58747
commit d0e94808bb
9 changed files with 81 additions and 31 deletions

View File

@ -1,5 +1,6 @@
import {ICredentials} from './ICredentials'
import {ICommentTree} from './ICommentTree'
import {IComment} from './IComment'
import {ICredentials} from './ICredentials'
import {IUser} from './IUser'
export interface IAPIDef {
@ -34,13 +35,14 @@ export interface IAPIDef {
}
'/story/:storyId/comments': {
'get': {
response: IComment[],
response: ICommentTree,
params: {
storyId: number // TODO might have to change to string (url)
storyId: number
}
}
'post': {
response: IComment,
body: IComment,
params: {
storyId: number
}

View File

@ -4,5 +4,5 @@ export * from './ICommentTree'
export * from './ICredentials'
export * from './IRoutes'
export * from './ISite'
export * from './ITeam'
export * from './IUser'
import * from './ITeam'

View File

@ -1,6 +1,7 @@
import {AsyncRouter} from '../router'
import {BaseRoute} from './BaseRoute'
import {IAPIDef} from '@rondo/common'
import {ICommentService} from '../services/ICommentService'
import {ensureLoggedInApi} from '../middleware'
export class CommentRoutes extends BaseRoute<IAPIDef> {
@ -15,53 +16,54 @@ export class CommentRoutes extends BaseRoute<IAPIDef> {
t.get('/story/:storyId/comments', async req => {
const {storyId} = req.params
// TODO retrieve comments from story
return []
return this.commentService.find(storyId)
})
t.use(ensureLoggedInApi)
t.post('/story/:storyId/comments', async req => {
const {storyId} = req.params
const comment = req.body
// TODO save a comment
return comment
comment.storyId = storyId
return this.commentService.saveRoot(comment, req.user!.id)
})
t.post('/comments/:parentId', async req => {
const {parentId} = req.params
const comment = req.body
// TODO save a comment
return comment
comment.parentId = parentId
return this.commentService.save(comment, req.user!.id)
})
t.put('/comments/:commentId', async req => {
const comment = req.body
// TODO edit a comment
return comment
comment.id = req.params.commentId
return this.commentService.edit(comment, req.user!.id)
})
t.delete('/comments/:commentId', async req => {
const {commentId} = req.params
// TODO delete a comment
return this.commentService.delete(commentId, req.user!.id)
})
t.post('/comments/:commentId/vote', async req => {
const {commentId} = req.params
// TODO upvote a comment
return this.commentService.upVote(commentId, req.user!.id)
})
t.delete('/comments/:commentId/vote', async req => {
const {commentId} = req.params
// TODO delete a vote
return this.commentService.deleteVote(commentId, req.user!.id)
})
t.post('/comments/:commentId/spam', async req => {
const {commentId} = req.params
// TODO report comment as spam
return this.commentService.markAsSpam(commentId, req.user!.id)
})
t.delete('/comments/:commentId/spam', async req => {
const {commentId} = req.params
// TODO delete spam report
return this.commentService.unmarkAsSpam(commentId, req.user!.id)
})
}

View File

@ -89,20 +89,16 @@ export class CommentService extends BaseService implements ICommentService {
return editedComment
}
async delete(comment: IComment, userId: number) {
new Validator(comment)
.ensure('id')
.throw()
async delete(commentId: number, userId: number) {
await this.getRepository(Comment)
.update({
id: comment.id,
id: commentId,
userId,
}, {
message: '(this message has been removed by the user)',
})
return this.findOne(comment.id)
return this.findOne(commentId)
}
async upVote(commentId: number, userId: number) {

View File

@ -11,7 +11,7 @@ export interface ICommentService {
edit(comment: IComment, userId: number): Promise<IComment>
delete(comment: IComment, userId: number): Promise<IComment | undefined>
delete(commentId: number, userId: number): Promise<IComment | undefined>
upVote(commentId: number, userId: number): Promise<void>

View File

@ -7,5 +7,7 @@ export interface ISiteService {
find(userId: number): Promise<ISite[]>
findByDomain(domain: string): Promise<ISite | undefined>
// TODO add other methods
}

View File

@ -4,6 +4,7 @@ import {Site} from '../entities/Site'
export class SiteService extends BaseService implements ISiteService {
async create(name: string, teamId: number, userId: number) {
// TODO check site limit per user
return this.getRepository(Site).save({
name,
teamId,
@ -11,7 +12,7 @@ export class SiteService extends BaseService implements ISiteService {
})
}
findOne(id: number, teamId: number) {
async findOne(id: number, teamId: number) {
return this.getRepository(Site).findOne({
where: {
id,
@ -20,6 +21,14 @@ export class SiteService extends BaseService implements ISiteService {
})
}
async findByDomain(domain: string) {
return this.getRepository(Site).findOne({
where: {
domain,
},
})
}
async find(teamId: number) {
return this.getRepository(Site).find({
where: { teamId },

View File

@ -1,10 +1,48 @@
import {IStoryService} from './IStoryService'
import {Story} from '../entities/Story'
import URL from 'url'
import {BaseService} from './BaseService'
import {ISiteService} from './ISiteService'
import {IStoryService} from './IStoryService'
import {ITransactionManager} from '../database/ITransactionManager'
import {Story} from '../entities/Story'
export class StoryService extends BaseService implements IStoryService {
constructor(
transactionManager: ITransactionManager,
protected readonly siteService: ISiteService,
) {
super(transactionManager)
}
export class StoryService implements IStoryService {
async findOne(url: string) {
const parsedUrl = URL.parse(url)
const hostname = parsedUrl.hostname
const storyRepo = this.getRepository(Story)
const story = await storyRepo.findOne({
where: {url},
})
if (story) {
return story
}
const domain = URL.parse(url).hostname
const site = await this.siteService.findByDomain(domain!)
if (!site) {
return undefined
}
try {
return await storyRepo.save({
url,
siteId: site.id,
})
} catch (err) {
// TODO check if unique constrint error
// This could happen if there are two concurrent requests coming in at
// the same time, and they both cannot find the story, then decide to
// create a record.
return await storyRepo.findOne({
where: {url},
})
}
}
}

View File

@ -3,6 +3,7 @@ import {ITeamService} from './ITeamService'
import {Team} from '../entities/Team'
export class TeamService extends BaseService implements ITeamService {
// TODO check team limit per user
async create(name: string, userId: number) {
return this.getRepository(Team).save({
name,