Compare commits

..

No commits in common. "b50f603ee2b2ace52d51334cae3ce760fe33422c" and "9fc6950664529548e5aed51e3276ed0b7b3606be" have entirely different histories.

8 changed files with 19 additions and 56 deletions

View File

@ -1,7 +1,6 @@
# Navy's webserver framework
A template repository for creating Node.js based webservers with sharding.
Main repository: https://git.corgi.wtf/Navy.gif/webserver-framework
Frontend: https://git.corgi.wtf/Navy.gif/webserver-framework-frontend
## Technologies
- Argon2
@ -22,12 +21,6 @@ Fetching the upstream changes
- Merge changes to the current branch `git merge upstream/master`.
(Use `git remote -v` to list remotes)
**OAuth callbacks**
By default any OAuth callbacks are expected at `/api/login/<methodname>`, where methodname is the name of the OAuth strategy. E.g. by default this framework has a discord strategy defined in Server.addAuthStrategies which expects a callback to `/api/login/discord`.
**Endpoints**
Any all endpoints should go in the `/endpoints` directory and are expected to inherit from the Endpoint superclass.
## Main components
**Controller:** `/src/controller/Controller.js`
Master process, orchestrates the whole program. Takes care of starting up the shards and communication with them.

View File

@ -11,7 +11,6 @@ MONGO_PORT=27017
MONGO_USER=
MONGO_PASS=
MONGO_DB=framework-proto
MONGO_AUTH_DB=auth
# Encryption secret
CRYPTO_SECRET=verySecretSecret

View File

@ -34,7 +34,7 @@ class Server extends EventEmitter {
const { MARIA_HOST, MARIA_USER, MARIA_PORT, MARIA_PASS, MARIA_DB,
MONGO_HOST, MONGO_USER, MONGO_PORT, MONGO_PASS, MONGO_DB,
NODE_ENV, SECRET, CRYPTO_SECRET, CRYPTO_SALT, MONGO_AUTH_DB } = process.env;
NODE_ENV, SECRET, CRYPTO_SECRET, CRYPTO_SALT } = process.env;
const { http: httpOpts, databases, validUserTypes } = options;
// This key never leaves memory and is exclusively used on the server, the salt can stay static
@ -66,7 +66,7 @@ class Server extends EventEmitter {
// Mariadb isn't strictly necessary here for anything, it's just here pre-emptively
this.mariadb = new MariaDB(this, { options: databases.mariadb, MARIA_HOST, MARIA_USER, MARIA_PORT, MARIA_PASS, MARIA_DB });
// Mongo is used for session and user storage
this.mongodb = new MongoDB(this, { options: databases.mongodb, MONGO_HOST, MONGO_USER, MONGO_PORT, MONGO_PASS, MONGO_DB, MONGO_AUTH_DB });
this.mongodb = new MongoDB(this, { options: databases.mongodb, MONGO_HOST, MONGO_USER, MONGO_PORT, MONGO_PASS, MONGO_DB });
this.userDatabase = new UserDatabase(this, this.mongodb, { validUserTypes });
// Alias
this.users = this.userDatabase;
@ -102,6 +102,9 @@ class Server extends EventEmitter {
},
crossOriginResourcePolicy: {
policy: 'cross-origin'
},
crossOriginEmbedderPolicy: {
policy: 'require-corp'
}
}));
this.app.use(express.json({ limit: '10mb' }));

View File

@ -156,7 +156,7 @@ class UserDatabase extends AbstractUserDatabase {
}
this.logger.info(`Creating new user from Discord profile: ${profile.username} (${profile.id})`);
user = this._createUser({ type: 'user', username: profile.username });
user = this._createUser({ type: 'user', name: profile.username });
user.addExternalProfile('discord', profile);
await user.save();
this.cache.set(user.id, user);

View File

@ -1,27 +0,0 @@
const { ApiEndpoint } = require("../../interfaces");
// Just so requests to /api/.. don't get sent the index.html file on invalid path
// Could've also just defined this quick and dirty in the Server class,
// but I feel this is better for readability
class Api404 extends ApiEndpoint {
constructor (server) {
super(server, {
name: 'api404',
path: '/*'
});
this.methods = [
[ 'get', this.get.bind(this) ]
];
}
async get (req, res) {
res.status(404).end();
}
}
module.exports = Api404;

View File

@ -18,7 +18,7 @@ class LogoutEndpoint extends ApiEndpoint {
logout (req, res) {
req.session.destroy();
res.clearCookie(this.server.auth.cookieName);
res.clearCookie(this.server.authenticator.cookieName);
res.end();
}

View File

@ -22,7 +22,7 @@ class UsersEndpoint extends ApiEndpoint {
const { amount, page } = query;
if (!page) return res.status(400).send('Missing page number');
const users = await this.server.users.fetchUsers(page, amount);
res.json(users.map(user => user.safeJson));
res.json(users.map(user => user.json));
}
async user (req, res) {
@ -30,7 +30,7 @@ class UsersEndpoint extends ApiEndpoint {
const { userid } = params;
const user = await this.server.users.fetchUser(userid);
if (!user) return res.status(404).end();
res.json(user.safeJson);
res.json(user);
}
async userApplications (req, res) {
@ -39,7 +39,7 @@ class UsersEndpoint extends ApiEndpoint {
const user = await this.server.users.fetchUser(userid);
if (!user) return res.status(404).send('Could not find the user');
const applications = await user.fetchApplications();
res.json(Object.values(applications).map(app => app.safeJson));
res.json(Object.values(applications).map(app => app.json));
}
}

View File

@ -3,9 +3,6 @@ const { ObjectId } = require('mongodb');
const { Util } = require('../../util');
const UserApplicataion = require('./UserApplication');
// Fields omitted in safeJson
const ProtectedFields = [ '_id', '_otpSecret', '_passwordHash' ];
class User {
static defaultPermissions = {
@ -32,7 +29,6 @@ class User {
this._db = db;
this.temporary = data.temporary || false;
this.disabled = data.disabled || false;
this._id = data._id || null;
if (this.temporary) this._tempId = `temp-${Date.now()}`;
@ -73,7 +69,6 @@ class User {
this._2fa = data.twoFactor || false;
this.cachedTimestamp = Date.now();
this.createdTimestamp = data.createdTimestamp || Date.now();
}
@ -176,21 +171,21 @@ class User {
otpSecret: this._otpSecret,
twoFactor: this._2fa,
applications: this._applications,
createdTimestamp: this.createdTimestamp,
disabled: this.disabled,
};
}
get safeJson () {
const { json } = this;
for (const key of ProtectedFields) delete json[key];
return {
...json,
id: this.id,
username: this.username,
displayName: this.displayName,
type: this.type,
permissions: this.permissions,
externalProfiles: Object.values(this.externalProfiles).map(prof => {
return { id: prof.id, provider: prof.provider, username: prof.username };
}),
twoFactor: this._2fa,
applications: this._applications,
};
}