aboutsummaryrefslogtreecommitdiff
path: root/src/api/structures/Route.js
blob: 9496d0fab677ab8c16c77695014a95ef142ca716 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
const JWT = require('jsonwebtoken');
const db = require('./Database');
const moment = require('moment');
const log = require('../utils/Log');
const Util = require('../utils/Util');

class Route {
	constructor(path, method, options) {
		if (!path) throw new Error('Every route needs a URL associated with it.');
		if (!method) throw new Error('Every route needs its method specified.');

		this.path = path;
		this.method = method;
		this.options = options || {};
	}

	async authorize(req, res) {
		const banned = await db
			.table('bans')
			.where({ ip: req.ip })
			.first();
		if (banned) return res.status(401).json({ message: 'This IP has been banned from using the service.' });

		if (this.options.bypassAuth) return this.run(req, res, db);
		// The only reason I call it token here and not Api Key is to be backwards compatible
		// with the uploader and sharex
		// Small price to pay.
		if (req.headers.token) return this.authorizeApiKey(req, res, req.headers.token);
		if (!req.headers.authorization) return res.status(401).json({ message: 'No authorization header provided' });

		const token = req.headers.authorization.split(' ')[1];
		if (!token) return res.status(401).json({ message: 'No authorization header provided' });

		return JWT.verify(token, Util.config.secret, async (error, decoded) => {
			if (error) {
				log.error(error);
				return res.status(401).json({ message: 'Invalid token' });
			}
			const id = decoded ? decoded.sub : '';
			const iat = decoded ? decoded.iat : '';

			const user = await db
				.table('users')
				.where({ id })
				.first();
			if (!user) return res.status(401).json({ message: 'Invalid authorization' });
			if (iat && iat < moment(user.passwordEditedAt).format('x')) {
				return res.status(401).json({ message: 'Token expired' });
			}
			if (!user.enabled) return res.status(401).json({ message: 'This account has been disabled' });
			if (this.options.adminOnly && !user.isAdmin) { return res.status(401).json({ message: 'Invalid authorization' }); }

			return this.run(req, res, db, user);
		});
	}

	async authorizeApiKey(req, res, apiKey) {
		if (!this.options.canApiKey) return res.status(401).json({ message: 'Api Key not allowed for this resource' });
		const user = await db
			.table('users')
			.where({ apiKey })
			.first();
		if (!user) return res.status(401).json({ message: 'Invalid authorization' });
		if (!user.enabled) return res.status(401).json({ message: 'This account has been disabled' });

		return this.run(req, res, db, user);
	}

	run() {}

	error(res, error) {
		log.error(error);
		return res.status(500).json({ message: 'There was a problem parsing the request' });
	}
}

module.exports = Route;