aboutsummaryrefslogtreecommitdiff
path: root/src/api/structures
diff options
context:
space:
mode:
authorZephyrrus <[email protected]>2020-07-10 01:17:00 +0300
committerGitHub <[email protected]>2020-07-10 01:17:00 +0300
commita721681944e9eb06742e5b3f71c71aed9c1c117d (patch)
tree93ff9fd13a0434d91fb1ae7ca0da48d6929c4d00 /src/api/structures
parentfeat: backend pagination for albums (diff)
parentrefactor: finish refactoring all the components to use vuex (diff)
downloadhost.fuwn.me-a721681944e9eb06742e5b3f71c71aed9c1c117d.tar.xz
host.fuwn.me-a721681944e9eb06742e5b3f71c71aed9c1c117d.zip
Merge pull request #1 from Zephyrrus/feature/store_refactor
Feature/store refactor
Diffstat (limited to 'src/api/structures')
-rw-r--r--src/api/structures/Route.js46
-rw-r--r--src/api/structures/Server.js41
2 files changed, 59 insertions, 28 deletions
diff --git a/src/api/structures/Route.js b/src/api/structures/Route.js
index 8956c24..6be0dc7 100644
--- a/src/api/structures/Route.js
+++ b/src/api/structures/Route.js
@@ -7,23 +7,19 @@ const db = require('knex')({
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_DATABASE,
- filename: nodePath.join(__dirname, '..', '..', '..', 'database.sqlite')
+ filename: nodePath.join(__dirname, '../../../database.sqlite'),
},
- postProcessResponse: result => {
+ postProcessResponse: (result) => {
/*
Fun fact: Depending on the database used by the user and given that I don't want
to force a specific database for everyone because of the nature of this project,
some things like different data types for booleans need to be considered like in
the implementation below where sqlite returns 1 and 0 instead of true and false.
*/
- const booleanFields = [
- 'enabled',
- 'enableDownload',
- 'isAdmin'
- ];
+ const booleanFields = ['enabled', 'enableDownload', 'isAdmin'];
- const processResponse = row => {
- Object.keys(row).forEach(key => {
+ const processResponse = (row) => {
+ Object.keys(row).forEach((key) => {
if (booleanFields.includes(key)) {
if (row[key] === 0) row[key] = false;
else if (row[key] === 1) row[key] = true;
@@ -32,11 +28,11 @@ const db = require('knex')({
return row;
};
- if (Array.isArray(result)) return result.map(row => processResponse(row));
+ if (Array.isArray(result)) return result.map((row) => processResponse(row));
if (typeof result === 'object') return processResponse(result);
return result;
},
- useNullAsDefault: process.env.DB_CLIENT === 'sqlite3' ? true : false
+ useNullAsDefault: process.env.DB_CLIENT === 'sqlite3',
});
const moment = require('moment');
const log = require('../utils/Log');
@@ -52,11 +48,15 @@ class Route {
}
async authorize(req, res) {
- const banned = await db.table('bans').where({ ip: req.ip }).first();
+ 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
+ // 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' });
@@ -72,11 +72,16 @@ class Route {
const id = decoded ? decoded.sub : '';
const iat = decoded ? decoded.iat : '';
- const user = await db.table('users').where({ id }).first();
+ 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 (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' });
+ if (this.options.adminOnly && !user.isAdmin) { return res.status(401).json({ message: 'Invalid authorization' }); }
return this.run(req, res, db, user);
});
@@ -84,16 +89,17 @@ class Route {
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();
+ 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(req, res, db) { // eslint-disable-line no-unused-vars
- return;
- }
+ run() {}
error(res, error) {
log.error(error);
diff --git a/src/api/structures/Server.js b/src/api/structures/Server.js
index a8eccd9..c8537fb 100644
--- a/src/api/structures/Server.js
+++ b/src/api/structures/Server.js
@@ -1,6 +1,5 @@
require('dotenv').config();
-const log = require('../utils/Log');
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
@@ -8,11 +7,15 @@ const RateLimit = require('express-rate-limit');
const bodyParser = require('body-parser');
const jetpack = require('fs-jetpack');
const path = require('path');
+const morgan = require('morgan');
+const log = require('../utils/Log');
+const ThumbUtil = require('../utils/ThumbUtil');
+// eslint-disable-next-line no-unused-vars
const rateLimiter = new RateLimit({
windowMs: parseInt(process.env.RATE_LIMIT_WINDOW, 10),
max: parseInt(process.env.RATE_LIMIT_MAX, 10),
- delayMs: 0
+ delayMs: 0,
});
class Server {
@@ -32,16 +35,38 @@ class Server {
});
this.server.use(bodyParser.urlencoded({ extended: true }));
this.server.use(bodyParser.json());
+ if (process.env.NODE_ENV !== 'production') {
+ this.server.use(morgan('combined', {
+ skip(req) {
+ let ext = req.path.split('.').pop();
+ if (ext) { ext = `.${ext.toLowerCase()}`; }
+
+ if (
+ ThumbUtil.imageExtensions.indexOf(ext) > -1
+ || ThumbUtil.videoExtensions.indexOf(ext) > -1
+ || req.path.indexOf('_nuxt') > -1
+ || req.path.indexOf('favicon.ico') > -1
+ ) {
+ return true;
+ }
+ return false;
+ },
+ 'stream': {
+ write(str) { log.debug(str); },
+ },
+ }));
+ }
// this.server.use(rateLimiter);
// Serve the uploads
- this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'uploads')));
- this.routesFolder = path.join(__dirname, '..', 'routes');
+ this.server.use(express.static(path.join(__dirname, '../../../uploads')));
+ this.routesFolder = path.join(__dirname, '../routes');
}
registerAllTheRoutes() {
- jetpack.find(this.routesFolder, { matching: '*.js' }).forEach(routeFile => {
- const RouteClass = require(path.join('..', '..', '..', routeFile));
+ jetpack.find(this.routesFolder, { matching: '*.js' }).forEach((routeFile) => {
+ // eslint-disable-next-line import/no-dynamic-require, global-require
+ const RouteClass = require(path.join('../../../', routeFile));
let routes = [RouteClass];
if (Array.isArray(RouteClass)) routes = RouteClass;
for (const File of routes) {
@@ -55,7 +80,7 @@ class Server {
serveNuxt() {
// Serve the frontend if we are in production mode
if (process.env.NODE_ENV === 'production') {
- this.server.use(express.static(path.join(__dirname, '..', '..', '..', 'dist')));
+ this.server.use(express.static(path.join(__dirname, '../../../dist')));
}
/*
@@ -66,7 +91,7 @@ class Server {
*/
this.server.all('*', (_req, res) => {
try {
- res.sendFile(path.join(__dirname, '..', '..', '..', 'dist', 'index.html'));
+ res.sendFile(path.join(__dirname, '../../../dist/index.html'));
} catch (error) {
res.json({ success: false, message: 'Something went wrong' });
}