Compare commits

..

2 Commits

Author SHA1 Message Date
Kayne Ruse 547d5dba1c Implemented permabans 2021-03-28 08:32:28 +11:00
Kayne Ruse e597974581 Updated admin and mod flag system 2021-03-24 08:22:47 +11:00
15 changed files with 240 additions and 48 deletions
-10
View File
@@ -76,14 +76,4 @@ Content-Type: application/json
{ {
"password": "helloworld" "password": "helloworld"
} }
//DOCS: Sets the privilege of the specified user; usable only by admins
PATCH /auth/admin/privilege
Authorization: Bearer accessToken
Content-Type: application/json
{
"username": "example",
"privilege: "administrator"
}
``` ```
-20
View File
@@ -1,20 +0,0 @@
const { accounts } = require('../database/models');
//auth/account/privilege
const route = async (req, res) => {
const updated = await accounts.update({
privilege: req.body.privilege
}, {
where: {
username: req.body.username
}
});
if (updated < 1) {
return res.status(403).send(`Unknown account`);
}
return res.status(200).end();
};
module.exports = route;
+37
View File
@@ -0,0 +1,37 @@
const { accounts, tokens } = require('../database/models');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
//admin/banuser
const route = async (req, res) => {
const updated = await accounts.update({
banned: true
}, {
where: {
username: {
[Op.eq]: req.body.username
},
admin: {
[Op.not]: true
},
mod: {
[Op.not]: true
}
}
});
if (!updated[0]) {
return res.status(500).send('Failed to set banned status');
}
//forcibly logout
tokens.destroy({
where: {
username: req.body.username
}
});
res.status(200).end();
};
module.exports = route;
+5 -3
View File
@@ -20,16 +20,18 @@ module.exports = async () => {
//check for an existing admin account //check for an existing admin account
const adminRecord = await accounts.findOne({ const adminRecord = await accounts.findOne({
where: { where: {
privilege: 'administrator' admin: true
} }
}); });
if (adminRecord == null) { if (adminRecord == null) {
await accounts.create({ await accounts.create({
privilege: 'administrator',
email: `${process.env.ADMIN_DEFAULT_USERNAME}@${process.env.WEB_ADDRESS}`, email: `${process.env.ADMIN_DEFAULT_USERNAME}@${process.env.WEB_ADDRESS}`,
username: `${process.env.ADMIN_DEFAULT_USERNAME}`, username: `${process.env.ADMIN_DEFAULT_USERNAME}`,
hash: await bcrypt.hash(`${process.env.ADMIN_DEFAULT_PASSWORD}`, await bcrypt.genSalt(11)) hash: await bcrypt.hash(`${process.env.ADMIN_DEFAULT_PASSWORD}`, await bcrypt.genSalt(11)),
type: 'normal',
admin: true,
mod: true
}); });
console.warn(`Created default admin account (email: ${process.env.ADMIN_DEFAULT_USERNAME}@${process.env.WEB_ADDRESS}; password: ${process.env.ADMIN_DEFAULT_PASSWORD})`); console.warn(`Created default admin account (email: ${process.env.ADMIN_DEFAULT_USERNAME}@${process.env.WEB_ADDRESS}; password: ${process.env.ADMIN_DEFAULT_PASSWORD})`);
+25
View File
@@ -0,0 +1,25 @@
const { accounts } = require('../database/models');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
//admin/admin
const route = async (req, res) => {
const updated = await accounts.update({
admin: true,
mod: true
}, {
where: {
username: {
[Op.eq]: req.body.username
}
}
});
if (!updated[0]) {
return res.status(500).send('Failed to set admin status');
}
res.status(200).end();
};
module.exports = route;
+24
View File
@@ -0,0 +1,24 @@
const { accounts } = require('../database/models');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
//admin/mod
const route = async (req, res) => {
const updated = await accounts.update({
mod: true
}, {
where: {
username: {
[Op.eq]: req.body.username
}
}
});
if (!updated[0]) {
return res.status(500).send('Failed to set mod status');
}
res.status(200).end();
};
module.exports = route;
+43 -4
View File
@@ -1,14 +1,50 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const { accounts } = require('../database/models');
//middleware //middleware
const tokenAuth = require('../utilities/token-auth'); const tokenAuth = require('../utilities/token-auth');
router.use(tokenAuth); router.use(tokenAuth);
//handle ban stuff
router.use(async (req, res, next) => {
const record = await accounts.findOne({
where: {
username: req.user.username
}
});
if (!record) {
return res.status(500).send('Account not found in banning middleware');
}
if (record.banned) {
return res.status(403).send('This account has been banned');
}
next();
});
//handle mod stuff
router.use((req, res, next) => { router.use((req, res, next) => {
//check the user's privilege //check the user's mod status
if (req.user.privilege != 'administrator') { if (!req.user.mod) {
return res.status(401).send('Admins only'); return res.status(401).send('Mods only');
}
next();
});
//routes
router.post('/banuser', require('./ban-user'));
//handle admin stuff
router.use((req, res, next) => {
//check the user's admin status
if (!req.user.admin) {
return res.status(401).send('Admin only');
} }
next(); next();
@@ -17,6 +53,9 @@ router.use((req, res, next) => {
require('./default-account')(); //generate the default accouunt require('./default-account')(); //generate the default accouunt
//basic route management //basic route management
router.patch('/privilege', require('./account-privilege')); router.post('/admin', require('./grant-admin'));
router.delete('/admin', require('./remove-admin'));
router.post('/mod', require('./grant-mod'));
router.delete('/mod', require('./remove-mod'));
module.exports = router; module.exports = router;
+24
View File
@@ -0,0 +1,24 @@
const { accounts } = require('../database/models');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
//admin/admin
const route = async (req, res) => {
const updated = await accounts.update({
admin: false
}, {
where: {
username: {
[Op.eq]: req.body.username
}
}
});
if (!updated[0]) {
return res.status(500).send('Failed to set admin status');
}
res.status(200).end();
};
module.exports = route;
+25
View File
@@ -0,0 +1,25 @@
const { accounts } = require('../database/models');
const Sequelize = require('sequelize');
const Op = Sequelize.Op;
//admin/admin
const route = async (req, res) => {
const updated = await accounts.update({
admin: false,
mod: false
}, {
where: {
username: {
[Op.eq]: req.body.username
}
}
});
if (!updated[0]) {
return res.status(500).send('Failed to set mod status');
}
res.status(200).end();
};
module.exports = route;
+20
View File
@@ -1,6 +1,8 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const { accounts } = require('../database/models');
//middleware //middleware
const tokenAuth = require('../utilities/token-auth'); const tokenAuth = require('../utilities/token-auth');
@@ -15,6 +17,24 @@ router.post('/token', require('./token'));
//middleware //middleware
router.use(tokenAuth); router.use(tokenAuth);
router.use(async (req, res, next) => {
const record = await accounts.findOne({
where: {
username: req.user.username
}
});
if (!record) {
return res.status(500).send('Account not found in banning middleware');
}
if (record.banned) {
return res.status(403).send('This account has been banned');
}
next();
});
//basic account management (needs a token) //basic account management (needs a token)
router.delete('/logout', require('./logout')); router.delete('/logout', require('./logout'));
router.get('/account', require('./account-query')); router.get('/account', require('./account-query'));
+6 -1
View File
@@ -42,8 +42,13 @@ const route = async (req, res) => {
} }
}); });
//reject on banned
if (account.banned) {
return res.status(403).send('this account has been banned');
}
//generate the JWT //generate the JWT
const tokens = generate(account.id, account.username, account.privilege); const tokens = generate(account.id, account.username, account.type, account.admin, account.mod);
//finally //finally
res.status(200).json(tokens); res.status(200).json(tokens);
+24 -6
View File
@@ -10,12 +10,6 @@ module.exports = sequelize.define('accounts', {
unique: true unique: true
}, },
privilege: {
type: Sequelize.ENUM,
values: ['administrator', 'moderator', 'alpha', 'beta', 'gamma', 'normal'],
defaultValue: 'normal'
},
email: { email: {
type: 'varchar(320)', type: 'varchar(320)',
unique: true unique: true
@@ -28,6 +22,30 @@ module.exports = sequelize.define('accounts', {
hash: 'varchar(100)', //for passwords hash: 'varchar(100)', //for passwords
type: {
type: Sequelize.ENUM,
values: ['normal', 'alpha', 'beta', 'gamma'],
defaultValue: 'normal'
},
admin: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
},
mod: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
},
banned: {
type: Sequelize.BOOLEAN,
allowNull: false,
defaultValue: false
},
contact: { contact: {
type: Sequelize.BOOLEAN, type: Sequelize.BOOLEAN,
allowNull: false, allowNull: false,
+1
View File
@@ -3,4 +3,5 @@ const sequelize = require('..');
module.exports = sequelize.define('tokens', { module.exports = sequelize.define('tokens', {
token: 'varchar(320)', token: 'varchar(320)',
username: 'varchar(320)'
}); });
+5 -3
View File
@@ -2,17 +2,19 @@ const jwt = require('jsonwebtoken');
const { tokens } = require('../database/models'); const { tokens } = require('../database/models');
//generates a JWT token based on the given arguments //generates a JWT token based on the given arguments
module.exports = (id, username, privilege) => { module.exports = (id, username, type, admin, mod) => {
const content = { const content = {
id, id,
username, username,
privilege type,
admin,
mod,
}; };
const accessToken = jwt.sign(content, process.env.SECRET_ACCESS, { expiresIn: '10m' }); const accessToken = jwt.sign(content, process.env.SECRET_ACCESS, { expiresIn: '10m' });
const refreshToken = jwt.sign(content, process.env.SECRET_REFRESH, { expiresIn: '30d' }); const refreshToken = jwt.sign(content, process.env.SECRET_REFRESH, { expiresIn: '30d' });
tokens.create({ token: refreshToken }); tokens.create({ token: refreshToken, username: username });
return { accessToken, refreshToken }; return { accessToken, refreshToken };
}; };
+1 -1
View File
@@ -24,7 +24,7 @@ module.exports = (token, callback) => {
return callback(403); return callback(403);
} }
const result = generate(user.id, user.username, user.privilege); const result = generate(user.id, user.username, user.type, user.admin, user.mod);
destroy(token); destroy(token);