Compare commits

..

5 Commits

Author SHA1 Message Date
Kayne Ruse ab0bad4f73 Chat report table working 2021-03-28 07:57:56 +11:00
Kayne Ruse f83ef938ab Updated admin and mod flag system 2021-03-24 08:23:02 +11:00
Kayne Ruse 0b5cc49e6e Added reporting feature 2021-03-24 03:20:29 +11:00
Kayne Ruse 2dad56d17e Updated libraries 2021-03-24 01:51:55 +11:00
Kayne Ruse 5f15228e53 Each microservice has received a tweak to .envdev, read more
This should make it easier to set time zones and enable database logging.

Related to krgamestudios/MERN-template#16
2021-03-22 16:44:12 +11:00
11 changed files with 158 additions and 24 deletions
+7 -1
View File
@@ -4,6 +4,12 @@ DB_HOSTNAME=database
DB_DATABASE=chat DB_DATABASE=chat
DB_USERNAME=chat DB_USERNAME=chat
DB_PASSWORD=blastoise DB_PASSWORD=blastoise
# Select a "TZ database name" that suits your needs: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
DB_TIMEZONE=Australia/Sydney DB_TIMEZONE=Australia/Sydney
SECRET_ACCESS=access # Give this any value to enable database logging (such as "true")
DB_LOGGING=
# Make sure this value matches the system that you connect to
SECRET_ACCESS=access
+1
View File
@@ -19,6 +19,7 @@ on 'error' -> Server emits and logs an error
on 'open chat' -> Preps the server for your messages, places you in the room 'general' on 'open chat' -> Preps the server for your messages, places you in the room 'general'
on 'message' -> Server broadcasts to all other users in your room on 'message' -> Server broadcasts to all other users in your room
on 'disconnect' -> Server will no longer accept your messages on 'disconnect' -> Server will no longer accept your messages
on 'report' -> Report the chatlog with the index 'id'
Chat Commands: Chat Commands:
+12 -14
View File
@@ -604,7 +604,6 @@
"version": "8.2.0", "version": "8.2.0",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==", "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=8" "node": ">=8"
} }
@@ -1807,10 +1806,9 @@
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
}, },
"node_modules/sequelize": { "node_modules/sequelize": {
"version": "6.5.1", "version": "6.6.2",
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.5.1.tgz", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.6.2.tgz",
"integrity": "sha512-DWgaF+Vw+gWpxomyyYppUOCWzP0ReoMol8EEaDMA+cbSUevyMb74BEwSAd0c8GKgDYiOjpq4DmKBQLHtLAgS1g==", "integrity": "sha512-H/zrzmTK+tis9PJaSigkuXI57nKBvNCtPQol0yxCvau1iWLzSOuq8t3tMOVeQ+Ep8QH2HoD9/+FCCIAqzUr/BQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"debug": "^4.1.1", "debug": "^4.1.1",
"dottie": "^2.0.0", "dottie": "^2.0.0",
@@ -1880,9 +1878,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/sequelize/node_modules/semver": { "node_modules/sequelize/node_modules/semver": {
"version": "7.3.4", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dependencies": { "dependencies": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
}, },
@@ -3722,9 +3720,9 @@
} }
}, },
"sequelize": { "sequelize": {
"version": "6.5.1", "version": "6.6.2",
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.5.1.tgz", "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.6.2.tgz",
"integrity": "sha512-DWgaF+Vw+gWpxomyyYppUOCWzP0ReoMol8EEaDMA+cbSUevyMb74BEwSAd0c8GKgDYiOjpq4DmKBQLHtLAgS1g==", "integrity": "sha512-H/zrzmTK+tis9PJaSigkuXI57nKBvNCtPQol0yxCvau1iWLzSOuq8t3tMOVeQ+Ep8QH2HoD9/+FCCIAqzUr/BQ==",
"requires": { "requires": {
"debug": "^4.1.1", "debug": "^4.1.1",
"dottie": "^2.0.0", "dottie": "^2.0.0",
@@ -3755,9 +3753,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"semver": { "semver": {
"version": "7.3.4", "version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"requires": { "requires": {
"lru-cache": "^6.0.0" "lru-cache": "^6.0.0"
} }
+21
View File
@@ -0,0 +1,21 @@
const express = require('express');
const router = express.Router();
//middleware
const tokenAuth = require('../utilities/token-auth');
router.use(tokenAuth);
router.use((req, res, next) => {
//check the user's admin status
if (!req.user.mod) {
return res.status(401).send('Mods only');
}
next();
});
//basic route management
router.get('/reports', require('./reports'));
router.delete('/reports', require('./reports-delete'));
module.exports = router;
+15
View File
@@ -0,0 +1,15 @@
const { chatlog, reports } = require('../database/models');
//admin/reports
const route = async (req, res) => {
const reps = await reports.destroy({
where: {
chatlogId: req.body.chatlogId
}
});
//respond
res.status(200).end();
};
module.exports = route;
+31
View File
@@ -0,0 +1,31 @@
const { chatlog, reports } = require('../database/models');
//admin/reports
const route = async (req, res) => {
const reps = await reports.findAll({
include: [{
model: chatlog,
required: true
}],
order: ['chatlogId']
});
//collate
const response = [];
for(let i = 0; i < reps.length; i++) {
//new chatlog
if (response.length == 0 || response[response.length - 1].chatlogId != reps[i].chatlogId) {
response.push(reps[i]);
response[response.length - 1].reporter = [response[response.length - 1].reporter]; //reporters in an array
continue;
}
//multiple people reported this, add to the existing array
response[response.length - 1].reporter.push(reps[i].reporter);
}
//respond
res.status(200).json(response);
};
module.exports = route;
+21 -8
View File
@@ -1,13 +1,13 @@
const jwt = require('jsonwebtoken'); const jwt = require('jsonwebtoken');
const { Op } = require('sequelize'); const { Op } = require('sequelize');
const { chatlog, mute } = require('../database/models'); const { chatlog, mute, reports } = require('../database/models');
const chat = io => { const chat = io => {
io.on('connection', socket => { io.on('connection', socket => {
//middleware //middleware
socket.use((request, next) => { socket.use((request, next) => {
//verify request format //verify request format
if (!['open chat', 'message'].includes(request[0])) { if (!['open chat', 'message', 'report'].includes(request[0])) {
return next(`Invalid request to the chat server ${request[0]}`); return next(`Invalid request to the chat server ${request[0]}`);
} }
return next(); return next();
@@ -109,15 +109,15 @@ const chat = io => {
return; return;
} }
//broadcast to this room
socket.broadcast.to(socket.user.room).emit('message', { username: socket.user.username, text: message.text });
//log //log
chatlog.create({ const log = await chatlog.create({
username: socket.user.username, username: socket.user.username,
text: message.text, text: message.text,
room: socket.user.room room: socket.user.room
}); });
//broadcast to this room (with the id)
socket.broadcast.to(socket.user.room).emit('message', log);
}); });
socket.on('disconnect', reason => { socket.on('disconnect', reason => {
@@ -137,6 +137,19 @@ const chat = io => {
emphasis: true emphasis: true
}); });
}); });
socket.on('report', info => {
//handle reports of malicious content
if (!info.id) {
return;
}
//report
reports.create({
reporter: socket.user.username,
chatlogId: info.id
});
});
}); });
}; };
@@ -186,7 +199,7 @@ const executeCommand = (io, socket, command) => {
} }
case '/mute': {//NOTE: mutes globally, broadcasts only to admin's room case '/mute': {//NOTE: mutes globally, broadcasts only to admin's room
if (socket.user.privilege != 'administrator' && socket.user.privilege != 'moderator') { if (!socket.user.admin && !socket.user.mod) {
socket.emit('message', { emphasis: true, text: '/mute is only available to admins and mods' }); socket.emit('message', { emphasis: true, text: '/mute is only available to admins and mods' });
break; break;
} }
@@ -229,7 +242,7 @@ const executeCommand = (io, socket, command) => {
} }
case '/unmute': { case '/unmute': {
if (socket.user.privilege != 'administrator' && socket.user.privilege != 'moderator') { if (!socket.user.admin && !socket.user.mod) {
socket.emit('message', { emphasis: true, text: '/unmute is only available to admins and mods' }); socket.emit('message', { emphasis: true, text: '/unmute is only available to admins and mods' });
break; break;
} }
+2 -1
View File
@@ -1,4 +1,5 @@
module.exports = { module.exports = {
chatlog: require('./chatlog'), chatlog: require('./chatlog'),
mute: require('./mute') mute: require('./mute'),
reports: require('./reports')
}; };
+24
View File
@@ -0,0 +1,24 @@
const Sequelize = require('sequelize');
const sequelize = require('..');
const chatlog = require('./chatlog');
const reports = sequelize.define('reports', {
id: {
type: Sequelize.INTEGER(11),
allowNull: false,
autoIncrement: true,
primaryKey: true,
unique: true
},
reporter: {
type: 'varchar(320)',
allowNull: false
},
});
chatlog.hasMany(reports, { foreignKey: 'chatlogId', foreignKeyConstraint: true });
reports.belongsTo(chatlog, { foreignKey: 'chatlogId' });
module.exports = reports;
+3
View File
@@ -20,6 +20,9 @@ app.use(cors());
//database connection //database connection
const database = require('./database'); const database = require('./database');
//admin stuff
app.use('/admin', require('./admin'));
//access the chat //access the chat
require('./chat')(io.of('/chat')); require('./chat')(io.of('/chat'));
+21
View File
@@ -0,0 +1,21 @@
const jwt = require('jsonwebtoken');
//middleware to authenticate the JWT token
module.exports = (req, res, next) => {
const authHeader = req.headers['authorization'];
const token = authHeader?.split (' ')[1]; //'Bearer token'
if (!token) {
return res.status(401).send('No token found');
}
return jwt.verify(token, process.env.SECRET_ACCESS, (err, user) => {
if (err) {
return res.status(403).send(err);
}
req.user = user;
return next();
});
};