Fix CommentRoutes
This commit is contained in:
parent
8865b58747
commit
d0e94808bb
@ -1,5 +1,6 @@
|
|||||||
import {ICredentials} from './ICredentials'
|
import {ICommentTree} from './ICommentTree'
|
||||||
import {IComment} from './IComment'
|
import {IComment} from './IComment'
|
||||||
|
import {ICredentials} from './ICredentials'
|
||||||
import {IUser} from './IUser'
|
import {IUser} from './IUser'
|
||||||
|
|
||||||
export interface IAPIDef {
|
export interface IAPIDef {
|
||||||
@ -34,13 +35,14 @@ export interface IAPIDef {
|
|||||||
}
|
}
|
||||||
'/story/:storyId/comments': {
|
'/story/:storyId/comments': {
|
||||||
'get': {
|
'get': {
|
||||||
response: IComment[],
|
response: ICommentTree,
|
||||||
params: {
|
params: {
|
||||||
storyId: number // TODO might have to change to string (url)
|
storyId: number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
'post': {
|
'post': {
|
||||||
response: IComment,
|
response: IComment,
|
||||||
|
body: IComment,
|
||||||
params: {
|
params: {
|
||||||
storyId: number
|
storyId: number
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,5 +4,5 @@ export * from './ICommentTree'
|
|||||||
export * from './ICredentials'
|
export * from './ICredentials'
|
||||||
export * from './IRoutes'
|
export * from './IRoutes'
|
||||||
export * from './ISite'
|
export * from './ISite'
|
||||||
|
export * from './ITeam'
|
||||||
export * from './IUser'
|
export * from './IUser'
|
||||||
import * from './ITeam'
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import {AsyncRouter} from '../router'
|
import {AsyncRouter} from '../router'
|
||||||
import {BaseRoute} from './BaseRoute'
|
import {BaseRoute} from './BaseRoute'
|
||||||
import {IAPIDef} from '@rondo/common'
|
import {IAPIDef} from '@rondo/common'
|
||||||
|
import {ICommentService} from '../services/ICommentService'
|
||||||
import {ensureLoggedInApi} from '../middleware'
|
import {ensureLoggedInApi} from '../middleware'
|
||||||
|
|
||||||
export class CommentRoutes extends BaseRoute<IAPIDef> {
|
export class CommentRoutes extends BaseRoute<IAPIDef> {
|
||||||
@ -15,53 +16,54 @@ export class CommentRoutes extends BaseRoute<IAPIDef> {
|
|||||||
|
|
||||||
t.get('/story/:storyId/comments', async req => {
|
t.get('/story/:storyId/comments', async req => {
|
||||||
const {storyId} = req.params
|
const {storyId} = req.params
|
||||||
// TODO retrieve comments from story
|
return this.commentService.find(storyId)
|
||||||
return []
|
|
||||||
})
|
})
|
||||||
|
|
||||||
t.use(ensureLoggedInApi)
|
t.use(ensureLoggedInApi)
|
||||||
|
|
||||||
t.post('/story/:storyId/comments', async req => {
|
t.post('/story/:storyId/comments', async req => {
|
||||||
|
const {storyId} = req.params
|
||||||
const comment = req.body
|
const comment = req.body
|
||||||
// TODO save a comment
|
comment.storyId = storyId
|
||||||
return comment
|
return this.commentService.saveRoot(comment, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.post('/comments/:parentId', async req => {
|
t.post('/comments/:parentId', async req => {
|
||||||
|
const {parentId} = req.params
|
||||||
const comment = req.body
|
const comment = req.body
|
||||||
// TODO save a comment
|
comment.parentId = parentId
|
||||||
return comment
|
return this.commentService.save(comment, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.put('/comments/:commentId', async req => {
|
t.put('/comments/:commentId', async req => {
|
||||||
const comment = req.body
|
const comment = req.body
|
||||||
// TODO edit a comment
|
comment.id = req.params.commentId
|
||||||
return comment
|
return this.commentService.edit(comment, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.delete('/comments/:commentId', async req => {
|
t.delete('/comments/:commentId', async req => {
|
||||||
const {commentId} = req.params
|
const {commentId} = req.params
|
||||||
// TODO delete a comment
|
return this.commentService.delete(commentId, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.post('/comments/:commentId/vote', async req => {
|
t.post('/comments/:commentId/vote', async req => {
|
||||||
const {commentId} = req.params
|
const {commentId} = req.params
|
||||||
// TODO upvote a comment
|
return this.commentService.upVote(commentId, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.delete('/comments/:commentId/vote', async req => {
|
t.delete('/comments/:commentId/vote', async req => {
|
||||||
const {commentId} = req.params
|
const {commentId} = req.params
|
||||||
// TODO delete a vote
|
return this.commentService.deleteVote(commentId, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.post('/comments/:commentId/spam', async req => {
|
t.post('/comments/:commentId/spam', async req => {
|
||||||
const {commentId} = req.params
|
const {commentId} = req.params
|
||||||
// TODO report comment as spam
|
return this.commentService.markAsSpam(commentId, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.delete('/comments/:commentId/spam', async req => {
|
t.delete('/comments/:commentId/spam', async req => {
|
||||||
const {commentId} = req.params
|
const {commentId} = req.params
|
||||||
// TODO delete spam report
|
return this.commentService.unmarkAsSpam(commentId, req.user!.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -89,20 +89,16 @@ export class CommentService extends BaseService implements ICommentService {
|
|||||||
return editedComment
|
return editedComment
|
||||||
}
|
}
|
||||||
|
|
||||||
async delete(comment: IComment, userId: number) {
|
async delete(commentId: number, userId: number) {
|
||||||
new Validator(comment)
|
|
||||||
.ensure('id')
|
|
||||||
.throw()
|
|
||||||
|
|
||||||
await this.getRepository(Comment)
|
await this.getRepository(Comment)
|
||||||
.update({
|
.update({
|
||||||
id: comment.id,
|
id: commentId,
|
||||||
userId,
|
userId,
|
||||||
}, {
|
}, {
|
||||||
message: '(this message has been removed by the user)',
|
message: '(this message has been removed by the user)',
|
||||||
})
|
})
|
||||||
|
|
||||||
return this.findOne(comment.id)
|
return this.findOne(commentId)
|
||||||
}
|
}
|
||||||
|
|
||||||
async upVote(commentId: number, userId: number) {
|
async upVote(commentId: number, userId: number) {
|
||||||
|
|||||||
@ -11,7 +11,7 @@ export interface ICommentService {
|
|||||||
|
|
||||||
edit(comment: IComment, userId: number): Promise<IComment>
|
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>
|
upVote(commentId: number, userId: number): Promise<void>
|
||||||
|
|
||||||
|
|||||||
@ -7,5 +7,7 @@ export interface ISiteService {
|
|||||||
|
|
||||||
find(userId: number): Promise<ISite[]>
|
find(userId: number): Promise<ISite[]>
|
||||||
|
|
||||||
|
findByDomain(domain: string): Promise<ISite | undefined>
|
||||||
|
|
||||||
// TODO add other methods
|
// TODO add other methods
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import {Site} from '../entities/Site'
|
|||||||
|
|
||||||
export class SiteService extends BaseService implements ISiteService {
|
export class SiteService extends BaseService implements ISiteService {
|
||||||
async create(name: string, teamId: number, userId: number) {
|
async create(name: string, teamId: number, userId: number) {
|
||||||
|
// TODO check site limit per user
|
||||||
return this.getRepository(Site).save({
|
return this.getRepository(Site).save({
|
||||||
name,
|
name,
|
||||||
teamId,
|
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({
|
return this.getRepository(Site).findOne({
|
||||||
where: {
|
where: {
|
||||||
id,
|
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) {
|
async find(teamId: number) {
|
||||||
return this.getRepository(Site).find({
|
return this.getRepository(Site).find({
|
||||||
where: { teamId },
|
where: { teamId },
|
||||||
|
|||||||
@ -1,10 +1,48 @@
|
|||||||
import {IStoryService} from './IStoryService'
|
|
||||||
import {Story} from '../entities/Story'
|
|
||||||
import URL from 'url'
|
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) {
|
async findOne(url: string) {
|
||||||
const parsedUrl = URL.parse(url)
|
const storyRepo = this.getRepository(Story)
|
||||||
const hostname = parsedUrl.hostname
|
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},
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ import {ITeamService} from './ITeamService'
|
|||||||
import {Team} from '../entities/Team'
|
import {Team} from '../entities/Team'
|
||||||
|
|
||||||
export class TeamService extends BaseService implements ITeamService {
|
export class TeamService extends BaseService implements ITeamService {
|
||||||
|
// TODO check team limit per user
|
||||||
async create(name: string, userId: number) {
|
async create(name: string, userId: number) {
|
||||||
return this.getRepository(Team).save({
|
return this.getRepository(Team).save({
|
||||||
name,
|
name,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user