2022-04-06 18:50:36 +03:00
import express from "express" ;
import { body , param , validationResult } from "express-validator" ;
import { authenticateRoute } from "../../../auth" ;
import { query } from "../../../database" ;
import { errors } from "../../../errors" ;
2022-04-12 00:19:29 +03:00
import { dispatch , dispatchChannelSubscribe } from "../../../gateway" ;
2022-04-10 22:14:10 +03:00
import { GatewayPayloadType } from "../../../gateway/gatewaypayloadtype" ;
2022-04-06 18:50:36 +03:00
const router = express . Router ( ) ;
router . post (
"/" ,
authenticateRoute ( ) ,
body ( "name" ) . isLength ( { min : 1 , max : 40 } ) . isAlphanumeric ( "en-US" , { ignore : " _-" } ) ,
async ( req , res ) = > {
const validationErrors = validationResult ( req ) ;
if ( ! validationErrors . isEmpty ( ) ) {
return res . status ( 400 ) . json ( { . . . errors . INVALID_DATA , errors : validationErrors.array ( ) } ) ;
}
const { name } = req . body ;
const result = await query ( "INSERT INTO channels(name, owner_id) VALUES ($1, $2) RETURNING id, name, owner_id" , [ name , req . user . id ] ) ;
if ( result . rowCount < 1 ) {
return res . status ( 500 ) . json ( {
. . . errors . GOT_NO_DATABASE_DATA
} ) ;
}
2022-04-10 22:14:10 +03:00
dispatch ( "*" , {
t : GatewayPayloadType.ChannelCreate ,
d : result.rows [ 0 ]
} ) ;
2022-04-12 00:19:29 +03:00
// When a new channel is created, we will currently subscribe every client
// on the gateway (this will be changed when the concept of "communities" is added)
dispatchChannelSubscribe ( "*" , ` channel: ${ result . rows [ 0 ] . id } ` ) ;
2022-04-06 18:50:36 +03:00
res . status ( 201 ) . send ( result . rows [ 0 ] ) ;
}
) ;
router . put (
"/:id" ,
authenticateRoute ( ) ,
body ( "name" ) . isLength ( { min : 1 , max : 40 } ) . isAlphanumeric ( "en-US" , { ignore : " _-" } ) ,
param ( "id" ) . isNumeric ( ) ,
async ( req , res ) = > {
const validationErrors = validationResult ( req ) ;
if ( ! validationErrors . isEmpty ( ) ) {
return res . status ( 400 ) . json ( { . . . errors . INVALID_DATA , errors : validationErrors.array ( ) } ) ;
}
const { name } = req . body ;
2022-04-10 22:14:10 +03:00
const id = parseInt ( req . params . id ) ; // TODO: ??
2022-04-06 18:50:36 +03:00
const permissionCheckResult = await query ( "SELECT owner_id FROM channels WHERE id = $1" , [ id ] ) ;
if ( permissionCheckResult . rowCount < 1 ) {
return res . status ( 404 ) . json ( {
. . . errors . NOT_FOUND
} ) ;
}
if ( permissionCheckResult . rows [ 0 ] . owner_id !== req . user . id ) {
return res . status ( 403 ) . json ( {
. . . errors . FORBIDDEN_DUE_TO_MISSING_PERMISSIONS
} ) ;
}
const result = await query ( "UPDATE channels SET name = $1 WHERE id = $2" , [ name , id ] ) ;
if ( result . rowCount < 1 ) {
return res . status ( 500 ) . json ( {
. . . errors . GOT_NO_DATABASE_DATA
} ) ;
}
2022-04-10 22:14:10 +03:00
const updatePayload = {
id ,
2022-04-06 18:50:36 +03:00
name ,
owner_id : permissionCheckResult.rows [ 0 ] . owner_id
2022-04-10 22:14:10 +03:00
} ;
2022-04-12 00:19:29 +03:00
dispatch ( ` channel: ${ id } ` , {
2022-04-10 22:14:10 +03:00
t : GatewayPayloadType.ChannelUpdate ,
d : updatePayload
2022-04-06 18:50:36 +03:00
} ) ;
2022-04-10 22:14:10 +03:00
return res . status ( 200 ) . send ( updatePayload ) ;
2022-04-06 18:50:36 +03:00
}
) ;
router . delete (
"/:id" ,
authenticateRoute ( ) ,
param ( "id" ) . isNumeric ( ) ,
async ( req , res ) = > {
const validationErrors = validationResult ( req ) ;
if ( ! validationErrors . isEmpty ( ) ) {
return res . status ( 400 ) . json ( { . . . errors . INVALID_DATA , errors : validationErrors.array ( ) } ) ;
}
2022-04-10 22:14:10 +03:00
const id = parseInt ( req . params . id ) ; // TODO: ??
2022-04-06 18:50:36 +03:00
const permissionCheckResult = await query ( "SELECT owner_id FROM channels WHERE id = $1" , [ id ] ) ;
if ( permissionCheckResult . rowCount < 1 ) {
return res . status ( 404 ) . json ( {
. . . errors . NOT_FOUND
} ) ;
}
if ( permissionCheckResult . rows [ 0 ] . owner_id !== req . user . id ) {
return res . status ( 403 ) . json ( {
. . . errors . FORBIDDEN_DUE_TO_MISSING_PERMISSIONS
} ) ;
}
const result = await query ( "DELETE FROM channels WHERE id = $1" , [ id ] ) ;
if ( result . rowCount < 1 ) {
return res . status ( 500 ) . json ( {
. . . errors . GOT_NO_DATABASE_DATA
} ) ;
}
2022-04-12 00:19:29 +03:00
dispatch ( ` channel: ${ id } ` , {
2022-04-10 22:14:10 +03:00
t : GatewayPayloadType.ChannelDelete ,
d : {
id
}
} ) ;
2022-04-06 18:50:36 +03:00
return res . status ( 204 ) . send ( "" ) ;
}
) ;
router . get (
"/:id" ,
authenticateRoute ( ) ,
param ( "id" ) . isNumeric ( ) ,
async ( req , res ) = > {
2022-04-12 00:02:43 +03:00
const validationErrors = validationResult ( req ) ;
if ( ! validationErrors . isEmpty ( ) ) {
return res . status ( 400 ) . json ( { . . . errors . INVALID_DATA , errors : validationErrors.array ( ) } ) ;
}
2022-04-06 18:50:36 +03:00
const { id } = req . params ;
const result = await query ( "SELECT id, name, owner_id FROM channels WHERE id = $1" , [ id ] ) ;
if ( result . rowCount < 1 ) {
return res . status ( 404 ) . json ( {
. . . errors . NOT_FOUND
} ) ;
}
return res . status ( 200 ) . send ( result . rows [ 0 ] ) ;
}
) ;
2022-04-07 13:35:36 +03:00
router . get (
"/" ,
authenticateRoute ( ) ,
async ( req , res ) = > {
const result = await query ( "SELECT id, name, owner_id FROM channels" ) ;
return res . status ( 200 ) . send ( result . rows ) ;
}
) ;
2022-04-12 00:02:43 +03:00
router . post (
"/:id/messages" ,
authenticateRoute ( ) ,
param ( "id" ) . isNumeric ( ) ,
body ( "content" ) . isLength ( { min : 1 , max : 4000 } ) ,
async ( req , res ) = > {
const validationErrors = validationResult ( req ) ;
if ( ! validationErrors . isEmpty ( ) ) {
return res . status ( 400 ) . json ( { . . . errors . INVALID_DATA , errors : validationErrors.array ( ) } ) ;
}
const channelId = parseInt ( req . params . id ) ;
const { content } = req . body ;
const authorId = req . user . id ;
const createdAt = Date . now ( ) . toString ( ) ;
const result = await query ( "INSERT INTO messages(content, channel_id, author_id, created_at) VALUES ($1, $2, $3, $4) RETURNING id" , [ content , channelId , authorId , createdAt ] ) ;
if ( result . rowCount < 1 ) {
return res . status ( 500 ) . json ( {
. . . errors . GOT_NO_DATABASE_DATA
} ) ;
}
const returnObject = {
id : result.rows [ 0 ] . id ,
content ,
channel_id : channelId ,
author_id : authorId ,
created_at : createdAt
} ;
dispatch ( ` channel: ${ channelId } ` , {
t : GatewayPayloadType.MessageCreate ,
d : returnObject
} ) ;
return res . status ( 201 ) . send ( returnObject ) ;
}
) ;
router . get (
"/:id/messages" ,
authenticateRoute ( ) ,
param ( "id" ) . isNumeric ( ) ,
async ( req , res ) = > {
const validationErrors = validationResult ( req ) ;
if ( ! validationErrors . isEmpty ( ) ) {
return res . status ( 400 ) . json ( { . . . errors . INVALID_DATA , errors : validationErrors.array ( ) } ) ;
}
const { before } = req . query ;
const channelId = parseInt ( req . params . id ) ;
let finalRows = [ ] ;
if ( before ) {
const result = await query ( "SELECT id, content, channel_id, author_id, created_at FROM messages WHERE id < $1 AND channel_id = $2 ORDER BY id DESC LIMIT 50" , [ before , channelId ] ) ;
finalRows = result . rows ;
} else {
const result = await query ( "SELECT id, content, channel_id, author_id, created_at FROM messages WHERE channel_id = $1 ORDER BY id DESC LIMIT 50" , [ channelId ] ) ;
finalRows = result . rows ;
}
return res . status ( 200 ) . send ( finalRows ) ;
}
) ;
2022-04-06 18:50:36 +03:00
export default router ;