Compare commits
No commits in common. "0b7f194ff415f65d58a16dbd267ffdadfd52d1eb" and "b50f603ee2b2ace52d51334cae3ce760fe33422c" have entirely different histories.
0b7f194ff4
...
b50f603ee2
@ -27,7 +27,6 @@ By default any OAuth callbacks are expected at `/api/login/<methodname>`, where
|
|||||||
|
|
||||||
**Endpoints**
|
**Endpoints**
|
||||||
Any all endpoints should go in the `/endpoints` directory and are expected to inherit from the Endpoint superclass.
|
Any all endpoints should go in the `/endpoints` directory and are expected to inherit from the Endpoint superclass.
|
||||||
Endpoints have a loadOrder property that can be adjusted, lower values are loaded first.
|
|
||||||
|
|
||||||
## Main components
|
## Main components
|
||||||
**Controller:** `/src/controller/Controller.js`
|
**Controller:** `/src/controller/Controller.js`
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
const fs = require('node:fs');
|
const fs = require('node:fs');
|
||||||
|
|
||||||
const { Endpoint: BaseEndpoint } = require('../interfaces');
|
const {Endpoint: BaseEndpoint} = require('../interfaces')
|
||||||
const { Util } = require('../../util');
|
const { Util } = require('../../util');
|
||||||
const { Collection } = require('@discordjs/collection');
|
const { Collection } = require('@discordjs/collection');
|
||||||
|
|
||||||
@ -33,13 +33,13 @@ class Registry {
|
|||||||
|
|
||||||
const { server, endpoints, logger } = this;
|
const { server, endpoints, logger } = this;
|
||||||
|
|
||||||
(function read (pth) {
|
return (async function read (pth) {
|
||||||
|
|
||||||
const dir = fs.readdirSync(pth, { withFileTypes: true });
|
const dir = fs.readdirSync(pth, { withFileTypes: true });
|
||||||
|
|
||||||
for (let file of dir) {
|
for (let file of dir) {
|
||||||
|
|
||||||
if (file.isDirectory()) read(path.join(pth, file.name));
|
if (file.isDirectory()) await read(path.join(pth, file.name));
|
||||||
else {
|
else {
|
||||||
|
|
||||||
file = path.join(pth, file.name);
|
file = path.join(pth, file.name);
|
||||||
@ -51,9 +51,10 @@ class Registry {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const endpoint = new Endpoint(server);
|
const endpoint = new Endpoint(server);
|
||||||
if (!(endpoint instanceof BaseEndpoint)) throw new Error(`Attempt to load invalid endpoint at ${file.name}`);
|
if(!(endpoint instanceof BaseEndpoint)) throw new Error(`Attempt to load invalid endpoint at ${file.name}`)
|
||||||
if (endpoints.has(endpoint.resolveable)) throw new Error(`Error registering endpoint ${endpoint.resolveable}: an endpoint with that resolveable already exists`);
|
endpoint.init();
|
||||||
|
|
||||||
|
if (endpoints.has(endpoint.resolveable)) throw new Error(`Error registering endpoint ${endpoint.resolveable}: an endpoint with that resolveable already exists`);
|
||||||
endpoints.set(endpoint.resolveable, endpoint);
|
endpoints.set(endpoint.resolveable, endpoint);
|
||||||
logger.info(`Created endpoint ${endpoint.name}`);
|
logger.info(`Created endpoint ${endpoint.name}`);
|
||||||
|
|
||||||
@ -63,9 +64,6 @@ class Registry {
|
|||||||
|
|
||||||
}(this.path));
|
}(this.path));
|
||||||
|
|
||||||
const sorted = this.endpoints.sort((a, b) => a.loadOrder - b.loadOrder);
|
|
||||||
for (const ep of sorted.values()) ep.init();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ const { inspect } = require('node:util');
|
|||||||
const { AbstractUserDatabase } = require("../interfaces/");
|
const { AbstractUserDatabase } = require("../interfaces/");
|
||||||
const { User } = require("../structures");
|
const { User } = require("../structures");
|
||||||
const UserApplicataion = require("../structures/UserApplication");
|
const UserApplicataion = require("../structures/UserApplication");
|
||||||
const { Util } = require("../../util");
|
|
||||||
|
|
||||||
// MongoDB based user db
|
// MongoDB based user db
|
||||||
class UserDatabase extends AbstractUserDatabase {
|
class UserDatabase extends AbstractUserDatabase {
|
||||||
@ -186,35 +185,6 @@ class UserDatabase extends AbstractUserDatabase {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create code for letting users register when registration is disabled
|
|
||||||
*
|
|
||||||
* @param {number} [validFor=1] Amount of days the code is valid
|
|
||||||
* @memberof UserDatabase
|
|
||||||
*/
|
|
||||||
async createRegistrationCode (validFor = 1) {
|
|
||||||
const string = Util.randomString();
|
|
||||||
const now = Date.now();
|
|
||||||
const obj = { code: string, validFor: validFor * 24 * 60 * 60 * 1000, created: now };
|
|
||||||
await this.db.insertOne('registrationCodes', obj);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
async consumeRegistrationCode (code) {
|
|
||||||
const result = await this.db.findOne('registrationCodes', { code });
|
|
||||||
|
|
||||||
// Invalid conditions
|
|
||||||
if (!result) return false;
|
|
||||||
if (result.created + result.validFor < Date.now()) {
|
|
||||||
// Code existed but is no longer valid
|
|
||||||
await this.db.deleteOne('registrationCodes', { _id: ObjectId(result._id) });
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// Valid code
|
|
||||||
await this.db.deleteOne('registrationCodes', { _id: ObjectId(result._id) });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates user entry
|
* Updates user entry
|
||||||
*
|
*
|
||||||
|
@ -9,8 +9,7 @@ class Api404 extends ApiEndpoint {
|
|||||||
|
|
||||||
super(server, {
|
super(server, {
|
||||||
name: 'api404',
|
name: 'api404',
|
||||||
path: '/*',
|
path: '/*'
|
||||||
loadOrder: 10
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.methods = [
|
this.methods = [
|
||||||
|
@ -13,9 +13,8 @@ class RegisterEndpoint extends ApiEndpoint {
|
|||||||
[ 'post', this.register.bind(this), [ this.notLoggedIn.bind(this) ]]
|
[ 'post', this.register.bind(this), [ this.notLoggedIn.bind(this) ]]
|
||||||
];
|
];
|
||||||
this.subpaths = [
|
this.subpaths = [
|
||||||
[ '/finalise', 'post', this.finaliseRegistration.bind(this), [ server.auth.authenticate ]],
|
[ '/finalise', 'post', this.finaliseRegistration.bind(this), [ this.loggedIn.bind(this) ]],
|
||||||
[ '/toggle', 'post', this.toggleRegistration.bind(this), [ server.auth.createAuthoriser('administrator', 5) ]],
|
[ '/toggle', 'post', this.toggleRegistration.bind(this), [ server.authenticator.createAuthoriser('administrator', 5) ]]
|
||||||
[ '/code', 'get', this.registrationCode.bind(this), [ server.auth.createAuthoriser('administrator', 5) ]]
|
|
||||||
];
|
];
|
||||||
this.middleware = [ ];
|
this.middleware = [ ];
|
||||||
|
|
||||||
@ -70,10 +69,9 @@ class RegisterEndpoint extends ApiEndpoint {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async registrationCode (req, res) {
|
loggedIn (req, res, next) {
|
||||||
const code = await this.userdb.createRegistrationCode();
|
if (!req.user) return res.status(400).end();
|
||||||
delete code._id;
|
next();
|
||||||
res.json(code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
notLoggedIn (req, res, next) {
|
notLoggedIn (req, res, next) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
const { Util } = require('../../util');
|
const { Util } = require('../../util');
|
||||||
|
|
||||||
class Endpoint {
|
class Endpoint {
|
||||||
constructor (server, { path, name, loadOrder = 5 }) {
|
constructor (server, { path, name }) {
|
||||||
|
|
||||||
if (!server) Util.fatal(new Error('Missing server object in endpoint'));
|
if (!server) Util.fatal(new Error('Missing server object in endpoint'));
|
||||||
this.server = server;
|
this.server = server;
|
||||||
@ -25,11 +25,6 @@ class Endpoint {
|
|||||||
this.logger = server.createLogger(this);
|
this.logger = server.createLogger(this);
|
||||||
this.debug = false;
|
this.debug = false;
|
||||||
|
|
||||||
// Used to sort the endpoints from smallest to highest before initialisation
|
|
||||||
// Useful when needing to have certain endpoints register before or after some other endpoint
|
|
||||||
// E.g. 404 pages should be initialised last by having a loadOrder of 10
|
|
||||||
this.loadOrder = loadOrder;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init () {
|
init () {
|
||||||
|
@ -130,7 +130,7 @@ class Authenticator {
|
|||||||
// we don't care about that, we just want the key, which will always be the last element
|
// we don't care about that, we just want the key, which will always be the last element
|
||||||
const authHeader = req.get('Authorization') || req.get('Authorisation');
|
const authHeader = req.get('Authorization') || req.get('Authorisation');
|
||||||
if (!authHeader) {
|
if (!authHeader) {
|
||||||
res.status(401).send('Invalid auth header');
|
res.status(400).send('Invalid auth header');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,6 +59,7 @@ class Util {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static createEncryptionKey (secret, salt, len = 32) {
|
static createEncryptionKey (secret, salt, len = 32) {
|
||||||
|
|
||||||
if (!secret) throw new Error('Missing secret');
|
if (!secret) throw new Error('Missing secret');
|
||||||
|
Loading…
Reference in New Issue
Block a user