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";
|
2022-04-12 22:34:54 +03:00
|
|
|
import { getMessageById, getMessagesByChannelFirstPage, getMessagesByChannelPage } from "../../../database/templates";
|
2022-04-06 18:50:36 +03:00
|
|
|
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,
|
2022-04-12 22:34:54 +03:00
|
|
|
author_username: req.user.username,
|
2022-04-12 00:02:43 +03:00
|
|
|
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) {
|
2022-04-12 22:34:54 +03:00
|
|
|
const result = await query(getMessagesByChannelPage, [before, channelId]);
|
2022-04-12 00:02:43 +03:00
|
|
|
finalRows = result.rows;
|
|
|
|
} else {
|
2022-04-12 22:34:54 +03:00
|
|
|
const result = await query(getMessagesByChannelFirstPage, [channelId]);
|
2022-04-12 00:02:43 +03:00
|
|
|
finalRows = result.rows;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res.status(200).send(finalRows);
|
|
|
|
}
|
|
|
|
);
|
|
|
|
|
|
|
|
|
2022-04-06 18:50:36 +03:00
|
|
|
export default router;
|