dh_demo

DreamHanks demo project
git clone git://git.lair.cx/dh_demo
Log | Files | Refs | README

[...path].ts (2222B)


      1 import {
      2   ApiError,
      3   ERR_FORBIDDEN,
      4   ERR_INVALID_REQUEST,
      5   ERR_METHOD_NOT_ALLOWED,
      6   ERR_NOT_FOUND,
      7   ERR_UNAUTHORIZED,
      8 } from '@/lib/apierror'
      9 import { withConnection } from '@/lib/model_helpers'
     10 import { createThreadComment } from '@/lib/models/thread'
     11 import { getWikiAndPageACLViaPath } from '@/lib/models/wiki_acl'
     12 import { createWikiTalk } from '@/lib/models/wiki_talk'
     13 import { ACL_ACTION_CREATE_THREAD, resolveACL } from '@/lib/security/acl'
     14 import { authenticationFromCookies } from '@/lib/security/token'
     15 import { NextApiRequest, NextApiResponse } from 'next'
     16 
     17 export interface CreateTalkRequest {
     18   title?: string
     19   content?: string
     20 }
     21 
     22 export interface CreateTalkResponse {
     23   thread: number
     24 }
     25 
     26 export default function handler (
     27   req: NextApiRequest,
     28   res: NextApiResponse,
     29 ) {
     30   switch (req.method) {
     31     case 'POST':
     32       return handlePost(req, res)
     33     default:
     34       res.status(405).json(ERR_METHOD_NOT_ALLOWED)
     35   }
     36 }
     37 
     38 async function handlePost (
     39   req: NextApiRequest,
     40   res: NextApiResponse<CreateTalkResponse | ApiError>,
     41 ) {
     42   const token = await authenticationFromCookies(req.cookies)
     43   const uid = token?.uid
     44   if (uid == null) {
     45     res.status(401).json(ERR_UNAUTHORIZED)
     46     return
     47   }
     48 
     49   const { slug, path: paths } = req.query
     50   if (typeof slug !== 'string' || !Array.isArray(paths)) {
     51     res.status(400).json(ERR_INVALID_REQUEST)
     52     return
     53   }
     54 
     55   const path = paths.join('/')
     56 
     57   const { title, content } = req.body as CreateTalkRequest
     58   if (typeof title !== 'string' || typeof content !== 'string') {
     59     res.status(400).json(ERR_INVALID_REQUEST)
     60     return
     61   }
     62 
     63   await withConnection(async conn => {
     64     // ACL Check
     65     const aclInfo = await getWikiAndPageACLViaPath(conn, [slug, path])
     66     if (aclInfo == null || aclInfo.pageId == null) {
     67       res.status(404).json(ERR_NOT_FOUND)
     68       return
     69     }
     70 
     71     if (!resolveACL(token, [aclInfo.wiki, aclInfo.page], ACL_ACTION_CREATE_THREAD)) {
     72       res.status(403).json(ERR_FORBIDDEN)
     73       return
     74     }
     75 
     76     // 새 토론과 첫 댓글 만듦
     77     const threadId = await createWikiTalk(conn, [aclInfo.pageId, uid, title])
     78     await createThreadComment(conn, [threadId, uid, content])
     79 
     80     res.status(200).json({ thread: threadId })
     81   })
     82 }