mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-12-06 08:16:51 +00:00
Compare commits
2 Commits
lang-persi
...
ebd9148813
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebd9148813 | ||
|
|
a12553fec7 |
@@ -1,73 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"node": true,
|
|
||||||
"es6": true
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended"
|
|
||||||
],
|
|
||||||
"globals": {
|
|
||||||
"Atomics": "readonly",
|
|
||||||
"SharedArrayBuffer": "readonly"
|
|
||||||
},
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaVersion": 2018,
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"plugins": [
|
|
||||||
"align-assignments"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"arrow-parens": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
],
|
|
||||||
"indent": [
|
|
||||||
"error",
|
|
||||||
"tab"
|
|
||||||
],
|
|
||||||
"linebreak-style": [
|
|
||||||
"error",
|
|
||||||
"unix"
|
|
||||||
],
|
|
||||||
"quotes": [
|
|
||||||
"error",
|
|
||||||
"single"
|
|
||||||
],
|
|
||||||
"semi": [
|
|
||||||
"error",
|
|
||||||
"always"
|
|
||||||
],
|
|
||||||
"key-spacing": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"align": "value"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"comma-spacing": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"before": false,
|
|
||||||
"after": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"func-call-spacing": [
|
|
||||||
"error",
|
|
||||||
"never"
|
|
||||||
],
|
|
||||||
"keyword-spacing": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"before": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-irregular-whitespace": "error",
|
|
||||||
"no-unused-expressions": 0,
|
|
||||||
"align-assignments/align-assignments": [
|
|
||||||
2,
|
|
||||||
{
|
|
||||||
"requiresOnly": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{
|
|
||||||
"printWidth": 320,
|
|
||||||
"tabWidth": 4,
|
|
||||||
"useTabs": true,
|
|
||||||
"semi": true,
|
|
||||||
"singleQuote": true,
|
|
||||||
"bracketSpacing": true,
|
|
||||||
"jsxBracketSameLine": true,
|
|
||||||
"trailingComma": "all",
|
|
||||||
"proseWrap": "always"
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
const express = require('express');
|
import bodyParser from "body-parser";
|
||||||
const bodyParser = require('body-parser');
|
import compression from "compression";
|
||||||
const fileUpload = require('express-fileupload');
|
import express from "express";
|
||||||
const compression = require('compression');
|
import fileUpload from "express-fileupload";
|
||||||
const config = require('./lib/config');
|
import { isDebugMode } from "./lib/config.js";
|
||||||
const log = require('./logger').express;
|
import cors from "./lib/express/cors.js";
|
||||||
|
import jwt from "./lib/express/jwt.js";
|
||||||
|
import { express as logger } from "./logger.js";
|
||||||
|
import mainRoutes from "./routes/main.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* App
|
* App
|
||||||
@@ -11,7 +14,7 @@ const log = require('./logger').express;
|
|||||||
const app = express();
|
const app = express();
|
||||||
app.use(fileUpload());
|
app.use(fileUpload());
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
app.use(bodyParser.urlencoded({extended: true}));
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
// Gzip
|
// Gzip
|
||||||
app.use(compression());
|
app.use(compression());
|
||||||
@@ -20,71 +23,70 @@ app.use(compression());
|
|||||||
* General Logging, BEFORE routes
|
* General Logging, BEFORE routes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
app.disable('x-powered-by');
|
app.disable("x-powered-by");
|
||||||
app.enable('trust proxy', ['loopback', 'linklocal', 'uniquelocal']);
|
app.enable("trust proxy", ["loopback", "linklocal", "uniquelocal"]);
|
||||||
app.enable('strict routing');
|
app.enable("strict routing");
|
||||||
|
|
||||||
// pretty print JSON when not live
|
// pretty print JSON when not live
|
||||||
if (config.debug()) {
|
if (isDebugMode()) {
|
||||||
app.set('json spaces', 2);
|
app.set("json spaces", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// CORS for everything
|
// CORS for everything
|
||||||
app.use(require('./lib/express/cors'));
|
app.use(cors);
|
||||||
|
|
||||||
// General security/cache related headers + server header
|
// General security/cache related headers + server header
|
||||||
app.use(function (req, res, next) {
|
app.use((_, res, next) => {
|
||||||
let x_frame_options = 'DENY';
|
let x_frame_options = "DENY";
|
||||||
|
|
||||||
if (typeof process.env.X_FRAME_OPTIONS !== 'undefined' && process.env.X_FRAME_OPTIONS) {
|
if (typeof process.env.X_FRAME_OPTIONS !== "undefined" && process.env.X_FRAME_OPTIONS) {
|
||||||
x_frame_options = process.env.X_FRAME_OPTIONS;
|
x_frame_options = process.env.X_FRAME_OPTIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'X-XSS-Protection': '1; mode=block',
|
"X-XSS-Protection": "1; mode=block",
|
||||||
'X-Content-Type-Options': 'nosniff',
|
"X-Content-Type-Options": "nosniff",
|
||||||
'X-Frame-Options': x_frame_options,
|
"X-Frame-Options": x_frame_options,
|
||||||
'Cache-Control': 'no-cache, no-store, max-age=0, must-revalidate',
|
"Cache-Control": "no-cache, no-store, max-age=0, must-revalidate",
|
||||||
Pragma: 'no-cache',
|
Pragma: "no-cache",
|
||||||
Expires: 0
|
Expires: 0,
|
||||||
});
|
});
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.use(require('./lib/express/jwt')());
|
app.use(jwt());
|
||||||
app.use('/', require('./routes/main'));
|
app.use("/", mainRoutes);
|
||||||
|
|
||||||
// production error handler
|
// production error handler
|
||||||
// no stacktraces leaked to user
|
// no stacktraces leaked to user
|
||||||
// eslint-disable-next-line
|
app.use((err, req, res, _) => {
|
||||||
app.use(function (err, req, res, next) {
|
const payload = {
|
||||||
|
|
||||||
let payload = {
|
|
||||||
error: {
|
error: {
|
||||||
code: err.status,
|
code: err.status,
|
||||||
message: err.public ? err.message : 'Internal Error'
|
message: err.public ? err.message : "Internal Error",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (config.debug() || (req.baseUrl + req.path).includes('nginx/certificates')) {
|
if (typeof err.message_i18n !== "undefined") {
|
||||||
|
payload.error.message_i18n = err.message_i18n;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isDebugMode() || (req.baseUrl + req.path).includes("nginx/certificates")) {
|
||||||
payload.debug = {
|
payload.debug = {
|
||||||
stack: typeof err.stack !== 'undefined' && err.stack ? err.stack.split('\n') : null,
|
stack: typeof err.stack !== "undefined" && err.stack ? err.stack.split("\n") : null,
|
||||||
previous: err.previous
|
previous: err.previous,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not every error is worth logging - but this is good for now until it gets annoying.
|
// Not every error is worth logging - but this is good for now until it gets annoying.
|
||||||
if (typeof err.stack !== 'undefined' && err.stack) {
|
if (typeof err.stack !== "undefined" && err.stack) {
|
||||||
if (config.debug()) {
|
logger.debug(err.stack);
|
||||||
log.debug(err.stack);
|
if (typeof err.public === "undefined" || !err.public) {
|
||||||
} else if (typeof err.public == 'undefined' || !err.public) {
|
logger.warn(err.message);
|
||||||
log.warn(err.message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res.status(err.status || 500).send(payload);
|
||||||
.status(err.status || 500)
|
|
||||||
.send(payload);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = app;
|
export default app;
|
||||||
|
|||||||
91
backend/biome.json
Normal file
91
backend/biome.json
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/2.2.0/schema.json",
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": true
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"ignoreUnknown": false,
|
||||||
|
"includes": [
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx",
|
||||||
|
"!**/dist/**/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"indentStyle": "tab",
|
||||||
|
"indentWidth": 4,
|
||||||
|
"lineWidth": 120,
|
||||||
|
"formatWithErrors": true
|
||||||
|
},
|
||||||
|
"assist": {
|
||||||
|
"actions": {
|
||||||
|
"source": {
|
||||||
|
"organizeImports": {
|
||||||
|
"level": "on",
|
||||||
|
"options": {
|
||||||
|
"groups": [
|
||||||
|
":BUN:",
|
||||||
|
":NODE:",
|
||||||
|
[
|
||||||
|
"npm:*",
|
||||||
|
"npm:*/**"
|
||||||
|
],
|
||||||
|
":PACKAGE_WITH_PROTOCOL:",
|
||||||
|
":URL:",
|
||||||
|
":PACKAGE:",
|
||||||
|
[
|
||||||
|
"/src/*",
|
||||||
|
"/src/**"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/**"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"#*",
|
||||||
|
"#*/**"
|
||||||
|
],
|
||||||
|
":PATH:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true,
|
||||||
|
"correctness": {
|
||||||
|
"useUniqueElementIds": "off"
|
||||||
|
},
|
||||||
|
"suspicious": {
|
||||||
|
"noExplicitAny": "off"
|
||||||
|
},
|
||||||
|
"performance": {
|
||||||
|
"noDelete": "off"
|
||||||
|
},
|
||||||
|
"nursery": "off",
|
||||||
|
"a11y": {
|
||||||
|
"useSemanticElements": "off",
|
||||||
|
"useValidAnchor": "off"
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"noParameterAssign": "error",
|
||||||
|
"useAsConstAssertion": "error",
|
||||||
|
"useDefaultParameterLast": "error",
|
||||||
|
"useEnumInitializers": "error",
|
||||||
|
"useSelfClosingElements": "error",
|
||||||
|
"useSingleVarDeclarator": "error",
|
||||||
|
"noUnusedTemplateLiteral": "error",
|
||||||
|
"useNumberNamespace": "error",
|
||||||
|
"noInferrableTypes": "error",
|
||||||
|
"noUselessElse": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,19 @@
|
|||||||
const config = require('./lib/config');
|
import knex from "knex";
|
||||||
|
import {configGet, configHas} from "./lib/config.js";
|
||||||
|
|
||||||
if (!config.has('database')) {
|
const generateDbConfig = () => {
|
||||||
throw new Error('Database config does not exist! Please read the instructions: https://nginxproxymanager.com/setup/');
|
if (!configHas("database")) {
|
||||||
}
|
throw new Error(
|
||||||
|
"Database config does not exist! Please read the instructions: https://nginxproxymanager.com/setup/",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
function generateDbConfig() {
|
const cfg = configGet("database");
|
||||||
const cfg = config.get('database');
|
|
||||||
if (cfg.engine === 'knex-native') {
|
if (cfg.engine === "knex-native") {
|
||||||
return cfg.knex;
|
return cfg.knex;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
client: cfg.engine,
|
client: cfg.engine,
|
||||||
connection: {
|
connection: {
|
||||||
@@ -16,12 +21,12 @@ function generateDbConfig() {
|
|||||||
user: cfg.user,
|
user: cfg.user,
|
||||||
password: cfg.password,
|
password: cfg.password,
|
||||||
database: cfg.name,
|
database: cfg.name,
|
||||||
port: cfg.port
|
port: cfg.port,
|
||||||
},
|
},
|
||||||
migrations: {
|
migrations: {
|
||||||
tableName: 'migrations'
|
tableName: "migrations",
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = require('knex')(generateDbConfig());
|
export default knex(generateDbConfig());
|
||||||
|
|||||||
@@ -1,48 +1,47 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
const schema = require('./schema');
|
import app from "./app.js";
|
||||||
const logger = require('./logger').global;
|
import internalCertificate from "./internal/certificate.js";
|
||||||
|
import internalIpRanges from "./internal/ip_ranges.js";
|
||||||
|
import { global as logger } from "./logger.js";
|
||||||
|
import { migrateUp } from "./migrate.js";
|
||||||
|
import { getCompiledSchema } from "./schema/index.js";
|
||||||
|
import setup from "./setup.js";
|
||||||
|
|
||||||
const IP_RANGES_FETCH_ENABLED = process.env.IP_RANGES_FETCH_ENABLED !== 'false';
|
const IP_RANGES_FETCH_ENABLED = process.env.IP_RANGES_FETCH_ENABLED !== "false";
|
||||||
|
|
||||||
async function appStart () {
|
async function appStart() {
|
||||||
const migrate = require('./migrate');
|
return migrateUp()
|
||||||
const setup = require('./setup');
|
|
||||||
const app = require('./app');
|
|
||||||
const internalCertificate = require('./internal/certificate');
|
|
||||||
const internalIpRanges = require('./internal/ip_ranges');
|
|
||||||
|
|
||||||
return migrate.latest()
|
|
||||||
.then(setup)
|
.then(setup)
|
||||||
.then(schema.getCompiledSchema)
|
.then(getCompiledSchema)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (IP_RANGES_FETCH_ENABLED) {
|
if (!IP_RANGES_FETCH_ENABLED) {
|
||||||
logger.info('IP Ranges fetch is enabled');
|
logger.info("IP Ranges fetch is disabled by environment variable");
|
||||||
return internalIpRanges.fetch().catch((err) => {
|
return;
|
||||||
logger.error('IP Ranges fetch failed, continuing anyway:', err.message);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
logger.info('IP Ranges fetch is disabled by environment variable');
|
|
||||||
}
|
}
|
||||||
|
logger.info("IP Ranges fetch is enabled");
|
||||||
|
return internalIpRanges.fetch().catch((err) => {
|
||||||
|
logger.error("IP Ranges fetch failed, continuing anyway:", err.message);
|
||||||
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
internalCertificate.initTimer();
|
internalCertificate.initTimer();
|
||||||
internalIpRanges.initTimer();
|
internalIpRanges.initTimer();
|
||||||
|
|
||||||
const server = app.listen(3000, () => {
|
const server = app.listen(3000, () => {
|
||||||
logger.info('Backend PID ' + process.pid + ' listening on port 3000 ...');
|
logger.info(`Backend PID ${process.pid} listening on port 3000 ...`);
|
||||||
|
|
||||||
process.on('SIGTERM', () => {
|
process.on("SIGTERM", () => {
|
||||||
logger.info('PID ' + process.pid + ' received SIGTERM');
|
logger.info(`PID ${process.pid} received SIGTERM`);
|
||||||
server.close(() => {
|
server.close(() => {
|
||||||
logger.info('Stopping.');
|
logger.info("Stopping.");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
logger.error(err.message, err);
|
logger.error(`Startup Error: ${err.message}`, err);
|
||||||
setTimeout(appStart, 1000);
|
setTimeout(appStart, 1000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -50,7 +49,6 @@ async function appStart () {
|
|||||||
try {
|
try {
|
||||||
appStart();
|
appStart();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error(err.message, err);
|
logger.fatal(err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
const _ = require('lodash');
|
import fs from "node:fs";
|
||||||
const fs = require('node:fs');
|
import batchflow from "batchflow";
|
||||||
const batchflow = require('batchflow');
|
import _ from "lodash";
|
||||||
const logger = require('../logger').access;
|
import errs from "../lib/error.js";
|
||||||
const error = require('../lib/error');
|
import utils from "../lib/utils.js";
|
||||||
const utils = require('../lib/utils');
|
import { access as logger } from "../logger.js";
|
||||||
const accessListModel = require('../models/access_list');
|
import accessListModel from "../models/access_list.js";
|
||||||
const accessListAuthModel = require('../models/access_list_auth');
|
import accessListAuthModel from "../models/access_list_auth.js";
|
||||||
const accessListClientModel = require('../models/access_list_client');
|
import accessListClientModel from "../models/access_list_client.js";
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
import proxyHostModel from "../models/proxy_host.js";
|
||||||
const internalAuditLog = require('./audit-log');
|
import internalAuditLog from "./audit-log.js";
|
||||||
const internalNginx = require('./nginx');
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
function omissions () {
|
const omissions = () => {
|
||||||
return ['is_deleted'];
|
return ["is_deleted"];
|
||||||
}
|
};
|
||||||
|
|
||||||
const internalAccessList = {
|
const internalAccessList = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
return access.can('access_lists:create', data)
|
return access
|
||||||
|
.can("access_lists:create", data)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
return accessListModel
|
return accessListModel
|
||||||
.query()
|
.query()
|
||||||
@@ -31,7 +31,7 @@ const internalAccessList = {
|
|||||||
name: data.name,
|
name: data.name,
|
||||||
satisfy_any: data.satisfy_any,
|
satisfy_any: data.satisfy_any,
|
||||||
pass_auth: data.pass_auth,
|
pass_auth: data.pass_auth,
|
||||||
owner_user_id: access.token.getUserId(1)
|
owner_user_id: access.token.getUserId(1),
|
||||||
})
|
})
|
||||||
.then(utils.omitRow(omissions()));
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
@@ -42,27 +42,27 @@ const internalAccessList = {
|
|||||||
|
|
||||||
// Now add the items
|
// Now add the items
|
||||||
data.items.map((item) => {
|
data.items.map((item) => {
|
||||||
promises.push(accessListAuthModel
|
promises.push(
|
||||||
.query()
|
accessListAuthModel.query().insert({
|
||||||
.insert({
|
|
||||||
access_list_id: row.id,
|
access_list_id: row.id,
|
||||||
username: item.username,
|
username: item.username,
|
||||||
password: item.password
|
password: item.password,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now add the clients
|
// Now add the clients
|
||||||
if (typeof data.clients !== 'undefined' && data.clients) {
|
if (typeof data.clients !== "undefined" && data.clients) {
|
||||||
data.clients.map((client) => {
|
data.clients.map((client) => {
|
||||||
promises.push(accessListClientModel
|
promises.push(
|
||||||
.query()
|
accessListClientModel.query().insert({
|
||||||
.insert({
|
|
||||||
access_list_id: row.id,
|
access_list_id: row.id,
|
||||||
address: client.address,
|
address: client.address,
|
||||||
directive: client.directive
|
directive: client.directive,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,28 +70,33 @@ const internalAccessList = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// re-fetch with expansions
|
// re-fetch with expansions
|
||||||
return internalAccessList.get(access, {
|
return internalAccessList.get(
|
||||||
|
access,
|
||||||
|
{
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'items', 'clients', 'proxy_hosts.access_list.[clients,items]']
|
expand: ["owner", "items", "clients", "proxy_hosts.access_list.[clients,items]"],
|
||||||
}, true /* <- skip masking */);
|
},
|
||||||
|
true /* <- skip masking */,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Audit log
|
// Audit log
|
||||||
data.meta = _.assign({}, data.meta || {}, row.meta);
|
data.meta = _.assign({}, data.meta || {}, row.meta);
|
||||||
|
|
||||||
return internalAccessList.build(row)
|
return internalAccessList
|
||||||
|
.build(row)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (parseInt(row.proxy_host_count, 10)) {
|
if (Number.parseInt(row.proxy_host_count, 10)) {
|
||||||
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
return internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'created',
|
action: "created",
|
||||||
object_type: 'access-list',
|
object_type: "access-list",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: internalAccessList.maskItems(data)
|
meta: internalAccessList.maskItems(data),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -109,23 +114,23 @@ const internalAccessList = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
return access.can('access_lists:update', data.id)
|
return access
|
||||||
|
.can("access_lists:update", data.id)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
return internalAccessList.get(access, {id: data.id});
|
return internalAccessList.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id !== data.id) {
|
if (row.id !== data.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError(`Access List could not be updated, IDs do not match: ${row.id} !== ${data.id}`);
|
throw new errs.InternalValidationError(
|
||||||
|
`Access List could not be updated, IDs do not match: ${row.id} !== ${data.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// patch name if specified
|
// patch name if specified
|
||||||
if (typeof data.name !== 'undefined' && data.name) {
|
if (typeof data.name !== "undefined" && data.name) {
|
||||||
return accessListModel
|
return accessListModel.query().where({ id: data.id }).patch({
|
||||||
.query()
|
|
||||||
.where({id: data.id})
|
|
||||||
.patch({
|
|
||||||
name: data.name,
|
name: data.name,
|
||||||
satisfy_any: data.satisfy_any,
|
satisfy_any: data.satisfy_any,
|
||||||
pass_auth: data.pass_auth,
|
pass_auth: data.pass_auth,
|
||||||
@@ -134,37 +139,33 @@ const internalAccessList = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Check for items and add/update/remove them
|
// Check for items and add/update/remove them
|
||||||
if (typeof data.items !== 'undefined' && data.items) {
|
if (typeof data.items !== "undefined" && data.items) {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
const items_to_keep = [];
|
const items_to_keep = [];
|
||||||
|
|
||||||
data.items.map((item) => {
|
data.items.map((item) => {
|
||||||
if (item.password) {
|
if (item.password) {
|
||||||
promises.push(accessListAuthModel
|
promises.push(
|
||||||
.query()
|
accessListAuthModel.query().insert({
|
||||||
.insert({
|
|
||||||
access_list_id: data.id,
|
access_list_id: data.id,
|
||||||
username: item.username,
|
username: item.username,
|
||||||
password: item.password
|
password: item.password,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// This was supplied with an empty password, which means keep it but don't change the password
|
// This was supplied with an empty password, which means keep it but don't change the password
|
||||||
items_to_keep.push(item.username);
|
items_to_keep.push(item.username);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const query = accessListAuthModel
|
const query = accessListAuthModel.query().delete().where("access_list_id", data.id);
|
||||||
.query()
|
|
||||||
.delete()
|
|
||||||
.where('access_list_id', data.id);
|
|
||||||
|
|
||||||
if (items_to_keep.length) {
|
if (items_to_keep.length) {
|
||||||
query.andWhere('username', 'NOT IN', items_to_keep);
|
query.andWhere("username", "NOT IN", items_to_keep);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query
|
return query.then(() => {
|
||||||
.then(() => {
|
|
||||||
// Add new items
|
// Add new items
|
||||||
if (promises.length) {
|
if (promises.length) {
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
@@ -174,29 +175,25 @@ const internalAccessList = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Check for clients and add/update/remove them
|
// Check for clients and add/update/remove them
|
||||||
if (typeof data.clients !== 'undefined' && data.clients) {
|
if (typeof data.clients !== "undefined" && data.clients) {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
data.clients.map((client) => {
|
data.clients.map((client) => {
|
||||||
if (client.address) {
|
if (client.address) {
|
||||||
promises.push(accessListClientModel
|
promises.push(
|
||||||
.query()
|
accessListClientModel.query().insert({
|
||||||
.insert({
|
|
||||||
access_list_id: data.id,
|
access_list_id: data.id,
|
||||||
address: client.address,
|
address: client.address,
|
||||||
directive: client.directive
|
directive: client.directive,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
const query = accessListClientModel
|
const query = accessListClientModel.query().delete().where("access_list_id", data.id);
|
||||||
.query()
|
|
||||||
.delete()
|
|
||||||
.where('access_list_id', data.id);
|
|
||||||
|
|
||||||
return query
|
return query.then(() => {
|
||||||
.then(() => {
|
|
||||||
// Add new items
|
// Add new items
|
||||||
if (promises.length) {
|
if (promises.length) {
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
@@ -207,26 +204,32 @@ const internalAccessList = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'updated',
|
action: "updated",
|
||||||
object_type: 'access-list',
|
object_type: "access-list",
|
||||||
object_id: data.id,
|
object_id: data.id,
|
||||||
meta: internalAccessList.maskItems(data)
|
meta: internalAccessList.maskItems(data),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// re-fetch with expansions
|
// re-fetch with expansions
|
||||||
return internalAccessList.get(access, {
|
return internalAccessList.get(
|
||||||
|
access,
|
||||||
|
{
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'items', 'clients', 'proxy_hosts.[certificate,access_list.[clients,items]]']
|
expand: ["owner", "items", "clients", "proxy_hosts.[certificate,access_list.[clients,items]]"],
|
||||||
}, true /* <- skip masking */);
|
},
|
||||||
|
true /* <- skip masking */,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
return internalAccessList.build(row)
|
return internalAccessList
|
||||||
|
.build(row)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
if (parseInt(row.proxy_host_count, 10)) {
|
if (Number.parseInt(row.proxy_host_count, 10)) {
|
||||||
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
return internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
|
||||||
}
|
}
|
||||||
}).then(internalNginx.reload)
|
})
|
||||||
|
.then(internalNginx.reload)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalAccessList.maskItems(row);
|
return internalAccessList.maskItems(row);
|
||||||
});
|
});
|
||||||
@@ -243,47 +246,50 @@ const internalAccessList = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data, skip_masking) => {
|
get: (access, data, skip_masking) => {
|
||||||
if (typeof data === 'undefined') {
|
const thisData = data || {};
|
||||||
data = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return access.can('access_lists:get', data.id)
|
return access
|
||||||
.then((access_data) => {
|
.can("access_lists:get", thisData.id)
|
||||||
|
.then((accessData) => {
|
||||||
const query = accessListModel
|
const query = accessListModel
|
||||||
.query()
|
.query()
|
||||||
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
|
.select("access_list.*", accessListModel.raw("COUNT(proxy_host.id) as proxy_host_count"))
|
||||||
.leftJoin('proxy_host', function() {
|
.leftJoin("proxy_host", function () {
|
||||||
this.on('proxy_host.access_list_id', '=', 'access_list.id')
|
this.on("proxy_host.access_list_id", "=", "access_list.id").andOn(
|
||||||
.andOn('proxy_host.is_deleted', '=', 0);
|
"proxy_host.is_deleted",
|
||||||
|
"=",
|
||||||
|
0,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.where('access_list.is_deleted', 0)
|
.where("access_list.is_deleted", 0)
|
||||||
.andWhere('access_list.id', data.id)
|
.andWhere("access_list.id", thisData.id)
|
||||||
.groupBy('access_list.id')
|
.groupBy("access_list.id")
|
||||||
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
|
.allowGraph("[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]")
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (accessData.permission_visibility !== "all") {
|
||||||
query.andWhere('access_list.owner_user_id', access.token.getUserId(1));
|
query.andWhere("access_list.owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
|
||||||
query.withGraphFetched(`[${data.expand.join(', ')}]`);
|
query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRow(omissions()));
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
|
let thisRow = row;
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(thisData.id);
|
||||||
}
|
}
|
||||||
if (!skip_masking && typeof row.items !== 'undefined' && row.items) {
|
if (!skip_masking && typeof thisRow.items !== "undefined" && thisRow.items) {
|
||||||
row = internalAccessList.maskItems(row);
|
thisRow = internalAccessList.maskItems(thisRow);
|
||||||
}
|
}
|
||||||
// Custom omissions
|
// Custom omissions
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
if (typeof data.omit !== "undefined" && data.omit !== null) {
|
||||||
row = _.omit(row, data.omit);
|
thisRow = _.omit(thisRow, data.omit);
|
||||||
}
|
}
|
||||||
return row;
|
return thisRow;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -295,13 +301,14 @@ const internalAccessList = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('access_lists:delete', data.id)
|
return access
|
||||||
|
.can("access_lists:delete", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalAccessList.get(access, {id: data.id, expand: ['proxy_hosts', 'items', 'clients']});
|
return internalAccessList.get(access, { id: data.id, expand: ["proxy_hosts", "items", "clients"] });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1. update row to be deleted
|
// 1. update row to be deleted
|
||||||
@@ -312,26 +319,27 @@ const internalAccessList = {
|
|||||||
// 1. update row to be deleted
|
// 1. update row to be deleted
|
||||||
return accessListModel
|
return accessListModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// 2. update any proxy hosts that were using it (ignoring permissions)
|
// 2. update any proxy hosts that were using it (ignoring permissions)
|
||||||
if (row.proxy_hosts) {
|
if (row.proxy_hosts) {
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('access_list_id', '=', row.id)
|
.where("access_list_id", "=", row.id)
|
||||||
.patch({access_list_id: 0})
|
.patch({ access_list_id: 0 })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// 3. reconfigure those hosts, then reload nginx
|
// 3. reconfigure those hosts, then reload nginx
|
||||||
|
|
||||||
// set the access_list_id to zero for these items
|
// set the access_list_id to zero for these items
|
||||||
row.proxy_hosts.map((_val, idx) => {
|
row.proxy_hosts.map((_val, idx) => {
|
||||||
row.proxy_hosts[idx].access_list_id = 0;
|
row.proxy_hosts[idx].access_list_id = 0;
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
return internalNginx.bulkGenerateConfigs("proxy_host", row.proxy_hosts);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
@@ -351,10 +359,10 @@ const internalAccessList = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// 4. audit log
|
// 4. audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'deleted',
|
action: "deleted",
|
||||||
object_type: 'access-list',
|
object_type: "access-list",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(internalAccessList.maskItems(row), ['is_deleted', 'proxy_hosts'])
|
meta: _.omit(internalAccessList.maskItems(row), ["is_deleted", "proxy_hosts"]),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -372,33 +380,37 @@ const internalAccessList = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('access_lists:list')
|
return access
|
||||||
|
.can("access_lists:list")
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
const query = accessListModel
|
const query = accessListModel
|
||||||
.query()
|
.query()
|
||||||
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
|
.select("access_list.*", accessListModel.raw("COUNT(proxy_host.id) as proxy_host_count"))
|
||||||
.leftJoin('proxy_host', function() {
|
.leftJoin("proxy_host", function () {
|
||||||
this.on('proxy_host.access_list_id', '=', 'access_list.id')
|
this.on("proxy_host.access_list_id", "=", "access_list.id").andOn(
|
||||||
.andOn('proxy_host.is_deleted', '=', 0);
|
"proxy_host.is_deleted",
|
||||||
|
"=",
|
||||||
|
0,
|
||||||
|
);
|
||||||
})
|
})
|
||||||
.where('access_list.is_deleted', 0)
|
.where("access_list.is_deleted", 0)
|
||||||
.groupBy('access_list.id')
|
.groupBy("access_list.id")
|
||||||
.allowGraph('[owner,items,clients]')
|
.allowGraph("[owner,items,clients]")
|
||||||
.orderBy('access_list.name', 'ASC');
|
.orderBy("access_list.name", "ASC");
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('access_list.owner_user_id', access.token.getUserId(1));
|
query.andWhere("access_list.owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string') {
|
if (typeof search_query === "string") {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where('name', 'like', `%${search_query}%`);
|
this.where("name", "like", `%${search_query}%`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched(`[${expand.join(', ')}]`);
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRows(omissions()));
|
return query.then(utils.omitRows(omissions()));
|
||||||
@@ -406,9 +418,10 @@ const internalAccessList = {
|
|||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (rows) {
|
if (rows) {
|
||||||
rows.map((row, idx) => {
|
rows.map((row, idx) => {
|
||||||
if (typeof row.items !== 'undefined' && row.items) {
|
if (typeof row.items !== "undefined" && row.items) {
|
||||||
rows[idx] = internalAccessList.maskItems(row);
|
rows[idx] = internalAccessList.maskItems(row);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,18 +437,14 @@ const internalAccessList = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
const query = accessListModel
|
const query = accessListModel.query().count("id as count").where("is_deleted", 0);
|
||||||
.query()
|
|
||||||
.count('id as count')
|
|
||||||
.where('is_deleted', 0);
|
|
||||||
|
|
||||||
if (visibility !== 'all') {
|
if (visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', user_id);
|
query.andWhere("owner_user_id", user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.first()
|
return query.first().then((row) => {
|
||||||
.then((row) => {
|
return Number.parseInt(row.count, 10);
|
||||||
return parseInt(row.count, 10);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -444,18 +453,19 @@ const internalAccessList = {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
maskItems: (list) => {
|
maskItems: (list) => {
|
||||||
if (list && typeof list.items !== 'undefined') {
|
if (list && typeof list.items !== "undefined") {
|
||||||
list.items.map((val, idx) => {
|
list.items.map((val, idx) => {
|
||||||
let repeat_for = 8;
|
let repeat_for = 8;
|
||||||
let first_char = '*';
|
let first_char = "*";
|
||||||
|
|
||||||
if (typeof val.password !== 'undefined' && val.password) {
|
if (typeof val.password !== "undefined" && val.password) {
|
||||||
repeat_for = val.password.length - 1;
|
repeat_for = val.password.length - 1;
|
||||||
first_char = val.password.charAt(0);
|
first_char = val.password.charAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
list.items[idx].hint = first_char + ('*').repeat(repeat_for);
|
list.items[idx].hint = first_char + "*".repeat(repeat_for);
|
||||||
list.items[idx].password = '';
|
list.items[idx].password = "";
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,25 +503,28 @@ const internalAccessList = {
|
|||||||
|
|
||||||
// 2. create empty access file
|
// 2. create empty access file
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(htpasswd_file, '', {encoding: 'utf8'});
|
fs.writeFileSync(htpasswd_file, "", { encoding: "utf8" });
|
||||||
resolve(htpasswd_file);
|
resolve(htpasswd_file);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
})
|
}).then((htpasswd_file) => {
|
||||||
.then((htpasswd_file) => {
|
|
||||||
// 3. generate password for each user
|
// 3. generate password for each user
|
||||||
if (list.items.length) {
|
if (list.items.length) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
batchflow(list.items).sequential()
|
batchflow(list.items)
|
||||||
|
.sequential()
|
||||||
.each((_i, item, next) => {
|
.each((_i, item, next) => {
|
||||||
if (typeof item.password !== 'undefined' && item.password.length) {
|
if (typeof item.password !== "undefined" && item.password.length) {
|
||||||
logger.info(`Adding: ${item.username}`);
|
logger.info(`Adding: ${item.username}`);
|
||||||
|
|
||||||
utils.execFile('openssl', ['passwd', '-apr1', item.password])
|
utils
|
||||||
|
.execFile("openssl", ["passwd", "-apr1", item.password])
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
try {
|
try {
|
||||||
fs.appendFileSync(htpasswd_file, `${item.username}:${res}\n`, {encoding: 'utf8'});
|
fs.appendFileSync(htpasswd_file, `${item.username}:${res}\n`, {
|
||||||
|
encoding: "utf8",
|
||||||
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
@@ -534,7 +547,7 @@ const internalAccessList = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalAccessList;
|
export default internalAccessList;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const auditLogModel = require('../models/audit-log');
|
import { castJsonIfNeed } from "../lib/helpers.js";
|
||||||
const {castJsonIfNeed} = require('../lib/helpers');
|
import auditLogModel from "../models/audit-log.js";
|
||||||
|
|
||||||
const internalAuditLog = {
|
const internalAuditLog = {
|
||||||
|
|
||||||
@@ -13,24 +13,23 @@ const internalAuditLog = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('auditlog:list')
|
return access.can("auditlog:list").then(() => {
|
||||||
.then(() => {
|
const query = auditLogModel
|
||||||
let query = auditLogModel
|
|
||||||
.query()
|
.query()
|
||||||
.orderBy('created_on', 'DESC')
|
.orderBy("created_on", "DESC")
|
||||||
.orderBy('id', 'DESC')
|
.orderBy("id", "DESC")
|
||||||
.limit(100)
|
.limit(100)
|
||||||
.allowGraph('[user]');
|
.allowGraph("[user]");
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string' && search_query.length > 0) {
|
if (typeof search_query === "string" && search_query.length > 0) {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where(castJsonIfNeed('meta'), 'like', '%' + search_query + '%');
|
this.where(castJsonIfNeed("meta"), "like", `%${search_query}`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched('[' + expand.join(', ') + ']');
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
@@ -54,26 +53,26 @@ const internalAuditLog = {
|
|||||||
add: (access, data) => {
|
add: (access, data) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// Default the user id
|
// Default the user id
|
||||||
if (typeof data.user_id === 'undefined' || !data.user_id) {
|
if (typeof data.user_id === "undefined" || !data.user_id) {
|
||||||
data.user_id = access.token.getUserId(1);
|
data.user_id = access.token.getUserId(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.action === 'undefined' || !data.action) {
|
if (typeof data.action === "undefined" || !data.action) {
|
||||||
reject(new error.InternalValidationError('Audit log entry must contain an Action'));
|
reject(new errs.InternalValidationError("Audit log entry must contain an Action"));
|
||||||
} else {
|
} else {
|
||||||
// Make sure at least 1 of the IDs are set and action
|
// Make sure at least 1 of the IDs are set and action
|
||||||
resolve(auditLogModel
|
resolve(
|
||||||
.query()
|
auditLogModel.query().insert({
|
||||||
.insert({
|
|
||||||
user_id: data.user_id,
|
user_id: data.user_id,
|
||||||
action: data.action,
|
action: data.action,
|
||||||
object_type: data.object_type || '',
|
object_type: data.object_type || "",
|
||||||
object_id: data.object_id || 0,
|
object_id: data.object_id || 0,
|
||||||
meta: data.meta || {}
|
meta: data.meta || {},
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalAuditLog;
|
export default internalAuditLog;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,93 +1,90 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const utils = require('../lib/utils');
|
import { castJsonIfNeed } from "../lib/helpers.js";
|
||||||
const deadHostModel = require('../models/dead_host');
|
import utils from "../lib/utils.js";
|
||||||
const internalHost = require('./host');
|
import deadHostModel from "../models/dead_host.js";
|
||||||
const internalNginx = require('./nginx');
|
import internalAuditLog from "./audit-log.js";
|
||||||
const internalAuditLog = require('./audit-log');
|
import internalCertificate from "./certificate.js";
|
||||||
const internalCertificate = require('./certificate');
|
import internalHost from "./host.js";
|
||||||
const {castJsonIfNeed} = require('../lib/helpers');
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
function omissions () {
|
const omissions = () => {
|
||||||
return ['is_deleted'];
|
return ["is_deleted"];
|
||||||
}
|
};
|
||||||
|
|
||||||
const internalDeadHost = {
|
const internalDeadHost = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
const createCertificate = data.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
delete data.certificate_id;
|
delete data.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('dead_hosts:create', data)
|
return access
|
||||||
|
.can("dead_hosts:create", data)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// Get a list of the domain names and check each of them against existing records
|
// Get a list of the domain names and check each of them against existing records
|
||||||
let domain_name_check_promises = [];
|
const domain_name_check_promises = [];
|
||||||
|
|
||||||
data.domain_names.map(function (domain_name) {
|
data.domain_names.map((domain_name) => {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
check_results.map((result) => {
|
||||||
check_results.map(function (result) {
|
|
||||||
if (result.is_taken) {
|
if (result.is_taken) {
|
||||||
throw new error.ValidationError(result.hostname + ' is already in use');
|
throw new errs.ValidationError(`${result.hostname} is already in use`);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point the domains should have been checked
|
// At this point the domains should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
data = internalHost.cleanSslHstsData(data);
|
const thisData = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
// Fix for db field not having a default value
|
// Fix for db field not having a default value
|
||||||
// for this optional field.
|
// for this optional field.
|
||||||
if (typeof data.advanced_config === 'undefined') {
|
if (typeof data.advanced_config === "undefined") {
|
||||||
data.advanced_config = '';
|
thisData.advanced_config = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel.query().insertAndFetch(thisData).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, data)
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, data)
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
return internalDeadHost.update(access, {
|
return internalDeadHost.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// re-fetch with cert
|
// re-fetch with cert
|
||||||
return internalDeadHost.get(access, {
|
return internalDeadHost.get(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
expand: ['certificate', 'owner']
|
expand: ["certificate", "owner"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(deadHostModel, 'dead_host', row)
|
return internalNginx.configure(deadHostModel, "dead_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -95,11 +92,12 @@ const internalDeadHost = {
|
|||||||
data.meta = _.assign({}, data.meta || {}, row.meta);
|
data.meta = _.assign({}, data.meta || {}, row.meta);
|
||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'created',
|
.add(access, {
|
||||||
object_type: 'dead-host',
|
action: "created",
|
||||||
|
object_type: "dead-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
@@ -114,76 +112,86 @@ const internalDeadHost = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
let thisData = data;
|
||||||
|
const createCertificate = thisData.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
delete data.certificate_id;
|
delete thisData.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('dead_hosts:update', data.id)
|
return access
|
||||||
|
.can("dead_hosts:update", thisData.id)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// Get a list of the domain names and check each of them against existing records
|
// Get a list of the domain names and check each of them against existing records
|
||||||
let domain_name_check_promises = [];
|
const domain_name_check_promises = [];
|
||||||
|
|
||||||
if (typeof data.domain_names !== 'undefined') {
|
if (typeof thisData.domain_names !== "undefined") {
|
||||||
data.domain_names.map(function (domain_name) {
|
thisData.domain_names.map((domain_name) => {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'dead', data.id));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, "dead", data.id));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
check_results.map((result) => {
|
||||||
check_results.map(function (result) {
|
|
||||||
if (result.is_taken) {
|
if (result.is_taken) {
|
||||||
throw new error.ValidationError(result.hostname + ' is already in use');
|
throw new errs.ValidationError(`${result.hostname} is already in use`);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {id: data.id});
|
return internalDeadHost.get(access, { id: thisData.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id !== data.id) {
|
if (row.id !== thisData.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('404 Host could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`404 Host could not be updated, IDs do not match: ${row.id} !== ${thisData.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
domain_names: data.domain_names || row.domain_names,
|
.createQuickCertificate(access, {
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
domain_names: thisData.domain_names || row.domain_names,
|
||||||
|
meta: _.assign({}, row.meta, thisData.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
thisData.certificate_id = cert.id;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
thisData = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
|
||||||
data = internalHost.cleanSslHstsData(data, row);
|
thisData = internalHost.cleanSslHstsData(thisData, row);
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where({id: data.id})
|
.where({ id: thisData.id })
|
||||||
.patch(data)
|
.patch(thisData)
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'updated',
|
.add(access, {
|
||||||
object_type: 'dead-host',
|
action: "updated",
|
||||||
|
object_type: "dead-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: thisData,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
@@ -191,17 +199,16 @@ const internalDeadHost = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {
|
return internalDeadHost
|
||||||
id: data.id,
|
.get(access, {
|
||||||
expand: ['owner', 'certificate']
|
id: thisData.id,
|
||||||
|
expand: ["owner", "certificate"],
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(deadHostModel, 'dead_host', row)
|
return internalNginx.configure(deadHostModel, "dead_host", row).then((new_meta) => {
|
||||||
.then((new_meta) => {
|
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
return _.omit(internalHost.cleanRowCertificateMeta(row), omissions());
|
||||||
return _.omit(row, omissions());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -216,36 +223,35 @@ const internalDeadHost = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data) => {
|
get: (access, data) => {
|
||||||
if (typeof data === 'undefined') {
|
const thisData = data || {};
|
||||||
data = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return access.can('dead_hosts:get', data.id)
|
return access
|
||||||
|
.can("dead_hosts:get", thisData.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = deadHostModel
|
const query = deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere("id", dthisDataata.id)
|
||||||
.allowGraph('[owner,certificate]')
|
.allowGraph("[owner,certificate]")
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
|
||||||
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched(`[${data.expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRow(omissions()));
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(thisData.id);
|
||||||
}
|
}
|
||||||
// Custom omissions
|
// Custom omissions
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
if (typeof thisData.omit !== "undefined" && thisData.omit !== null) {
|
||||||
row = _.omit(row, data.omit);
|
return _.omit(row, thisData.omit);
|
||||||
}
|
}
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
@@ -259,35 +265,35 @@ const internalDeadHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('dead_hosts:delete', data.id)
|
return access
|
||||||
|
.can("dead_hosts:delete", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {id: data.id});
|
return internalDeadHost.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('dead_host', row)
|
return internalNginx.deleteConfig("dead_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'deleted',
|
action: "deleted",
|
||||||
object_type: 'dead-host',
|
object_type: "dead-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -304,39 +310,41 @@ const internalDeadHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
enable: (access, data) => {
|
enable: (access, data) => {
|
||||||
return access.can('dead_hosts:update', data.id)
|
return access
|
||||||
|
.can("dead_hosts:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {
|
return internalDeadHost.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['certificate', 'owner']
|
expand: ["certificate", "owner"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Host is already enabled');
|
if (row.enabled) {
|
||||||
|
throw new errs.ValidationError("Host is already enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 1;
|
row.enabled = 1;
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(deadHostModel, 'dead_host', row);
|
return internalNginx.configure(deadHostModel, "dead_host", row);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'enabled',
|
action: "enabled",
|
||||||
object_type: 'dead-host',
|
object_type: "dead-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -353,39 +361,40 @@ const internalDeadHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
disable: (access, data) => {
|
disable: (access, data) => {
|
||||||
return access.can('dead_hosts:update', data.id)
|
return access
|
||||||
|
.can("dead_hosts:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {id: data.id});
|
return internalDeadHost.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (!row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Host is already disabled');
|
if (!row.enabled) {
|
||||||
|
throw new errs.ValidationError("Host is already disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 0;
|
row.enabled = 0;
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 0
|
enabled: 0,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('dead_host', row)
|
return internalNginx.deleteConfig("dead_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'disabled',
|
action: "disabled",
|
||||||
object_type: 'dead-host',
|
object_type: "dead-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -403,34 +412,35 @@ const internalDeadHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('dead_hosts:list')
|
return access
|
||||||
|
.can("dead_hosts:list")
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = deadHostModel
|
const query = deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.groupBy('id')
|
.groupBy("id")
|
||||||
.allowGraph('[owner,certificate]')
|
.allowGraph("[owner,certificate]")
|
||||||
.orderBy(castJsonIfNeed('domain_names'), 'ASC');
|
.orderBy(castJsonIfNeed("domain_names"), "ASC");
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string' && search_query.length > 0) {
|
if (typeof search_query === "string" && search_query.length > 0) {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where(castJsonIfNeed('domain_names'), 'like', '%' + search_query + '%');
|
this.where(castJsonIfNeed("domain_names"), "like", `%${search_query}%`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched('[' + expand.join(', ') + ']');
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRows(omissions()));
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== "undefined" && expand !== null && expand.indexOf("certificate") !== -1) {
|
||||||
return internalHost.cleanAllRowsCertificateMeta(rows);
|
return internalHost.cleanAllRowsCertificateMeta(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,20 +456,16 @@ const internalDeadHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
let query = deadHostModel
|
const query = deadHostModel.query().count("id as count").where("is_deleted", 0);
|
||||||
.query()
|
|
||||||
.count('id as count')
|
|
||||||
.where('is_deleted', 0);
|
|
||||||
|
|
||||||
if (visibility !== 'all') {
|
if (visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', user_id);
|
query.andWhere("owner_user_id", user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.first()
|
return query.first().then((row) => {
|
||||||
.then((row) => {
|
return Number.parseInt(row.count, 10);
|
||||||
return parseInt(row.count, 10);
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalDeadHost;
|
export default internalDeadHost;
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
import { castJsonIfNeed } from "../lib/helpers.js";
|
||||||
const redirectionHostModel = require('../models/redirection_host');
|
import deadHostModel from "../models/dead_host.js";
|
||||||
const deadHostModel = require('../models/dead_host');
|
import proxyHostModel from "../models/proxy_host.js";
|
||||||
const {castJsonIfNeed} = require('../lib/helpers');
|
import redirectionHostModel from "../models/redirection_host.js";
|
||||||
|
|
||||||
const internalHost = {
|
const internalHost = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes sure that the ssl_* and hsts_* fields play nicely together.
|
* Makes sure that the ssl_* and hsts_* fields play nicely together.
|
||||||
* ie: if there is no cert, then force_ssl is off.
|
* ie: if there is no cert, then force_ssl is off.
|
||||||
@@ -15,25 +14,23 @@ const internalHost = {
|
|||||||
* @param {object} [existing_data]
|
* @param {object} [existing_data]
|
||||||
* @returns {object}
|
* @returns {object}
|
||||||
*/
|
*/
|
||||||
cleanSslHstsData: function (data, existing_data) {
|
cleanSslHstsData: (data, existingData) => {
|
||||||
existing_data = existing_data === undefined ? {} : existing_data;
|
const combinedData = _.assign({}, existingData || {}, data);
|
||||||
|
|
||||||
const combined_data = _.assign({}, existing_data, data);
|
if (!combinedData.certificate_id) {
|
||||||
|
combinedData.ssl_forced = false;
|
||||||
if (!combined_data.certificate_id) {
|
combinedData.http2_support = false;
|
||||||
combined_data.ssl_forced = false;
|
|
||||||
combined_data.http2_support = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!combined_data.ssl_forced) {
|
if (!combinedData.ssl_forced) {
|
||||||
combined_data.hsts_enabled = false;
|
combinedData.hsts_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!combined_data.hsts_enabled) {
|
if (!combinedData.hsts_enabled) {
|
||||||
combined_data.hsts_subdomains = false;
|
combinedData.hsts_subdomains = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return combined_data;
|
return combinedData;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -42,11 +39,12 @@ const internalHost = {
|
|||||||
* @param {Array} rows
|
* @param {Array} rows
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
cleanAllRowsCertificateMeta: function (rows) {
|
cleanAllRowsCertificateMeta: (rows) => {
|
||||||
rows.map(function (row, idx) {
|
rows.map((_, idx) => {
|
||||||
if (typeof rows[idx].certificate !== 'undefined' && rows[idx].certificate) {
|
if (typeof rows[idx].certificate !== "undefined" && rows[idx].certificate) {
|
||||||
rows[idx].certificate.meta = {};
|
rows[idx].certificate.meta = {};
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return rows;
|
return rows;
|
||||||
@@ -58,8 +56,8 @@ const internalHost = {
|
|||||||
* @param {Object} row
|
* @param {Object} row
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
cleanRowCertificateMeta: function (row) {
|
cleanRowCertificateMeta: (row) => {
|
||||||
if (typeof row.certificate !== 'undefined' && row.certificate) {
|
if (typeof row.certificate !== "undefined" && row.certificate) {
|
||||||
row.certificate.meta = {};
|
row.certificate.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,26 +71,19 @@ const internalHost = {
|
|||||||
* @param {Array} domain_names
|
* @param {Array} domain_names
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getHostsWithDomains: function (domain_names) {
|
getHostsWithDomains: (domain_names) => {
|
||||||
const promises = [
|
const promises = [
|
||||||
proxyHostModel
|
proxyHostModel.query().where("is_deleted", 0),
|
||||||
.query()
|
redirectionHostModel.query().where("is_deleted", 0),
|
||||||
.where('is_deleted', 0),
|
deadHostModel.query().where("is_deleted", 0),
|
||||||
redirectionHostModel
|
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0),
|
|
||||||
deadHostModel
|
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises).then((promises_results) => {
|
||||||
.then((promises_results) => {
|
const response_object = {
|
||||||
let response_object = {
|
|
||||||
total_count: 0,
|
total_count: 0,
|
||||||
dead_hosts: [],
|
dead_hosts: [],
|
||||||
proxy_hosts: [],
|
proxy_hosts: [],
|
||||||
redirection_hosts: []
|
redirection_hosts: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (promises_results[0]) {
|
if (promises_results[0]) {
|
||||||
@@ -103,7 +94,10 @@ const internalHost = {
|
|||||||
|
|
||||||
if (promises_results[1]) {
|
if (promises_results[1]) {
|
||||||
// Redirection Hosts
|
// Redirection Hosts
|
||||||
response_object.redirection_hosts = internalHost._getHostsWithDomains(promises_results[1], domain_names);
|
response_object.redirection_hosts = internalHost._getHostsWithDomains(
|
||||||
|
promises_results[1],
|
||||||
|
domain_names,
|
||||||
|
);
|
||||||
response_object.total_count += response_object.redirection_hosts.length;
|
response_object.total_count += response_object.redirection_hosts.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,50 +119,67 @@ const internalHost = {
|
|||||||
* @param {Integer} [ignore_id] Must be supplied if type was also supplied
|
* @param {Integer} [ignore_id] Must be supplied if type was also supplied
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
isHostnameTaken: function (hostname, ignore_type, ignore_id) {
|
isHostnameTaken: (hostname, ignore_type, ignore_id) => {
|
||||||
const promises = [
|
const promises = [
|
||||||
proxyHostModel
|
proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere(castJsonIfNeed('domain_names'), 'like', '%' + hostname + '%'),
|
.andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`),
|
||||||
redirectionHostModel
|
redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere(castJsonIfNeed('domain_names'), 'like', '%' + hostname + '%'),
|
.andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`),
|
||||||
deadHostModel
|
deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere(castJsonIfNeed('domain_names'), 'like', '%' + hostname + '%')
|
.andWhere(castJsonIfNeed("domain_names"), "like", `%${hostname}%`),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises).then((promises_results) => {
|
||||||
.then((promises_results) => {
|
|
||||||
let is_taken = false;
|
let is_taken = false;
|
||||||
|
|
||||||
if (promises_results[0]) {
|
if (promises_results[0]) {
|
||||||
// Proxy Hosts
|
// Proxy Hosts
|
||||||
if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[0], ignore_type === 'proxy' && ignore_id ? ignore_id : 0)) {
|
if (
|
||||||
|
internalHost._checkHostnameRecordsTaken(
|
||||||
|
hostname,
|
||||||
|
promises_results[0],
|
||||||
|
ignore_type === "proxy" && ignore_id ? ignore_id : 0,
|
||||||
|
)
|
||||||
|
) {
|
||||||
is_taken = true;
|
is_taken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promises_results[1]) {
|
if (promises_results[1]) {
|
||||||
// Redirection Hosts
|
// Redirection Hosts
|
||||||
if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[1], ignore_type === 'redirection' && ignore_id ? ignore_id : 0)) {
|
if (
|
||||||
|
internalHost._checkHostnameRecordsTaken(
|
||||||
|
hostname,
|
||||||
|
promises_results[1],
|
||||||
|
ignore_type === "redirection" && ignore_id ? ignore_id : 0,
|
||||||
|
)
|
||||||
|
) {
|
||||||
is_taken = true;
|
is_taken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (promises_results[2]) {
|
if (promises_results[2]) {
|
||||||
// Dead Hosts
|
// Dead Hosts
|
||||||
if (internalHost._checkHostnameRecordsTaken(hostname, promises_results[2], ignore_type === 'dead' && ignore_id ? ignore_id : 0)) {
|
if (
|
||||||
|
internalHost._checkHostnameRecordsTaken(
|
||||||
|
hostname,
|
||||||
|
promises_results[2],
|
||||||
|
ignore_type === "dead" && ignore_id ? ignore_id : 0,
|
||||||
|
)
|
||||||
|
) {
|
||||||
is_taken = true;
|
is_taken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hostname: hostname,
|
hostname: hostname,
|
||||||
is_taken: is_taken
|
is_taken: is_taken,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -177,60 +188,64 @@ const internalHost = {
|
|||||||
* Private call only
|
* Private call only
|
||||||
*
|
*
|
||||||
* @param {String} hostname
|
* @param {String} hostname
|
||||||
* @param {Array} existing_rows
|
* @param {Array} existingRows
|
||||||
* @param {Integer} [ignore_id]
|
* @param {Integer} [ignoreId]
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
_checkHostnameRecordsTaken: function (hostname, existing_rows, ignore_id) {
|
_checkHostnameRecordsTaken: (hostname, existingRows, ignoreId) => {
|
||||||
let is_taken = false;
|
let isTaken = false;
|
||||||
|
|
||||||
if (existing_rows && existing_rows.length) {
|
if (existingRows?.length) {
|
||||||
existing_rows.map(function (existing_row) {
|
existingRows.map((existingRow) => {
|
||||||
existing_row.domain_names.map(function (existing_hostname) {
|
existingRow.domain_names.map((existingHostname) => {
|
||||||
// Does this domain match?
|
// Does this domain match?
|
||||||
if (existing_hostname.toLowerCase() === hostname.toLowerCase()) {
|
if (existingHostname.toLowerCase() === hostname.toLowerCase()) {
|
||||||
if (!ignore_id || ignore_id !== existing_row.id) {
|
if (!ignoreId || ignoreId !== existingRow.id) {
|
||||||
is_taken = true;
|
isTaken = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return is_taken;
|
return isTaken;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private call only
|
* Private call only
|
||||||
*
|
*
|
||||||
* @param {Array} hosts
|
* @param {Array} hosts
|
||||||
* @param {Array} domain_names
|
* @param {Array} domainNames
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
_getHostsWithDomains: function (hosts, domain_names) {
|
_getHostsWithDomains: (hosts, domainNames) => {
|
||||||
let response = [];
|
const response = [];
|
||||||
|
|
||||||
if (hosts && hosts.length) {
|
if (hosts?.length) {
|
||||||
hosts.map(function (host) {
|
hosts.map((host) => {
|
||||||
let host_matches = false;
|
let hostMatches = false;
|
||||||
|
|
||||||
domain_names.map(function (domain_name) {
|
domainNames.map((domainName) => {
|
||||||
host.domain_names.map(function (host_domain_name) {
|
host.domain_names.map((hostDomainName) => {
|
||||||
if (domain_name.toLowerCase() === host_domain_name.toLowerCase()) {
|
if (domainName.toLowerCase() === hostDomainName.toLowerCase()) {
|
||||||
host_matches = true;
|
hostMatches = true;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (host_matches) {
|
if (hostMatches) {
|
||||||
response.push(host);
|
response.push(host);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalHost;
|
export default internalHost;
|
||||||
|
|||||||
@@ -1,43 +1,49 @@
|
|||||||
const https = require('https');
|
import fs from "node:fs";
|
||||||
const fs = require('fs');
|
import https from "node:https";
|
||||||
const logger = require('../logger').ip_ranges;
|
import { dirname } from "node:path";
|
||||||
const error = require('../lib/error');
|
import { fileURLToPath } from "node:url";
|
||||||
const utils = require('../lib/utils');
|
import errs from "../lib/error.js";
|
||||||
const internalNginx = require('./nginx');
|
import utils from "../lib/utils.js";
|
||||||
|
import { ipRanges as logger } from "../logger.js";
|
||||||
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
const CLOUDFRONT_URL = 'https://ip-ranges.amazonaws.com/ip-ranges.json';
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
const CLOUDFARE_V4_URL = 'https://www.cloudflare.com/ips-v4';
|
const __dirname = dirname(__filename);
|
||||||
const CLOUDFARE_V6_URL = 'https://www.cloudflare.com/ips-v6';
|
|
||||||
|
const CLOUDFRONT_URL = "https://ip-ranges.amazonaws.com/ip-ranges.json";
|
||||||
|
const CLOUDFARE_V4_URL = "https://www.cloudflare.com/ips-v4";
|
||||||
|
const CLOUDFARE_V6_URL = "https://www.cloudflare.com/ips-v6";
|
||||||
|
|
||||||
const regIpV4 = /^(\d+\.?){4}\/\d+/;
|
const regIpV4 = /^(\d+\.?){4}\/\d+/;
|
||||||
const regIpV6 = /^(([\da-fA-F]+)?:)+\/\d+/;
|
const regIpV6 = /^(([\da-fA-F]+)?:)+\/\d+/;
|
||||||
|
|
||||||
const internalIpRanges = {
|
const internalIpRanges = {
|
||||||
|
|
||||||
interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
|
interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
|
||||||
interval: null,
|
interval: null,
|
||||||
interval_processing: false,
|
interval_processing: false,
|
||||||
iteration_count: 0,
|
iteration_count: 0,
|
||||||
|
|
||||||
initTimer: () => {
|
initTimer: () => {
|
||||||
logger.info('IP Ranges Renewal Timer initialized');
|
logger.info("IP Ranges Renewal Timer initialized");
|
||||||
internalIpRanges.interval = setInterval(internalIpRanges.fetch, internalIpRanges.interval_timeout);
|
internalIpRanges.interval = setInterval(internalIpRanges.fetch, internalIpRanges.interval_timeout);
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchUrl: (url) => {
|
fetchUrl: (url) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
logger.info('Fetching ' + url);
|
logger.info(`Fetching ${url}`);
|
||||||
return https.get(url, (res) => {
|
return https
|
||||||
res.setEncoding('utf8');
|
.get(url, (res) => {
|
||||||
let raw_data = '';
|
res.setEncoding("utf8");
|
||||||
res.on('data', (chunk) => {
|
let raw_data = "";
|
||||||
|
res.on("data", (chunk) => {
|
||||||
raw_data += chunk;
|
raw_data += chunk;
|
||||||
});
|
});
|
||||||
|
|
||||||
res.on('end', () => {
|
res.on("end", () => {
|
||||||
resolve(raw_data);
|
resolve(raw_data);
|
||||||
});
|
});
|
||||||
}).on('error', (err) => {
|
})
|
||||||
|
.on("error", (err) => {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -49,27 +55,30 @@ const internalIpRanges = {
|
|||||||
fetch: () => {
|
fetch: () => {
|
||||||
if (!internalIpRanges.interval_processing) {
|
if (!internalIpRanges.interval_processing) {
|
||||||
internalIpRanges.interval_processing = true;
|
internalIpRanges.interval_processing = true;
|
||||||
logger.info('Fetching IP Ranges from online services...');
|
logger.info("Fetching IP Ranges from online services...");
|
||||||
|
|
||||||
let ip_ranges = [];
|
let ip_ranges = [];
|
||||||
|
|
||||||
return internalIpRanges.fetchUrl(CLOUDFRONT_URL)
|
return internalIpRanges
|
||||||
|
.fetchUrl(CLOUDFRONT_URL)
|
||||||
.then((cloudfront_data) => {
|
.then((cloudfront_data) => {
|
||||||
let data = JSON.parse(cloudfront_data);
|
const data = JSON.parse(cloudfront_data);
|
||||||
|
|
||||||
if (data && typeof data.prefixes !== 'undefined') {
|
if (data && typeof data.prefixes !== "undefined") {
|
||||||
data.prefixes.map((item) => {
|
data.prefixes.map((item) => {
|
||||||
if (item.service === 'CLOUDFRONT') {
|
if (item.service === "CLOUDFRONT") {
|
||||||
ip_ranges.push(item.ip_prefix);
|
ip_ranges.push(item.ip_prefix);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data && typeof data.ipv6_prefixes !== 'undefined') {
|
if (data && typeof data.ipv6_prefixes !== "undefined") {
|
||||||
data.ipv6_prefixes.map((item) => {
|
data.ipv6_prefixes.map((item) => {
|
||||||
if (item.service === 'CLOUDFRONT') {
|
if (item.service === "CLOUDFRONT") {
|
||||||
ip_ranges.push(item.ipv6_prefix);
|
ip_ranges.push(item.ipv6_prefix);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -77,26 +86,26 @@ const internalIpRanges = {
|
|||||||
return internalIpRanges.fetchUrl(CLOUDFARE_V4_URL);
|
return internalIpRanges.fetchUrl(CLOUDFARE_V4_URL);
|
||||||
})
|
})
|
||||||
.then((cloudfare_data) => {
|
.then((cloudfare_data) => {
|
||||||
let items = cloudfare_data.split('\n').filter((line) => regIpV4.test(line));
|
const items = cloudfare_data.split("\n").filter((line) => regIpV4.test(line));
|
||||||
ip_ranges = [... ip_ranges, ... items];
|
ip_ranges = [...ip_ranges, ...items];
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalIpRanges.fetchUrl(CLOUDFARE_V6_URL);
|
return internalIpRanges.fetchUrl(CLOUDFARE_V6_URL);
|
||||||
})
|
})
|
||||||
.then((cloudfare_data) => {
|
.then((cloudfare_data) => {
|
||||||
let items = cloudfare_data.split('\n').filter((line) => regIpV6.test(line));
|
const items = cloudfare_data.split("\n").filter((line) => regIpV6.test(line));
|
||||||
ip_ranges = [... ip_ranges, ... items];
|
ip_ranges = [...ip_ranges, ...items];
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let clean_ip_ranges = [];
|
const clean_ip_ranges = [];
|
||||||
ip_ranges.map((range) => {
|
ip_ranges.map((range) => {
|
||||||
if (range) {
|
if (range) {
|
||||||
clean_ip_ranges.push(range);
|
clean_ip_ranges.push(range);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return internalIpRanges.generateConfig(clean_ip_ranges)
|
return internalIpRanges.generateConfig(clean_ip_ranges).then(() => {
|
||||||
.then(() => {
|
|
||||||
if (internalIpRanges.iteration_count) {
|
if (internalIpRanges.iteration_count) {
|
||||||
// Reload nginx
|
// Reload nginx
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
@@ -108,7 +117,7 @@ const internalIpRanges = {
|
|||||||
internalIpRanges.iteration_count++;
|
internalIpRanges.iteration_count++;
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
logger.error(err.message);
|
logger.fatal(err.message);
|
||||||
internalIpRanges.interval_processing = false;
|
internalIpRanges.interval_processing = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -122,26 +131,26 @@ const internalIpRanges = {
|
|||||||
const renderEngine = utils.getRenderEngine();
|
const renderEngine = utils.getRenderEngine();
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let filename = '/etc/nginx/conf.d/include/ip_ranges.conf';
|
const filename = "/etc/nginx/conf.d/include/ip_ranges.conf";
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/ip_ranges.conf', {encoding: 'utf8'});
|
template = fs.readFileSync(`${__dirname}/../templates/ip_ranges.conf`, { encoding: "utf8" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new errs.ConfigurationError(err.message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEngine
|
renderEngine
|
||||||
.parseAndRender(template, {ip_ranges: ip_ranges})
|
.parseAndRender(template, { ip_ranges: ip_ranges })
|
||||||
.then((config_text) => {
|
.then((config_text) => {
|
||||||
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
fs.writeFileSync(filename, config_text, { encoding: "utf8" });
|
||||||
resolve(true);
|
resolve(true);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
logger.warn('Could not write ' + filename + ':', err.message);
|
logger.warn(`Could not write ${filename}: ${err.message}`);
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new errs.ConfigurationError(err.message));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalIpRanges;
|
export default internalIpRanges;
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
const _ = require('lodash');
|
import fs from "node:fs";
|
||||||
const fs = require('node:fs');
|
import { dirname } from "node:path";
|
||||||
const logger = require('../logger').nginx;
|
import { fileURLToPath } from "node:url";
|
||||||
const config = require('../lib/config');
|
import _ from "lodash";
|
||||||
const utils = require('../lib/utils');
|
import errs from "../lib/error.js";
|
||||||
const error = require('../lib/error');
|
import utils from "../lib/utils.js";
|
||||||
|
import { nginx as logger } from "../logger.js";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
const internalNginx = {
|
const internalNginx = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will:
|
* This will:
|
||||||
* - test the nginx config first to make sure it's OK
|
* - test the nginx config first to make sure it's OK
|
||||||
@@ -24,7 +27,8 @@ const internalNginx = {
|
|||||||
configure: (model, host_type, host) => {
|
configure: (model, host_type, host) => {
|
||||||
let combined_meta = {};
|
let combined_meta = {};
|
||||||
|
|
||||||
return internalNginx.test()
|
return internalNginx
|
||||||
|
.test()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Nginx is OK
|
// Nginx is OK
|
||||||
// We're deleting this config regardless.
|
// We're deleting this config regardless.
|
||||||
@@ -37,19 +41,17 @@ const internalNginx = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Test nginx again and update meta with result
|
// Test nginx again and update meta with result
|
||||||
return internalNginx.test()
|
return internalNginx
|
||||||
|
.test()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// nginx is ok
|
// nginx is ok
|
||||||
combined_meta = _.assign({}, host.meta, {
|
combined_meta = _.assign({}, host.meta, {
|
||||||
nginx_online: true,
|
nginx_online: true,
|
||||||
nginx_err: null
|
nginx_err: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return model
|
return model.query().where("id", host.id).patch({
|
||||||
.query()
|
meta: combined_meta,
|
||||||
.where('id', host.id)
|
|
||||||
.patch({
|
|
||||||
meta: combined_meta
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -58,28 +60,27 @@ const internalNginx = {
|
|||||||
// nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (6: No such device or address)
|
// nginx: [alert] could not open error log file: open() "/var/log/nginx/error.log" failed (6: No such device or address)
|
||||||
|
|
||||||
const valid_lines = [];
|
const valid_lines = [];
|
||||||
const err_lines = err.message.split('\n');
|
const err_lines = err.message.split("\n");
|
||||||
err_lines.map((line) => {
|
err_lines.map((line) => {
|
||||||
if (line.indexOf('/var/log/nginx/error.log') === -1) {
|
if (line.indexOf("/var/log/nginx/error.log") === -1) {
|
||||||
valid_lines.push(line);
|
valid_lines.push(line);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (config.debug()) {
|
logger.debug("Nginx test failed:", valid_lines.join("\n"));
|
||||||
logger.error('Nginx test failed:', valid_lines.join('\n'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// config is bad, update meta and delete config
|
// config is bad, update meta and delete config
|
||||||
combined_meta = _.assign({}, host.meta, {
|
combined_meta = _.assign({}, host.meta, {
|
||||||
nginx_online: false,
|
nginx_online: false,
|
||||||
nginx_err: valid_lines.join('\n')
|
nginx_err: valid_lines.join("\n"),
|
||||||
});
|
});
|
||||||
|
|
||||||
return model
|
return model
|
||||||
.query()
|
.query()
|
||||||
.where('id', host.id)
|
.where("id", host.id)
|
||||||
.patch({
|
.patch({
|
||||||
meta: combined_meta
|
meta: combined_meta,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
internalNginx.renameConfigAsError(host_type, host);
|
internalNginx.renameConfigAsError(host_type, host);
|
||||||
@@ -101,21 +102,17 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
test: () => {
|
test: () => {
|
||||||
if (config.debug()) {
|
logger.debug("Testing Nginx configuration");
|
||||||
logger.info('Testing Nginx configuration');
|
return utils.execFile("/usr/sbin/nginx", ["-t", "-g", "error_log off;"]);
|
||||||
}
|
|
||||||
|
|
||||||
return utils.execFile('/usr/sbin/nginx', ['-t', '-g', 'error_log off;']);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
reload: () => {
|
reload: () => {
|
||||||
return internalNginx.test()
|
return internalNginx.test().then(() => {
|
||||||
.then(() => {
|
logger.info("Reloading Nginx");
|
||||||
logger.info('Reloading Nginx');
|
return utils.execFile("/usr/sbin/nginx", ["-s", "reload"]);
|
||||||
return utils.execFile('/usr/sbin/nginx', ['-s', 'reload']);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -125,8 +122,8 @@ const internalNginx = {
|
|||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
getConfigName: (host_type, host_id) => {
|
getConfigName: (host_type, host_id) => {
|
||||||
if (host_type === 'default') {
|
if (host_type === "default") {
|
||||||
return '/data/nginx/default_host/site.conf';
|
return "/data/nginx/default_host/site.conf";
|
||||||
}
|
}
|
||||||
return `/data/nginx/${internalNginx.getFileFriendlyHostType(host_type)}/${host_id}.conf`;
|
return `/data/nginx/${internalNginx.getFileFriendlyHostType(host_type)}/${host_id}.conf`;
|
||||||
},
|
},
|
||||||
@@ -141,38 +138,45 @@ const internalNginx = {
|
|||||||
let template;
|
let template;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(`${__dirname}/../templates/_location.conf`, {encoding: 'utf8'});
|
template = fs.readFileSync(`${__dirname}/../templates/_location.conf`, { encoding: "utf8" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new errs.ConfigurationError(err.message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderEngine = utils.getRenderEngine();
|
const renderEngine = utils.getRenderEngine();
|
||||||
let renderedLocations = '';
|
let renderedLocations = "";
|
||||||
|
|
||||||
const locationRendering = async () => {
|
const locationRendering = async () => {
|
||||||
for (let i = 0; i < host.locations.length; i++) {
|
for (let i = 0; i < host.locations.length; i++) {
|
||||||
const locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
|
const locationCopy = Object.assign(
|
||||||
{ssl_forced: host.ssl_forced}, {caching_enabled: host.caching_enabled}, {block_exploits: host.block_exploits},
|
{},
|
||||||
{allow_websocket_upgrade: host.allow_websocket_upgrade}, {http2_support: host.http2_support},
|
{ access_list_id: host.access_list_id },
|
||||||
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
|
{ certificate_id: host.certificate_id },
|
||||||
{certificate: host.certificate}, host.locations[i]);
|
{ ssl_forced: host.ssl_forced },
|
||||||
|
{ caching_enabled: host.caching_enabled },
|
||||||
|
{ block_exploits: host.block_exploits },
|
||||||
|
{ allow_websocket_upgrade: host.allow_websocket_upgrade },
|
||||||
|
{ http2_support: host.http2_support },
|
||||||
|
{ hsts_enabled: host.hsts_enabled },
|
||||||
|
{ hsts_subdomains: host.hsts_subdomains },
|
||||||
|
{ access_list: host.access_list },
|
||||||
|
{ certificate: host.certificate },
|
||||||
|
host.locations[i],
|
||||||
|
);
|
||||||
|
|
||||||
if (locationCopy.forward_host.indexOf('/') > -1) {
|
if (locationCopy.forward_host.indexOf("/") > -1) {
|
||||||
const splitted = locationCopy.forward_host.split('/');
|
const splitted = locationCopy.forward_host.split("/");
|
||||||
|
|
||||||
locationCopy.forward_host = splitted.shift();
|
locationCopy.forward_host = splitted.shift();
|
||||||
locationCopy.forward_path = `/${splitted.join('/')}`;
|
locationCopy.forward_path = `/${splitted.join("/")}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
renderedLocations += await renderEngine.parseAndRender(template, locationCopy);
|
renderedLocations += await renderEngine.parseAndRender(template, locationCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
locationRendering().then(() => resolve(renderedLocations));
|
locationRendering().then(() => resolve(renderedLocations));
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -186,9 +190,7 @@ const internalNginx = {
|
|||||||
const host = JSON.parse(JSON.stringify(host_row));
|
const host = JSON.parse(JSON.stringify(host_row));
|
||||||
const nice_host_type = internalNginx.getFileFriendlyHostType(host_type);
|
const nice_host_type = internalNginx.getFileFriendlyHostType(host_type);
|
||||||
|
|
||||||
if (config.debug()) {
|
logger.debug(`Generating ${nice_host_type} Config:`, JSON.stringify(host, null, 2));
|
||||||
logger.info(`Generating ${nice_host_type} Config:`, JSON.stringify(host, null, 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderEngine = utils.getRenderEngine();
|
const renderEngine = utils.getRenderEngine();
|
||||||
|
|
||||||
@@ -197,9 +199,9 @@ const internalNginx = {
|
|||||||
const filename = internalNginx.getConfigName(nice_host_type, host.id);
|
const filename = internalNginx.getConfigName(nice_host_type, host.id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(`${__dirname}/../templates/${nice_host_type}.conf`, {encoding: 'utf8'});
|
template = fs.readFileSync(`${__dirname}/../templates/${nice_host_type}.conf`, { encoding: "utf8" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new errs.ConfigurationError(err.message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,9 +209,9 @@ const internalNginx = {
|
|||||||
let origLocations;
|
let origLocations;
|
||||||
|
|
||||||
// Manipulate the data a bit before sending it to the template
|
// Manipulate the data a bit before sending it to the template
|
||||||
if (nice_host_type !== 'default') {
|
if (nice_host_type !== "default") {
|
||||||
host.use_default_location = true;
|
host.use_default_location = true;
|
||||||
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
|
if (typeof host.advanced_config !== "undefined" && host.advanced_config) {
|
||||||
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,11 +225,10 @@ const internalNginx = {
|
|||||||
|
|
||||||
// Allow someone who is using / custom location path to use it, and skip the default / location
|
// Allow someone who is using / custom location path to use it, and skip the default / location
|
||||||
_.map(host.locations, (location) => {
|
_.map(host.locations, (location) => {
|
||||||
if (location.path === '/') {
|
if (location.path === "/") {
|
||||||
host.use_default_location = false;
|
host.use_default_location = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
locationsPromise = Promise.resolve();
|
locationsPromise = Promise.resolve();
|
||||||
}
|
}
|
||||||
@@ -239,11 +240,8 @@ const internalNginx = {
|
|||||||
renderEngine
|
renderEngine
|
||||||
.parseAndRender(template, host)
|
.parseAndRender(template, host)
|
||||||
.then((config_text) => {
|
.then((config_text) => {
|
||||||
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
fs.writeFileSync(filename, config_text, { encoding: "utf8" });
|
||||||
|
logger.debug("Wrote config:", filename, config_text);
|
||||||
if (config.debug()) {
|
|
||||||
logger.success('Wrote config:', filename, config_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore locations array
|
// Restore locations array
|
||||||
host.locations = origLocations;
|
host.locations = origLocations;
|
||||||
@@ -251,11 +249,8 @@ const internalNginx = {
|
|||||||
resolve(true);
|
resolve(true);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (config.debug()) {
|
logger.debug(`Could not write ${filename}:`, err.message);
|
||||||
logger.warn(`Could not write ${filename}:`, err.message);
|
reject(new errs.ConfigurationError(err.message));
|
||||||
}
|
|
||||||
|
|
||||||
reject(new error.ConfigurationError(err.message));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -270,10 +265,7 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
generateLetsEncryptRequestConfig: (certificate) => {
|
generateLetsEncryptRequestConfig: (certificate) => {
|
||||||
if (config.debug()) {
|
logger.debug("Generating LetsEncrypt Request Config:", certificate);
|
||||||
logger.info('Generating LetsEncrypt Request Config:', certificate);
|
|
||||||
}
|
|
||||||
|
|
||||||
const renderEngine = utils.getRenderEngine();
|
const renderEngine = utils.getRenderEngine();
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -281,9 +273,9 @@ const internalNginx = {
|
|||||||
const filename = `/data/nginx/temp/letsencrypt_${certificate.id}.conf`;
|
const filename = `/data/nginx/temp/letsencrypt_${certificate.id}.conf`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(`${__dirname}/../templates/letsencrypt-request.conf`, {encoding: 'utf8'});
|
template = fs.readFileSync(`${__dirname}/../templates/letsencrypt-request.conf`, { encoding: "utf8" });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new errs.ConfigurationError(err.message));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,20 +284,13 @@ const internalNginx = {
|
|||||||
renderEngine
|
renderEngine
|
||||||
.parseAndRender(template, certificate)
|
.parseAndRender(template, certificate)
|
||||||
.then((config_text) => {
|
.then((config_text) => {
|
||||||
fs.writeFileSync(filename, config_text, {encoding: 'utf8'});
|
fs.writeFileSync(filename, config_text, { encoding: "utf8" });
|
||||||
|
logger.debug("Wrote config:", filename, config_text);
|
||||||
if (config.debug()) {
|
|
||||||
logger.success('Wrote config:', filename, config_text);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(true);
|
resolve(true);
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
if (config.debug()) {
|
logger.debug(`Could not write ${filename}:`, err.message);
|
||||||
logger.warn(`Could not write ${filename}:`, err.message);
|
reject(new errs.ConfigurationError(err.message));
|
||||||
}
|
|
||||||
|
|
||||||
reject(new error.ConfigurationError(err.message));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -320,7 +305,7 @@ const internalNginx = {
|
|||||||
try {
|
try {
|
||||||
fs.unlinkSync(filename);
|
fs.unlinkSync(filename);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.debug('Could not delete file:', JSON.stringify(err, null, 2));
|
logger.debug("Could not delete file:", JSON.stringify(err, null, 2));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -330,7 +315,7 @@ const internalNginx = {
|
|||||||
* @returns String
|
* @returns String
|
||||||
*/
|
*/
|
||||||
getFileFriendlyHostType: (host_type) => {
|
getFileFriendlyHostType: (host_type) => {
|
||||||
return host_type.replace(/-/g, '_');
|
return host_type.replace(/-/g, "_");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -341,7 +326,7 @@ const internalNginx = {
|
|||||||
*/
|
*/
|
||||||
deleteLetsEncryptRequestConfig: (certificate) => {
|
deleteLetsEncryptRequestConfig: (certificate) => {
|
||||||
const config_file = `/data/nginx/temp/letsencrypt_${certificate.id}.conf`;
|
const config_file = `/data/nginx/temp/letsencrypt_${certificate.id}.conf`;
|
||||||
return new Promise((resolve/*, reject*/) => {
|
return new Promise((resolve /*, reject*/) => {
|
||||||
internalNginx.deleteFile(config_file);
|
internalNginx.deleteFile(config_file);
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
@@ -354,10 +339,13 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
deleteConfig: (host_type, host, delete_err_file) => {
|
deleteConfig: (host_type, host, delete_err_file) => {
|
||||||
const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id);
|
const config_file = internalNginx.getConfigName(
|
||||||
|
internalNginx.getFileFriendlyHostType(host_type),
|
||||||
|
typeof host === "undefined" ? 0 : host.id,
|
||||||
|
);
|
||||||
const config_file_err = `${config_file}.err`;
|
const config_file_err = `${config_file}.err`;
|
||||||
|
|
||||||
return new Promise((resolve/*, reject*/) => {
|
return new Promise((resolve /*, reject*/) => {
|
||||||
internalNginx.deleteFile(config_file);
|
internalNginx.deleteFile(config_file);
|
||||||
if (delete_err_file) {
|
if (delete_err_file) {
|
||||||
internalNginx.deleteFile(config_file_err);
|
internalNginx.deleteFile(config_file_err);
|
||||||
@@ -372,10 +360,13 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
renameConfigAsError: (host_type, host) => {
|
renameConfigAsError: (host_type, host) => {
|
||||||
const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id);
|
const config_file = internalNginx.getConfigName(
|
||||||
|
internalNginx.getFileFriendlyHostType(host_type),
|
||||||
|
typeof host === "undefined" ? 0 : host.id,
|
||||||
|
);
|
||||||
const config_file_err = `${config_file}.err`;
|
const config_file_err = `${config_file}.err`;
|
||||||
|
|
||||||
return new Promise((resolve/*, reject*/) => {
|
return new Promise((resolve /*, reject*/) => {
|
||||||
fs.unlink(config_file, () => {
|
fs.unlink(config_file, () => {
|
||||||
// ignore result, continue
|
// ignore result, continue
|
||||||
fs.rename(config_file, config_file_err, () => {
|
fs.rename(config_file, config_file_err, () => {
|
||||||
@@ -395,6 +386,7 @@ const internalNginx = {
|
|||||||
const promises = [];
|
const promises = [];
|
||||||
hosts.map((host) => {
|
hosts.map((host) => {
|
||||||
promises.push(internalNginx.generateConfig(host_type, host));
|
promises.push(internalNginx.generateConfig(host_type, host));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
@@ -409,6 +401,7 @@ const internalNginx = {
|
|||||||
const promises = [];
|
const promises = [];
|
||||||
hosts.map((host) => {
|
hosts.map((host) => {
|
||||||
promises.push(internalNginx.deleteConfig(host_type, host, true));
|
promises.push(internalNginx.deleteConfig(host_type, host, true));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
@@ -424,13 +417,13 @@ const internalNginx = {
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
ipv6Enabled: () => {
|
ipv6Enabled: () => {
|
||||||
if (typeof process.env.DISABLE_IPV6 !== 'undefined') {
|
if (typeof process.env.DISABLE_IPV6 !== "undefined") {
|
||||||
const disabled = process.env.DISABLE_IPV6.toLowerCase();
|
const disabled = process.env.DISABLE_IPV6.toLowerCase();
|
||||||
return !(disabled === 'on' || disabled === 'true' || disabled === '1' || disabled === 'yes');
|
return !(disabled === "on" || disabled === "true" || disabled === "1" || disabled === "yes");
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalNginx;
|
export default internalNginx;
|
||||||
|
|||||||
@@ -1,106 +1,105 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const utils = require('../lib/utils');
|
import { castJsonIfNeed } from "../lib/helpers.js";
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
import utils from "../lib/utils.js";
|
||||||
const internalHost = require('./host');
|
import proxyHostModel from "../models/proxy_host.js";
|
||||||
const internalNginx = require('./nginx');
|
import internalAuditLog from "./audit-log.js";
|
||||||
const internalAuditLog = require('./audit-log');
|
import internalCertificate from "./certificate.js";
|
||||||
const internalCertificate = require('./certificate');
|
import internalHost from "./host.js";
|
||||||
const {castJsonIfNeed} = require('../lib/helpers');
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
function omissions () {
|
const omissions = () => {
|
||||||
return ['is_deleted', 'owner.is_deleted'];
|
return ["is_deleted", "owner.is_deleted"];
|
||||||
}
|
};
|
||||||
|
|
||||||
const internalProxyHost = {
|
const internalProxyHost = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
let thisData = data;
|
||||||
|
const createCertificate = thisData.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
delete data.certificate_id;
|
delete thisData.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('proxy_hosts:create', data)
|
return access
|
||||||
|
.can("proxy_hosts:create", thisData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Get a list of the domain names and check each of them against existing records
|
// Get a list of the domain names and check each of them against existing records
|
||||||
let domain_name_check_promises = [];
|
const domain_name_check_promises = [];
|
||||||
|
|
||||||
data.domain_names.map(function (domain_name) {
|
thisData.domain_names.map((domain_name) => {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
check_results.map((result) => {
|
||||||
check_results.map(function (result) {
|
|
||||||
if (result.is_taken) {
|
if (result.is_taken) {
|
||||||
throw new error.ValidationError(result.hostname + ' is already in use');
|
throw new errs.ValidationError(`${result.hostname} is already in use`);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point the domains should have been checked
|
// At this point the domains should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
thisData.owner_user_id = access.token.getUserId(1);
|
||||||
data = internalHost.cleanSslHstsData(data);
|
thisData = internalHost.cleanSslHstsData(thisData);
|
||||||
|
|
||||||
// Fix for db field not having a default value
|
// Fix for db field not having a default value
|
||||||
// for this optional field.
|
// for this optional field.
|
||||||
if (typeof data.advanced_config === 'undefined') {
|
if (typeof thisData.advanced_config === "undefined") {
|
||||||
data.advanced_config = '';
|
thisData.advanced_config = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel.query().insertAndFetch(thisData).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, data)
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, thisData)
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
return internalProxyHost.update(access, {
|
return internalProxyHost.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// re-fetch with cert
|
// re-fetch with cert
|
||||||
return internalProxyHost.get(access, {
|
return internalProxyHost.get(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
expand: ['certificate', 'owner', 'access_list.[clients,items]']
|
expand: ["certificate", "owner", "access_list.[clients,items]"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(proxyHostModel, 'proxy_host', row)
|
return internalNginx.configure(proxyHostModel, "proxy_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Audit log
|
// Audit log
|
||||||
data.meta = _.assign({}, data.meta || {}, row.meta);
|
thisData.meta = _.assign({}, thisData.meta || {}, row.meta);
|
||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'created',
|
.add(access, {
|
||||||
object_type: 'proxy-host',
|
action: "created",
|
||||||
|
object_type: "proxy-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: thisData,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
@@ -115,77 +114,88 @@ const internalProxyHost = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
let thisData = data;
|
||||||
|
const create_certificate = thisData.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
delete data.certificate_id;
|
delete thisData.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('proxy_hosts:update', data.id)
|
return access
|
||||||
|
.can("proxy_hosts:update", thisData.id)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// Get a list of the domain names and check each of them against existing records
|
// Get a list of the domain names and check each of them against existing records
|
||||||
let domain_name_check_promises = [];
|
const domain_name_check_promises = [];
|
||||||
|
|
||||||
if (typeof data.domain_names !== 'undefined') {
|
if (typeof thisData.domain_names !== "undefined") {
|
||||||
data.domain_names.map(function (domain_name) {
|
thisData.domain_names.map((domain_name) => {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'proxy', data.id));
|
return domain_name_check_promises.push(
|
||||||
|
internalHost.isHostnameTaken(domain_name, "proxy", thisData.id),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
check_results.map((result) => {
|
||||||
check_results.map(function (result) {
|
|
||||||
if (result.is_taken) {
|
if (result.is_taken) {
|
||||||
throw new error.ValidationError(result.hostname + ' is already in use');
|
throw new errs.ValidationError(`${result.hostname} is already in use`);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {id: data.id});
|
return internalProxyHost.get(access, { id: thisData.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id !== data.id) {
|
if (row.id !== thisData.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('Proxy Host could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`Proxy Host could not be updated, IDs do not match: ${row.id} !== ${thisData.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
domain_names: data.domain_names || row.domain_names,
|
.createQuickCertificate(access, {
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
domain_names: thisData.domain_names || row.domain_names,
|
||||||
|
meta: _.assign({}, row.meta, thisData.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
thisData.certificate_id = cert.id;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
thisData = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
|
||||||
data = internalHost.cleanSslHstsData(data, row);
|
thisData = internalHost.cleanSslHstsData(thisData, row);
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where({id: data.id})
|
.where({ id: thisData.id })
|
||||||
.patch(data)
|
.patch(thisData)
|
||||||
.then(utils.omitRow(omissions()))
|
.then(utils.omitRow(omissions()))
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'updated',
|
.add(access, {
|
||||||
object_type: 'proxy-host',
|
action: "updated",
|
||||||
|
object_type: "proxy-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: thisData,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return saved_row;
|
return saved_row;
|
||||||
@@ -193,9 +203,10 @@ const internalProxyHost = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {
|
return internalProxyHost
|
||||||
id: data.id,
|
.get(access, {
|
||||||
expand: ['owner', 'certificate', 'access_list.[clients,items]']
|
id: thisData.id,
|
||||||
|
expand: ["owner", "certificate", "access_list.[clients,items]"],
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row.enabled) {
|
if (!row.enabled) {
|
||||||
@@ -203,11 +214,9 @@ const internalProxyHost = {
|
|||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(proxyHostModel, 'proxy_host', row)
|
return internalNginx.configure(proxyHostModel, "proxy_host", row).then((new_meta) => {
|
||||||
.then((new_meta) => {
|
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
return _.omit(internalHost.cleanRowCertificateMeta(row), omissions());
|
||||||
return _.omit(row, omissions());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -222,39 +231,38 @@ const internalProxyHost = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data) => {
|
get: (access, data) => {
|
||||||
if (typeof data === 'undefined') {
|
const thisData = data || {};
|
||||||
data = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return access.can('proxy_hosts:get', data.id)
|
return access
|
||||||
|
.can("proxy_hosts:get", thisData.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = proxyHostModel
|
const query = proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere("id", thisData.id)
|
||||||
.allowGraph('[owner,access_list.[clients,items],certificate]')
|
.allowGraph("[owner,access_list.[clients,items],certificate]")
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
|
||||||
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRow(omissions()));
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(thisData.id);
|
||||||
}
|
}
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
const thisRow = internalHost.cleanRowCertificateMeta(row);
|
||||||
// Custom omissions
|
// Custom omissions
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
if (typeof thisData.omit !== "undefined" && thisData.omit !== null) {
|
||||||
row = _.omit(row, data.omit);
|
return _.omit(row, thisData.omit);
|
||||||
}
|
}
|
||||||
return row;
|
return thisRow;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -266,35 +274,35 @@ const internalProxyHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('proxy_hosts:delete', data.id)
|
return access
|
||||||
|
.can("proxy_hosts:delete", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {id: data.id});
|
return internalProxyHost.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('proxy_host', row)
|
return internalNginx.deleteConfig("proxy_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'deleted',
|
action: "deleted",
|
||||||
object_type: 'proxy-host',
|
object_type: "proxy-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -311,39 +319,41 @@ const internalProxyHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
enable: (access, data) => {
|
enable: (access, data) => {
|
||||||
return access.can('proxy_hosts:update', data.id)
|
return access
|
||||||
|
.can("proxy_hosts:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {
|
return internalProxyHost.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['certificate', 'owner', 'access_list']
|
expand: ["certificate", "owner", "access_list"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Host is already enabled');
|
if (row.enabled) {
|
||||||
|
throw new errs.ValidationError("Host is already enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 1;
|
row.enabled = 1;
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(proxyHostModel, 'proxy_host', row);
|
return internalNginx.configure(proxyHostModel, "proxy_host", row);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'enabled',
|
action: "enabled",
|
||||||
object_type: 'proxy-host',
|
object_type: "proxy-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -360,39 +370,40 @@ const internalProxyHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
disable: (access, data) => {
|
disable: (access, data) => {
|
||||||
return access.can('proxy_hosts:update', data.id)
|
return access
|
||||||
|
.can("proxy_hosts:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {id: data.id});
|
return internalProxyHost.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (!row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Host is already disabled');
|
if (!row.enabled) {
|
||||||
|
throw new errs.ValidationError("Host is already disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 0;
|
row.enabled = 0;
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 0
|
enabled: 0,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('proxy_host', row)
|
return internalNginx.deleteConfig("proxy_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'disabled',
|
action: "disabled",
|
||||||
object_type: 'proxy-host',
|
object_type: "proxy-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -410,34 +421,35 @@ const internalProxyHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('proxy_hosts:list')
|
return access
|
||||||
|
.can("proxy_hosts:list")
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = proxyHostModel
|
const query = proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.groupBy('id')
|
.groupBy("id")
|
||||||
.allowGraph('[owner,access_list,certificate]')
|
.allowGraph("[owner,access_list,certificate]")
|
||||||
.orderBy(castJsonIfNeed('domain_names'), 'ASC');
|
.orderBy(castJsonIfNeed("domain_names"), "ASC");
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string' && search_query.length > 0) {
|
if (typeof search_query === "string" && search_query.length > 0) {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where(castJsonIfNeed('domain_names'), 'like', `%${search_query}%`);
|
this.where(castJsonIfNeed("domain_names"), "like", `%${search_query}%`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched('[' + expand.join(', ') + ']');
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRows(omissions()));
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== "undefined" && expand !== null && expand.indexOf("certificate") !== -1) {
|
||||||
return internalHost.cleanAllRowsCertificateMeta(rows);
|
return internalHost.cleanAllRowsCertificateMeta(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -453,20 +465,16 @@ const internalProxyHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
let query = proxyHostModel
|
const query = proxyHostModel.query().count("id as count").where("is_deleted", 0);
|
||||||
.query()
|
|
||||||
.count('id as count')
|
|
||||||
.where('is_deleted', 0);
|
|
||||||
|
|
||||||
if (visibility !== 'all') {
|
if (visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', user_id);
|
query.andWhere("owner_user_id", user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.first()
|
return query.first().then((row) => {
|
||||||
.then((row) => {
|
return Number.parseInt(row.count, 10);
|
||||||
return parseInt(row.count, 10);
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalProxyHost;
|
export default internalProxyHost;
|
||||||
|
|||||||
@@ -1,73 +1,73 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const utils = require('../lib/utils');
|
import { castJsonIfNeed } from "../lib/helpers.js";
|
||||||
const redirectionHostModel = require('../models/redirection_host');
|
import utils from "../lib/utils.js";
|
||||||
const internalHost = require('./host');
|
import redirectionHostModel from "../models/redirection_host.js";
|
||||||
const internalNginx = require('./nginx');
|
import internalAuditLog from "./audit-log.js";
|
||||||
const internalAuditLog = require('./audit-log');
|
import internalCertificate from "./certificate.js";
|
||||||
const internalCertificate = require('./certificate');
|
import internalHost from "./host.js";
|
||||||
const {castJsonIfNeed} = require('../lib/helpers');
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
function omissions () {
|
const omissions = () => {
|
||||||
return ['is_deleted'];
|
return ["is_deleted"];
|
||||||
}
|
};
|
||||||
|
|
||||||
const internalRedirectionHost = {
|
const internalRedirectionHost = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
let thisData = data || {};
|
||||||
|
const createCertificate = thisData.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
delete data.certificate_id;
|
delete thisData.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('redirection_hosts:create', data)
|
return access
|
||||||
|
.can("redirection_hosts:create", thisData)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// Get a list of the domain names and check each of them against existing records
|
// Get a list of the domain names and check each of them against existing records
|
||||||
let domain_name_check_promises = [];
|
const domain_name_check_promises = [];
|
||||||
|
|
||||||
data.domain_names.map(function (domain_name) {
|
thisData.domain_names.map((domain_name) => {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
check_results.map((result) => {
|
||||||
check_results.map(function (result) {
|
|
||||||
if (result.is_taken) {
|
if (result.is_taken) {
|
||||||
throw new error.ValidationError(result.hostname + ' is already in use');
|
throw new errs.ValidationError(`${result.hostname} is already in use`);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// At this point the domains should have been checked
|
// At this point the domains should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
thisData.owner_user_id = access.token.getUserId(1);
|
||||||
data = internalHost.cleanSslHstsData(data);
|
thisData = internalHost.cleanSslHstsData(thisData);
|
||||||
|
|
||||||
// Fix for db field not having a default value
|
// Fix for db field not having a default value
|
||||||
// for this optional field.
|
// for this optional field.
|
||||||
if (typeof data.advanced_config === 'undefined') {
|
if (typeof data.advanced_config === "undefined") {
|
||||||
data.advanced_config = '';
|
data.advanced_config = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel.query().insertAndFetch(thisData).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, data)
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, thisData)
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
return internalRedirectionHost.update(access, {
|
return internalRedirectionHost.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -80,25 +80,25 @@ const internalRedirectionHost = {
|
|||||||
// re-fetch with cert
|
// re-fetch with cert
|
||||||
return internalRedirectionHost.get(access, {
|
return internalRedirectionHost.get(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
expand: ['certificate', 'owner']
|
expand: ["certificate", "owner"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(redirectionHostModel, 'redirection_host', row)
|
return internalNginx.configure(redirectionHostModel, "redirection_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
data.meta = _.assign({}, data.meta || {}, row.meta);
|
thisData.meta = _.assign({}, thisData.meta || {}, row.meta);
|
||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'created',
|
.add(access, {
|
||||||
object_type: 'redirection-host',
|
action: "created",
|
||||||
|
object_type: "redirection-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: thisData,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
@@ -113,76 +113,88 @@ const internalRedirectionHost = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let create_certificate = data.certificate_id === 'new';
|
let thisData = data || {};
|
||||||
|
const createCertificate = thisData.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
delete data.certificate_id;
|
delete thisData.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('redirection_hosts:update', data.id)
|
return access
|
||||||
|
.can("redirection_hosts:update", thisData.id)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// Get a list of the domain names and check each of them against existing records
|
// Get a list of the domain names and check each of them against existing records
|
||||||
let domain_name_check_promises = [];
|
const domain_name_check_promises = [];
|
||||||
|
|
||||||
if (typeof data.domain_names !== 'undefined') {
|
if (typeof thisData.domain_names !== "undefined") {
|
||||||
data.domain_names.map(function (domain_name) {
|
thisData.domain_names.map((domain_name) => {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'redirection', data.id));
|
domain_name_check_promises.push(
|
||||||
|
internalHost.isHostnameTaken(domain_name, "redirection", thisData.id),
|
||||||
|
);
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
check_results.map((result) => {
|
||||||
check_results.map(function (result) {
|
|
||||||
if (result.is_taken) {
|
if (result.is_taken) {
|
||||||
throw new error.ValidationError(result.hostname + ' is already in use');
|
throw new errs.ValidationError(`${result.hostname} is already in use`);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {id: data.id});
|
return internalRedirectionHost.get(access, { id: thisData.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id !== data.id) {
|
if (row.id !== thisData.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('Redirection Host could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`Redirection Host could not be updated, IDs do not match: ${row.id} !== ${thisData.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (createCertificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
domain_names: data.domain_names || row.domain_names,
|
.createQuickCertificate(access, {
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
domain_names: thisData.domain_names || row.domain_names,
|
||||||
|
meta: _.assign({}, row.meta, thisData.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
thisData.certificate_id = cert.id;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
thisData = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
thisData,
|
||||||
|
);
|
||||||
|
|
||||||
data = internalHost.cleanSslHstsData(data, row);
|
thisData = internalHost.cleanSslHstsData(thisData, row);
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where({id: data.id})
|
.where({ id: thisData.id })
|
||||||
.patch(data)
|
.patch(thisData)
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'updated',
|
.add(access, {
|
||||||
object_type: 'redirection-host',
|
action: "updated",
|
||||||
|
object_type: "redirection-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: thisData,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
@@ -190,17 +202,18 @@ const internalRedirectionHost = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {
|
return internalRedirectionHost
|
||||||
id: data.id,
|
.get(access, {
|
||||||
expand: ['owner', 'certificate']
|
id: thisData.id,
|
||||||
|
expand: ["owner", "certificate"],
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(redirectionHostModel, 'redirection_host', row)
|
return internalNginx
|
||||||
|
.configure(redirectionHostModel, "redirection_host", row)
|
||||||
.then((new_meta) => {
|
.then((new_meta) => {
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
return _.omit(internalHost.cleanRowCertificateMeta(row), omissions());
|
||||||
return _.omit(row, omissions());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -215,39 +228,39 @@ const internalRedirectionHost = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data) => {
|
get: (access, data) => {
|
||||||
if (typeof data === 'undefined') {
|
const thisData = data || {};
|
||||||
data = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return access.can('redirection_hosts:get', data.id)
|
return access
|
||||||
|
.can("redirection_hosts:get", thisData.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = redirectionHostModel
|
const query = redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere("id", thisData.id)
|
||||||
.allowGraph('[owner,certificate]')
|
.allowGraph("[owner,certificate]")
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
|
||||||
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRow(omissions()));
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
let thisRow = row;
|
||||||
throw new error.ItemNotFoundError(data.id);
|
if (!thisRow || !thisRow.id) {
|
||||||
|
throw new errs.ItemNotFoundError(thisData.id);
|
||||||
}
|
}
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
thisRow = internalHost.cleanRowCertificateMeta(thisRow);
|
||||||
// Custom omissions
|
// Custom omissions
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
if (typeof thisData.omit !== "undefined" && thisData.omit !== null) {
|
||||||
row = _.omit(row, data.omit);
|
return _.omit(thisRow, thisData.omit);
|
||||||
}
|
}
|
||||||
return row;
|
return thisRow;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -259,35 +272,35 @@ const internalRedirectionHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('redirection_hosts:delete', data.id)
|
return access
|
||||||
|
.can("redirection_hosts:delete", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {id: data.id});
|
return internalRedirectionHost.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('redirection_host', row)
|
return internalNginx.deleteConfig("redirection_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'deleted',
|
action: "deleted",
|
||||||
object_type: 'redirection-host',
|
object_type: "redirection-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -304,39 +317,41 @@ const internalRedirectionHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
enable: (access, data) => {
|
enable: (access, data) => {
|
||||||
return access.can('redirection_hosts:update', data.id)
|
return access
|
||||||
|
.can("redirection_hosts:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {
|
return internalRedirectionHost.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['certificate', 'owner']
|
expand: ["certificate", "owner"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Host is already enabled');
|
if (row.enabled) {
|
||||||
|
throw new errs.ValidationError("Host is already enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 1;
|
row.enabled = 1;
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(redirectionHostModel, 'redirection_host', row);
|
return internalNginx.configure(redirectionHostModel, "redirection_host", row);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'enabled',
|
action: "enabled",
|
||||||
object_type: 'redirection-host',
|
object_type: "redirection-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -353,39 +368,40 @@ const internalRedirectionHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
disable: (access, data) => {
|
disable: (access, data) => {
|
||||||
return access.can('redirection_hosts:update', data.id)
|
return access
|
||||||
|
.can("redirection_hosts:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {id: data.id});
|
return internalRedirectionHost.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (!row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Host is already disabled');
|
if (!row.enabled) {
|
||||||
|
throw new errs.ValidationError("Host is already disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 0;
|
row.enabled = 0;
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 0
|
enabled: 0,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('redirection_host', row)
|
return internalNginx.deleteConfig("redirection_host", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'disabled',
|
action: "disabled",
|
||||||
object_type: 'redirection-host',
|
object_type: "redirection-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -403,34 +419,35 @@ const internalRedirectionHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('redirection_hosts:list')
|
return access
|
||||||
|
.can("redirection_hosts:list")
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = redirectionHostModel
|
const query = redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.groupBy('id')
|
.groupBy("id")
|
||||||
.allowGraph('[owner,certificate]')
|
.allowGraph("[owner,certificate]")
|
||||||
.orderBy(castJsonIfNeed('domain_names'), 'ASC');
|
.orderBy(castJsonIfNeed("domain_names"), "ASC");
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string' && search_query.length > 0) {
|
if (typeof search_query === "string" && search_query.length > 0) {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where(castJsonIfNeed('domain_names'), 'like', `%${search_query}%`);
|
this.where(castJsonIfNeed("domain_names"), "like", `%${search_query}%`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched('[' + expand.join(', ') + ']');
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRows(omissions()));
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== "undefined" && expand !== null && expand.indexOf("certificate") !== -1) {
|
||||||
return internalHost.cleanAllRowsCertificateMeta(rows);
|
return internalHost.cleanAllRowsCertificateMeta(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -446,20 +463,16 @@ const internalRedirectionHost = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
let query = redirectionHostModel
|
const query = redirectionHostModel.query().count("id as count").where("is_deleted", 0);
|
||||||
.query()
|
|
||||||
.count('id as count')
|
|
||||||
.where('is_deleted', 0);
|
|
||||||
|
|
||||||
if (visibility !== 'all') {
|
if (visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', user_id);
|
query.andWhere("owner_user_id", user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.first()
|
return query.first().then((row) => {
|
||||||
.then((row) => {
|
return Number.parseInt(row.count, 10);
|
||||||
return parseInt(row.count, 10);
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalRedirectionHost;
|
export default internalRedirectionHost;
|
||||||
|
|||||||
@@ -1,24 +1,24 @@
|
|||||||
const internalProxyHost = require('./proxy-host');
|
import internalDeadHost from "./dead-host.js";
|
||||||
const internalRedirectionHost = require('./redirection-host');
|
import internalProxyHost from "./proxy-host.js";
|
||||||
const internalDeadHost = require('./dead-host');
|
import internalRedirectionHost from "./redirection-host.js";
|
||||||
const internalStream = require('./stream');
|
import internalStream from "./stream.js";
|
||||||
|
|
||||||
const internalReport = {
|
const internalReport = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
getHostsReport: (access) => {
|
getHostsReport: (access) => {
|
||||||
return access.can('reports:hosts', 1)
|
return access
|
||||||
|
.can("reports:hosts", 1)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let user_id = access.token.getUserId(1);
|
const userId = access.token.getUserId(1);
|
||||||
|
|
||||||
let promises = [
|
const promises = [
|
||||||
internalProxyHost.getCount(user_id, access_data.visibility),
|
internalProxyHost.getCount(userId, access_data.visibility),
|
||||||
internalRedirectionHost.getCount(user_id, access_data.visibility),
|
internalRedirectionHost.getCount(userId, access_data.visibility),
|
||||||
internalStream.getCount(user_id, access_data.visibility),
|
internalStream.getCount(userId, access_data.visibility),
|
||||||
internalDeadHost.getCount(user_id, access_data.visibility)
|
internalDeadHost.getCount(userId, access_data.visibility),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
@@ -28,11 +28,10 @@ const internalReport = {
|
|||||||
proxy: counts.shift(),
|
proxy: counts.shift(),
|
||||||
redirection: counts.shift(),
|
redirection: counts.shift(),
|
||||||
stream: counts.shift(),
|
stream: counts.shift(),
|
||||||
dead: counts.shift()
|
dead: counts.shift(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
},
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalReport;
|
export default internalReport;
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
const fs = require('fs');
|
import fs from "node:fs";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const settingModel = require('../models/setting');
|
import settingModel from "../models/setting.js";
|
||||||
const internalNginx = require('./nginx');
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
const internalSetting = {
|
const internalSetting = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
@@ -12,37 +11,38 @@ const internalSetting = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
return access.can('settings:update', data.id)
|
return access
|
||||||
|
.can("settings:update", data.id)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
return internalSetting.get(access, {id: data.id});
|
return internalSetting.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id !== data.id) {
|
if (row.id !== data.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('Setting could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`Setting could not be updated, IDs do not match: ${row.id} !== ${data.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return settingModel
|
return settingModel.query().where({ id: data.id }).patch(data);
|
||||||
.query()
|
|
||||||
.where({id: data.id})
|
|
||||||
.patch(data);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalSetting.get(access, {
|
return internalSetting.get(access, {
|
||||||
id: data.id
|
id: data.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id === 'default-site') {
|
if (row.id === "default-site") {
|
||||||
// write the html if we need to
|
// write the html if we need to
|
||||||
if (row.value === 'html') {
|
if (row.value === "html") {
|
||||||
fs.writeFileSync('/data/nginx/default_www/index.html', row.meta.html, {encoding: 'utf8'});
|
fs.writeFileSync("/data/nginx/default_www/index.html", row.meta.html, { encoding: "utf8" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.deleteConfig('default')
|
return internalNginx
|
||||||
|
.deleteConfig("default")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.generateConfig('default', row);
|
return internalNginx.generateConfig("default", row);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.test();
|
return internalNginx.test();
|
||||||
@@ -54,7 +54,8 @@ const internalSetting = {
|
|||||||
return row;
|
return row;
|
||||||
})
|
})
|
||||||
.catch((/*err*/) => {
|
.catch((/*err*/) => {
|
||||||
internalNginx.deleteConfig('default')
|
internalNginx
|
||||||
|
.deleteConfig("default")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.test();
|
return internalNginx.test();
|
||||||
})
|
})
|
||||||
@@ -63,12 +64,11 @@ const internalSetting = {
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// I'm being slack here I know..
|
// I'm being slack here I know..
|
||||||
throw new error.ValidationError('Could not reconfigure Nginx. Please check logs.');
|
throw new errs.ValidationError("Could not reconfigure Nginx. Please check logs.");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -79,19 +79,16 @@ const internalSetting = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data) => {
|
get: (access, data) => {
|
||||||
return access.can('settings:get', data.id)
|
return access
|
||||||
|
.can("settings:get", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return settingModel
|
return settingModel.query().where("id", data.id).first();
|
||||||
.query()
|
|
||||||
.where('id', data.id)
|
|
||||||
.first();
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (row) {
|
||||||
return row;
|
return row;
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
|
||||||
}
|
}
|
||||||
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -102,15 +99,13 @@ const internalSetting = {
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getCount: (access) => {
|
getCount: (access) => {
|
||||||
return access.can('settings:list')
|
return access
|
||||||
|
.can("settings:list")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return settingModel
|
return settingModel.query().count("id as count").first();
|
||||||
.query()
|
|
||||||
.count('id as count')
|
|
||||||
.first();
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
return parseInt(row.count, 10);
|
return Number.parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -121,13 +116,10 @@ const internalSetting = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access) => {
|
getAll: (access) => {
|
||||||
return access.can('settings:list')
|
return access.can("settings:list").then(() => {
|
||||||
.then(() => {
|
return settingModel.query().orderBy("description", "ASC");
|
||||||
return settingModel
|
|
||||||
.query()
|
|
||||||
.orderBy('description', 'ASC');
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalSetting;
|
export default internalSetting;
|
||||||
|
|||||||
@@ -1,87 +1,84 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const utils = require('../lib/utils');
|
import { castJsonIfNeed } from "../lib/helpers.js";
|
||||||
const streamModel = require('../models/stream');
|
import utils from "../lib/utils.js";
|
||||||
const internalNginx = require('./nginx');
|
import streamModel from "../models/stream.js";
|
||||||
const internalAuditLog = require('./audit-log');
|
import internalAuditLog from "./audit-log.js";
|
||||||
const internalCertificate = require('./certificate');
|
import internalCertificate from "./certificate.js";
|
||||||
const internalHost = require('./host');
|
import internalHost from "./host.js";
|
||||||
const {castJsonIfNeed} = require('../lib/helpers');
|
import internalNginx from "./nginx.js";
|
||||||
|
|
||||||
function omissions () {
|
const omissions = () => {
|
||||||
return ['is_deleted', 'owner.is_deleted', 'certificate.is_deleted'];
|
return ["is_deleted", "owner.is_deleted", "certificate.is_deleted"];
|
||||||
}
|
};
|
||||||
|
|
||||||
const internalStream = {
|
const internalStream = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
const create_certificate = data.certificate_id === 'new';
|
const create_certificate = data.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
delete data.certificate_id;
|
delete data.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('streams:create', data)
|
return access
|
||||||
|
.can("streams:create", data)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// TODO: At this point the existing ports should have been checked
|
// TODO: At this point the existing ports should have been checked
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
|
|
||||||
if (typeof data.meta === 'undefined') {
|
if (typeof data.meta === "undefined") {
|
||||||
data.meta = {};
|
data.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// streams aren't routed by domain name so don't store domain names in the DB
|
// streams aren't routed by domain name so don't store domain names in the DB
|
||||||
let data_no_domains = structuredClone(data);
|
const data_no_domains = structuredClone(data);
|
||||||
delete data_no_domains.domain_names;
|
delete data_no_domains.domain_names;
|
||||||
|
|
||||||
return streamModel
|
return streamModel.query().insertAndFetch(data_no_domains).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data_no_domains)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, data)
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, data)
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
return internalStream.update(access, {
|
return internalStream.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// re-fetch with cert
|
// re-fetch with cert
|
||||||
return internalStream.get(access, {
|
return internalStream.get(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
expand: ['certificate', 'owner']
|
expand: ["certificate", "owner"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(streamModel, 'stream', row)
|
return internalNginx.configure(streamModel, "stream", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'created',
|
.add(access, {
|
||||||
object_type: 'stream',
|
action: "created",
|
||||||
|
object_type: "stream",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
@@ -96,56 +93,65 @@ const internalStream = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
const create_certificate = data.certificate_id === 'new';
|
let thisData = data;
|
||||||
|
const create_certificate = thisData.certificate_id === "new";
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
delete data.certificate_id;
|
delete thisData.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('streams:update', data.id)
|
return access
|
||||||
|
.can("streams:update", thisData.id)
|
||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
// TODO: at this point the existing streams should have been checked
|
// TODO: at this point the existing streams should have been checked
|
||||||
return internalStream.get(access, {id: data.id});
|
return internalStream.get(access, { id: thisData.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row.id !== data.id) {
|
if (row.id !== thisData.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('Stream could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`Stream could not be updated, IDs do not match: ${row.id} !== ${thisData.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
domain_names: data.domain_names || row.domain_names,
|
.createQuickCertificate(access, {
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
domain_names: thisData.domain_names || row.domain_names,
|
||||||
|
meta: _.assign({}, row.meta, thisData.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
data.certificate_id = cert.id;
|
thisData.certificate_id = cert.id;
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
// Add domain_names to the data in case it isn't there, so that the audit log renders correctly. The order is important here.
|
||||||
data = _.assign({}, {
|
thisData = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
thisData,
|
||||||
|
);
|
||||||
|
|
||||||
return streamModel
|
return streamModel
|
||||||
.query()
|
.query()
|
||||||
.patchAndFetchById(row.id, data)
|
.patchAndFetchById(row.id, thisData)
|
||||||
.then(utils.omitRow(omissions()))
|
.then(utils.omitRow(omissions()))
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'updated',
|
.add(access, {
|
||||||
object_type: 'stream',
|
action: "updated",
|
||||||
|
object_type: "stream",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: thisData,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return saved_row;
|
return saved_row;
|
||||||
@@ -153,13 +159,10 @@ const internalStream = {
|
|||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalStream.get(access, {id: data.id, expand: ['owner', 'certificate']})
|
return internalStream.get(access, { id: thisData.id, expand: ["owner", "certificate"] }).then((row) => {
|
||||||
.then((row) => {
|
return internalNginx.configure(streamModel, "stream", row).then((new_meta) => {
|
||||||
return internalNginx.configure(streamModel, 'stream', row)
|
|
||||||
.then((new_meta) => {
|
|
||||||
row.meta = new_meta;
|
row.meta = new_meta;
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
return _.omit(internalHost.cleanRowCertificateMeta(row), omissions());
|
||||||
return _.omit(row, omissions());
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -174,39 +177,39 @@ const internalStream = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data) => {
|
get: (access, data) => {
|
||||||
if (typeof data === 'undefined') {
|
const thisData = data || {};
|
||||||
data = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return access.can('streams:get', data.id)
|
return access
|
||||||
|
.can("streams:get", thisData.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = streamModel
|
const query = streamModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere("id", thisData.id)
|
||||||
.allowGraph('[owner,certificate]')
|
.allowGraph("[owner,certificate]")
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
|
||||||
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRow(omissions()));
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
let thisRow = row;
|
||||||
throw new error.ItemNotFoundError(data.id);
|
if (!thisRow || !thisRow.id) {
|
||||||
|
throw new errs.ItemNotFoundError(thisData.id);
|
||||||
}
|
}
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
thisRow = internalHost.cleanRowCertificateMeta(thisRow);
|
||||||
// Custom omissions
|
// Custom omissions
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
if (typeof thisData.omit !== "undefined" && thisData.omit !== null) {
|
||||||
row = _.omit(row, data.omit);
|
return _.omit(thisRow, thisData.omit);
|
||||||
}
|
}
|
||||||
return row;
|
return thisRow;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -218,35 +221,35 @@ const internalStream = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('streams:delete', data.id)
|
return access
|
||||||
|
.can("streams:delete", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalStream.get(access, {id: data.id});
|
return internalStream.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return streamModel
|
return streamModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('stream', row)
|
return internalNginx.deleteConfig("stream", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'deleted',
|
action: "deleted",
|
||||||
object_type: 'stream',
|
object_type: "stream",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -263,39 +266,41 @@ const internalStream = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
enable: (access, data) => {
|
enable: (access, data) => {
|
||||||
return access.can('streams:update', data.id)
|
return access
|
||||||
|
.can("streams:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalStream.get(access, {
|
return internalStream.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['certificate', 'owner']
|
expand: ["certificate", "owner"],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Stream is already enabled');
|
if (row.enabled) {
|
||||||
|
throw new errs.ValidationError("Stream is already enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 1;
|
row.enabled = 1;
|
||||||
|
|
||||||
return streamModel
|
return streamModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(streamModel, 'stream', row);
|
return internalNginx.configure(streamModel, "stream", row);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'enabled',
|
action: "enabled",
|
||||||
object_type: 'stream',
|
object_type: "stream",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -312,39 +317,40 @@ const internalStream = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
disable: (access, data) => {
|
disable: (access, data) => {
|
||||||
return access.can('streams:update', data.id)
|
return access
|
||||||
|
.can("streams:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalStream.get(access, {id: data.id});
|
return internalStream.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
} else if (!row.enabled) {
|
}
|
||||||
throw new error.ValidationError('Stream is already disabled');
|
if (!row.enabled) {
|
||||||
|
throw new errs.ValidationError("Stream is already disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
row.enabled = 0;
|
row.enabled = 0;
|
||||||
|
|
||||||
return streamModel
|
return streamModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where("id", row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 0
|
enabled: 0,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Delete Nginx Config
|
// Delete Nginx Config
|
||||||
return internalNginx.deleteConfig('stream', row)
|
return internalNginx.deleteConfig("stream", row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalNginx.reload();
|
return internalNginx.reload();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'disabled',
|
action: "disabled",
|
||||||
object_type: 'stream-host',
|
object_type: "stream-host",
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -362,34 +368,35 @@ const internalStream = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('streams:list')
|
return access
|
||||||
|
.can("streams:list")
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
const query = streamModel
|
const query = streamModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.groupBy('id')
|
.groupBy("id")
|
||||||
.allowGraph('[owner,certificate]')
|
.allowGraph("[owner,certificate]")
|
||||||
.orderBy('incoming_port', 'ASC');
|
.orderBy("incoming_port", "ASC");
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere("owner_user_id", access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string' && search_query.length > 0) {
|
if (typeof search_query === "string" && search_query.length > 0) {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where(castJsonIfNeed('incoming_port'), 'like', `%${search_query}%`);
|
this.where(castJsonIfNeed("incoming_port"), "like", `%${search_query}%`);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched('[' + expand.join(', ') + ']');
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRows(omissions()));
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== "undefined" && expand !== null && expand.indexOf("certificate") !== -1) {
|
||||||
return internalHost.cleanAllRowsCertificateMeta(rows);
|
return internalHost.cleanAllRowsCertificateMeta(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,20 +412,16 @@ const internalStream = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
const query = streamModel
|
const query = streamModel.query().count("id AS count").where("is_deleted", 0);
|
||||||
.query()
|
|
||||||
.count('id AS count')
|
|
||||||
.where('is_deleted', 0);
|
|
||||||
|
|
||||||
if (visibility !== 'all') {
|
if (visibility !== "all") {
|
||||||
query.andWhere('owner_user_id', user_id);
|
query.andWhere("owner_user_id", user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.first()
|
return query.first().then((row) => {
|
||||||
.then((row) => {
|
return Number.parseInt(row.count, 10);
|
||||||
return parseInt(row.count, 10);
|
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalStream;
|
export default internalStream;
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const userModel = require('../models/user');
|
import { parseDatePeriod } from "../lib/helpers.js";
|
||||||
const authModel = require('../models/auth');
|
import authModel from "../models/auth.js";
|
||||||
const helpers = require('../lib/helpers');
|
import TokenModel from "../models/token.js";
|
||||||
const TokenModel = require('../models/token');
|
import userModel from "../models/user.js";
|
||||||
|
|
||||||
const ERROR_MESSAGE_INVALID_AUTH = 'Invalid email or password';
|
const ERROR_MESSAGE_INVALID_AUTH = "Invalid email or password";
|
||||||
|
const ERROR_MESSAGE_INVALID_AUTH_I18N = "error.invalid-auth";
|
||||||
module.exports = {
|
|
||||||
|
|
||||||
|
export default {
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {String} data.identity
|
* @param {String} data.identity
|
||||||
@@ -19,68 +19,65 @@ module.exports = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getTokenFromEmail: (data, issuer) => {
|
getTokenFromEmail: (data, issuer) => {
|
||||||
let Token = new TokenModel();
|
const Token = TokenModel();
|
||||||
|
|
||||||
data.scope = data.scope || 'user';
|
data.scope = data.scope || "user";
|
||||||
data.expiry = data.expiry || '1d';
|
data.expiry = data.expiry || "1d";
|
||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.where('email', data.identity.toLowerCase().trim())
|
.where("email", data.identity.toLowerCase().trim())
|
||||||
.andWhere('is_deleted', 0)
|
.andWhere("is_deleted", 0)
|
||||||
.andWhere('is_disabled', 0)
|
.andWhere("is_disabled", 0)
|
||||||
.first()
|
.first()
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
// Get auth
|
// Get auth
|
||||||
return authModel
|
return authModel
|
||||||
.query()
|
.query()
|
||||||
.where('user_id', '=', user.id)
|
.where("user_id", "=", user.id)
|
||||||
.where('type', '=', 'password')
|
.where("type", "=", "password")
|
||||||
.first()
|
.first()
|
||||||
.then((auth) => {
|
.then((auth) => {
|
||||||
if (auth) {
|
if (auth) {
|
||||||
return auth.verifyPassword(data.secret)
|
return auth.verifyPassword(data.secret).then((valid) => {
|
||||||
.then((valid) => {
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
if (data.scope !== "user" && _.indexOf(user.roles, data.scope) === -1) {
|
||||||
if (data.scope !== 'user' && _.indexOf(user.roles, data.scope) === -1) {
|
|
||||||
// The scope requested doesn't exist as a role against the user,
|
// The scope requested doesn't exist as a role against the user,
|
||||||
// you shall not pass.
|
// you shall not pass.
|
||||||
throw new error.AuthError('Invalid scope: ' + data.scope);
|
throw new errs.AuthError(`Invalid scope: ${data.scope}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a moment of the expiry expression
|
// Create a moment of the expiry expression
|
||||||
let expiry = helpers.parseDatePeriod(data.expiry);
|
const expiry = parseDatePeriod(data.expiry);
|
||||||
if (expiry === null) {
|
if (expiry === null) {
|
||||||
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
|
throw new errs.AuthError(`Invalid expiry time: ${data.expiry}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Token.create({
|
return Token.create({
|
||||||
iss: issuer || 'api',
|
iss: issuer || "api",
|
||||||
attrs: {
|
attrs: {
|
||||||
id: user.id
|
id: user.id,
|
||||||
},
|
},
|
||||||
scope: [data.scope],
|
scope: [data.scope],
|
||||||
expiresIn: data.expiry
|
expiresIn: data.expiry,
|
||||||
})
|
}).then((signed) => {
|
||||||
.then((signed) => {
|
|
||||||
return {
|
return {
|
||||||
token: signed.token,
|
token: signed.token,
|
||||||
expires: expiry.toISOString()
|
expires: expiry.toISOString(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
throw new error.AuthError(ERROR_MESSAGE_INVALID_AUTH);
|
|
||||||
}
|
}
|
||||||
|
throw new errs.AuthError(
|
||||||
|
ERROR_MESSAGE_INVALID_AUTH,
|
||||||
|
ERROR_MESSAGE_INVALID_AUTH_I18N,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
throw new error.AuthError(ERROR_MESSAGE_INVALID_AUTH);
|
|
||||||
}
|
}
|
||||||
|
throw new errs.AuthError(ERROR_MESSAGE_INVALID_AUTH);
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
throw new error.AuthError(ERROR_MESSAGE_INVALID_AUTH);
|
|
||||||
}
|
}
|
||||||
|
throw new errs.AuthError(ERROR_MESSAGE_INVALID_AUTH);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -92,48 +89,45 @@ module.exports = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getFreshToken: (access, data) => {
|
getFreshToken: (access, data) => {
|
||||||
let Token = new TokenModel();
|
const Token = TokenModel();
|
||||||
|
const thisData = data || {};
|
||||||
|
|
||||||
data = data || {};
|
thisData.expiry = thisData.expiry || "1d";
|
||||||
data.expiry = data.expiry || '1d';
|
|
||||||
|
|
||||||
if (access && access.token.getUserId(0)) {
|
|
||||||
|
|
||||||
|
if (access?.token.getUserId(0)) {
|
||||||
// Create a moment of the expiry expression
|
// Create a moment of the expiry expression
|
||||||
let expiry = helpers.parseDatePeriod(data.expiry);
|
const expiry = parseDatePeriod(thisData.expiry);
|
||||||
if (expiry === null) {
|
if (expiry === null) {
|
||||||
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
|
throw new errs.AuthError(`Invalid expiry time: ${thisData.expiry}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let token_attrs = {
|
const token_attrs = {
|
||||||
id: access.token.getUserId(0)
|
id: access.token.getUserId(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only admins can request otherwise scoped tokens
|
// Only admins can request otherwise scoped tokens
|
||||||
let scope = access.token.get('scope');
|
let scope = access.token.get("scope");
|
||||||
if (data.scope && access.token.hasScope('admin')) {
|
if (thisData.scope && access.token.hasScope("admin")) {
|
||||||
scope = [data.scope];
|
scope = [thisData.scope];
|
||||||
|
|
||||||
if (data.scope === 'job-board' || data.scope === 'worker') {
|
if (thisData.scope === "job-board" || thisData.scope === "worker") {
|
||||||
token_attrs.id = 0;
|
token_attrs.id = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Token.create({
|
return Token.create({
|
||||||
iss: 'api',
|
iss: "api",
|
||||||
scope: scope,
|
scope: scope,
|
||||||
attrs: token_attrs,
|
attrs: token_attrs,
|
||||||
expiresIn: data.expiry
|
expiresIn: thisData.expiry,
|
||||||
})
|
}).then((signed) => {
|
||||||
.then((signed) => {
|
|
||||||
return {
|
return {
|
||||||
token: signed.token,
|
token: signed.token,
|
||||||
expires: expiry.toISOString()
|
expires: expiry.toISOString(),
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
throw new error.AssertionFailedError('Existing token contained invalid user data');
|
|
||||||
}
|
}
|
||||||
|
throw new error.AssertionFailedError("Existing token contained invalid user data");
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,24 +135,23 @@ module.exports = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getTokenFromUser: (user) => {
|
getTokenFromUser: (user) => {
|
||||||
const expire = '1d';
|
const expire = "1d";
|
||||||
const Token = new TokenModel();
|
const Token = new TokenModel();
|
||||||
const expiry = helpers.parseDatePeriod(expire);
|
const expiry = parseDatePeriod(expire);
|
||||||
|
|
||||||
return Token.create({
|
return Token.create({
|
||||||
iss: 'api',
|
iss: "api",
|
||||||
attrs: {
|
attrs: {
|
||||||
id: user.id
|
id: user.id,
|
||||||
},
|
},
|
||||||
scope: ['user'],
|
scope: ["user"],
|
||||||
expiresIn: expire
|
expiresIn: expire,
|
||||||
})
|
}).then((signed) => {
|
||||||
.then((signed) => {
|
|
||||||
return {
|
return {
|
||||||
token: signed.token,
|
token: signed.token,
|
||||||
expires: expiry.toISOString(),
|
expires: expiry.toISOString(),
|
||||||
user: user
|
user: user,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,43 +1,41 @@
|
|||||||
const _ = require('lodash');
|
import gravatar from "gravatar";
|
||||||
const error = require('../lib/error');
|
import _ from "lodash";
|
||||||
const utils = require('../lib/utils');
|
import errs from "../lib/error.js";
|
||||||
const userModel = require('../models/user');
|
import utils from "../lib/utils.js";
|
||||||
const userPermissionModel = require('../models/user_permission');
|
import authModel from "../models/auth.js";
|
||||||
const authModel = require('../models/auth');
|
import userModel from "../models/user.js";
|
||||||
const gravatar = require('gravatar');
|
import userPermissionModel from "../models/user_permission.js";
|
||||||
const internalToken = require('./token');
|
import internalAuditLog from "./audit-log.js";
|
||||||
const internalAuditLog = require('./audit-log');
|
import internalToken from "./token.js";
|
||||||
|
|
||||||
function omissions () {
|
const omissions = () => {
|
||||||
return ['is_deleted'];
|
return ["is_deleted"];
|
||||||
}
|
}
|
||||||
|
|
||||||
const internalUser = {
|
const DEFAULT_AVATAR = 'https://gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=200&d=mp&r=g';
|
||||||
|
|
||||||
|
const internalUser = {
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
let auth = data.auth || null;
|
const auth = data.auth || null;
|
||||||
delete data.auth;
|
delete data.auth;
|
||||||
|
|
||||||
data.avatar = data.avatar || '';
|
data.avatar = data.avatar || "";
|
||||||
data.roles = data.roles || [];
|
data.roles = data.roles || [];
|
||||||
|
|
||||||
if (typeof data.is_disabled !== 'undefined') {
|
if (typeof data.is_disabled !== "undefined") {
|
||||||
data.is_disabled = data.is_disabled ? 1 : 0;
|
data.is_disabled = data.is_disabled ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('users:create', data)
|
return access
|
||||||
|
.can("users:create", data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
data.avatar = gravatar.url(data.email, {default: 'mm'});
|
data.avatar = gravatar.url(data.email, { default: "mm" });
|
||||||
|
return userModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
return userModel
|
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (auth) {
|
if (auth) {
|
||||||
@@ -47,42 +45,42 @@ const internalUser = {
|
|||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
type: auth.type,
|
type: auth.type,
|
||||||
secret: auth.secret,
|
secret: auth.secret,
|
||||||
meta: {}
|
meta: {},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return user;
|
return user;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return user;
|
|
||||||
}
|
}
|
||||||
|
return user;
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
// Create permissions row as well
|
// Create permissions row as well
|
||||||
let is_admin = data.roles.indexOf('admin') !== -1;
|
const is_admin = data.roles.indexOf("admin") !== -1;
|
||||||
|
|
||||||
return userPermissionModel
|
return userPermissionModel
|
||||||
.query()
|
.query()
|
||||||
.insert({
|
.insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
visibility: is_admin ? 'all' : 'user',
|
visibility: is_admin ? "all" : "user",
|
||||||
proxy_hosts: 'manage',
|
proxy_hosts: "manage",
|
||||||
redirection_hosts: 'manage',
|
redirection_hosts: "manage",
|
||||||
dead_hosts: 'manage',
|
dead_hosts: "manage",
|
||||||
streams: 'manage',
|
streams: "manage",
|
||||||
access_lists: 'manage',
|
access_lists: "manage",
|
||||||
certificates: 'manage'
|
certificates: "manage",
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: user.id, expand: ['permissions']});
|
return internalUser.get(access, { id: user.id, expand: ["permissions"] });
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'created',
|
.add(access, {
|
||||||
object_type: 'user',
|
action: "created",
|
||||||
|
object_type: "user",
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: user
|
meta: user,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return user;
|
return user;
|
||||||
@@ -99,29 +97,25 @@ const internalUser = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
if (typeof data.is_disabled !== 'undefined') {
|
if (typeof data.is_disabled !== "undefined") {
|
||||||
data.is_disabled = data.is_disabled ? 1 : 0;
|
data.is_disabled = data.is_disabled ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('users:update', data.id)
|
return access
|
||||||
|
.can("users:update", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
||||||
// Make sure that the user being updated doesn't change their email to another user that is already using it
|
// Make sure that the user being updated doesn't change their email to another user that is already using it
|
||||||
// 1. get user we want to update
|
// 1. get user we want to update
|
||||||
return internalUser.get(access, {id: data.id})
|
return internalUser.get(access, { id: data.id }).then((user) => {
|
||||||
.then((user) => {
|
|
||||||
|
|
||||||
// 2. if email is to be changed, find other users with that email
|
// 2. if email is to be changed, find other users with that email
|
||||||
if (typeof data.email !== 'undefined') {
|
if (typeof data.email !== "undefined") {
|
||||||
data.email = data.email.toLowerCase().trim();
|
data.email = data.email.toLowerCase().trim();
|
||||||
|
|
||||||
if (user.email !== data.email) {
|
if (user.email !== data.email) {
|
||||||
return internalUser.isEmailAvailable(data.email, data.id)
|
return internalUser.isEmailAvailable(data.email, data.id).then((available) => {
|
||||||
.then((available) => {
|
|
||||||
if (!available) {
|
if (!available) {
|
||||||
throw new error.ValidationError('Email address already in use - ' + data.email);
|
throw new errs.ValidationError(`Email address already in use - ${data.email}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -134,26 +128,25 @@ const internalUser = {
|
|||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (user.id !== data.id) {
|
if (user.id !== data.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('User could not be updated, IDs do not match: ' + user.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`User could not be updated, IDs do not match: ${user.id} !== ${data.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
data.avatar = gravatar.url(data.email || user.email, {default: 'mm'});
|
data.avatar = gravatar.url(data.email || user.email, { default: "mm" });
|
||||||
|
return userModel.query().patchAndFetchById(user.id, data).then(utils.omitRow(omissions()));
|
||||||
return userModel
|
|
||||||
.query()
|
|
||||||
.patchAndFetchById(user.id, data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: data.id});
|
return internalUser.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
action: 'updated',
|
.add(access, {
|
||||||
object_type: 'user',
|
action: "updated",
|
||||||
|
object_type: "user",
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return user;
|
return user;
|
||||||
@@ -170,37 +163,41 @@ const internalUser = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
get: (access, data) => {
|
get: (access, data) => {
|
||||||
if (typeof data === 'undefined') {
|
const thisData = data || {};
|
||||||
data = {};
|
|
||||||
|
if (typeof thisData.id === "undefined" || !thisData.id) {
|
||||||
|
thisData.id = access.token.getUserId(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.id === 'undefined' || !data.id) {
|
return access
|
||||||
data.id = access.token.getUserId(0);
|
.can("users:get", thisData.id)
|
||||||
}
|
|
||||||
|
|
||||||
return access.can('users:get', data.id)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let query = userModel
|
const query = userModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere("id", thisData.id)
|
||||||
.allowGraph('[permissions]')
|
.allowGraph("[permissions]")
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof thisData.expand !== "undefined" && thisData.expand !== null) {
|
||||||
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched(`[${thisData.expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRow(omissions()));
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(thisData.id);
|
||||||
}
|
}
|
||||||
// Custom omissions
|
// Custom omissions
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
if (typeof thisData.omit !== "undefined" && thisData.omit !== null) {
|
||||||
row = _.omit(row, data.omit);
|
return _.omit(row, thisData.omit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (row.avatar === "") {
|
||||||
|
row.avatar = DEFAULT_AVATAR;
|
||||||
|
}
|
||||||
|
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -213,18 +210,13 @@ const internalUser = {
|
|||||||
* @param user_id
|
* @param user_id
|
||||||
*/
|
*/
|
||||||
isEmailAvailable: (email, user_id) => {
|
isEmailAvailable: (email, user_id) => {
|
||||||
let query = userModel
|
const query = userModel.query().where("email", "=", email.toLowerCase().trim()).where("is_deleted", 0).first();
|
||||||
.query()
|
|
||||||
.where('email', '=', email.toLowerCase().trim())
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.first();
|
|
||||||
|
|
||||||
if (typeof user_id !== 'undefined') {
|
if (typeof user_id !== "undefined") {
|
||||||
query.where('id', '!=', user_id);
|
query.where("id", "!=", user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query
|
return query.then((user) => {
|
||||||
.then((user) => {
|
|
||||||
return !user;
|
return !user;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -237,33 +229,34 @@ const internalUser = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('users:delete', data.id)
|
return access
|
||||||
|
.can("users:delete", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: data.id});
|
return internalUser.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new errs.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure user can't delete themselves
|
// Make sure user can't delete themselves
|
||||||
if (user.id === access.token.getUserId(0)) {
|
if (user.id === access.token.getUserId(0)) {
|
||||||
throw new error.PermissionError('You cannot delete yourself.');
|
throw new errs.PermissionError("You cannot delete yourself.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', user.id)
|
.where("id", user.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'deleted',
|
action: "deleted",
|
||||||
object_type: 'user',
|
object_type: "user",
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: _.omit(user, omissions())
|
meta: _.omit(user, omissions()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -280,26 +273,26 @@ const internalUser = {
|
|||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
getCount: (access, search_query) => {
|
getCount: (access, search_query) => {
|
||||||
return access.can('users:list')
|
return access
|
||||||
|
.can("users:list")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let query = userModel
|
const query = userModel.query().count("id as count").where("is_deleted", 0).first();
|
||||||
.query()
|
|
||||||
.count('id as count')
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.first();
|
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string') {
|
if (typeof search_query === "string") {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where('user.name', 'like', '%' + search_query + '%')
|
this.where("user.name", "like", `%${search_query}%`).orWhere(
|
||||||
.orWhere('user.email', 'like', '%' + search_query + '%');
|
"user.email",
|
||||||
|
"like",
|
||||||
|
`%${search_query}%`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
return parseInt(row.count, 10);
|
return Number.parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -311,30 +304,32 @@ const internalUser = {
|
|||||||
* @param {String} [search_query]
|
* @param {String} [search_query]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: async (access, expand, search_query) => {
|
||||||
return access.can('users:list')
|
await access.can("users:list");
|
||||||
.then(() => {
|
const query = userModel
|
||||||
let query = userModel
|
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.groupBy('id')
|
.groupBy("id")
|
||||||
.allowGraph('[permissions]')
|
.allowGraph("[permissions]")
|
||||||
.orderBy('name', 'ASC');
|
.orderBy("name", "ASC");
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string') {
|
if (typeof search_query === "string") {
|
||||||
query.where(function () {
|
query.where(function () {
|
||||||
this.where('name', 'like', '%' + search_query + '%')
|
this.where("name", "like", `%${search_query}%`).orWhere(
|
||||||
.orWhere('email', 'like', '%' + search_query + '%');
|
"email",
|
||||||
|
"like",
|
||||||
|
`%${search_query}%`,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== "undefined" && expand !== null) {
|
||||||
query.withGraphFetched('[' + expand.join(', ') + ']');
|
query.withGraphFetched(`[${expand.join(", ")}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return query.then(utils.omitRows(omissions()));
|
const res = await query;
|
||||||
});
|
return utils.omitRows(omissions())(res);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -345,8 +340,8 @@ const internalUser = {
|
|||||||
getUserOmisionsByAccess: (access, id_requested) => {
|
getUserOmisionsByAccess: (access, id_requested) => {
|
||||||
let response = []; // Admin response
|
let response = []; // Admin response
|
||||||
|
|
||||||
if (!access.token.hasScope('admin') && access.token.getUserId(0) !== id_requested) {
|
if (!access.token.hasScope("admin") && access.token.getUserId(0) !== id_requested) {
|
||||||
response = ['roles', 'is_deleted']; // Restricted response
|
response = ["roles", "is_deleted"]; // Restricted response
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
@@ -361,25 +356,29 @@ const internalUser = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
setPassword: (access, data) => {
|
setPassword: (access, data) => {
|
||||||
return access.can('users:password', data.id)
|
return access
|
||||||
|
.can("users:password", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: data.id});
|
return internalUser.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (user.id !== data.id) {
|
if (user.id !== data.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('User could not be updated, IDs do not match: ' + user.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`User could not be updated, IDs do not match: ${user.id} !== ${data.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user.id === access.token.getUserId(0)) {
|
if (user.id === access.token.getUserId(0)) {
|
||||||
// they're setting their own password. Make sure their current password is correct
|
// they're setting their own password. Make sure their current password is correct
|
||||||
if (typeof data.current === 'undefined' || !data.current) {
|
if (typeof data.current === "undefined" || !data.current) {
|
||||||
throw new error.ValidationError('Current password was not supplied');
|
throw new errs.ValidationError("Current password was not supplied");
|
||||||
}
|
}
|
||||||
|
|
||||||
return internalToken.getTokenFromEmail({
|
return internalToken
|
||||||
|
.getTokenFromEmail({
|
||||||
identity: user.email,
|
identity: user.email,
|
||||||
secret: data.current
|
secret: data.current,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return user;
|
return user;
|
||||||
@@ -392,43 +391,36 @@ const internalUser = {
|
|||||||
// Get auth, patch if it exists
|
// Get auth, patch if it exists
|
||||||
return authModel
|
return authModel
|
||||||
.query()
|
.query()
|
||||||
.where('user_id', user.id)
|
.where("user_id", user.id)
|
||||||
.andWhere('type', data.type)
|
.andWhere("type", data.type)
|
||||||
.first()
|
.first()
|
||||||
.then((existing_auth) => {
|
.then((existing_auth) => {
|
||||||
if (existing_auth) {
|
if (existing_auth) {
|
||||||
// patch
|
// patch
|
||||||
return authModel
|
return authModel.query().where("user_id", user.id).andWhere("type", data.type).patch({
|
||||||
.query()
|
|
||||||
.where('user_id', user.id)
|
|
||||||
.andWhere('type', data.type)
|
|
||||||
.patch({
|
|
||||||
type: data.type, // This is required for the model to encrypt on save
|
type: data.type, // This is required for the model to encrypt on save
|
||||||
secret: data.secret
|
secret: data.secret,
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
// insert
|
// insert
|
||||||
return authModel
|
return authModel.query().insert({
|
||||||
.query()
|
|
||||||
.insert({
|
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
type: data.type,
|
type: data.type,
|
||||||
secret: data.secret,
|
secret: data.secret,
|
||||||
meta: {}
|
meta: {},
|
||||||
});
|
});
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to Audit Log
|
// Add to Audit Log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'updated',
|
action: "updated",
|
||||||
object_type: 'user',
|
object_type: "user",
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: {
|
meta: {
|
||||||
name: user.name,
|
name: user.name,
|
||||||
password_changed: true,
|
password_changed: true,
|
||||||
auth_type: data.type
|
auth_type: data.type,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@@ -443,14 +435,17 @@ const internalUser = {
|
|||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
setPermissions: (access, data) => {
|
setPermissions: (access, data) => {
|
||||||
return access.can('users:permissions', data.id)
|
return access
|
||||||
|
.can("users:permissions", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: data.id});
|
return internalUser.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (user.id !== data.id) {
|
if (user.id !== data.id) {
|
||||||
// Sanity check that something crazy hasn't happened
|
// Sanity check that something crazy hasn't happened
|
||||||
throw new error.InternalValidationError('User could not be updated, IDs do not match: ' + user.id + ' !== ' + data.id);
|
throw new errs.InternalValidationError(
|
||||||
|
`User could not be updated, IDs do not match: ${user.id} !== ${data.id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
@@ -459,34 +454,30 @@ const internalUser = {
|
|||||||
// Get perms row, patch if it exists
|
// Get perms row, patch if it exists
|
||||||
return userPermissionModel
|
return userPermissionModel
|
||||||
.query()
|
.query()
|
||||||
.where('user_id', user.id)
|
.where("user_id", user.id)
|
||||||
.first()
|
.first()
|
||||||
.then((existing_auth) => {
|
.then((existing_auth) => {
|
||||||
if (existing_auth) {
|
if (existing_auth) {
|
||||||
// patch
|
// patch
|
||||||
return userPermissionModel
|
return userPermissionModel
|
||||||
.query()
|
.query()
|
||||||
.where('user_id', user.id)
|
.where("user_id", user.id)
|
||||||
.patchAndFetchById(existing_auth.id, _.assign({user_id: user.id}, data));
|
.patchAndFetchById(existing_auth.id, _.assign({ user_id: user.id }, data));
|
||||||
} else {
|
|
||||||
// insert
|
|
||||||
return userPermissionModel
|
|
||||||
.query()
|
|
||||||
.insertAndFetch(_.assign({user_id: user.id}, data));
|
|
||||||
}
|
}
|
||||||
|
// insert
|
||||||
|
return userPermissionModel.query().insertAndFetch(_.assign({ user_id: user.id }, data));
|
||||||
})
|
})
|
||||||
.then((permissions) => {
|
.then((permissions) => {
|
||||||
// Add to Audit Log
|
// Add to Audit Log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog.add(access, {
|
||||||
action: 'updated',
|
action: "updated",
|
||||||
object_type: 'user',
|
object_type: "user",
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: {
|
meta: {
|
||||||
name: user.name,
|
name: user.name,
|
||||||
permissions: permissions
|
permissions: permissions,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@@ -500,14 +491,15 @@ const internalUser = {
|
|||||||
* @param {Integer} data.id
|
* @param {Integer} data.id
|
||||||
*/
|
*/
|
||||||
loginAs: (access, data) => {
|
loginAs: (access, data) => {
|
||||||
return access.can('users:loginas', data.id)
|
return access
|
||||||
|
.can("users:loginas", data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, data);
|
return internalUser.get(access, data);
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
return internalToken.getTokenFromUser(user);
|
return internalToken.getTokenFromUser(user);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalUser;
|
export default internalUser;
|
||||||
|
|||||||
@@ -4,25 +4,29 @@
|
|||||||
* "scope" in this file means "where did this token come from and what is using it", so 99% of the time
|
* "scope" in this file means "where did this token come from and what is using it", so 99% of the time
|
||||||
* the "scope" is going to be "user" because it would be a user token. This is not to be confused with
|
* the "scope" is going to be "user" because it would be a user token. This is not to be confused with
|
||||||
* the "role" which could be "user" or "admin". The scope in fact, could be "worker" or anything else.
|
* the "role" which could be "user" or "admin". The scope in fact, could be "worker" or anything else.
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const _ = require('lodash');
|
import fs from "node:fs";
|
||||||
const logger = require('../logger').access;
|
import { dirname } from "node:path";
|
||||||
const Ajv = require('ajv/dist/2020');
|
import { fileURLToPath } from "node:url";
|
||||||
const error = require('./error');
|
import Ajv from "ajv/dist/2020.js";
|
||||||
const userModel = require('../models/user');
|
import _ from "lodash";
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
import { access as logger } from "../logger.js";
|
||||||
const TokenModel = require('../models/token');
|
import proxyHostModel from "../models/proxy_host.js";
|
||||||
const roleSchema = require('./access/roles.json');
|
import TokenModel from "../models/token.js";
|
||||||
const permsSchema = require('./access/permissions.json');
|
import userModel from "../models/user.js";
|
||||||
|
import permsSchema from "./access/permissions.json" with { type: "json" };
|
||||||
|
import roleSchema from "./access/roles.json" with { type: "json" };
|
||||||
|
import errs from "./error.js";
|
||||||
|
|
||||||
module.exports = function (token_string) {
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
let Token = new TokenModel();
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
|
export default function (token_string) {
|
||||||
|
const Token = TokenModel();
|
||||||
let token_data = null;
|
let token_data = null;
|
||||||
let initialised = false;
|
let initialised = false;
|
||||||
let object_cache = {};
|
const object_cache = {};
|
||||||
let allow_internal_access = false;
|
let allow_internal_access = false;
|
||||||
let user_roles = [];
|
let user_roles = [];
|
||||||
let permissions = {};
|
let permissions = {};
|
||||||
@@ -37,10 +41,10 @@ module.exports = function (token_string) {
|
|||||||
if (initialised) {
|
if (initialised) {
|
||||||
resolve();
|
resolve();
|
||||||
} else if (!token_string) {
|
} else if (!token_string) {
|
||||||
reject(new error.PermissionError('Permission Denied'));
|
reject(new errs.PermissionError("Permission Denied"));
|
||||||
} else {
|
} else {
|
||||||
resolve(Token.load(token_string)
|
resolve(
|
||||||
.then((data) => {
|
Token.load(token_string).then((data) => {
|
||||||
token_data = data;
|
token_data = data;
|
||||||
|
|
||||||
// At this point we need to load the user from the DB and make sure they:
|
// At this point we need to load the user from the DB and make sure they:
|
||||||
@@ -48,21 +52,25 @@ module.exports = function (token_string) {
|
|||||||
// - still have the appropriate scopes for this token
|
// - still have the appropriate scopes for this token
|
||||||
// This is only required when the User ID is supplied or if the token scope has `user`
|
// This is only required when the User ID is supplied or if the token scope has `user`
|
||||||
|
|
||||||
if (token_data.attrs.id || (typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, 'user') !== -1)) {
|
if (
|
||||||
|
token_data.attrs.id ||
|
||||||
|
(typeof token_data.scope !== "undefined" &&
|
||||||
|
_.indexOf(token_data.scope, "user") !== -1)
|
||||||
|
) {
|
||||||
// Has token user id or token user scope
|
// Has token user id or token user scope
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', token_data.attrs.id)
|
.where("id", token_data.attrs.id)
|
||||||
.andWhere('is_deleted', 0)
|
.andWhere("is_deleted", 0)
|
||||||
.andWhere('is_disabled', 0)
|
.andWhere("is_disabled", 0)
|
||||||
.allowGraph('[permissions]')
|
.allowGraph("[permissions]")
|
||||||
.withGraphFetched('[permissions]')
|
.withGraphFetched("[permissions]")
|
||||||
.first()
|
.first()
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
// make sure user has all scopes of the token
|
// make sure user has all scopes of the token
|
||||||
// The `user` role is not added against the user row, so we have to just add it here to get past this check.
|
// The `user` role is not added against the user row, so we have to just add it here to get past this check.
|
||||||
user.roles.push('user');
|
user.roles.push("user");
|
||||||
|
|
||||||
let is_ok = true;
|
let is_ok = true;
|
||||||
_.forEach(token_data.scope, (scope_item) => {
|
_.forEach(token_data.scope, (scope_item) => {
|
||||||
@@ -72,21 +80,19 @@ module.exports = function (token_string) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!is_ok) {
|
if (!is_ok) {
|
||||||
throw new error.AuthError('Invalid token scope for User');
|
throw new errs.AuthError("Invalid token scope for User");
|
||||||
} else {
|
}
|
||||||
initialised = true;
|
initialised = true;
|
||||||
user_roles = user.roles;
|
user_roles = user.roles;
|
||||||
permissions = user.permissions;
|
permissions = user.permissions;
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new error.AuthError('User cannot be loaded for Token');
|
throw new errs.AuthError("User cannot be loaded for Token");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
initialised = true;
|
|
||||||
}
|
}
|
||||||
}));
|
initialised = true;
|
||||||
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -101,35 +107,37 @@ module.exports = function (token_string) {
|
|||||||
*/
|
*/
|
||||||
this.loadObjects = (object_type) => {
|
this.loadObjects = (object_type) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (Token.hasScope('user')) {
|
if (Token.hasScope("user")) {
|
||||||
if (typeof token_data.attrs.id === 'undefined' || !token_data.attrs.id) {
|
if (
|
||||||
reject(new error.AuthError('User Token supplied without a User ID'));
|
typeof token_data.attrs.id === "undefined" ||
|
||||||
|
!token_data.attrs.id
|
||||||
|
) {
|
||||||
|
reject(new errs.AuthError("User Token supplied without a User ID"));
|
||||||
} else {
|
} else {
|
||||||
let token_user_id = token_data.attrs.id ? token_data.attrs.id : 0;
|
const token_user_id = token_data.attrs.id ? token_data.attrs.id : 0;
|
||||||
let query;
|
let query;
|
||||||
|
|
||||||
if (typeof object_cache[object_type] === 'undefined') {
|
if (typeof object_cache[object_type] === "undefined") {
|
||||||
switch (object_type) {
|
switch (object_type) {
|
||||||
|
|
||||||
// USERS - should only return yourself
|
// USERS - should only return yourself
|
||||||
case 'users':
|
case "users":
|
||||||
resolve(token_user_id ? [token_user_id] : []);
|
resolve(token_user_id ? [token_user_id] : []);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Proxy Hosts
|
// Proxy Hosts
|
||||||
case 'proxy_hosts':
|
case "proxy_hosts":
|
||||||
query = proxyHostModel
|
query = proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.select('id')
|
.select("id")
|
||||||
.andWhere('is_deleted', 0);
|
.andWhere("is_deleted", 0);
|
||||||
|
|
||||||
if (permissions.visibility === 'user') {
|
if (permissions.visibility === "user") {
|
||||||
query.andWhere('owner_user_id', token_user_id);
|
query.andWhere("owner_user_id", token_user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(query
|
resolve(
|
||||||
.then((rows) => {
|
query.then((rows) => {
|
||||||
let result = [];
|
const result = [];
|
||||||
_.forEach(rows, (rule_row) => {
|
_.forEach(rows, (rule_row) => {
|
||||||
result.push(rule_row.id);
|
result.push(rule_row.id);
|
||||||
});
|
});
|
||||||
@@ -140,7 +148,7 @@ module.exports = function (token_string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -156,8 +164,7 @@ module.exports = function (token_string) {
|
|||||||
} else {
|
} else {
|
||||||
resolve(null);
|
resolve(null);
|
||||||
}
|
}
|
||||||
})
|
}).then((objects) => {
|
||||||
.then((objects) => {
|
|
||||||
object_cache[object_type] = objects;
|
object_cache[object_type] = objects;
|
||||||
return objects;
|
return objects;
|
||||||
});
|
});
|
||||||
@@ -170,41 +177,40 @@ module.exports = function (token_string) {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
this.getObjectSchema = (permission_label) => {
|
this.getObjectSchema = (permission_label) => {
|
||||||
let base_object_type = permission_label.split(':').shift();
|
const base_object_type = permission_label.split(":").shift();
|
||||||
|
|
||||||
let schema = {
|
const schema = {
|
||||||
$id: 'objects',
|
$id: "objects",
|
||||||
description: 'Actor Properties',
|
description: "Actor Properties",
|
||||||
type: 'object',
|
type: "object",
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
user_id: {
|
user_id: {
|
||||||
anyOf: [
|
anyOf: [
|
||||||
{
|
{
|
||||||
type: 'number',
|
type: "number",
|
||||||
enum: [Token.get('attrs').id]
|
enum: [Token.get("attrs").id],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
scope: {
|
scope: {
|
||||||
type: 'string',
|
type: "string",
|
||||||
pattern: '^' + Token.get('scope') + '$'
|
pattern: `^${Token.get("scope")}$`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return this.loadObjects(base_object_type)
|
return this.loadObjects(base_object_type).then((object_result) => {
|
||||||
.then((object_result) => {
|
if (typeof object_result === "object" && object_result !== null) {
|
||||||
if (typeof object_result === 'object' && object_result !== null) {
|
|
||||||
schema.properties[base_object_type] = {
|
schema.properties[base_object_type] = {
|
||||||
type: 'number',
|
type: "number",
|
||||||
enum: object_result,
|
enum: object_result,
|
||||||
minimum: 1
|
minimum: 1,
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
schema.properties[base_object_type] = {
|
schema.properties[base_object_type] = {
|
||||||
type: 'number',
|
type: "number",
|
||||||
minimum: 1
|
minimum: 1,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +219,6 @@ module.exports = function (token_string) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
token: Token,
|
token: Token,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -222,7 +227,7 @@ module.exports = function (token_string) {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
load: (allow_internal) => {
|
load: (allow_internal) => {
|
||||||
return new Promise(function (resolve/*, reject*/) {
|
return new Promise((resolve /*, reject*/) => {
|
||||||
if (token_string) {
|
if (token_string) {
|
||||||
resolve(Token.load(token_string));
|
resolve(Token.load(token_string));
|
||||||
} else {
|
} else {
|
||||||
@@ -240,20 +245,19 @@ module.exports = function (token_string) {
|
|||||||
* @param {*} [data]
|
* @param {*} [data]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
can: (permission, data) => {
|
can: async (permission, data) => {
|
||||||
if (allow_internal_access === true) {
|
if (allow_internal_access === true) {
|
||||||
return Promise.resolve(true);
|
return true;
|
||||||
//return true;
|
}
|
||||||
} else {
|
|
||||||
return this.init()
|
try {
|
||||||
.then(() => {
|
await this.init();
|
||||||
// Initialised, token decoded ok
|
const objectSchema = await this.getObjectSchema(permission);
|
||||||
return this.getObjectSchema(permission)
|
|
||||||
.then((objectSchema) => {
|
const dataSchema = {
|
||||||
const data_schema = {
|
|
||||||
[permission]: {
|
[permission]: {
|
||||||
data: data,
|
data: data,
|
||||||
scope: Token.get('scope'),
|
scope: Token.get("scope"),
|
||||||
roles: user_roles,
|
roles: user_roles,
|
||||||
permission_visibility: permissions.visibility,
|
permission_visibility: permissions.visibility,
|
||||||
permission_proxy_hosts: permissions.proxy_hosts,
|
permission_proxy_hosts: permissions.proxy_hosts,
|
||||||
@@ -261,47 +265,40 @@ module.exports = function (token_string) {
|
|||||||
permission_dead_hosts: permissions.dead_hosts,
|
permission_dead_hosts: permissions.dead_hosts,
|
||||||
permission_streams: permissions.streams,
|
permission_streams: permissions.streams,
|
||||||
permission_access_lists: permissions.access_lists,
|
permission_access_lists: permissions.access_lists,
|
||||||
permission_certificates: permissions.certificates
|
permission_certificates: permissions.certificates,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let permissionSchema = {
|
const permissionSchema = {
|
||||||
$async: true,
|
$async: true,
|
||||||
$id: 'permissions',
|
$id: "permissions",
|
||||||
type: 'object',
|
type: "object",
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {}
|
properties: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json');
|
const rawData = fs.readFileSync(
|
||||||
|
`${__dirname}/access/${permission.replace(/:/gim, "-")}.json`,
|
||||||
|
{ encoding: "utf8" },
|
||||||
|
);
|
||||||
|
permissionSchema.properties[permission] = JSON.parse(rawData);
|
||||||
|
|
||||||
const ajv = new Ajv({
|
const ajv = new Ajv({
|
||||||
verbose: true,
|
verbose: true,
|
||||||
allErrors: true,
|
allErrors: true,
|
||||||
breakOnError: true,
|
breakOnError: true,
|
||||||
coerceTypes: true,
|
coerceTypes: true,
|
||||||
schemas: [
|
schemas: [roleSchema, permsSchema, objectSchema, permissionSchema],
|
||||||
roleSchema,
|
|
||||||
permsSchema,
|
|
||||||
objectSchema,
|
|
||||||
permissionSchema
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return ajv.validate('permissions', data_schema)
|
const valid = ajv.validate("permissions", dataSchema);
|
||||||
.then(() => {
|
return valid && dataSchema[permission];
|
||||||
return data_schema[permission];
|
} catch (err) {
|
||||||
});
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
err.permission = permission;
|
err.permission = permission;
|
||||||
err.permission_data = data;
|
err.permission_data = data;
|
||||||
logger.error(permission, data, err.message);
|
logger.error(permission, data, err.message);
|
||||||
|
throw errs.PermissionError("Permission Denied", err);
|
||||||
throw new error.PermissionError('Permission Denied', err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
import batchflow from "batchflow";
|
||||||
const utils = require('./utils');
|
import dnsPlugins from "../global/certbot-dns-plugins.json" with { type: "json" };
|
||||||
const error = require('./error');
|
import { certbot as logger } from "../logger.js";
|
||||||
const logger = require('../logger').certbot;
|
import errs from "./error.js";
|
||||||
const batchflow = require('batchflow');
|
import utils from "./utils.js";
|
||||||
|
|
||||||
const CERTBOT_VERSION_REPLACEMENT = '$(certbot --version | grep -Eo \'[0-9](\\.[0-9]+)+\')';
|
const CERTBOT_VERSION_REPLACEMENT = "$(certbot --version | grep -Eo '[0-9](\\.[0-9]+)+')";
|
||||||
|
|
||||||
const certbot = {
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {array} pluginKeys
|
* @param {array} pluginKeys
|
||||||
*/
|
*/
|
||||||
installPlugins: async (pluginKeys) => {
|
const installPlugins = async (pluginKeys) => {
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@@ -20,9 +18,11 @@ const certbot = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
batchflow(pluginKeys).sequential()
|
batchflow(pluginKeys)
|
||||||
|
.sequential()
|
||||||
.each((_i, pluginKey, next) => {
|
.each((_i, pluginKey, next) => {
|
||||||
certbot.installPlugin(pluginKey)
|
certbot
|
||||||
|
.installPlugin(pluginKey)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
@@ -36,25 +36,27 @@ const certbot = {
|
|||||||
})
|
})
|
||||||
.end(() => {
|
.end(() => {
|
||||||
if (hasErrors) {
|
if (hasErrors) {
|
||||||
reject(new error.CommandError('Some plugins failed to install. Please check the logs above', 1));
|
reject(
|
||||||
|
new errs.CommandError("Some plugins failed to install. Please check the logs above", 1),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Installs a cerbot plugin given the key for the object from
|
* Installs a cerbot plugin given the key for the object from
|
||||||
* ../global/certbot-dns-plugins.json
|
* ../global/certbot-dns-plugins.json
|
||||||
*
|
*
|
||||||
* @param {string} pluginKey
|
* @param {string} pluginKey
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
installPlugin: async (pluginKey) => {
|
const installPlugin = async (pluginKey) => {
|
||||||
if (typeof dnsPlugins[pluginKey] === 'undefined') {
|
if (typeof dnsPlugins[pluginKey] === "undefined") {
|
||||||
// throw Error(`Certbot plugin ${pluginKey} not found`);
|
// throw Error(`Certbot plugin ${pluginKey} not found`);
|
||||||
throw new error.ItemNotFoundError(pluginKey);
|
throw new errs.ItemNotFoundError(pluginKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugin = dnsPlugins[pluginKey];
|
const plugin = dnsPlugins[pluginKey];
|
||||||
@@ -65,13 +67,14 @@ const certbot = {
|
|||||||
|
|
||||||
// SETUPTOOLS_USE_DISTUTILS is required for certbot plugins to install correctly
|
// SETUPTOOLS_USE_DISTUTILS is required for certbot plugins to install correctly
|
||||||
// in new versions of Python
|
// in new versions of Python
|
||||||
let env = Object.assign({}, process.env, {SETUPTOOLS_USE_DISTUTILS: 'stdlib'});
|
let env = Object.assign({}, process.env, { SETUPTOOLS_USE_DISTUTILS: "stdlib" });
|
||||||
if (typeof plugin.env === 'object') {
|
if (typeof plugin.env === "object") {
|
||||||
env = Object.assign(env, plugin.env);
|
env = Object.assign(env, plugin.env);
|
||||||
}
|
}
|
||||||
|
|
||||||
const cmd = `. /opt/certbot/bin/activate && pip install --no-cache-dir ${plugin.dependencies} ${plugin.package_name}${plugin.version} && deactivate`;
|
const cmd = `. /opt/certbot/bin/activate && pip install --no-cache-dir ${plugin.dependencies} ${plugin.package_name}${plugin.version} && deactivate`;
|
||||||
return utils.exec(cmd, {env})
|
return utils
|
||||||
|
.exec(cmd, { env })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
logger.complete(`Installed ${pluginKey}`);
|
logger.complete(`Installed ${pluginKey}`);
|
||||||
return result;
|
return result;
|
||||||
@@ -79,7 +82,6 @@ const certbot = {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = certbot;
|
export { installPlugins, installPlugin };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const fs = require('fs');
|
import fs from "node:fs";
|
||||||
const NodeRSA = require('node-rsa');
|
import NodeRSA from "node-rsa";
|
||||||
const logger = require('../logger').global;
|
import { global as logger } from "../logger.js";
|
||||||
|
|
||||||
const keysFile = '/data/keys.json';
|
const keysFile = '/data/keys.json';
|
||||||
const mysqlEngine = 'mysql2';
|
const mysqlEngine = 'mysql2';
|
||||||
@@ -12,16 +12,18 @@ let instance = null;
|
|||||||
// 1. Load from config file first (not recommended anymore)
|
// 1. Load from config file first (not recommended anymore)
|
||||||
// 2. Use config env variables next
|
// 2. Use config env variables next
|
||||||
const configure = () => {
|
const configure = () => {
|
||||||
const filename = (process.env.NODE_CONFIG_DIR || './config') + '/' + (process.env.NODE_ENV || 'default') + '.json';
|
const filename = `${process.env.NODE_CONFIG_DIR || "./config"}/${process.env.NODE_ENV || "default"}.json`;
|
||||||
if (fs.existsSync(filename)) {
|
if (fs.existsSync(filename)) {
|
||||||
let configData;
|
let configData;
|
||||||
try {
|
try {
|
||||||
configData = require(filename);
|
// Load this json synchronously
|
||||||
|
const rawData = fs.readFileSync(filename);
|
||||||
|
configData = JSON.parse(rawData);
|
||||||
} catch (_) {
|
} catch (_) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configData && configData.database) {
|
if (configData?.database) {
|
||||||
logger.info(`Using configuration from file: ${filename}`);
|
logger.info(`Using configuration from file: ${filename}`);
|
||||||
instance = configData;
|
instance = configData;
|
||||||
instance.keys = getKeys();
|
instance.keys = getKeys();
|
||||||
@@ -34,7 +36,7 @@ const configure = () => {
|
|||||||
const envMysqlName = process.env.DB_MYSQL_NAME || null;
|
const envMysqlName = process.env.DB_MYSQL_NAME || null;
|
||||||
if (envMysqlHost && envMysqlUser && envMysqlName) {
|
if (envMysqlHost && envMysqlUser && envMysqlName) {
|
||||||
// we have enough mysql creds to go with mysql
|
// we have enough mysql creds to go with mysql
|
||||||
logger.info('Using MySQL configuration');
|
logger.info("Using MySQL configuration");
|
||||||
instance = {
|
instance = {
|
||||||
database: {
|
database: {
|
||||||
engine: mysqlEngine,
|
engine: mysqlEngine,
|
||||||
@@ -54,7 +56,7 @@ const configure = () => {
|
|||||||
const envPostgresName = process.env.DB_POSTGRES_NAME || null;
|
const envPostgresName = process.env.DB_POSTGRES_NAME || null;
|
||||||
if (envPostgresHost && envPostgresUser && envPostgresName) {
|
if (envPostgresHost && envPostgresUser && envPostgresName) {
|
||||||
// we have enough postgres creds to go with postgres
|
// we have enough postgres creds to go with postgres
|
||||||
logger.info('Using Postgres configuration');
|
logger.info("Using Postgres configuration");
|
||||||
instance = {
|
instance = {
|
||||||
database: {
|
database: {
|
||||||
engine: postgresEngine,
|
engine: postgresEngine,
|
||||||
@@ -69,18 +71,18 @@ const configure = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const envSqliteFile = process.env.DB_SQLITE_FILE || '/data/database.sqlite';
|
const envSqliteFile = process.env.DB_SQLITE_FILE || "/data/database.sqlite";
|
||||||
logger.info(`Using Sqlite: ${envSqliteFile}`);
|
logger.info(`Using Sqlite: ${envSqliteFile}`);
|
||||||
instance = {
|
instance = {
|
||||||
database: {
|
database: {
|
||||||
engine: 'knex-native',
|
engine: "knex-native",
|
||||||
knex: {
|
knex: {
|
||||||
client: sqliteClientName,
|
client: sqliteClientName,
|
||||||
connection: {
|
connection: {
|
||||||
filename: envSqliteFile
|
filename: envSqliteFile,
|
||||||
|
},
|
||||||
|
useNullAsDefault: true,
|
||||||
},
|
},
|
||||||
useNullAsDefault: true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
keys: getKeys(),
|
keys: getKeys(),
|
||||||
};
|
};
|
||||||
@@ -88,54 +90,55 @@ const configure = () => {
|
|||||||
|
|
||||||
const getKeys = () => {
|
const getKeys = () => {
|
||||||
// Get keys from file
|
// Get keys from file
|
||||||
|
logger.debug("Cheecking for keys file:", keysFile);
|
||||||
if (!fs.existsSync(keysFile)) {
|
if (!fs.existsSync(keysFile)) {
|
||||||
generateKeys();
|
generateKeys();
|
||||||
} else if (process.env.DEBUG) {
|
} else if (process.env.DEBUG) {
|
||||||
logger.info('Keys file exists OK');
|
logger.info("Keys file exists OK");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return require(keysFile);
|
// Load this json keysFile synchronously and return the json object
|
||||||
|
const rawData = fs.readFileSync(keysFile);
|
||||||
|
return JSON.parse(rawData);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Could not read JWT key pair from config file: ' + keysFile, err);
|
logger.error(`Could not read JWT key pair from config file: ${keysFile}`, err);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const generateKeys = () => {
|
const generateKeys = () => {
|
||||||
logger.info('Creating a new JWT key pair...');
|
logger.info("Creating a new JWT key pair...");
|
||||||
// Now create the keys and save them in the config.
|
// Now create the keys and save them in the config.
|
||||||
const key = new NodeRSA({ b: 2048 });
|
const key = new NodeRSA({ b: 2048 });
|
||||||
key.generateKeyPair();
|
key.generateKeyPair();
|
||||||
|
|
||||||
const keys = {
|
const keys = {
|
||||||
key: key.exportKey('private').toString(),
|
key: key.exportKey("private").toString(),
|
||||||
pub: key.exportKey('public').toString(),
|
pub: key.exportKey("public").toString(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Write keys config
|
// Write keys config
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2));
|
fs.writeFileSync(keysFile, JSON.stringify(keys, null, 2));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Could not write JWT key pair to config file: ' + keysFile + ': ' + err.message);
|
logger.error(`Could not write JWT key pair to config file: ${keysFile}: ${err.message}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
logger.info('Wrote JWT key pair to config file: ' + keysFile);
|
logger.info(`Wrote JWT key pair to config file: ${keysFile}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
*
|
||||||
* @param {string} key ie: 'database' or 'database.engine'
|
* @param {string} key ie: 'database' or 'database.engine'
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
has: function(key) {
|
const configHas = (key) => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
const keys = key.split('.');
|
const keys = key.split(".");
|
||||||
let level = instance;
|
let level = instance;
|
||||||
let has = true;
|
let has = true;
|
||||||
keys.forEach((keyItem) =>{
|
keys.forEach((keyItem) => {
|
||||||
if (typeof level[keyItem] === 'undefined') {
|
if (typeof level[keyItem] === "undefined") {
|
||||||
has = false;
|
has = false;
|
||||||
} else {
|
} else {
|
||||||
level = level[keyItem];
|
level = level[keyItem];
|
||||||
@@ -143,95 +146,92 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
|
|
||||||
return has;
|
return has;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a specific key from the top level
|
* Gets a specific key from the top level
|
||||||
*
|
*
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
get: function (key) {
|
const configGet = (key) => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
if (key && typeof instance[key] !== 'undefined') {
|
if (key && typeof instance[key] !== "undefined") {
|
||||||
return instance[key];
|
return instance[key];
|
||||||
}
|
}
|
||||||
return instance;
|
return instance;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this a sqlite configuration?
|
* Is this a sqlite configuration?
|
||||||
*
|
*
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isSqlite: function () {
|
const isSqlite = () => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
return instance.database.knex && instance.database.knex.client === sqliteClientName;
|
return instance.database.knex && instance.database.knex.client === sqliteClientName;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this a mysql configuration?
|
* Is this a mysql configuration?
|
||||||
*
|
*
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isMysql: function () {
|
const isMysql = () => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
return instance.database.engine === mysqlEngine;
|
return instance.database.engine === mysqlEngine;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this a postgres configuration?
|
* Is this a postgres configuration?
|
||||||
*
|
*
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isPostgres: function () {
|
const isPostgres = () => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
return instance.database.engine === postgresEngine;
|
return instance.database.engine === postgresEngine;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Are we running in debug mdoe?
|
* Are we running in debug mdoe?
|
||||||
*
|
*
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
debug: function () {
|
const isDebugMode = () => !!process.env.DEBUG;
|
||||||
return !!process.env.DEBUG;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a public key
|
* Returns a public key
|
||||||
*
|
*
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
getPublicKey: function () {
|
const getPublicKey = () => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
return instance.keys.pub;
|
return instance.keys.pub;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a private key
|
* Returns a private key
|
||||||
*
|
*
|
||||||
* @returns {string}
|
* @returns {string}
|
||||||
*/
|
*/
|
||||||
getPrivateKey: function () {
|
const getPrivateKey = () => {
|
||||||
instance === null && configure();
|
instance === null && configure();
|
||||||
return instance.keys.key;
|
return instance.keys.key;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
useLetsencryptStaging: function () {
|
const useLetsencryptStaging = () => !!process.env.LE_STAGING;
|
||||||
return !!process.env.LE_STAGING;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {string|null}
|
* @returns {string|null}
|
||||||
*/
|
*/
|
||||||
useLetsencryptServer: function () {
|
const useLetsencryptServer = () => {
|
||||||
if (process.env.LE_SERVER) {
|
if (process.env.LE_SERVER) {
|
||||||
return process.env.LE_SERVER;
|
return process.env.LE_SERVER;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { configHas, configGet, isSqlite, isMysql, isPostgres, isDebugMode, getPrivateKey, getPublicKey, useLetsencryptStaging, useLetsencryptServer };
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
const _ = require('lodash');
|
import _ from "lodash";
|
||||||
const util = require('util');
|
|
||||||
|
|
||||||
module.exports = {
|
const errs = {
|
||||||
|
PermissionError: function (_, previous) {
|
||||||
PermissionError: function (message, previous) {
|
|
||||||
Error.captureStackTrace(this, this.constructor);
|
Error.captureStackTrace(this, this.constructor);
|
||||||
this.name = this.constructor.name;
|
this.name = this.constructor.name;
|
||||||
this.previous = previous;
|
this.previous = previous;
|
||||||
this.message = 'Permission Denied';
|
this.message = "Permission Denied";
|
||||||
this.public = true;
|
this.public = true;
|
||||||
this.status = 403;
|
this.status = 403;
|
||||||
},
|
},
|
||||||
@@ -16,18 +14,19 @@ module.exports = {
|
|||||||
Error.captureStackTrace(this, this.constructor);
|
Error.captureStackTrace(this, this.constructor);
|
||||||
this.name = this.constructor.name;
|
this.name = this.constructor.name;
|
||||||
this.previous = previous;
|
this.previous = previous;
|
||||||
this.message = 'Item Not Found - ' + id;
|
this.message = `Item Not Found - ${id}`;
|
||||||
this.public = true;
|
this.public = true;
|
||||||
this.status = 404;
|
this.status = 404;
|
||||||
},
|
},
|
||||||
|
|
||||||
AuthError: function (message, previous) {
|
AuthError: function (message, messageI18n, previous) {
|
||||||
Error.captureStackTrace(this, this.constructor);
|
Error.captureStackTrace(this, this.constructor);
|
||||||
this.name = this.constructor.name;
|
this.name = this.constructor.name;
|
||||||
this.previous = previous;
|
this.previous = previous;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
this.message_i18n = messageI18n;
|
||||||
this.public = true;
|
this.public = true;
|
||||||
this.status = 401;
|
this.status = 400;
|
||||||
},
|
},
|
||||||
|
|
||||||
InternalError: function (message, previous) {
|
InternalError: function (message, previous) {
|
||||||
@@ -94,6 +93,8 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
_.forEach(module.exports, function (error) {
|
_.forEach(errs, (err) => {
|
||||||
util.inherits(error, Error);
|
err.prototype = Object.create(Error.prototype);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export default errs;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
module.exports = function (req, res, next) {
|
export default (req, res, next) => {
|
||||||
if (req.headers.origin) {
|
if (req.headers.origin) {
|
||||||
res.set({
|
res.set({
|
||||||
'Access-Control-Allow-Origin': req.headers.origin,
|
"Access-Control-Allow-Origin": req.headers.origin,
|
||||||
'Access-Control-Allow-Credentials': true,
|
"Access-Control-Allow-Credentials": true,
|
||||||
'Access-Control-Allow-Methods': 'OPTIONS, GET, POST',
|
"Access-Control-Allow-Methods": "OPTIONS, GET, POST",
|
||||||
'Access-Control-Allow-Headers': 'Content-Type, Cache-Control, Pragma, Expires, Authorization, X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit',
|
"Access-Control-Allow-Headers":
|
||||||
'Access-Control-Max-Age': 5 * 60,
|
"Content-Type, Cache-Control, Pragma, Expires, Authorization, X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit",
|
||||||
'Access-Control-Expose-Headers': 'X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit'
|
"Access-Control-Max-Age": 5 * 60,
|
||||||
|
"Access-Control-Expose-Headers": "X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit",
|
||||||
});
|
});
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
const Access = require('../access');
|
import Access from "../access.js";
|
||||||
|
|
||||||
module.exports = () => {
|
export default () => {
|
||||||
return function (req, res, next) {
|
return (_, res, next) => {
|
||||||
res.locals.access = null;
|
res.locals.access = null;
|
||||||
let access = new Access(res.locals.token || null);
|
const access = new Access(res.locals.token || null);
|
||||||
access.load()
|
access
|
||||||
|
.load()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
res.locals.access = access;
|
res.locals.access = access;
|
||||||
next();
|
next();
|
||||||
@@ -12,4 +13,3 @@ module.exports = () => {
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
module.exports = function () {
|
export default function () {
|
||||||
return function (req, res, next) {
|
return (req, res, next) => {
|
||||||
if (req.headers.authorization) {
|
if (req.headers.authorization) {
|
||||||
let parts = req.headers.authorization.split(' ');
|
const parts = req.headers.authorization.split(" ");
|
||||||
|
|
||||||
if (parts && parts[0] === 'Bearer' && parts[1]) {
|
if (parts && parts[0] === "Bearer" && parts[1]) {
|
||||||
res.locals.token = parts[1];
|
res.locals.token = parts[1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
};
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
let _ = require('lodash');
|
import _ from "lodash";
|
||||||
|
|
||||||
module.exports = function (default_sort, default_offset, default_limit, max_limit) {
|
|
||||||
|
|
||||||
|
export default (default_sort, default_offset, default_limit, max_limit) => {
|
||||||
/**
|
/**
|
||||||
* This will setup the req query params with filtered data and defaults
|
* This will setup the req query params with filtered data and defaults
|
||||||
*
|
*
|
||||||
@@ -11,34 +10,35 @@ module.exports = function (default_sort, default_offset, default_limit, max_limi
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return function (req, res, next) {
|
return (req, _res, next) => {
|
||||||
|
req.query.offset =
|
||||||
req.query.offset = typeof req.query.limit === 'undefined' ? default_offset || 0 : parseInt(req.query.offset, 10);
|
typeof req.query.limit === "undefined" ? default_offset || 0 : Number.parseInt(req.query.offset, 10);
|
||||||
req.query.limit = typeof req.query.limit === 'undefined' ? default_limit || 50 : parseInt(req.query.limit, 10);
|
req.query.limit =
|
||||||
|
typeof req.query.limit === "undefined" ? default_limit || 50 : Number.parseInt(req.query.limit, 10);
|
||||||
|
|
||||||
if (max_limit && req.query.limit > max_limit) {
|
if (max_limit && req.query.limit > max_limit) {
|
||||||
req.query.limit = max_limit;
|
req.query.limit = max_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sorting
|
// Sorting
|
||||||
let sort = typeof req.query.sort === 'undefined' ? default_sort : req.query.sort;
|
let sort = typeof req.query.sort === "undefined" ? default_sort : req.query.sort;
|
||||||
let myRegexp = /.*\.(asc|desc)$/ig;
|
const myRegexp = /.*\.(asc|desc)$/gi;
|
||||||
let sort_array = [];
|
const sort_array = [];
|
||||||
|
|
||||||
sort = sort.split(',');
|
sort = sort.split(",");
|
||||||
_.map(sort, function (val) {
|
_.map(sort, (val) => {
|
||||||
let matches = myRegexp.exec(val);
|
const matches = myRegexp.exec(val);
|
||||||
|
|
||||||
if (matches !== null) {
|
if (matches !== null) {
|
||||||
let dir = matches[1];
|
const dir = matches[1];
|
||||||
sort_array.push({
|
sort_array.push({
|
||||||
field: val.substr(0, val.length - (dir.length + 1)),
|
field: val.substr(0, val.length - (dir.length + 1)),
|
||||||
dir: dir.toLowerCase()
|
dir: dir.toLowerCase(),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
sort_array.push({
|
sort_array.push({
|
||||||
field: val,
|
field: val,
|
||||||
dir: 'asc'
|
dir: "asc",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
module.exports = (req, res, next) => {
|
export default (req, res, next) => {
|
||||||
if (req.params.user_id === 'me' && res.locals.access) {
|
if (req.params.user_id === 'me' && res.locals.access) {
|
||||||
req.params.user_id = res.locals.access.token.get('attrs').id;
|
req.params.user_id = res.locals.access.token.get('attrs').id;
|
||||||
} else {
|
} else {
|
||||||
req.params.user_id = parseInt(req.params.user_id, 10);
|
req.params.user_id = Number.parseInt(req.params.user_id, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
const moment = require('moment');
|
import moment from "moment";
|
||||||
const {isPostgres} = require('./config');
|
import { ref } from "objection";
|
||||||
const {ref} = require('objection');
|
import { isPostgres } from "./config.js";
|
||||||
|
|
||||||
module.exports = {
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* Takes an expression such as 30d and returns a moment object of that date in future
|
* Takes an expression such as 30d and returns a moment object of that date in future
|
||||||
*
|
*
|
||||||
* Key Shorthand
|
* Key Shorthand
|
||||||
@@ -22,41 +20,39 @@ module.exports = {
|
|||||||
* @param {String} expression
|
* @param {String} expression
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
parseDatePeriod: function (expression) {
|
const parseDatePeriod = (expression) => {
|
||||||
let matches = expression.match(/^([0-9]+)(y|Q|M|w|d|h|m|s|ms)$/m);
|
const matches = expression.match(/^([0-9]+)(y|Q|M|w|d|h|m|s|ms)$/m);
|
||||||
if (matches) {
|
if (matches) {
|
||||||
return moment().add(matches[1], matches[2]);
|
return moment().add(matches[1], matches[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
},
|
};
|
||||||
|
|
||||||
convertIntFieldsToBool: function (obj, fields) {
|
const convertIntFieldsToBool = (obj, fields) => {
|
||||||
fields.forEach(function (field) {
|
fields.forEach((field) => {
|
||||||
if (typeof obj[field] !== 'undefined') {
|
if (typeof obj[field] !== "undefined") {
|
||||||
obj[field] = obj[field] === 1;
|
obj[field] = obj[field] === 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return obj;
|
return obj;
|
||||||
},
|
};
|
||||||
|
|
||||||
convertBoolFieldsToInt: function (obj, fields) {
|
const convertBoolFieldsToInt = (obj, fields) => {
|
||||||
fields.forEach(function (field) {
|
fields.forEach((field) => {
|
||||||
if (typeof obj[field] !== 'undefined') {
|
if (typeof obj[field] !== "undefined") {
|
||||||
obj[field] = obj[field] ? 1 : 0;
|
obj[field] = obj[field] ? 1 : 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return obj;
|
return obj;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Casts a column to json if using postgres
|
* Casts a column to json if using postgres
|
||||||
*
|
*
|
||||||
* @param {string} colName
|
* @param {string} colName
|
||||||
* @returns {string|Objection.ReferenceBuilder}
|
* @returns {string|Objection.ReferenceBuilder}
|
||||||
*/
|
*/
|
||||||
castJsonIfNeed: function (colName) {
|
const castJsonIfNeed = (colName) => (isPostgres() ? ref(colName).castText() : colName);
|
||||||
return isPostgres() ? ref(colName).castText() : colName;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
export { parseDatePeriod, convertIntFieldsToBool, convertBoolFieldsToInt, castJsonIfNeed };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'identifier_for_migrate';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "identifier_for_migrate";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,16 +8,15 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex, Promise) {
|
const up = (_knex) => {
|
||||||
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
|
||||||
|
|
||||||
// Create Table example:
|
// Create Table example:
|
||||||
|
|
||||||
/*return knex.schema.createTable('notification', (table) => {
|
/*
|
||||||
|
return knex.schema.createTable('notification', (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.string('name').notNull();
|
table.string('name').notNull();
|
||||||
table.string('type').notNull();
|
table.string('type').notNull();
|
||||||
@@ -24,10 +24,11 @@ exports.up = function (knex, Promise) {
|
|||||||
table.integer('modified_on').notNull();
|
table.integer('modified_on').notNull();
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
logger.info('[' + migrate_name + '] Notification Table created');
|
logger.info('[' + migrateName + '] Notification Table created');
|
||||||
});*/
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up Complete');
|
logger.info(`[${migrateName}] Migrating Up Complete`);
|
||||||
|
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
@@ -36,20 +37,23 @@ exports.up = function (knex, Promise) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
// Drop table example:
|
// Drop table example:
|
||||||
|
|
||||||
/*return knex.schema.dropTable('notification')
|
/*
|
||||||
|
return knex.schema.dropTable('notification')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] Notification Table dropped');
|
logger.info(`[${migrateName}] Notification Table dropped`);
|
||||||
});*/
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Down Complete');
|
logger.info(`[${migrateName}] Migrating Down Complete`);
|
||||||
|
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,61 +1,60 @@
|
|||||||
const _ = require('lodash');
|
import { exec as nodeExec, execFile as nodeExecFile } from "node:child_process";
|
||||||
const exec = require('node:child_process').exec;
|
import { dirname } from "node:path";
|
||||||
const execFile = require('node:child_process').execFile;
|
import { fileURLToPath } from "node:url";
|
||||||
const { Liquid } = require('liquidjs');
|
import { Liquid } from "liquidjs";
|
||||||
const logger = require('../logger').global;
|
import _ from "lodash";
|
||||||
const error = require('./error');
|
import { global as logger } from "../logger.js";
|
||||||
|
import errs from "./error.js";
|
||||||
|
|
||||||
module.exports = {
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
exec: async (cmd, options = {}) => {
|
|
||||||
logger.debug('CMD:', cmd);
|
|
||||||
|
|
||||||
|
const exec = async (cmd, options = {}) => {
|
||||||
|
logger.debug("CMD:", cmd);
|
||||||
const { stdout, stderr } = await new Promise((resolve, reject) => {
|
const { stdout, stderr } = await new Promise((resolve, reject) => {
|
||||||
const child = exec(cmd, options, (isError, stdout, stderr) => {
|
const child = nodeExec(cmd, options, (isError, stdout, stderr) => {
|
||||||
if (isError) {
|
if (isError) {
|
||||||
reject(new error.CommandError(stderr, isError));
|
reject(new errs.CommandError(stderr, isError));
|
||||||
} else {
|
} else {
|
||||||
resolve({ stdout, stderr });
|
resolve({ stdout, stderr });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
child.on('error', (e) => {
|
child.on("error", (e) => {
|
||||||
reject(new error.CommandError(stderr, 1, e));
|
reject(new errs.CommandError(stderr, 1, e));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return stdout;
|
return stdout;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} cmd
|
* @param {String} cmd
|
||||||
* @param {Array} args
|
* @param {Array} args
|
||||||
* @param {Object|undefined} options
|
* @param {Object|undefined} options
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
execFile: (cmd, args, options) => {
|
const execFile = (cmd, args, options) => {
|
||||||
logger.debug(`CMD: ${cmd} ${args ? args.join(' ') : ''}`);
|
logger.debug(`CMD: ${cmd} ${args ? args.join(" ") : ""}`);
|
||||||
if (typeof options === 'undefined') {
|
const opts = options || {};
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
execFile(cmd, args, options, (err, stdout, stderr) => {
|
nodeExecFile(cmd, args, opts, (err, stdout, stderr) => {
|
||||||
if (err && typeof err === 'object') {
|
if (err && typeof err === "object") {
|
||||||
reject(new error.CommandError(stderr, 1, err));
|
reject(new errs.CommandError(stderr, 1, err));
|
||||||
} else {
|
} else {
|
||||||
resolve(stdout.trim());
|
resolve(stdout.trim());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in objection query builder
|
* Used in objection query builder
|
||||||
*
|
*
|
||||||
* @param {Array} omissions
|
* @param {Array} omissions
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
omitRow: (omissions) => {
|
const omitRow = (omissions) => {
|
||||||
/**
|
/**
|
||||||
* @param {Object} row
|
* @param {Object} row
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
@@ -63,15 +62,15 @@ module.exports = {
|
|||||||
return (row) => {
|
return (row) => {
|
||||||
return _.omit(row, omissions);
|
return _.omit(row, omissions);
|
||||||
};
|
};
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in objection query builder
|
* Used in objection query builder
|
||||||
*
|
*
|
||||||
* @param {Array} omissions
|
* @param {Array} omissions
|
||||||
* @returns {Function}
|
* @returns {Function}
|
||||||
*/
|
*/
|
||||||
omitRows: (omissions) => {
|
const omitRows = (omissions) => {
|
||||||
/**
|
/**
|
||||||
* @param {Array} rows
|
* @param {Array} rows
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
@@ -82,14 +81,14 @@ module.exports = {
|
|||||||
});
|
});
|
||||||
return rows;
|
return rows;
|
||||||
};
|
};
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {Object} Liquid render engine
|
* @returns {Object} Liquid render engine
|
||||||
*/
|
*/
|
||||||
getRenderEngine: () => {
|
const getRenderEngine = () => {
|
||||||
const renderEngine = new Liquid({
|
const renderEngine = new Liquid({
|
||||||
root: `${__dirname}/../templates/`
|
root: `${__dirname}/../templates/`,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -98,13 +97,14 @@ module.exports = {
|
|||||||
* directive string
|
* directive string
|
||||||
* address string
|
* address string
|
||||||
*/
|
*/
|
||||||
renderEngine.registerFilter('nginxAccessRule', (v) => {
|
renderEngine.registerFilter("nginxAccessRule", (v) => {
|
||||||
if (typeof v.directive !== 'undefined' && typeof v.address !== 'undefined' && v.directive && v.address) {
|
if (typeof v.directive !== "undefined" && typeof v.address !== "undefined" && v.directive && v.address) {
|
||||||
return `${v.directive} ${v.address};`;
|
return `${v.directive} ${v.address};`;
|
||||||
}
|
}
|
||||||
return '';
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
return renderEngine;
|
return renderEngine;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default { exec, execFile, omitRow, omitRows, getRenderEngine };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const Ajv = require('ajv/dist/2020');
|
import Ajv from "ajv/dist/2020.js";
|
||||||
const error = require('../error');
|
import errs from "../error.js";
|
||||||
|
|
||||||
const ajv = new Ajv({
|
const ajv = new Ajv({
|
||||||
verbose: true,
|
verbose: true,
|
||||||
@@ -14,15 +14,15 @@ const ajv = new Ajv({
|
|||||||
* @param {Object} payload
|
* @param {Object} payload
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
function apiValidator (schema, payload/*, description*/) {
|
function apiValidator(schema, payload /*, description*/) {
|
||||||
return new Promise(function Promise_apiValidator (resolve, reject) {
|
return new Promise(function Promise_apiValidator(resolve, reject) {
|
||||||
if (schema === null) {
|
if (schema === null) {
|
||||||
reject(new error.ValidationError('Schema is undefined'));
|
reject(new errs.ValidationError("Schema is undefined"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof payload === 'undefined') {
|
if (typeof payload === "undefined") {
|
||||||
reject(new error.ValidationError('Payload is undefined'));
|
reject(new errs.ValidationError("Payload is undefined"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -32,12 +32,12 @@ function apiValidator (schema, payload/*, description*/) {
|
|||||||
if (valid && !validate.errors) {
|
if (valid && !validate.errors) {
|
||||||
resolve(payload);
|
resolve(payload);
|
||||||
} else {
|
} else {
|
||||||
let message = ajv.errorsText(validate.errors);
|
const message = ajv.errorsText(validate.errors);
|
||||||
let err = new error.ValidationError(message);
|
const err = new errs.ValidationError(message);
|
||||||
err.debug = [validate.errors, payload];
|
err.debug = [validate.errors, payload];
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = apiValidator;
|
export default apiValidator;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const _ = require('lodash');
|
import Ajv from 'ajv/dist/2020.js';
|
||||||
const Ajv = require('ajv/dist/2020');
|
import _ from "lodash";
|
||||||
const error = require('../error');
|
import commonDefinitions from "../../schema/common.json" with { type: "json" };
|
||||||
const commonDefinitions = require('../../schema/common.json');
|
import errs from "../error.js";
|
||||||
|
|
||||||
RegExp.prototype.toJSON = RegExp.prototype.toString;
|
RegExp.prototype.toJSON = RegExp.prototype.toString;
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ const ajv = new Ajv({
|
|||||||
allowUnionTypes: true,
|
allowUnionTypes: true,
|
||||||
coerceTypes: true,
|
coerceTypes: true,
|
||||||
strict: false,
|
strict: false,
|
||||||
schemas: [commonDefinitions]
|
schemas: [commonDefinitions],
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,26 +20,26 @@ const ajv = new Ajv({
|
|||||||
* @param {Object} payload
|
* @param {Object} payload
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
function validator (schema, payload) {
|
const validator = (schema, payload) => {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise((resolve, reject) => {
|
||||||
if (!payload) {
|
if (!payload) {
|
||||||
reject(new error.InternalValidationError('Payload is falsy'));
|
reject(new errs.InternalValidationError("Payload is falsy"));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
let validate = ajv.compile(schema);
|
const validate = ajv.compile(schema);
|
||||||
let valid = validate(payload);
|
const valid = validate(payload);
|
||||||
|
|
||||||
if (valid && !validate.errors) {
|
if (valid && !validate.errors) {
|
||||||
resolve(_.cloneDeep(payload));
|
resolve(_.cloneDeep(payload));
|
||||||
} else {
|
} else {
|
||||||
let message = ajv.errorsText(validate.errors);
|
const message = ajv.errorsText(validate.errors);
|
||||||
reject(new error.InternalValidationError(message));
|
reject(new errs.InternalValidationError(message));
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
module.exports = validator;
|
export default validator;
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
const {Signale} = require('signale');
|
import signale from "signale";
|
||||||
|
|
||||||
module.exports = {
|
const opts = {
|
||||||
global: new Signale({scope: 'Global '}),
|
logLevel: "info",
|
||||||
migrate: new Signale({scope: 'Migrate '}),
|
|
||||||
express: new Signale({scope: 'Express '}),
|
|
||||||
access: new Signale({scope: 'Access '}),
|
|
||||||
nginx: new Signale({scope: 'Nginx '}),
|
|
||||||
ssl: new Signale({scope: 'SSL '}),
|
|
||||||
certbot: new Signale({scope: 'Certbot '}),
|
|
||||||
import: new Signale({scope: 'Importer '}),
|
|
||||||
setup: new Signale({scope: 'Setup '}),
|
|
||||||
ip_ranges: new Signale({scope: 'IP Ranges'})
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const global = new signale.Signale({ scope: "Global ", ...opts });
|
||||||
|
const migrate = new signale.Signale({ scope: "Migrate ", ...opts });
|
||||||
|
const express = new signale.Signale({ scope: "Express ", ...opts });
|
||||||
|
const access = new signale.Signale({ scope: "Access ", ...opts });
|
||||||
|
const nginx = new signale.Signale({ scope: "Nginx ", ...opts });
|
||||||
|
const ssl = new signale.Signale({ scope: "SSL ", ...opts });
|
||||||
|
const certbot = new signale.Signale({ scope: "Certbot ", ...opts });
|
||||||
|
const importer = new signale.Signale({ scope: "Importer ", ...opts });
|
||||||
|
const setup = new signale.Signale({ scope: "Setup ", ...opts });
|
||||||
|
const ipRanges = new signale.Signale({ scope: "IP Ranges", ...opts });
|
||||||
|
|
||||||
|
export { global, migrate, express, access, nginx, ssl, certbot, importer, setup, ipRanges };
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
const db = require('./db');
|
import db from "./db.js";
|
||||||
const logger = require('./logger').migrate;
|
import { migrate as logger } from "./logger.js";
|
||||||
|
|
||||||
module.exports = {
|
const migrateUp = async () => {
|
||||||
latest: function () {
|
const version = await db.migrate.currentVersion();
|
||||||
return db.migrate.currentVersion()
|
logger.info("Current database version:", version);
|
||||||
.then((version) => {
|
return await db.migrate.latest({
|
||||||
logger.info('Current database version:', version);
|
tableName: "migrations",
|
||||||
return db.migrate.latest({
|
directory: "migrations",
|
||||||
tableName: 'migrations',
|
|
||||||
directory: 'migrations'
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { migrateUp };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'initial-schema';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "initial-schema";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,199 +8,199 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.createTable('auth', (table) => {
|
return knex.schema
|
||||||
|
.createTable("auth", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('user_id').notNull().unsigned();
|
table.integer("user_id").notNull().unsigned();
|
||||||
table.string('type', 30).notNull();
|
table.string("type", 30).notNull();
|
||||||
table.string('secret').notNull();
|
table.string("secret").notNull();
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] auth Table created');
|
logger.info(`[${migrateName}] auth Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('user', (table) => {
|
return knex.schema.createTable("user", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('is_disabled').notNull().unsigned().defaultTo(0);
|
table.integer("is_disabled").notNull().unsigned().defaultTo(0);
|
||||||
table.string('email').notNull();
|
table.string("email").notNull();
|
||||||
table.string('name').notNull();
|
table.string("name").notNull();
|
||||||
table.string('nickname').notNull();
|
table.string("nickname").notNull();
|
||||||
table.string('avatar').notNull();
|
table.string("avatar").notNull();
|
||||||
table.json('roles').notNull();
|
table.json("roles").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] user Table created');
|
logger.info(`[${migrateName}] user Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('user_permission', (table) => {
|
return knex.schema.createTable("user_permission", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('user_id').notNull().unsigned();
|
table.integer("user_id").notNull().unsigned();
|
||||||
table.string('visibility').notNull();
|
table.string("visibility").notNull();
|
||||||
table.string('proxy_hosts').notNull();
|
table.string("proxy_hosts").notNull();
|
||||||
table.string('redirection_hosts').notNull();
|
table.string("redirection_hosts").notNull();
|
||||||
table.string('dead_hosts').notNull();
|
table.string("dead_hosts").notNull();
|
||||||
table.string('streams').notNull();
|
table.string("streams").notNull();
|
||||||
table.string('access_lists').notNull();
|
table.string("access_lists").notNull();
|
||||||
table.string('certificates').notNull();
|
table.string("certificates").notNull();
|
||||||
table.unique('user_id');
|
table.unique("user_id");
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] user_permission Table created');
|
logger.info(`[${migrateName}] user_permission Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('proxy_host', (table) => {
|
return knex.schema.createTable("proxy_host", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('owner_user_id').notNull().unsigned();
|
table.integer("owner_user_id").notNull().unsigned();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.json('domain_names').notNull();
|
table.json("domain_names").notNull();
|
||||||
table.string('forward_ip').notNull();
|
table.string("forward_ip").notNull();
|
||||||
table.integer('forward_port').notNull().unsigned();
|
table.integer("forward_port").notNull().unsigned();
|
||||||
table.integer('access_list_id').notNull().unsigned().defaultTo(0);
|
table.integer("access_list_id").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
|
table.integer("certificate_id").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('ssl_forced').notNull().unsigned().defaultTo(0);
|
table.integer("ssl_forced").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('caching_enabled').notNull().unsigned().defaultTo(0);
|
table.integer("caching_enabled").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('block_exploits').notNull().unsigned().defaultTo(0);
|
table.integer("block_exploits").notNull().unsigned().defaultTo(0);
|
||||||
table.text('advanced_config').notNull().defaultTo('');
|
table.text("advanced_config").notNull().defaultTo("");
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table created');
|
logger.info(`[${migrateName}] proxy_host Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('redirection_host', (table) => {
|
return knex.schema.createTable("redirection_host", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('owner_user_id').notNull().unsigned();
|
table.integer("owner_user_id").notNull().unsigned();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.json('domain_names').notNull();
|
table.json("domain_names").notNull();
|
||||||
table.string('forward_domain_name').notNull();
|
table.string("forward_domain_name").notNull();
|
||||||
table.integer('preserve_path').notNull().unsigned().defaultTo(0);
|
table.integer("preserve_path").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
|
table.integer("certificate_id").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('ssl_forced').notNull().unsigned().defaultTo(0);
|
table.integer("ssl_forced").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('block_exploits').notNull().unsigned().defaultTo(0);
|
table.integer("block_exploits").notNull().unsigned().defaultTo(0);
|
||||||
table.text('advanced_config').notNull().defaultTo('');
|
table.text("advanced_config").notNull().defaultTo("");
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table created');
|
logger.info(`[${migrateName}] redirection_host Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('dead_host', (table) => {
|
return knex.schema.createTable("dead_host", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('owner_user_id').notNull().unsigned();
|
table.integer("owner_user_id").notNull().unsigned();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.json('domain_names').notNull();
|
table.json("domain_names").notNull();
|
||||||
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
|
table.integer("certificate_id").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('ssl_forced').notNull().unsigned().defaultTo(0);
|
table.integer("ssl_forced").notNull().unsigned().defaultTo(0);
|
||||||
table.text('advanced_config').notNull().defaultTo('');
|
table.text("advanced_config").notNull().defaultTo("");
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] dead_host Table created');
|
logger.info(`[${migrateName}] dead_host Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('stream', (table) => {
|
return knex.schema.createTable("stream", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('owner_user_id').notNull().unsigned();
|
table.integer("owner_user_id").notNull().unsigned();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('incoming_port').notNull().unsigned();
|
table.integer("incoming_port").notNull().unsigned();
|
||||||
table.string('forward_ip').notNull();
|
table.string("forward_ip").notNull();
|
||||||
table.integer('forwarding_port').notNull().unsigned();
|
table.integer("forwarding_port").notNull().unsigned();
|
||||||
table.integer('tcp_forwarding').notNull().unsigned().defaultTo(0);
|
table.integer("tcp_forwarding").notNull().unsigned().defaultTo(0);
|
||||||
table.integer('udp_forwarding').notNull().unsigned().defaultTo(0);
|
table.integer("udp_forwarding").notNull().unsigned().defaultTo(0);
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] stream Table created');
|
logger.info(`[${migrateName}] stream Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('access_list', (table) => {
|
return knex.schema.createTable("access_list", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('owner_user_id').notNull().unsigned();
|
table.integer("owner_user_id").notNull().unsigned();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.string('name').notNull();
|
table.string("name").notNull();
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list Table created');
|
logger.info(`[${migrateName}] access_list Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('certificate', (table) => {
|
return knex.schema.createTable("certificate", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('owner_user_id').notNull().unsigned();
|
table.integer("owner_user_id").notNull().unsigned();
|
||||||
table.integer('is_deleted').notNull().unsigned().defaultTo(0);
|
table.integer("is_deleted").notNull().unsigned().defaultTo(0);
|
||||||
table.string('provider').notNull();
|
table.string("provider").notNull();
|
||||||
table.string('nice_name').notNull().defaultTo('');
|
table.string("nice_name").notNull().defaultTo("");
|
||||||
table.json('domain_names').notNull();
|
table.json("domain_names").notNull();
|
||||||
table.dateTime('expires_on').notNull();
|
table.dateTime("expires_on").notNull();
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] certificate Table created');
|
logger.info(`[${migrateName}] certificate Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('access_list_auth', (table) => {
|
return knex.schema.createTable("access_list_auth", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('access_list_id').notNull().unsigned();
|
table.integer("access_list_id").notNull().unsigned();
|
||||||
table.string('username').notNull();
|
table.string("username").notNull();
|
||||||
table.string('password').notNull();
|
table.string("password").notNull();
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list_auth Table created');
|
logger.info(`[${migrateName}] access_list_auth Table created`);
|
||||||
|
|
||||||
return knex.schema.createTable('audit_log', (table) => {
|
return knex.schema.createTable("audit_log", (table) => {
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('user_id').notNull().unsigned();
|
table.integer("user_id").notNull().unsigned();
|
||||||
table.string('object_type').notNull().defaultTo('');
|
table.string("object_type").notNull().defaultTo("");
|
||||||
table.integer('object_id').notNull().unsigned().defaultTo(0);
|
table.integer("object_id").notNull().unsigned().defaultTo(0);
|
||||||
table.string('action').notNull();
|
table.string("action").notNull();
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] audit_log Table created');
|
logger.info(`[${migrateName}] audit_log Table created`);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down the initial data.');
|
logger.warn(`[${migrateName}] You can't migrate down the initial data.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'websockets';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "websockets";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,29 +8,29 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.integer('allow_websocket_upgrade').notNull().unsigned().defaultTo(0);
|
.table("proxy_host", (proxy_host) => {
|
||||||
|
proxy_host.integer("allow_websocket_upgrade").notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'forward_host';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "forward_host";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,17 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.renameColumn('forward_ip', 'forward_host');
|
.table("proxy_host", (proxy_host) => {
|
||||||
|
proxy_host.renameColumn("forward_ip", "forward_host");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,10 +26,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'http2_support';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "http2_support";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,31 +8,31 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
.table("proxy_host", (proxy_host) => {
|
||||||
|
proxy_host.integer("http2_support").notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', function (redirection_host) {
|
return knex.schema.table("redirection_host", (redirection_host) => {
|
||||||
redirection_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
redirection_host.integer("http2_support").notNull().unsigned().defaultTo(0);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('dead_host', function (dead_host) {
|
return knex.schema.table("dead_host", (dead_host) => {
|
||||||
dead_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
dead_host.integer("http2_support").notNull().unsigned().defaultTo(0);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] dead_host Table altered');
|
logger.info(`[${migrateName}] dead_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,11 +40,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'forward_scheme';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "forward_scheme";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,17 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.string('forward_scheme').notNull().defaultTo('http');
|
.table("proxy_host", (proxy_host) => {
|
||||||
|
proxy_host.string("forward_scheme").notNull().defaultTo("http");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,10 +26,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'disabled';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "disabled";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,38 +8,38 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
.table("proxy_host", (proxy_host) => {
|
||||||
|
proxy_host.integer("enabled").notNull().unsigned().defaultTo(1);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', function (redirection_host) {
|
return knex.schema.table("redirection_host", (redirection_host) => {
|
||||||
redirection_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
redirection_host.integer("enabled").notNull().unsigned().defaultTo(1);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('dead_host', function (dead_host) {
|
return knex.schema.table("dead_host", (dead_host) => {
|
||||||
dead_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
dead_host.integer("enabled").notNull().unsigned().defaultTo(1);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] dead_host Table altered');
|
logger.info(`[${migrateName}] dead_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('stream', function (stream) {
|
return knex.schema.table("stream", (stream) => {
|
||||||
stream.integer('enabled').notNull().unsigned().defaultTo(1);
|
stream.integer("enabled").notNull().unsigned().defaultTo(1);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] stream Table altered');
|
logger.info(`[${migrateName}] stream Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,10 +47,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'custom_locations';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "custom_locations";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -8,17 +9,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.json('locations');
|
.table("proxy_host", (proxy_host) => {
|
||||||
|
proxy_host.json("locations");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,10 +27,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'hsts';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "hsts";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,34 +8,34 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
proxy_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
.table("proxy_host", (proxy_host) => {
|
||||||
proxy_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
proxy_host.integer("hsts_enabled").notNull().unsigned().defaultTo(0);
|
||||||
|
proxy_host.integer("hsts_subdomains").notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info(`[${migrateName}] proxy_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', function (redirection_host) {
|
return knex.schema.table("redirection_host", (redirection_host) => {
|
||||||
redirection_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
redirection_host.integer("hsts_enabled").notNull().unsigned().defaultTo(0);
|
||||||
redirection_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
redirection_host.integer("hsts_subdomains").notNull().unsigned().defaultTo(0);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
|
|
||||||
return knex.schema.table('dead_host', function (dead_host) {
|
return knex.schema.table("dead_host", (dead_host) => {
|
||||||
dead_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
dead_host.integer("hsts_enabled").notNull().unsigned().defaultTo(0);
|
||||||
dead_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
dead_host.integer("hsts_subdomains").notNull().unsigned().defaultTo(0);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] dead_host Table altered');
|
logger.info(`[${migrateName}] dead_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,10 +43,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'settings';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "settings";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,11 +8,10 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.createTable('setting', (table) => {
|
return knex.schema.createTable('setting', (table) => {
|
||||||
table.string('id').notNull().primary();
|
table.string('id').notNull().primary();
|
||||||
@@ -21,7 +21,7 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
table.json('meta').notNull();
|
table.json('meta').notNull();
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] setting Table created');
|
logger.info(`[${migrateName}] setting Table created`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,10 +29,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down the initial data.');
|
logger.warn(`[${migrateName}] You can't migrate down the initial data.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'access_list_client';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "access_list_client";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,32 +8,30 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
return knex.schema
|
||||||
|
.createTable("access_list_client", (table) => {
|
||||||
return knex.schema.createTable('access_list_client', (table) => {
|
|
||||||
table.increments().primary();
|
table.increments().primary();
|
||||||
table.dateTime('created_on').notNull();
|
table.dateTime("created_on").notNull();
|
||||||
table.dateTime('modified_on').notNull();
|
table.dateTime("modified_on").notNull();
|
||||||
table.integer('access_list_id').notNull().unsigned();
|
table.integer("access_list_id").notNull().unsigned();
|
||||||
table.string('address').notNull();
|
table.string("address").notNull();
|
||||||
table.string('directive').notNull();
|
table.string("directive").notNull();
|
||||||
table.json('meta').notNull();
|
table.json("meta").notNull();
|
||||||
|
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list_client Table created');
|
logger.info(`[${migrateName}] access_list_client Table created`);
|
||||||
|
|
||||||
return knex.schema.table('access_list', function (access_list) {
|
return knex.schema.table("access_list", (access_list) => {
|
||||||
access_list.integer('satify_any').notNull().defaultTo(0);
|
access_list.integer("satify_any").notNull().defaultTo(0);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list Table altered');
|
logger.info(`[${migrateName}] access_list Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -40,14 +39,14 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex/*, Promise*/) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return knex.schema.dropTable('access_list_client')
|
return knex.schema.dropTable("access_list_client").then(() => {
|
||||||
.then(() => {
|
logger.info(`[${migrateName}] access_list_client Table dropped`);
|
||||||
logger.info('[' + migrate_name + '] access_list_client Table dropped');
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'access_list_client_fix';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "access_list_client_fix";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,17 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('access_list', function (access_list) {
|
return knex.schema
|
||||||
access_list.renameColumn('satify_any', 'satisfy_any');
|
.table("access_list", (access_list) => {
|
||||||
|
access_list.renameColumn("satify_any", "satisfy_any");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list Table altered');
|
logger.info(`[${migrateName}] access_list Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,10 +26,11 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
const down = (_knex) => {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn(`[${migrateName}] You can't migrate down this one.`);
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'pass_auth';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "pass_auth";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,18 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
return knex.schema
|
||||||
|
.table("access_list", (access_list) => {
|
||||||
return knex.schema.table('access_list', function (access_list) {
|
access_list.integer("pass_auth").notNull().defaultTo(1);
|
||||||
access_list.integer('pass_auth').notNull().defaultTo(1);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list Table altered');
|
logger.info(`[${migrateName}] access_list Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,16 +26,18 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex/*, Promise*/) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return knex.schema.table('access_list', function (access_list) {
|
return knex.schema
|
||||||
access_list.dropColumn('pass_auth');
|
.table("access_list", (access_list) => {
|
||||||
|
access_list.dropColumn("pass_auth");
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] access_list pass_auth Column dropped');
|
logger.info(`[${migrateName}] access_list pass_auth Column dropped`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'redirection_scheme';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "redirection_scheme";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,18 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
return knex.schema
|
||||||
|
.table("redirection_host", (table) => {
|
||||||
return knex.schema.table('redirection_host', (table) => {
|
table.string("forward_scheme").notNull().defaultTo("$scheme");
|
||||||
table.string('forward_scheme').notNull().defaultTo('$scheme');
|
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,16 +26,18 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex/*, Promise*/) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', (table) => {
|
return knex.schema
|
||||||
table.dropColumn('forward_scheme');
|
.table("redirection_host", (table) => {
|
||||||
|
table.dropColumn("forward_scheme");
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'redirection_status_code';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "redirection_status_code";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,18 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
return knex.schema
|
||||||
|
.table("redirection_host", (table) => {
|
||||||
return knex.schema.table('redirection_host', (table) => {
|
table.integer("forward_http_code").notNull().unsigned().defaultTo(302);
|
||||||
table.integer('forward_http_code').notNull().unsigned().defaultTo(302);
|
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,16 +26,18 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex/*, Promise*/) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', (table) => {
|
return knex.schema
|
||||||
table.dropColumn('forward_http_code');
|
.table("redirection_host", (table) => {
|
||||||
|
table.dropColumn("forward_http_code");
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] redirection_host Table altered');
|
logger.info(`[${migrateName}] redirection_host Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'stream_domain';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "stream_domain";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -7,17 +8,17 @@ const logger = require('../logger').migrate;
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex/*, Promise*/) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('stream', (table) => {
|
return knex.schema
|
||||||
table.renameColumn('forward_ip', 'forwarding_host');
|
.table("stream", (table) => {
|
||||||
|
table.renameColumn("forward_ip", "forwarding_host");
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] stream Table altered');
|
logger.info(`[${migrateName}] stream Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -25,16 +26,18 @@ exports.up = function (knex/*, Promise*/) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex/*, Promise*/) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return knex.schema.table('stream', (table) => {
|
return knex.schema
|
||||||
table.renameColumn('forwarding_host', 'forward_ip');
|
.table("stream", (table) => {
|
||||||
|
table.renameColumn("forwarding_host", "forward_ip");
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] stream Table altered');
|
logger.info(`[${migrateName}] stream Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,17 +1,19 @@
|
|||||||
const migrate_name = 'stream_domain';
|
import internalNginx from "../internal/nginx.js";
|
||||||
const logger = require('../logger').migrate;
|
import { migrate as logger } from "../logger.js";
|
||||||
const internalNginx = require('../internal/nginx');
|
|
||||||
|
const migrateName = "stream_domain";
|
||||||
|
|
||||||
async function regenerateDefaultHost(knex) {
|
async function regenerateDefaultHost(knex) {
|
||||||
const row = await knex('setting').select('*').where('id', 'default-site').first();
|
const row = await knex("setting").select("*").where("id", "default-site").first();
|
||||||
|
|
||||||
if (!row) {
|
if (!row) {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
return internalNginx.deleteConfig('default')
|
return internalNginx
|
||||||
|
.deleteConfig("default")
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.generateConfig('default', row);
|
return internalNginx.generateConfig("default", row);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.test();
|
return internalNginx.test();
|
||||||
@@ -27,11 +29,10 @@ async function regenerateDefaultHost(knex) {
|
|||||||
* @see http://knexjs.org/#Schema
|
* @see http://knexjs.org/#Schema
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return regenerateDefaultHost(knex);
|
return regenerateDefaultHost(knex);
|
||||||
};
|
};
|
||||||
@@ -40,11 +41,12 @@ exports.up = function (knex) {
|
|||||||
* Undo Migrate
|
* Undo Migrate
|
||||||
*
|
*
|
||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @param {Promise} Promise
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return regenerateDefaultHost(knex);
|
return regenerateDefaultHost(knex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const migrate_name = 'stream_ssl';
|
import { migrate as logger } from "../logger.js";
|
||||||
const logger = require('../logger').migrate;
|
|
||||||
|
const migrateName = "stream_ssl";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Migrate
|
* Migrate
|
||||||
@@ -9,14 +10,15 @@ const logger = require('../logger').migrate;
|
|||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex) {
|
const up = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info(`[${migrateName}] Migrating Up...`);
|
||||||
|
|
||||||
return knex.schema.table('stream', (table) => {
|
return knex.schema
|
||||||
table.integer('certificate_id').notNull().unsigned().defaultTo(0);
|
.table("stream", (table) => {
|
||||||
|
table.integer("certificate_id").notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] stream Table altered');
|
logger.info(`[${migrateName}] stream Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -26,13 +28,16 @@ exports.up = function (knex) {
|
|||||||
* @param {Object} knex
|
* @param {Object} knex
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex) {
|
const down = (knex) => {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info(`[${migrateName}] Migrating Down...`);
|
||||||
|
|
||||||
return knex.schema.table('stream', (table) => {
|
return knex.schema
|
||||||
table.dropColumn('certificate_id');
|
.table("stream", (table) => {
|
||||||
|
table.dropColumn("certificate_id");
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] stream Table altered');
|
logger.info(`[${migrateName}] stream Table altered`);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { up, down };
|
||||||
|
|||||||
@@ -1,103 +1,98 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const User = require('./user');
|
import AccessListAuth from "./access_list_auth.js";
|
||||||
const AccessListAuth = require('./access_list_auth');
|
import AccessListClient from "./access_list_client.js";
|
||||||
const AccessListClient = require('./access_list_client');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import ProxyHostModel from "./proxy_host.js";
|
||||||
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = ["is_deleted", "satisfy_any", "pass_auth"];
|
||||||
'is_deleted',
|
|
||||||
'satisfy_any',
|
|
||||||
'pass_auth',
|
|
||||||
];
|
|
||||||
|
|
||||||
class AccessList extends Model {
|
class AccessList extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'AccessList';
|
return "AccessList";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'access_list';
|
return "access_list";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['meta'];
|
return ["meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
const ProxyHost = require('./proxy_host');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
owner: {
|
owner: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list.owner_user_id',
|
from: "access_list.owner_user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("user.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('user.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
items: {
|
items: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: AccessListAuth,
|
modelClass: AccessListAuth,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list.id',
|
from: "access_list.id",
|
||||||
to: 'access_list_auth.access_list_id'
|
to: "access_list_auth.access_list_id",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
clients: {
|
clients: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: AccessListClient,
|
modelClass: AccessListClient,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list.id',
|
from: "access_list.id",
|
||||||
to: 'access_list_client.access_list_id'
|
to: "access_list_client.access_list_id",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
proxy_hosts: {
|
proxy_hosts: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: ProxyHost,
|
modelClass: ProxyHostModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list.id',
|
from: "access_list.id",
|
||||||
to: 'proxy_host.access_list_id'
|
to: "proxy_host.access_list_id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("proxy_host.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('proxy_host.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AccessList;
|
export default AccessList;
|
||||||
|
|||||||
@@ -1,54 +1,55 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const Model = require('objection').Model;
|
import db from "../db.js";
|
||||||
const now = require('./now_helper');
|
import accessListModel from "./access_list.js";
|
||||||
|
import now from "./now_helper.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
class AccessListAuth extends Model {
|
class AccessListAuth extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'AccessListAuth';
|
return "AccessListAuth";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'access_list_auth';
|
return "access_list_auth";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['meta'];
|
return ["meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
access_list: {
|
access_list: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: require('./access_list'),
|
modelClass: accessListModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list_auth.access_list_id',
|
from: "access_list_auth.access_list_id",
|
||||||
to: 'access_list.id'
|
to: "access_list.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("access_list.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('access_list.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AccessListAuth;
|
export default AccessListAuth;
|
||||||
|
|||||||
@@ -1,54 +1,55 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const Model = require('objection').Model;
|
import db from "../db.js";
|
||||||
const now = require('./now_helper');
|
import accessListModel from "./access_list.js";
|
||||||
|
import now from "./now_helper.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
class AccessListClient extends Model {
|
class AccessListClient extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'AccessListClient';
|
return "AccessListClient";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'access_list_client';
|
return "access_list_client";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['meta'];
|
return ["meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
access_list: {
|
access_list: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: require('./access_list'),
|
modelClass: accessListModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list_client.access_list_id',
|
from: "access_list_client.access_list_id",
|
||||||
to: 'access_list.id'
|
to: "access_list.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("access_list.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('access_list.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AccessListClient;
|
export default AccessListClient;
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const Model = require('objection').Model;
|
import db from "../db.js";
|
||||||
const User = require('./user');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
class AuditLog extends Model {
|
class AuditLog extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'AuditLog';
|
return "AuditLog";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'audit_log';
|
return "audit_log";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['meta'];
|
return ["meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
user: {
|
user: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'audit_log.user_id',
|
from: "audit_log.user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AuditLog;
|
export default AuditLog;
|
||||||
|
|||||||
@@ -1,27 +1,21 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const bcrypt = require('bcrypt');
|
import bcrypt from "bcrypt";
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const User = require('./user');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = ["is_deleted"];
|
||||||
'is_deleted',
|
|
||||||
];
|
|
||||||
|
|
||||||
function encryptPassword () {
|
function encryptPassword() {
|
||||||
/* jshint -W040 */
|
if (this.type === "password" && this.secret) {
|
||||||
let _this = this;
|
return bcrypt.hash(this.secret, 13).then((hash) => {
|
||||||
|
this.secret = hash;
|
||||||
if (_this.type === 'password' && _this.secret) {
|
|
||||||
return bcrypt.hash(_this.secret, 13)
|
|
||||||
.then(function (hash) {
|
|
||||||
_this.secret = hash;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,31 +23,31 @@ function encryptPassword () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Auth extends Model {
|
class Auth extends Model {
|
||||||
$beforeInsert (queryContext) {
|
$beforeInsert(queryContext) {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return encryptPassword.apply(this, queryContext);
|
return encryptPassword.apply(this, queryContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate (queryContext) {
|
$beforeUpdate(queryContext) {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
return encryptPassword.apply(this, queryContext);
|
return encryptPassword.apply(this, queryContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,37 +56,37 @@ class Auth extends Model {
|
|||||||
* @param {String} password
|
* @param {String} password
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
verifyPassword (password) {
|
verifyPassword(password) {
|
||||||
return bcrypt.compare(password, this.secret);
|
return bcrypt.compare(password, this.secret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'Auth';
|
return "Auth";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'auth';
|
return "auth";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['meta'];
|
return ["meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
user: {
|
user: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'auth.user_id',
|
from: "auth.user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
},
|
},
|
||||||
filter: {
|
filter: {
|
||||||
is_deleted: 0
|
is_deleted: 0,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Auth;
|
export default Auth;
|
||||||
|
|||||||
@@ -1,124 +1,121 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const now = require('./now_helper');
|
import deadHostModel from "./dead_host.js";
|
||||||
|
import now from "./now_helper.js";
|
||||||
|
import proxyHostModel from "./proxy_host.js";
|
||||||
|
import redirectionHostModel from "./redirection_host.js";
|
||||||
|
import userModel from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = ["is_deleted"];
|
||||||
'is_deleted',
|
|
||||||
];
|
|
||||||
|
|
||||||
class Certificate extends Model {
|
class Certificate extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for expires_on
|
// Default for expires_on
|
||||||
if (typeof this.expires_on === 'undefined') {
|
if (typeof this.expires_on === "undefined") {
|
||||||
this.expires_on = now();
|
this.expires_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default for domain_names
|
// Default for domain_names
|
||||||
if (typeof this.domain_names === 'undefined') {
|
if (typeof this.domain_names === "undefined") {
|
||||||
this.domain_names = [];
|
this.domain_names = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Sort domain_names
|
// Sort domain_names
|
||||||
if (typeof this.domain_names !== 'undefined') {
|
if (typeof this.domain_names !== "undefined") {
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'Certificate';
|
return "Certificate";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'certificate';
|
return "certificate";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['domain_names', 'meta'];
|
return ["domain_names", "meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
const ProxyHost = require('./proxy_host');
|
|
||||||
const DeadHost = require('./dead_host');
|
|
||||||
const User = require('./user');
|
|
||||||
const RedirectionHost = require('./redirection_host');
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
owner: {
|
owner: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: userModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'certificate.owner_user_id',
|
from: "certificate.owner_user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("user.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('user.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
proxy_hosts: {
|
proxy_hosts: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: ProxyHost,
|
modelClass: proxyHostModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'certificate.id',
|
from: "certificate.id",
|
||||||
to: 'proxy_host.certificate_id'
|
to: "proxy_host.certificate_id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("proxy_host.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('proxy_host.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
dead_hosts: {
|
dead_hosts: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: DeadHost,
|
modelClass: deadHostModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'certificate.id',
|
from: "certificate.id",
|
||||||
to: 'dead_host.certificate_id'
|
to: "dead_host.certificate_id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("dead_host.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('dead_host.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
redirection_hosts: {
|
redirection_hosts: {
|
||||||
relation: Model.HasManyRelation,
|
relation: Model.HasManyRelation,
|
||||||
modelClass: RedirectionHost,
|
modelClass: redirectionHostModel,
|
||||||
join: {
|
join: {
|
||||||
from: 'certificate.id',
|
from: "certificate.id",
|
||||||
to: 'redirection_host.certificate_id'
|
to: "redirection_host.certificate_id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("redirection_host.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('redirection_host.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Certificate;
|
export default Certificate;
|
||||||
|
|||||||
@@ -1,99 +1,92 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const User = require('./user');
|
import Certificate from "./certificate.js";
|
||||||
const Certificate = require('./certificate');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = ["is_deleted", "ssl_forced", "http2_support", "enabled", "hsts_enabled", "hsts_subdomains"];
|
||||||
'is_deleted',
|
|
||||||
'ssl_forced',
|
|
||||||
'http2_support',
|
|
||||||
'enabled',
|
|
||||||
'hsts_enabled',
|
|
||||||
'hsts_subdomains',
|
|
||||||
];
|
|
||||||
|
|
||||||
class DeadHost extends Model {
|
class DeadHost extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for domain_names
|
// Default for domain_names
|
||||||
if (typeof this.domain_names === 'undefined') {
|
if (typeof this.domain_names === "undefined") {
|
||||||
this.domain_names = [];
|
this.domain_names = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Sort domain_names
|
// Sort domain_names
|
||||||
if (typeof this.domain_names !== 'undefined') {
|
if (typeof this.domain_names !== "undefined") {
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'DeadHost';
|
return "DeadHost";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'dead_host';
|
return "dead_host";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['domain_names', 'meta'];
|
return ["domain_names", "meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
owner: {
|
owner: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'dead_host.owner_user_id',
|
from: "dead_host.owner_user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("user.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('user.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: Certificate,
|
modelClass: Certificate,
|
||||||
join: {
|
join: {
|
||||||
from: 'dead_host.certificate_id',
|
from: "dead_host.certificate_id",
|
||||||
to: 'certificate.id'
|
to: "certificate.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("certificate.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('certificate.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = DeadHost;
|
export default DeadHost;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const config = require('../lib/config');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { isSqlite } from "../lib/config.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
module.exports = function () {
|
export default () => {
|
||||||
if (config.isSqlite()) {
|
if (isSqlite()) {
|
||||||
// eslint-disable-next-line
|
|
||||||
return Model.raw("datetime('now','localtime')");
|
return Model.raw("datetime('now','localtime')");
|
||||||
}
|
}
|
||||||
return Model.raw('NOW()');
|
return Model.raw("NOW()");
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,114 +1,114 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const User = require('./user');
|
import AccessList from "./access_list.js";
|
||||||
const AccessList = require('./access_list');
|
import Certificate from "./certificate.js";
|
||||||
const Certificate = require('./certificate');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = [
|
||||||
'is_deleted',
|
"is_deleted",
|
||||||
'ssl_forced',
|
"ssl_forced",
|
||||||
'caching_enabled',
|
"caching_enabled",
|
||||||
'block_exploits',
|
"block_exploits",
|
||||||
'allow_websocket_upgrade',
|
"allow_websocket_upgrade",
|
||||||
'http2_support',
|
"http2_support",
|
||||||
'enabled',
|
"enabled",
|
||||||
'hsts_enabled',
|
"hsts_enabled",
|
||||||
'hsts_subdomains',
|
"hsts_subdomains",
|
||||||
];
|
];
|
||||||
|
|
||||||
class ProxyHost extends Model {
|
class ProxyHost extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for domain_names
|
// Default for domain_names
|
||||||
if (typeof this.domain_names === 'undefined') {
|
if (typeof this.domain_names === "undefined") {
|
||||||
this.domain_names = [];
|
this.domain_names = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Sort domain_names
|
// Sort domain_names
|
||||||
if (typeof this.domain_names !== 'undefined') {
|
if (typeof this.domain_names !== "undefined") {
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'ProxyHost';
|
return "ProxyHost";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'proxy_host';
|
return "proxy_host";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['domain_names', 'meta', 'locations'];
|
return ["domain_names", "meta", "locations"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
owner: {
|
owner: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'proxy_host.owner_user_id',
|
from: "proxy_host.owner_user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("user.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('user.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
access_list: {
|
access_list: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: AccessList,
|
modelClass: AccessList,
|
||||||
join: {
|
join: {
|
||||||
from: 'proxy_host.access_list_id',
|
from: "proxy_host.access_list_id",
|
||||||
to: 'access_list.id'
|
to: "access_list.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("access_list.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('access_list.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: Certificate,
|
modelClass: Certificate,
|
||||||
join: {
|
join: {
|
||||||
from: 'proxy_host.certificate_id',
|
from: "proxy_host.certificate_id",
|
||||||
to: 'certificate.id'
|
to: "certificate.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("certificate.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('certificate.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = ProxyHost;
|
export default ProxyHost;
|
||||||
|
|||||||
@@ -1,102 +1,101 @@
|
|||||||
|
|
||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const User = require('./user');
|
import Certificate from "./certificate.js";
|
||||||
const Certificate = require('./certificate');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = [
|
||||||
'is_deleted',
|
"is_deleted",
|
||||||
'enabled',
|
"enabled",
|
||||||
'preserve_path',
|
"preserve_path",
|
||||||
'ssl_forced',
|
"ssl_forced",
|
||||||
'block_exploits',
|
"block_exploits",
|
||||||
'hsts_enabled',
|
"hsts_enabled",
|
||||||
'hsts_subdomains',
|
"hsts_subdomains",
|
||||||
'http2_support',
|
"http2_support",
|
||||||
];
|
];
|
||||||
|
|
||||||
class RedirectionHost extends Model {
|
class RedirectionHost extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for domain_names
|
// Default for domain_names
|
||||||
if (typeof this.domain_names === 'undefined') {
|
if (typeof this.domain_names === "undefined") {
|
||||||
this.domain_names = [];
|
this.domain_names = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Sort domain_names
|
// Sort domain_names
|
||||||
if (typeof this.domain_names !== 'undefined') {
|
if (typeof this.domain_names !== "undefined") {
|
||||||
this.domain_names.sort();
|
this.domain_names.sort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'RedirectionHost';
|
return "RedirectionHost";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'redirection_host';
|
return "redirection_host";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['domain_names', 'meta'];
|
return ["domain_names", "meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
owner: {
|
owner: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'redirection_host.owner_user_id',
|
from: "redirection_host.owner_user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("user.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('user.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: Certificate,
|
modelClass: Certificate,
|
||||||
join: {
|
join: {
|
||||||
from: 'redirection_host.certificate_id',
|
from: "redirection_host.certificate_id",
|
||||||
to: 'certificate.id'
|
to: "certificate.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("certificate.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('certificate.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = RedirectionHost;
|
export default RedirectionHost;
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const Model = require('objection').Model;
|
import db from "../db.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
@@ -27,4 +27,4 @@ class Setting extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Setting;
|
export default Setting;
|
||||||
|
|||||||
@@ -1,82 +1,77 @@
|
|||||||
const Model = require('objection').Model;
|
import { Model } from "objection";
|
||||||
const db = require('../db');
|
import db from "../db.js";
|
||||||
const helpers = require('../lib/helpers');
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const User = require('./user');
|
import Certificate from "./certificate.js";
|
||||||
const Certificate = require('./certificate');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import User from "./user.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = ["is_deleted", "enabled", "tcp_forwarding", "udp_forwarding"];
|
||||||
'is_deleted',
|
|
||||||
'enabled',
|
|
||||||
'tcp_forwarding',
|
|
||||||
'udp_forwarding',
|
|
||||||
];
|
|
||||||
|
|
||||||
class Stream extends Model {
|
class Stream extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for meta
|
// Default for meta
|
||||||
if (typeof this.meta === 'undefined') {
|
if (typeof this.meta === "undefined") {
|
||||||
this.meta = {};
|
this.meta = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'Stream';
|
return "Stream";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'stream';
|
return "stream";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['meta'];
|
return ["meta"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
owner: {
|
owner: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'stream.owner_user_id',
|
from: "stream.owner_user_id",
|
||||||
to: 'user.id'
|
to: "user.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("user.is_deleted", 0);
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('user.is_deleted', 0);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: Certificate,
|
modelClass: Certificate,
|
||||||
join: {
|
join: {
|
||||||
from: 'stream.certificate_id',
|
from: "stream.certificate_id",
|
||||||
to: 'certificate.id'
|
to: "certificate.id",
|
||||||
|
},
|
||||||
|
modify: (qb) => {
|
||||||
|
qb.where("certificate.is_deleted", 0);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
|
||||||
qb.where('certificate.is_deleted', 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = Stream;
|
export default Stream;
|
||||||
|
|||||||
@@ -3,16 +3,16 @@
|
|||||||
and then has abilities after that.
|
and then has abilities after that.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const _ = require('lodash');
|
import crypto from "node:crypto";
|
||||||
const jwt = require('jsonwebtoken');
|
import jwt from "jsonwebtoken";
|
||||||
const crypto = require('crypto');
|
import _ from "lodash";
|
||||||
const config = require('../lib/config');
|
import { getPrivateKey, getPublicKey } from "../lib/config.js";
|
||||||
const error = require('../lib/error');
|
import errs from "../lib/error.js";
|
||||||
const logger = require('../logger').global;
|
import { global as logger } from "../logger.js";
|
||||||
const ALGO = 'RS256';
|
|
||||||
|
|
||||||
module.exports = function () {
|
const ALGO = "RS256";
|
||||||
|
|
||||||
|
export default () => {
|
||||||
let token_data = {};
|
let token_data = {};
|
||||||
|
|
||||||
const self = {
|
const self = {
|
||||||
@@ -21,28 +21,26 @@ module.exports = function () {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (payload) => {
|
create: (payload) => {
|
||||||
if (!config.getPrivateKey()) {
|
if (!getPrivateKey()) {
|
||||||
logger.error('Private key is empty!');
|
logger.error("Private key is empty!");
|
||||||
}
|
}
|
||||||
// sign with RSA SHA256
|
// sign with RSA SHA256
|
||||||
const options = {
|
const options = {
|
||||||
algorithm: ALGO,
|
algorithm: ALGO,
|
||||||
expiresIn: payload.expiresIn || '1d'
|
expiresIn: payload.expiresIn || "1d",
|
||||||
};
|
};
|
||||||
|
|
||||||
payload.jti = crypto.randomBytes(12)
|
payload.jti = crypto.randomBytes(12).toString("base64").substring(-8);
|
||||||
.toString('base64')
|
|
||||||
.substring(-8);
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
jwt.sign(payload, config.getPrivateKey(), options, (err, token) => {
|
jwt.sign(payload, getPrivateKey(), options, (err, token) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
token_data = payload;
|
token_data = payload;
|
||||||
resolve({
|
resolve({
|
||||||
token: token,
|
token: token,
|
||||||
payload: payload
|
payload: payload,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -53,42 +51,47 @@ module.exports = function () {
|
|||||||
* @param {String} token
|
* @param {String} token
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
load: function (token) {
|
load: (token) => {
|
||||||
if (!config.getPublicKey()) {
|
if (!getPublicKey()) {
|
||||||
logger.error('Public key is empty!');
|
logger.error("Public key is empty!");
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
if (!token || token === null || token === 'null') {
|
if (!token || token === null || token === "null") {
|
||||||
reject(new error.AuthError('Empty token'));
|
reject(new errs.AuthError("Empty token"));
|
||||||
} else {
|
} else {
|
||||||
jwt.verify(token, config.getPublicKey(), {ignoreExpiration: false, algorithms: [ALGO]}, (err, result) => {
|
jwt.verify(
|
||||||
|
token,
|
||||||
|
getPublicKey(),
|
||||||
|
{ ignoreExpiration: false, algorithms: [ALGO] },
|
||||||
|
(err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
if (err.name === "TokenExpiredError") {
|
||||||
if (err.name === 'TokenExpiredError') {
|
reject(new errs.AuthError("Token has expired", err));
|
||||||
reject(new error.AuthError('Token has expired', err));
|
|
||||||
} else {
|
} else {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
token_data = result;
|
token_data = result;
|
||||||
|
|
||||||
// Hack: some tokens out in the wild have a scope of 'all' instead of 'user'.
|
// Hack: some tokens out in the wild have a scope of 'all' instead of 'user'.
|
||||||
// For 30 days at least, we need to replace 'all' with user.
|
// For 30 days at least, we need to replace 'all' with user.
|
||||||
if ((typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, 'all') !== -1)) {
|
if (
|
||||||
token_data.scope = ['user'];
|
typeof token_data.scope !== "undefined" &&
|
||||||
|
_.indexOf(token_data.scope, "all") !== -1
|
||||||
|
) {
|
||||||
|
token_data.scope = ["user"];
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(token_data);
|
resolve(token_data);
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -97,16 +100,14 @@ module.exports = function () {
|
|||||||
* @param {String} scope
|
* @param {String} scope
|
||||||
* @returns {Boolean}
|
* @returns {Boolean}
|
||||||
*/
|
*/
|
||||||
hasScope: function (scope) {
|
hasScope: (scope) => typeof token_data.scope !== "undefined" && _.indexOf(token_data.scope, scope) !== -1,
|
||||||
return typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, scope) !== -1;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} key
|
* @param {String} key
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
get: function (key) {
|
get: (key) => {
|
||||||
if (typeof token_data[key] !== 'undefined') {
|
if (typeof token_data[key] !== "undefined") {
|
||||||
return token_data[key];
|
return token_data[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +118,7 @@ module.exports = function () {
|
|||||||
* @param {String} key
|
* @param {String} key
|
||||||
* @param {*} value
|
* @param {*} value
|
||||||
*/
|
*/
|
||||||
set: function (key, value) {
|
set: (key, value) => {
|
||||||
token_data[key] = value;
|
token_data[key] = value;
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -126,13 +127,13 @@ module.exports = function () {
|
|||||||
* @returns {Integer}
|
* @returns {Integer}
|
||||||
*/
|
*/
|
||||||
getUserId: (default_value) => {
|
getUserId: (default_value) => {
|
||||||
const attrs = self.get('attrs');
|
const attrs = self.get("attrs");
|
||||||
if (attrs && typeof attrs.id !== 'undefined' && attrs.id) {
|
if (attrs && typeof attrs.id !== "undefined" && attrs.id) {
|
||||||
return attrs.id;
|
return attrs.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_value || 0;
|
return default_value || 0;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|||||||
@@ -1,69 +1,65 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const helpers = require('../lib/helpers');
|
import db from "../db.js";
|
||||||
const Model = require('objection').Model;
|
import { convertBoolFieldsToInt, convertIntFieldsToBool } from "../lib/helpers.js";
|
||||||
const UserPermission = require('./user_permission');
|
import now from "./now_helper.js";
|
||||||
const now = require('./now_helper');
|
import UserPermission from "./user_permission.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
const boolFields = [
|
const boolFields = ["is_deleted", "is_disabled"];
|
||||||
'is_deleted',
|
|
||||||
'is_disabled',
|
|
||||||
];
|
|
||||||
|
|
||||||
class User extends Model {
|
class User extends Model {
|
||||||
$beforeInsert () {
|
$beforeInsert() {
|
||||||
this.created_on = now();
|
this.created_on = now();
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
|
|
||||||
// Default for roles
|
// Default for roles
|
||||||
if (typeof this.roles === 'undefined') {
|
if (typeof this.roles === "undefined") {
|
||||||
this.roles = [];
|
this.roles = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$beforeUpdate () {
|
$beforeUpdate() {
|
||||||
this.modified_on = now();
|
this.modified_on = now();
|
||||||
}
|
}
|
||||||
|
|
||||||
$parseDatabaseJson(json) {
|
$parseDatabaseJson(json) {
|
||||||
json = super.$parseDatabaseJson(json);
|
const thisJson = super.$parseDatabaseJson(json);
|
||||||
return helpers.convertIntFieldsToBool(json, boolFields);
|
return convertIntFieldsToBool(thisJson, boolFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
$formatDatabaseJson(json) {
|
$formatDatabaseJson(json) {
|
||||||
json = helpers.convertBoolFieldsToInt(json, boolFields);
|
const thisJson = convertBoolFieldsToInt(json, boolFields);
|
||||||
return super.$formatDatabaseJson(json);
|
return super.$formatDatabaseJson(thisJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get name () {
|
static get name() {
|
||||||
return 'User';
|
return "User";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get tableName () {
|
static get tableName() {
|
||||||
return 'user';
|
return "user";
|
||||||
}
|
}
|
||||||
|
|
||||||
static get jsonAttributes () {
|
static get jsonAttributes() {
|
||||||
return ['roles'];
|
return ["roles"];
|
||||||
}
|
}
|
||||||
|
|
||||||
static get relationMappings () {
|
static get relationMappings() {
|
||||||
return {
|
return {
|
||||||
permissions: {
|
permissions: {
|
||||||
relation: Model.HasOneRelation,
|
relation: Model.HasOneRelation,
|
||||||
modelClass: UserPermission,
|
modelClass: UserPermission,
|
||||||
join: {
|
join: {
|
||||||
from: 'user.id',
|
from: "user.id",
|
||||||
to: 'user_permission.user_id'
|
to: "user_permission.user_id",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = User;
|
export default User;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
const db = require('../db');
|
import { Model } from "objection";
|
||||||
const Model = require('objection').Model;
|
import db from "../db.js";
|
||||||
const now = require('./now_helper');
|
import now from "./now_helper.js";
|
||||||
|
|
||||||
Model.knex(db);
|
Model.knex(db);
|
||||||
|
|
||||||
@@ -26,4 +26,4 @@ class UserPermission extends Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = UserPermission;
|
export default UserPermission;
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "nginx-proxy-manager",
|
"name": "nginx-proxy-manager",
|
||||||
"version": "0.0.0",
|
"version": "2.0.0",
|
||||||
"description": "A beautiful interface for creating Nginx endpoints",
|
"description": "A beautiful interface for creating Nginx endpoints",
|
||||||
|
"author": "Jamie Curnow <jc@jc21.com>",
|
||||||
|
"license": "MIT",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"lint": "biome lint",
|
||||||
|
"prettier": "biome format --write .",
|
||||||
|
"validate-schema": "node validate-schema.js"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/json-schema-ref-parser": "^11.7.0",
|
"@apidevtools/json-schema-ref-parser": "^11.7.0",
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
@@ -28,21 +36,14 @@
|
|||||||
"sqlite3": "5.1.6",
|
"sqlite3": "5.1.6",
|
||||||
"temp-write": "^4.0.0"
|
"temp-write": "^4.0.0"
|
||||||
},
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@apidevtools/swagger-parser": "^10.1.0",
|
||||||
|
"@biomejs/biome": "2.2.0",
|
||||||
|
"chalk": "4.1.2",
|
||||||
|
"nodemon": "^2.0.2"
|
||||||
|
},
|
||||||
"signale": {
|
"signale": {
|
||||||
"displayDate": true,
|
"displayDate": true,
|
||||||
"displayTimestamp": true
|
"displayTimestamp": true
|
||||||
},
|
|
||||||
"author": "Jamie Curnow <jc@jc21.com>",
|
|
||||||
"license": "MIT",
|
|
||||||
"devDependencies": {
|
|
||||||
"@apidevtools/swagger-parser": "^10.1.0",
|
|
||||||
"chalk": "4.1.2",
|
|
||||||
"eslint": "^8.36.0",
|
|
||||||
"eslint-plugin-align-assignments": "^1.1.2",
|
|
||||||
"nodemon": "^2.0.2",
|
|
||||||
"prettier": "^2.0.4"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"validate-schema": "node validate-schema.js"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../lib/validator');
|
import internalAuditLog from "../internal/audit-log.js";
|
||||||
const jwtdecode = require('../lib/express/jwt-decode');
|
import jwtdecode from "../lib/express/jwt-decode.js";
|
||||||
const internalAuditLog = require('../internal/audit-log');
|
import validator from "../lib/validator/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/audit-log
|
* /api/audit-log
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -25,28 +25,30 @@ router
|
|||||||
* Retrieve all logs
|
* Retrieve all logs
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalAuditLog.getAll(res.locals.access, data.expand, data.query);
|
return internalAuditLog.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,51 +1,63 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const pjson = require('../package.json');
|
import errs from "../lib/error.js";
|
||||||
const error = require('../lib/error');
|
import pjson from "../package.json" with { type: "json" };
|
||||||
|
import auditLogRoutes from "./audit-log.js";
|
||||||
|
import accessListsRoutes from "./nginx/access_lists.js";
|
||||||
|
import certificatesHostsRoutes from "./nginx/certificates.js";
|
||||||
|
import deadHostsRoutes from "./nginx/dead_hosts.js";
|
||||||
|
import proxyHostsRoutes from "./nginx/proxy_hosts.js";
|
||||||
|
import redirectionHostsRoutes from "./nginx/redirection_hosts.js";
|
||||||
|
import streamsRoutes from "./nginx/streams.js";
|
||||||
|
import reportsRoutes from "./reports.js";
|
||||||
|
import schemaRoutes from "./schema.js";
|
||||||
|
import settingsRoutes from "./settings.js";
|
||||||
|
import tokensRoutes from "./tokens.js";
|
||||||
|
import usersRoutes from "./users.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Health Check
|
* Health Check
|
||||||
* GET /api
|
* GET /api
|
||||||
*/
|
*/
|
||||||
router.get('/', (req, res/*, next*/) => {
|
router.get("/", (_, res /*, next*/) => {
|
||||||
let version = pjson.version.split('-').shift().split('.');
|
const version = pjson.version.split("-").shift().split(".");
|
||||||
|
|
||||||
res.status(200).send({
|
res.status(200).send({
|
||||||
status: 'OK',
|
status: "OK",
|
||||||
version: {
|
version: {
|
||||||
major: parseInt(version.shift(), 10),
|
major: Number.parseInt(version.shift(), 10),
|
||||||
minor: parseInt(version.shift(), 10),
|
minor: Number.parseInt(version.shift(), 10),
|
||||||
revision: parseInt(version.shift(), 10)
|
revision: Number.parseInt(version.shift(), 10),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
router.use('/schema', require('./schema'));
|
router.use("/schema", schemaRoutes);
|
||||||
router.use('/tokens', require('./tokens'));
|
router.use("/tokens", tokensRoutes);
|
||||||
router.use('/users', require('./users'));
|
router.use("/users", usersRoutes);
|
||||||
router.use('/audit-log', require('./audit-log'));
|
router.use("/audit-log", auditLogRoutes);
|
||||||
router.use('/reports', require('./reports'));
|
router.use("/reports", reportsRoutes);
|
||||||
router.use('/settings', require('./settings'));
|
router.use("/settings", settingsRoutes);
|
||||||
router.use('/nginx/proxy-hosts', require('./nginx/proxy_hosts'));
|
router.use("/nginx/proxy-hosts", proxyHostsRoutes);
|
||||||
router.use('/nginx/redirection-hosts', require('./nginx/redirection_hosts'));
|
router.use("/nginx/redirection-hosts", redirectionHostsRoutes);
|
||||||
router.use('/nginx/dead-hosts', require('./nginx/dead_hosts'));
|
router.use("/nginx/dead-hosts", deadHostsRoutes);
|
||||||
router.use('/nginx/streams', require('./nginx/streams'));
|
router.use("/nginx/streams", streamsRoutes);
|
||||||
router.use('/nginx/access-lists', require('./nginx/access_lists'));
|
router.use("/nginx/access-lists", accessListsRoutes);
|
||||||
router.use('/nginx/certificates', require('./nginx/certificates'));
|
router.use("/nginx/certificates", certificatesHostsRoutes);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API 404 for all other routes
|
* API 404 for all other routes
|
||||||
*
|
*
|
||||||
* ALL /api/*
|
* ALL /api/*
|
||||||
*/
|
*/
|
||||||
router.all(/(.+)/, function (req, _, next) {
|
router.all(/(.+)/, (req, _, next) => {
|
||||||
req.params.page = req.params['0'];
|
req.params.page = req.params["0"];
|
||||||
next(new error.ItemNotFoundError(req.params.page));
|
next(new errs.ItemNotFoundError(req.params.page));
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../../lib/validator');
|
import internalAccessList from "../../internal/access-list.js";
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../../lib/validator/api');
|
import apiValidator from "../../lib/validator/api.js";
|
||||||
const internalAccessList = require('../../internal/access-list');
|
import validator from "../../lib/validator/index.js";
|
||||||
const schema = require('../../schema');
|
import { getValidationSchema } from "../../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/nginx/access-lists
|
* /api/nginx/access-lists
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -27,26 +27,28 @@ router
|
|||||||
* Retrieve all access-lists
|
* Retrieve all access-lists
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalAccessList.getAll(res.locals.access, data.expand, data.query);
|
return internalAccessList.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -57,13 +59,12 @@ router
|
|||||||
* Create a new access-list
|
* Create a new access-list
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/access-lists', 'post'), req.body)
|
apiValidator(getValidationSchema("/nginx/access-lists", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
return internalAccessList.create(res.locals.access, payload);
|
return internalAccessList.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -74,7 +75,7 @@ router
|
|||||||
* /api/nginx/access-lists/123
|
* /api/nginx/access-lists/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:list_id')
|
.route("/:list_id")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -86,30 +87,32 @@ router
|
|||||||
* Retrieve a specific access-list
|
* Retrieve a specific access-list
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['list_id'],
|
{
|
||||||
|
required: ["list_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
list_id: {
|
list_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
list_id: req.params.list_id,
|
list_id: req.params.list_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalAccessList.get(res.locals.access, {
|
return internalAccessList.get(res.locals.access, {
|
||||||
id: parseInt(data.list_id, 10),
|
id: Number.parseInt(data.list_id, 10),
|
||||||
expand: data.expand
|
expand: data.expand,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -120,14 +123,13 @@ router
|
|||||||
* Update and existing access-list
|
* Update and existing access-list
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/access-lists/{listID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/nginx/access-lists/{listID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = parseInt(req.params.list_id, 10);
|
payload.id = Number.parseInt(req.params.list_id, 10);
|
||||||
return internalAccessList.update(res.locals.access, payload);
|
return internalAccessList.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -138,12 +140,12 @@ router
|
|||||||
* Delete and existing access-list
|
* Delete and existing access-list
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalAccessList.delete(res.locals.access, {id: parseInt(req.params.list_id, 10)})
|
internalAccessList
|
||||||
|
.delete(res.locals.access, { id: Number.parseInt(req.params.list_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const error = require('../../lib/error');
|
import internalCertificate from "../../internal/certificate.js";
|
||||||
const validator = require('../../lib/validator');
|
import errs from "../../lib/error.js";
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../../lib/validator/api');
|
import apiValidator from "../../lib/validator/api.js";
|
||||||
const internalCertificate = require('../../internal/certificate');
|
import validator from "../../lib/validator/index.js";
|
||||||
const schema = require('../../schema');
|
import { getValidationSchema } from "../../schema/index.js";
|
||||||
|
|
||||||
const router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/nginx/certificates
|
* /api/nginx/certificates
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -28,26 +28,28 @@ router
|
|||||||
* Retrieve all certificates
|
* Retrieve all certificates
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalCertificate.getAll(res.locals.access, data.expand, data.query);
|
return internalCertificate.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -58,14 +60,13 @@ router
|
|||||||
* Create a new certificate
|
* Create a new certificate
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/certificates', 'post'), req.body)
|
apiValidator(getValidationSchema("/nginx/certificates", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
req.setTimeout(900000); // 15 minutes timeout
|
req.setTimeout(900000); // 15 minutes timeout
|
||||||
return internalCertificate.create(res.locals.access, payload);
|
return internalCertificate.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -76,7 +77,7 @@ router
|
|||||||
* /api/nginx/certificates/test-http
|
* /api/nginx/certificates/test-http
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/test-http')
|
.route("/test-http")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -89,14 +90,14 @@ router
|
|||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
if (req.query.domains === undefined) {
|
if (req.query.domains === undefined) {
|
||||||
next(new error.ValidationError('Domains are required as query parameters'));
|
next(new errs.ValidationError("Domains are required as query parameters"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
internalCertificate.testHttpsChallenge(res.locals.access, JSON.parse(req.query.domains))
|
internalCertificate
|
||||||
|
.testHttpsChallenge(res.locals.access, JSON.parse(req.query.domains))
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -107,7 +108,7 @@ router
|
|||||||
* /api/nginx/certificates/123
|
* /api/nginx/certificates/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:certificate_id')
|
.route("/:certificate_id")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -119,30 +120,32 @@ router
|
|||||||
* Retrieve a specific certificate
|
* Retrieve a specific certificate
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['certificate_id'],
|
{
|
||||||
|
required: ["certificate_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
certificate_id: {
|
certificate_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
certificate_id: req.params.certificate_id,
|
certificate_id: req.params.certificate_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalCertificate.get(res.locals.access, {
|
return internalCertificate.get(res.locals.access, {
|
||||||
id: parseInt(data.certificate_id, 10),
|
id: Number.parseInt(data.certificate_id, 10),
|
||||||
expand: data.expand
|
expand: data.expand,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -153,10 +156,10 @@ router
|
|||||||
* Update and existing certificate
|
* Update and existing certificate
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalCertificate.delete(res.locals.access, {id: parseInt(req.params.certificate_id, 10)})
|
internalCertificate
|
||||||
|
.delete(res.locals.access, { id: Number.parseInt(req.params.certificate_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -167,7 +170,7 @@ router
|
|||||||
* /api/nginx/certificates/123/upload
|
* /api/nginx/certificates/123/upload
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:certificate_id/upload')
|
.route("/:certificate_id/upload")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -180,16 +183,15 @@ router
|
|||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
if (!req.files) {
|
if (!req.files) {
|
||||||
res.status(400)
|
res.status(400).send({ error: "No files were uploaded" });
|
||||||
.send({error: 'No files were uploaded'});
|
|
||||||
} else {
|
} else {
|
||||||
internalCertificate.upload(res.locals.access, {
|
internalCertificate
|
||||||
id: parseInt(req.params.certificate_id, 10),
|
.upload(res.locals.access, {
|
||||||
files: req.files
|
id: Number.parseInt(req.params.certificate_id, 10),
|
||||||
|
files: req.files,
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
}
|
}
|
||||||
@@ -201,7 +203,7 @@ router
|
|||||||
* /api/nginx/certificates/123/renew
|
* /api/nginx/certificates/123/renew
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:certificate_id/renew')
|
.route("/:certificate_id/renew")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -214,12 +216,12 @@ router
|
|||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
req.setTimeout(900000); // 15 minutes timeout
|
req.setTimeout(900000); // 15 minutes timeout
|
||||||
internalCertificate.renew(res.locals.access, {
|
internalCertificate
|
||||||
id: parseInt(req.params.certificate_id, 10)
|
.renew(res.locals.access, {
|
||||||
|
id: Number.parseInt(req.params.certificate_id, 10),
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -230,7 +232,7 @@ router
|
|||||||
* /api/nginx/certificates/123/download
|
* /api/nginx/certificates/123/download
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:certificate_id/download')
|
.route("/:certificate_id/download")
|
||||||
.options((_req, res) => {
|
.options((_req, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -242,12 +244,12 @@ router
|
|||||||
* Renew certificate
|
* Renew certificate
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
internalCertificate.download(res.locals.access, {
|
internalCertificate
|
||||||
id: parseInt(req.params.certificate_id, 10)
|
.download(res.locals.access, {
|
||||||
|
id: Number.parseInt(req.params.certificate_id, 10),
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).download(result.fileName);
|
||||||
.download(result.fileName);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -258,7 +260,7 @@ router
|
|||||||
* /api/nginx/certificates/validate
|
* /api/nginx/certificates/validate
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/validate')
|
.route("/validate")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -271,18 +273,17 @@ router
|
|||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
if (!req.files) {
|
if (!req.files) {
|
||||||
res.status(400)
|
res.status(400).send({ error: "No files were uploaded" });
|
||||||
.send({error: 'No files were uploaded'});
|
|
||||||
} else {
|
} else {
|
||||||
internalCertificate.validate({
|
internalCertificate
|
||||||
files: req.files
|
.validate({
|
||||||
|
files: req.files,
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../../lib/validator');
|
import internalDeadHost from "../../internal/dead-host.js";
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../../lib/validator/api');
|
import apiValidator from "../../lib/validator/api.js";
|
||||||
const internalDeadHost = require('../../internal/dead-host');
|
import validator from "../../lib/validator/index.js";
|
||||||
const schema = require('../../schema');
|
import { getValidationSchema } from "../../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/nginx/dead-hosts
|
* /api/nginx/dead-hosts
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -27,26 +27,28 @@ router
|
|||||||
* Retrieve all dead-hosts
|
* Retrieve all dead-hosts
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalDeadHost.getAll(res.locals.access, data.expand, data.query);
|
return internalDeadHost.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -57,13 +59,12 @@ router
|
|||||||
* Create a new dead-host
|
* Create a new dead-host
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/dead-hosts', 'post'), req.body)
|
apiValidator(getValidationSchema("/nginx/dead-hosts", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
return internalDeadHost.create(res.locals.access, payload);
|
return internalDeadHost.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -74,8 +75,8 @@ router
|
|||||||
* /api/nginx/dead-hosts/123
|
* /api/nginx/dead-hosts/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id')
|
.route("/:host_id")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -86,30 +87,32 @@ router
|
|||||||
* Retrieve a specific dead-host
|
* Retrieve a specific dead-host
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['host_id'],
|
{
|
||||||
|
required: ["host_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
host_id: {
|
host_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
host_id: req.params.host_id,
|
host_id: req.params.host_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalDeadHost.get(res.locals.access, {
|
return internalDeadHost.get(res.locals.access, {
|
||||||
id: parseInt(data.host_id, 10),
|
id: Number.parseInt(data.host_id, 10),
|
||||||
expand: data.expand
|
expand: data.expand,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -120,14 +123,13 @@ router
|
|||||||
* Update and existing dead-host
|
* Update and existing dead-host
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/dead-hosts/{hostID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/nginx/dead-hosts/{hostID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = parseInt(req.params.host_id, 10);
|
payload.id = Number.parseInt(req.params.host_id, 10);
|
||||||
return internalDeadHost.update(res.locals.access, payload);
|
return internalDeadHost.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -138,10 +140,10 @@ router
|
|||||||
* Update and existing dead-host
|
* Update and existing dead-host
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalDeadHost.delete(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalDeadHost
|
||||||
|
.delete(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -152,7 +154,7 @@ router
|
|||||||
* /api/nginx/dead-hosts/123/enable
|
* /api/nginx/dead-hosts/123/enable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/enable')
|
.route("/:host_id/enable")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -162,10 +164,10 @@ router
|
|||||||
* POST /api/nginx/dead-hosts/123/enable
|
* POST /api/nginx/dead-hosts/123/enable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalDeadHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalDeadHost
|
||||||
|
.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -176,7 +178,7 @@ router
|
|||||||
* /api/nginx/dead-hosts/123/disable
|
* /api/nginx/dead-hosts/123/disable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/disable')
|
.route("/:host_id/disable")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -186,12 +188,12 @@ router
|
|||||||
* POST /api/nginx/dead-hosts/123/disable
|
* POST /api/nginx/dead-hosts/123/disable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalDeadHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalDeadHost
|
||||||
|
.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../../lib/validator');
|
import internalProxyHost from "../../internal/proxy-host.js";
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../../lib/validator/api');
|
import apiValidator from "../../lib/validator/api.js";
|
||||||
const internalProxyHost = require('../../internal/proxy-host');
|
import validator from "../../lib/validator/index.js";
|
||||||
const schema = require('../../schema');
|
import { getValidationSchema } from "../../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/nginx/proxy-hosts
|
* /api/nginx/proxy-hosts
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -27,26 +27,28 @@ router
|
|||||||
* Retrieve all proxy-hosts
|
* Retrieve all proxy-hosts
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalProxyHost.getAll(res.locals.access, data.expand, data.query);
|
return internalProxyHost.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -57,13 +59,12 @@ router
|
|||||||
* Create a new proxy-host
|
* Create a new proxy-host
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/proxy-hosts', 'post'), req.body)
|
apiValidator(getValidationSchema("/nginx/proxy-hosts", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
return internalProxyHost.create(res.locals.access, payload);
|
return internalProxyHost.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -74,8 +75,8 @@ router
|
|||||||
* /api/nginx/proxy-hosts/123
|
* /api/nginx/proxy-hosts/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id')
|
.route("/:host_id")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -86,30 +87,32 @@ router
|
|||||||
* Retrieve a specific proxy-host
|
* Retrieve a specific proxy-host
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['host_id'],
|
{
|
||||||
|
required: ["host_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
host_id: {
|
host_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
host_id: req.params.host_id,
|
host_id: req.params.host_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalProxyHost.get(res.locals.access, {
|
return internalProxyHost.get(res.locals.access, {
|
||||||
id: parseInt(data.host_id, 10),
|
id: Number.parseInt(data.host_id, 10),
|
||||||
expand: data.expand
|
expand: data.expand,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -120,14 +123,13 @@ router
|
|||||||
* Update and existing proxy-host
|
* Update and existing proxy-host
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/proxy-hosts/{hostID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/nginx/proxy-hosts/{hostID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = parseInt(req.params.host_id, 10);
|
payload.id = Number.parseInt(req.params.host_id, 10);
|
||||||
return internalProxyHost.update(res.locals.access, payload);
|
return internalProxyHost.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -138,10 +140,10 @@ router
|
|||||||
* Update and existing proxy-host
|
* Update and existing proxy-host
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalProxyHost.delete(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalProxyHost
|
||||||
|
.delete(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -152,7 +154,7 @@ router
|
|||||||
* /api/nginx/proxy-hosts/123/enable
|
* /api/nginx/proxy-hosts/123/enable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/enable')
|
.route("/:host_id/enable")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -162,10 +164,10 @@ router
|
|||||||
* POST /api/nginx/proxy-hosts/123/enable
|
* POST /api/nginx/proxy-hosts/123/enable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalProxyHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalProxyHost
|
||||||
|
.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -176,7 +178,7 @@ router
|
|||||||
* /api/nginx/proxy-hosts/123/disable
|
* /api/nginx/proxy-hosts/123/disable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/disable')
|
.route("/:host_id/disable")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -186,12 +188,12 @@ router
|
|||||||
* POST /api/nginx/proxy-hosts/123/disable
|
* POST /api/nginx/proxy-hosts/123/disable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalProxyHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalProxyHost
|
||||||
|
.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../../lib/validator');
|
import internalRedirectionHost from "../../internal/redirection-host.js";
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../../lib/validator/api');
|
import apiValidator from "../../lib/validator/api.js";
|
||||||
const internalRedirectionHost = require('../../internal/redirection-host');
|
import validator from "../../lib/validator/index.js";
|
||||||
const schema = require('../../schema');
|
import { getValidationSchema } from "../../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/nginx/redirection-hosts
|
* /api/nginx/redirection-hosts
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -27,26 +27,28 @@ router
|
|||||||
* Retrieve all redirection-hosts
|
* Retrieve all redirection-hosts
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalRedirectionHost.getAll(res.locals.access, data.expand, data.query);
|
return internalRedirectionHost.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -57,13 +59,12 @@ router
|
|||||||
* Create a new redirection-host
|
* Create a new redirection-host
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/redirection-hosts', 'post'), req.body)
|
apiValidator(getValidationSchema("/nginx/redirection-hosts", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
return internalRedirectionHost.create(res.locals.access, payload);
|
return internalRedirectionHost.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -74,8 +75,8 @@ router
|
|||||||
* /api/nginx/redirection-hosts/123
|
* /api/nginx/redirection-hosts/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id')
|
.route("/:host_id")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -86,30 +87,32 @@ router
|
|||||||
* Retrieve a specific redirection-host
|
* Retrieve a specific redirection-host
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['host_id'],
|
{
|
||||||
|
required: ["host_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
host_id: {
|
host_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
host_id: req.params.host_id,
|
host_id: req.params.host_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalRedirectionHost.get(res.locals.access, {
|
return internalRedirectionHost.get(res.locals.access, {
|
||||||
id: parseInt(data.host_id, 10),
|
id: Number.parseInt(data.host_id, 10),
|
||||||
expand: data.expand
|
expand: data.expand,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -120,14 +123,13 @@ router
|
|||||||
* Update and existing redirection-host
|
* Update and existing redirection-host
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/redirection-hosts/{hostID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/nginx/redirection-hosts/{hostID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = parseInt(req.params.host_id, 10);
|
payload.id = Number.parseInt(req.params.host_id, 10);
|
||||||
return internalRedirectionHost.update(res.locals.access, payload);
|
return internalRedirectionHost.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -138,10 +140,10 @@ router
|
|||||||
* Update and existing redirection-host
|
* Update and existing redirection-host
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalRedirectionHost.delete(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalRedirectionHost
|
||||||
|
.delete(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -152,8 +154,8 @@ router
|
|||||||
* /api/nginx/redirection-hosts/123/enable
|
* /api/nginx/redirection-hosts/123/enable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/enable')
|
.route("/:host_id/enable")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -162,10 +164,10 @@ router
|
|||||||
* POST /api/nginx/redirection-hosts/123/enable
|
* POST /api/nginx/redirection-hosts/123/enable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalRedirectionHost.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalRedirectionHost
|
||||||
|
.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -176,8 +178,8 @@ router
|
|||||||
* /api/nginx/redirection-hosts/123/disable
|
* /api/nginx/redirection-hosts/123/disable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/disable')
|
.route("/:host_id/disable")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -186,12 +188,12 @@ router
|
|||||||
* POST /api/nginx/redirection-hosts/123/disable
|
* POST /api/nginx/redirection-hosts/123/disable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalRedirectionHost.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalRedirectionHost
|
||||||
|
.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../../lib/validator');
|
import internalStream from "../../internal/stream.js";
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
import jwtdecode from "../../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../../lib/validator/api');
|
import apiValidator from "../../lib/validator/api.js";
|
||||||
const internalStream = require('../../internal/stream');
|
import validator from "../../lib/validator/index.js";
|
||||||
const schema = require('../../schema');
|
import { getValidationSchema } from "../../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/nginx/streams
|
* /api/nginx/streams
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
@@ -27,26 +27,28 @@ router
|
|||||||
* Retrieve all streams
|
* Retrieve all streams
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalStream.getAll(res.locals.access, data.expand, data.query);
|
return internalStream.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -57,13 +59,12 @@ router
|
|||||||
* Create a new stream
|
* Create a new stream
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/streams', 'post'), req.body)
|
apiValidator(getValidationSchema("/nginx/streams", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
return internalStream.create(res.locals.access, payload);
|
return internalStream.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -74,8 +75,8 @@ router
|
|||||||
* /api/nginx/streams/123
|
* /api/nginx/streams/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:stream_id')
|
.route("/:stream_id")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
.all(jwtdecode()) // preferred so it doesn't apply to nonexistent routes
|
||||||
@@ -86,30 +87,32 @@ router
|
|||||||
* Retrieve a specific stream
|
* Retrieve a specific stream
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['stream_id'],
|
{
|
||||||
|
required: ["stream_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
stream_id: {
|
stream_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
stream_id: req.params.stream_id,
|
stream_id: req.params.stream_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalStream.get(res.locals.access, {
|
return internalStream.get(res.locals.access, {
|
||||||
id: parseInt(data.stream_id, 10),
|
id: Number.parseInt(data.stream_id, 10),
|
||||||
expand: data.expand
|
expand: data.expand,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -120,14 +123,13 @@ router
|
|||||||
* Update and existing stream
|
* Update and existing stream
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/nginx/streams/{streamID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/nginx/streams/{streamID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = parseInt(req.params.stream_id, 10);
|
payload.id = Number.parseInt(req.params.stream_id, 10);
|
||||||
return internalStream.update(res.locals.access, payload);
|
return internalStream.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -138,10 +140,10 @@ router
|
|||||||
* Update and existing stream
|
* Update and existing stream
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalStream.delete(res.locals.access, {id: parseInt(req.params.stream_id, 10)})
|
internalStream
|
||||||
|
.delete(res.locals.access, { id: Number.parseInt(req.params.stream_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -152,7 +154,7 @@ router
|
|||||||
* /api/nginx/streams/123/enable
|
* /api/nginx/streams/123/enable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/enable')
|
.route("/:host_id/enable")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -162,10 +164,10 @@ router
|
|||||||
* POST /api/nginx/streams/123/enable
|
* POST /api/nginx/streams/123/enable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalStream.enable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalStream
|
||||||
|
.enable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -176,7 +178,7 @@ router
|
|||||||
* /api/nginx/streams/123/disable
|
* /api/nginx/streams/123/disable
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:host_id/disable')
|
.route("/:host_id/disable")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -186,12 +188,12 @@ router
|
|||||||
* POST /api/nginx/streams/123/disable
|
* POST /api/nginx/streams/123/disable
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalStream.disable(res.locals.access, {id: parseInt(req.params.host_id, 10)})
|
internalStream
|
||||||
|
.disable(res.locals.access, { id: Number.parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const jwtdecode = require('../lib/express/jwt-decode');
|
import internalReport from "../internal/report.js";
|
||||||
const internalReport = require('../internal/report');
|
import jwtdecode from "../lib/express/jwt-decode.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
router
|
router
|
||||||
.route('/hosts')
|
.route("/hosts")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -18,12 +18,12 @@ router
|
|||||||
* GET /reports/hosts
|
* GET /reports/hosts
|
||||||
*/
|
*/
|
||||||
.get(jwtdecode(), (_, res, next) => {
|
.get(jwtdecode(), (_, res, next) => {
|
||||||
internalReport.getHostsReport(res.locals.access)
|
internalReport
|
||||||
|
.getHostsReport(res.locals.access)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
res.status(200)
|
res.status(200).send(data);
|
||||||
.send(data);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const schema = require('../schema');
|
import PACKAGE from "../package.json" with { type: "json" };
|
||||||
const PACKAGE = require('../package.json');
|
import { getCompiledSchema } from "../schema/index.js";
|
||||||
|
|
||||||
const router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -18,21 +18,21 @@ router
|
|||||||
* GET /schema
|
* GET /schema
|
||||||
*/
|
*/
|
||||||
.get(async (req, res) => {
|
.get(async (req, res) => {
|
||||||
let swaggerJSON = await schema.getCompiledSchema();
|
const swaggerJSON = await getCompiledSchema();
|
||||||
|
|
||||||
let proto = req.protocol;
|
let proto = req.protocol;
|
||||||
if (typeof req.headers['x-forwarded-proto'] !== 'undefined' && req.headers['x-forwarded-proto']) {
|
if (typeof req.headers["x-forwarded-proto"] !== "undefined" && req.headers["x-forwarded-proto"]) {
|
||||||
proto = req.headers['x-forwarded-proto'];
|
proto = req.headers["x-forwarded-proto"];
|
||||||
}
|
}
|
||||||
|
|
||||||
let origin = proto + '://' + req.hostname;
|
let origin = `${proto}://${req.hostname}`;
|
||||||
if (typeof req.headers.origin !== 'undefined' && req.headers.origin) {
|
if (typeof req.headers.origin !== "undefined" && req.headers.origin) {
|
||||||
origin = req.headers.origin;
|
origin = req.headers.origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
swaggerJSON.info.version = PACKAGE.version;
|
swaggerJSON.info.version = PACKAGE.version;
|
||||||
swaggerJSON.servers[0].url = origin + '/api';
|
swaggerJSON.servers[0].url = `${origin}/api`;
|
||||||
res.status(200).send(swaggerJSON);
|
res.status(200).send(swaggerJSON);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../lib/validator');
|
import internalSetting from "../internal/setting.js";
|
||||||
const jwtdecode = require('../lib/express/jwt-decode');
|
import jwtdecode from "../lib/express/jwt-decode.js";
|
||||||
const apiValidator = require('../lib/validator/api');
|
import apiValidator from "../lib/validator/api.js";
|
||||||
const internalSetting = require('../internal/setting');
|
import validator from "../lib/validator/index.js";
|
||||||
const schema = require('../schema');
|
import { getValidationSchema } from "../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/settings
|
* /api/settings
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -27,10 +27,10 @@ router
|
|||||||
* Retrieve all settings
|
* Retrieve all settings
|
||||||
*/
|
*/
|
||||||
.get((_, res, next) => {
|
.get((_, res, next) => {
|
||||||
internalSetting.getAll(res.locals.access)
|
internalSetting
|
||||||
|
.getAll(res.locals.access)
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
res.status(200)
|
res.status(200).send(rows);
|
||||||
.send(rows);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -41,7 +41,7 @@ router
|
|||||||
* /api/settings/something
|
* /api/settings/something
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:setting_id')
|
.route("/:setting_id")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -53,26 +53,28 @@ router
|
|||||||
* Retrieve a specific setting
|
* Retrieve a specific setting
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['setting_id'],
|
{
|
||||||
|
required: ["setting_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
setting_id: {
|
setting_id: {
|
||||||
type: 'string',
|
type: "string",
|
||||||
minLength: 1
|
minLength: 1,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
setting_id: req.params.setting_id
|
{
|
||||||
})
|
setting_id: req.params.setting_id,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalSetting.get(res.locals.access, {
|
return internalSetting.get(res.locals.access, {
|
||||||
id: data.setting_id
|
id: data.setting_id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
res.status(200)
|
res.status(200).send(row);
|
||||||
.send(row);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -83,16 +85,15 @@ router
|
|||||||
* Update and existing setting
|
* Update and existing setting
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/settings/{settingID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/settings/{settingID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = req.params.setting_id;
|
payload.id = req.params.setting_id;
|
||||||
return internalSetting.update(res.locals.access, payload);
|
return internalSetting.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const jwtdecode = require('../lib/express/jwt-decode');
|
import internalToken from "../internal/token.js";
|
||||||
const apiValidator = require('../lib/validator/api');
|
import jwtdecode from "../lib/express/jwt-decode.js";
|
||||||
const internalToken = require('../internal/token');
|
import apiValidator from "../lib/validator/api.js";
|
||||||
const schema = require('../schema');
|
import { getValidationSchema } from "../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -24,13 +24,13 @@ router
|
|||||||
* for services like Job board and Worker.
|
* for services like Job board and Worker.
|
||||||
*/
|
*/
|
||||||
.get(jwtdecode(), (req, res, next) => {
|
.get(jwtdecode(), (req, res, next) => {
|
||||||
internalToken.getFreshToken(res.locals.access, {
|
internalToken
|
||||||
expiry: (typeof req.query.expiry !== 'undefined' ? req.query.expiry : null),
|
.getFreshToken(res.locals.access, {
|
||||||
scope: (typeof req.query.scope !== 'undefined' ? req.query.scope : null)
|
expiry: typeof req.query.expiry !== "undefined" ? req.query.expiry : null,
|
||||||
|
scope: typeof req.query.scope !== "undefined" ? req.query.scope : null,
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
res.status(200)
|
res.status(200).send(data);
|
||||||
.send(data);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -41,13 +41,12 @@ router
|
|||||||
* Create a new Token
|
* Create a new Token
|
||||||
*/
|
*/
|
||||||
.post(async (req, res, next) => {
|
.post(async (req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/tokens', 'post'), req.body)
|
apiValidator(getValidationSchema("/tokens", "post"), req.body)
|
||||||
.then(internalToken.getTokenFromEmail)
|
.then(internalToken.getTokenFromEmail)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
res.status(200)
|
res.status(200).send(data);
|
||||||
.send(data);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
const express = require('express');
|
import express from "express";
|
||||||
const validator = require('../lib/validator');
|
import internalUser from "../internal/user.js";
|
||||||
const jwtdecode = require('../lib/express/jwt-decode');
|
import jwtdecode from "../lib/express/jwt-decode.js";
|
||||||
const userIdFromMe = require('../lib/express/user-id-from-me');
|
import userIdFromMe from "../lib/express/user-id-from-me.js";
|
||||||
const internalUser = require('../internal/user');
|
import apiValidator from "../lib/validator/api.js";
|
||||||
const apiValidator = require('../lib/validator/api');
|
import validator from "../lib/validator/index.js";
|
||||||
const schema = require('../schema');
|
import { getValidationSchema } from "../schema/index.js";
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* /api/users
|
* /api/users
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/')
|
.route("/")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -28,26 +28,28 @@ router
|
|||||||
* Retrieve all users
|
* Retrieve all users
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
|
{
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'common#/properties/query'
|
$ref: "common#/properties/query",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null),
|
{
|
||||||
query: (typeof req.query.query === 'string' ? req.query.query : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
query: typeof req.query.query === "string" ? req.query.query : null,
|
||||||
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalUser.getAll(res.locals.access, data.expand, data.query);
|
return internalUser.getAll(res.locals.access, data.expand, data.query);
|
||||||
})
|
})
|
||||||
.then((users) => {
|
.then((users) => {
|
||||||
res.status(200)
|
res.status(200).send(users);
|
||||||
.send(users);
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -62,13 +64,12 @@ router
|
|||||||
* Create a new User
|
* Create a new User
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/users', 'post'), req.body)
|
apiValidator(getValidationSchema("/users", "post"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
return internalUser.create(res.locals.access, payload);
|
return internalUser.create(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -79,7 +80,7 @@ router
|
|||||||
* /api/users/123
|
* /api/users/123
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:user_id')
|
.route("/:user_id")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -92,31 +93,33 @@ router
|
|||||||
* Retrieve a specific user
|
* Retrieve a specific user
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
validator({
|
validator(
|
||||||
required: ['user_id'],
|
{
|
||||||
|
required: ["user_id"],
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {
|
properties: {
|
||||||
user_id: {
|
user_id: {
|
||||||
$ref: 'common#/properties/id'
|
$ref: "common#/properties/id",
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'common#/properties/expand'
|
$ref: "common#/properties/expand",
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
user_id: req.params.user_id,
|
user_id: req.params.user_id,
|
||||||
expand: (typeof req.query.expand === 'string' ? req.query.expand.split(',') : null)
|
expand: typeof req.query.expand === "string" ? req.query.expand.split(",") : null,
|
||||||
})
|
},
|
||||||
|
)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
return internalUser.get(res.locals.access, {
|
return internalUser.get(res.locals.access, {
|
||||||
id: data.user_id,
|
id: data.user_id,
|
||||||
expand: data.expand,
|
expand: data.expand,
|
||||||
omit: internalUser.getUserOmisionsByAccess(res.locals.access, data.user_id)
|
omit: internalUser.getUserOmisionsByAccess(res.locals.access, data.user_id),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
res.status(200)
|
res.status(200).send(user);
|
||||||
.send(user);
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@@ -130,14 +133,13 @@ router
|
|||||||
* Update and existing user
|
* Update and existing user
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/users/{userID}', 'put'), req.body)
|
apiValidator(getValidationSchema("/users/{userID}", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = req.params.user_id;
|
payload.id = req.params.user_id;
|
||||||
return internalUser.update(res.locals.access, payload);
|
return internalUser.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
@@ -148,10 +150,10 @@ router
|
|||||||
* Update and existing user
|
* Update and existing user
|
||||||
*/
|
*/
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
internalUser.delete(res.locals.access, {id: req.params.user_id})
|
internalUser
|
||||||
|
.delete(res.locals.access, { id: req.params.user_id })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -162,8 +164,8 @@ router
|
|||||||
* /api/users/123/auth
|
* /api/users/123/auth
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:user_id/auth')
|
.route("/:user_id/auth")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -175,14 +177,13 @@ router
|
|||||||
* Update password for a user
|
* Update password for a user
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/users/{userID}/auth', 'put'), req.body)
|
apiValidator(getValidationSchema("/users/{userID}/auth", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = req.params.user_id;
|
payload.id = req.params.user_id;
|
||||||
return internalUser.setPassword(res.locals.access, payload);
|
return internalUser.setPassword(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -193,8 +194,8 @@ router
|
|||||||
* /api/users/123/permissions
|
* /api/users/123/permissions
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:user_id/permissions')
|
.route("/:user_id/permissions")
|
||||||
.options((req, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
.all(jwtdecode())
|
.all(jwtdecode())
|
||||||
@@ -206,14 +207,13 @@ router
|
|||||||
* Set some or all permissions for a user
|
* Set some or all permissions for a user
|
||||||
*/
|
*/
|
||||||
.put((req, res, next) => {
|
.put((req, res, next) => {
|
||||||
apiValidator(schema.getValidationSchema('/users/{userID}/permissions', 'put'), req.body)
|
apiValidator(getValidationSchema("/users/{userID}/permissions", "put"), req.body)
|
||||||
.then((payload) => {
|
.then((payload) => {
|
||||||
payload.id = req.params.user_id;
|
payload.id = req.params.user_id;
|
||||||
return internalUser.setPermissions(res.locals.access, payload);
|
return internalUser.setPermissions(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
@@ -224,7 +224,7 @@ router
|
|||||||
* /api/users/123/login
|
* /api/users/123/login
|
||||||
*/
|
*/
|
||||||
router
|
router
|
||||||
.route('/:user_id/login')
|
.route("/:user_id/login")
|
||||||
.options((_, res) => {
|
.options((_, res) => {
|
||||||
res.sendStatus(204);
|
res.sendStatus(204);
|
||||||
})
|
})
|
||||||
@@ -236,12 +236,12 @@ router
|
|||||||
* Log in as a user
|
* Log in as a user
|
||||||
*/
|
*/
|
||||||
.post((req, res, next) => {
|
.post((req, res, next) => {
|
||||||
internalUser.loginAs(res.locals.access, {id: parseInt(req.params.user_id, 10)})
|
internalUser
|
||||||
|
.loginAs(res.locals.access, { id: Number.parseInt(req.params.user_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
export default router;
|
||||||
|
|||||||
@@ -1,23 +1,26 @@
|
|||||||
const refParser = require('@apidevtools/json-schema-ref-parser');
|
import { dirname } from "node:path";
|
||||||
|
import { fileURLToPath } from "node:url";
|
||||||
|
import $RefParser from "@apidevtools/json-schema-ref-parser";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = dirname(__filename);
|
||||||
|
|
||||||
let compiledSchema = null;
|
let compiledSchema = null;
|
||||||
|
|
||||||
module.exports = {
|
/**
|
||||||
|
|
||||||
/**
|
|
||||||
* Compiles the schema, by dereferencing it, only once
|
* Compiles the schema, by dereferencing it, only once
|
||||||
* and returns the memory cached value
|
* and returns the memory cached value
|
||||||
*/
|
*/
|
||||||
getCompiledSchema: async () => {
|
const getCompiledSchema = async () => {
|
||||||
if (compiledSchema === null) {
|
if (compiledSchema === null) {
|
||||||
compiledSchema = await refParser.dereference(__dirname + '/swagger.json', {
|
compiledSchema = await $RefParser.dereference(`${__dirname}/swagger.json`, {
|
||||||
mutateInputSchema: false,
|
mutateInputSchema: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return compiledSchema;
|
return compiledSchema;
|
||||||
},
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scans the schema for the validation schema for the given path and method
|
* Scans the schema for the validation schema for the given path and method
|
||||||
* and returns it.
|
* and returns it.
|
||||||
*
|
*
|
||||||
@@ -25,17 +28,19 @@ module.exports = {
|
|||||||
* @param {string} method
|
* @param {string} method
|
||||||
* @returns string|null
|
* @returns string|null
|
||||||
*/
|
*/
|
||||||
getValidationSchema: (path, method) => {
|
const getValidationSchema = (path, method) => {
|
||||||
if (compiledSchema !== null &&
|
if (
|
||||||
typeof compiledSchema.paths[path] !== 'undefined' &&
|
compiledSchema !== null &&
|
||||||
typeof compiledSchema.paths[path][method] !== 'undefined' &&
|
typeof compiledSchema.paths[path] !== "undefined" &&
|
||||||
typeof compiledSchema.paths[path][method].requestBody !== 'undefined' &&
|
typeof compiledSchema.paths[path][method] !== "undefined" &&
|
||||||
typeof compiledSchema.paths[path][method].requestBody.content !== 'undefined' &&
|
typeof compiledSchema.paths[path][method].requestBody !== "undefined" &&
|
||||||
typeof compiledSchema.paths[path][method].requestBody.content['application/json'] !== 'undefined' &&
|
typeof compiledSchema.paths[path][method].requestBody.content !== "undefined" &&
|
||||||
typeof compiledSchema.paths[path][method].requestBody.content['application/json'].schema !== 'undefined'
|
typeof compiledSchema.paths[path][method].requestBody.content["application/json"] !== "undefined" &&
|
||||||
|
typeof compiledSchema.paths[path][method].requestBody.content["application/json"].schema !== "undefined"
|
||||||
) {
|
) {
|
||||||
return compiledSchema.paths[path][method].requestBody.content['application/json'].schema;
|
return compiledSchema.paths[path][method].requestBody.content["application/json"].schema;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { getCompiledSchema, getValidationSchema };
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
// docker exec npm_core /command/s6-setuidgid 1000:1000 bash -c "/app/scripts/install-certbot-plugins"
|
// docker exec npm_core /command/s6-setuidgid 1000:1000 bash -c "/app/scripts/install-certbot-plugins"
|
||||||
//
|
//
|
||||||
|
|
||||||
const dnsPlugins = require('../global/certbot-dns-plugins.json');
|
import dnsPlugins from "../global/certbot-dns-plugins.json" with { type: "json" };
|
||||||
const certbot = require('../lib/certbot');
|
import { installPlugin } from "../lib/certbot.js";
|
||||||
const logger = require('../logger').certbot;
|
import { certbot as logger } from "../logger.js";
|
||||||
const batchflow = require('batchflow');
|
import batchflow from "batchflow";
|
||||||
|
|
||||||
let hasErrors = false;
|
let hasErrors = false;
|
||||||
let failingPlugins = [];
|
let failingPlugins = [];
|
||||||
@@ -25,7 +25,7 @@ if (process.argv.length > 2) {
|
|||||||
|
|
||||||
batchflow(pluginKeys).sequential()
|
batchflow(pluginKeys).sequential()
|
||||||
.each((i, pluginKey, next) => {
|
.each((i, pluginKey, next) => {
|
||||||
certbot.installPlugin(pluginKey)
|
installPlugin(pluginKey)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
|
|||||||
106
backend/setup.js
106
backend/setup.js
@@ -1,12 +1,12 @@
|
|||||||
const config = require('./lib/config');
|
import { installPlugins } from "./lib/certbot.js";
|
||||||
const logger = require('./logger').setup;
|
import utils from "./lib/utils.js";
|
||||||
const certificateModel = require('./models/certificate');
|
import { setup as logger } from "./logger.js";
|
||||||
const userModel = require('./models/user');
|
import authModel from "./models/auth.js";
|
||||||
const userPermissionModel = require('./models/user_permission');
|
import certificateModel from "./models/certificate.js";
|
||||||
const utils = require('./lib/utils');
|
import settingModel from "./models/setting.js";
|
||||||
const authModel = require('./models/auth');
|
import userModel from "./models/user.js";
|
||||||
const settingModel = require('./models/setting');
|
import userPermissionModel from "./models/user_permission.js";
|
||||||
const certbot = require('./lib/certbot');
|
|
||||||
/**
|
/**
|
||||||
* Creates a default admin users if one doesn't already exist in the database
|
* Creates a default admin users if one doesn't already exist in the database
|
||||||
*
|
*
|
||||||
@@ -15,24 +15,24 @@ const certbot = require('./lib/certbot');
|
|||||||
const setupDefaultUser = () => {
|
const setupDefaultUser = () => {
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.select('id', )
|
.select("id")
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.first()
|
.first()
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
// Create a new user and set password
|
// Create a new user and set password
|
||||||
const email = (process.env.INITIAL_ADMIN_EMAIL || 'admin@example.com').toLowerCase();
|
const email = (process.env.INITIAL_ADMIN_EMAIL || 'admin@example.com').toLowerCase();
|
||||||
const password = process.env.INITIAL_ADMIN_PASSWORD || 'changeme';
|
const password = process.env.INITIAL_ADMIN_PASSWORD || "changeme";
|
||||||
|
|
||||||
logger.info(`Creating a new user: ${email} with password: ${password}`);
|
logger.info(`Creating a new user: ${email} with password: ${password}`);
|
||||||
|
|
||||||
const data = {
|
const data = {
|
||||||
is_deleted: 0,
|
is_deleted: 0,
|
||||||
email: email,
|
email: email,
|
||||||
name: 'Administrator',
|
name: "Administrator",
|
||||||
nickname: 'Admin',
|
nickname: "Admin",
|
||||||
avatar: '',
|
avatar: "",
|
||||||
roles: ['admin'],
|
roles: ["admin"],
|
||||||
};
|
};
|
||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
@@ -43,29 +43,28 @@ const setupDefaultUser = () => {
|
|||||||
.query()
|
.query()
|
||||||
.insert({
|
.insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
type: 'password',
|
type: "password",
|
||||||
secret: password,
|
secret: password,
|
||||||
meta: {},
|
meta: {},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return userPermissionModel.query().insert({
|
return userPermissionModel.query().insert({
|
||||||
user_id: user.id,
|
user_id: user.id,
|
||||||
visibility: 'all',
|
visibility: "all",
|
||||||
proxy_hosts: 'manage',
|
proxy_hosts: "manage",
|
||||||
redirection_hosts: 'manage',
|
redirection_hosts: "manage",
|
||||||
dead_hosts: 'manage',
|
dead_hosts: "manage",
|
||||||
streams: 'manage',
|
streams: "manage",
|
||||||
access_lists: 'manage',
|
access_lists: "manage",
|
||||||
certificates: 'manage',
|
certificates: "manage",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('Initial admin setup completed');
|
logger.info("Initial admin setup completed");
|
||||||
});
|
});
|
||||||
} else if (config.debug()) {
|
|
||||||
logger.info('Admin user setup not required');
|
|
||||||
}
|
}
|
||||||
|
logger.debug("Admin user setup not required");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -77,27 +76,25 @@ const setupDefaultUser = () => {
|
|||||||
const setupDefaultSettings = () => {
|
const setupDefaultSettings = () => {
|
||||||
return settingModel
|
return settingModel
|
||||||
.query()
|
.query()
|
||||||
.select('id')
|
.select("id")
|
||||||
.where({id: 'default-site'})
|
.where({ id: "default-site" })
|
||||||
.first()
|
.first()
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row || !row.id) {
|
if (!row || !row.id) {
|
||||||
settingModel
|
settingModel
|
||||||
.query()
|
.query()
|
||||||
.insert({
|
.insert({
|
||||||
id: 'default-site',
|
id: "default-site",
|
||||||
name: 'Default Site',
|
name: "Default Site",
|
||||||
description: 'What to show when Nginx is hit with an unknown Host',
|
description: "What to show when Nginx is hit with an unknown Host",
|
||||||
value: 'congratulations',
|
value: "congratulations",
|
||||||
meta: {},
|
meta: {},
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('Default settings added');
|
logger.info("Default settings added");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (config.debug()) {
|
logger.debug("Default setting setup not required");
|
||||||
logger.info('Default setting setup not required');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -109,10 +106,10 @@ const setupDefaultSettings = () => {
|
|||||||
const setupCertbotPlugins = () => {
|
const setupCertbotPlugins = () => {
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where("is_deleted", 0)
|
||||||
.andWhere('provider', 'letsencrypt')
|
.andWhere("provider", "letsencrypt")
|
||||||
.then((certificates) => {
|
.then((certificates) => {
|
||||||
if (certificates && certificates.length) {
|
if (certificates?.length) {
|
||||||
const plugins = [];
|
const plugins = [];
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
@@ -125,18 +122,19 @@ const setupCertbotPlugins = () => {
|
|||||||
// Make sure credentials file exists
|
// Make sure credentials file exists
|
||||||
const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
|
const credentials_loc = `/etc/letsencrypt/credentials/credentials-${certificate.id}`;
|
||||||
// Escape single quotes and backslashes
|
// Escape single quotes and backslashes
|
||||||
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
const escapedCredentials = certificate.meta.dns_provider_credentials
|
||||||
|
.replaceAll("'", "\\'")
|
||||||
|
.replaceAll("\\", "\\\\");
|
||||||
const credentials_cmd = `[ -f '${credentials_loc}' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo '${escapedCredentials}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'; }`;
|
const credentials_cmd = `[ -f '${credentials_loc}' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo '${escapedCredentials}' > '${credentials_loc}' && chmod 600 '${credentials_loc}'; }`;
|
||||||
promises.push(utils.exec(credentials_cmd));
|
promises.push(utils.exec(credentials_cmd));
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
return certbot.installPlugins(plugins)
|
return installPlugins(plugins).then(() => {
|
||||||
.then(() => {
|
|
||||||
if (promises.length) {
|
if (promises.length) {
|
||||||
return Promise.all(promises)
|
return Promise.all(promises).then(() => {
|
||||||
.then(() => {
|
logger.info(`Added Certbot plugins ${plugins.join(", ")}`);
|
||||||
logger.info(`Added Certbot plugins ${plugins.join(', ')}`);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -144,7 +142,6 @@ const setupCertbotPlugins = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Starts a timer to call run the logrotation binary every two days
|
* Starts a timer to call run the logrotation binary every two days
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
@@ -154,18 +151,17 @@ const setupLogrotation = () => {
|
|||||||
|
|
||||||
const runLogrotate = async () => {
|
const runLogrotate = async () => {
|
||||||
try {
|
try {
|
||||||
await utils.exec('logrotate /etc/logrotate.d/nginx-proxy-manager');
|
await utils.exec("logrotate /etc/logrotate.d/nginx-proxy-manager");
|
||||||
logger.info('Logrotate completed.');
|
logger.info("Logrotate completed.");
|
||||||
} catch (e) { logger.warn(e); }
|
} catch (e) {
|
||||||
|
logger.warn(e);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
logger.info('Logrotate Timer initialized');
|
logger.info("Logrotate Timer initialized");
|
||||||
setInterval(runLogrotate, intervalTimeout);
|
setInterval(runLogrotate, intervalTimeout);
|
||||||
// And do this now as well
|
// And do this now as well
|
||||||
return runLogrotate();
|
return runLogrotate();
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = () => setupDefaultUser()
|
export default () => setupDefaultUser().then(setupDefaultSettings).then(setupCertbotPlugins).then(setupLogrotation);
|
||||||
.then(setupDefaultSettings)
|
|
||||||
.then(setupCertbotPlugins)
|
|
||||||
.then(setupLogrotation);
|
|
||||||
|
|||||||
17
backend/validate-schema.js
Normal file → Executable file
17
backend/validate-schema.js
Normal file → Executable file
@@ -1,16 +1,19 @@
|
|||||||
const SwaggerParser = require('@apidevtools/swagger-parser');
|
#!/usr/bin/node
|
||||||
const chalk = require('chalk');
|
|
||||||
const schema = require('./schema');
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
||||||
|
import chalk from "chalk";
|
||||||
|
import { getCompiledSchema } from "./schema/index.js";
|
||||||
|
|
||||||
const log = console.log;
|
const log = console.log;
|
||||||
|
|
||||||
schema.getCompiledSchema().then(async (swaggerJSON) => {
|
getCompiledSchema().then(async (swaggerJSON) => {
|
||||||
try {
|
try {
|
||||||
const api = await SwaggerParser.validate(swaggerJSON);
|
const api = await SwaggerParser.validate(swaggerJSON);
|
||||||
console.log('API name: %s, Version: %s', api.info.title, api.info.version);
|
console.log("API name: %s, Version: %s", api.info.title, api.info.version);
|
||||||
log(chalk.green('❯ Schema is valid'));
|
log(chalk.green("❯ Schema is valid"));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
log(chalk.red('❯', e.message), '\n');
|
log(chalk.red("❯", e.message), "\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
2501
backend/yarn.lock
2501
backend/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,7 @@ server {
|
|||||||
|
|
||||||
location /api/ {
|
location /api/ {
|
||||||
add_header X-Served-By $host;
|
add_header X-Served-By $host;
|
||||||
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
@@ -23,7 +24,14 @@ server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
index index.html;
|
add_header X-Served-By $host;
|
||||||
try_files $uri $uri.html $uri/ /index.html;
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection "Upgrade";
|
||||||
|
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
proxy_pass http://127.0.0.1:5173;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ if [ "$DEVELOPMENT" = 'true' ]; then
|
|||||||
|
|
||||||
log_info 'Starting frontend ...'
|
log_info 'Starting frontend ...'
|
||||||
s6-setuidgid "$PUID:$PGID" yarn install
|
s6-setuidgid "$PUID:$PGID" yarn install
|
||||||
exec s6-setuidgid "$PUID:$PGID" yarn watch
|
exec s6-setuidgid "$PUID:$PGID" yarn dev
|
||||||
else
|
else
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"presets": [
|
|
||||||
[
|
|
||||||
"env",
|
|
||||||
{
|
|
||||||
"targets": {
|
|
||||||
"browsers": [
|
|
||||||
"Chrome >= 65"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"debug": false,
|
|
||||||
"modules": false,
|
|
||||||
"useBuiltIns": "usage"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
]
|
|
||||||
}
|
|
||||||
24
frontend/.gitignore
vendored
24
frontend/.gitignore
vendored
@@ -1,4 +1,22 @@
|
|||||||
dist
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
node_modules
|
node_modules
|
||||||
webpack_stats.html
|
dist
|
||||||
yarn-error.log
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|||||||
91
frontend/biome.json
Normal file
91
frontend/biome.json
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://biomejs.dev/schemas/2.2.2/schema.json",
|
||||||
|
"vcs": {
|
||||||
|
"enabled": true,
|
||||||
|
"clientKind": "git",
|
||||||
|
"useIgnoreFile": true
|
||||||
|
},
|
||||||
|
"files": {
|
||||||
|
"ignoreUnknown": false,
|
||||||
|
"includes": [
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
"**/*.js",
|
||||||
|
"**/*.jsx",
|
||||||
|
"!**/dist/**/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"formatter": {
|
||||||
|
"enabled": true,
|
||||||
|
"indentStyle": "tab",
|
||||||
|
"indentWidth": 4,
|
||||||
|
"lineWidth": 120,
|
||||||
|
"formatWithErrors": true
|
||||||
|
},
|
||||||
|
"assist": {
|
||||||
|
"actions": {
|
||||||
|
"source": {
|
||||||
|
"organizeImports": {
|
||||||
|
"level": "on",
|
||||||
|
"options": {
|
||||||
|
"groups": [
|
||||||
|
":BUN:",
|
||||||
|
":NODE:",
|
||||||
|
[
|
||||||
|
"npm:*",
|
||||||
|
"npm:*/**"
|
||||||
|
],
|
||||||
|
":PACKAGE_WITH_PROTOCOL:",
|
||||||
|
":URL:",
|
||||||
|
":PACKAGE:",
|
||||||
|
[
|
||||||
|
"/src/*",
|
||||||
|
"/src/**"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"/**"
|
||||||
|
],
|
||||||
|
[
|
||||||
|
"#*",
|
||||||
|
"#*/**"
|
||||||
|
],
|
||||||
|
":PATH:"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"linter": {
|
||||||
|
"enabled": true,
|
||||||
|
"rules": {
|
||||||
|
"recommended": true,
|
||||||
|
"correctness": {
|
||||||
|
"useUniqueElementIds": "off"
|
||||||
|
},
|
||||||
|
"suspicious": {
|
||||||
|
"noExplicitAny": "off"
|
||||||
|
},
|
||||||
|
"performance": {
|
||||||
|
"noDelete": "off"
|
||||||
|
},
|
||||||
|
"nursery": "off",
|
||||||
|
"a11y": {
|
||||||
|
"useSemanticElements": "off",
|
||||||
|
"useValidAnchor": "off"
|
||||||
|
},
|
||||||
|
"style": {
|
||||||
|
"noParameterAssign": "error",
|
||||||
|
"useAsConstAssertion": "error",
|
||||||
|
"useDefaultParameterLast": "error",
|
||||||
|
"useEnumInitializers": "error",
|
||||||
|
"useSelfClosingElements": "error",
|
||||||
|
"useSingleVarDeclarator": "error",
|
||||||
|
"noUnusedTemplateLiteral": "error",
|
||||||
|
"useNumberNamespace": "error",
|
||||||
|
"noInferrableTypes": "error",
|
||||||
|
"noUselessElse": "error"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
172
frontend/check-locales.cjs
Executable file
172
frontend/check-locales.cjs
Executable file
@@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
// This file does a few things to ensure that the Locales are present and valid:
|
||||||
|
// - Ensures that the name of the locale exists in the language list
|
||||||
|
// - Ensures that each locale contains the translations used in the application
|
||||||
|
// - Ensures that there are no unused translations in the locale files
|
||||||
|
// - Also checks the error messages returned by the backend
|
||||||
|
|
||||||
|
const allLocales = [
|
||||||
|
["en", "en-US"],
|
||||||
|
["de", "de-DE"],
|
||||||
|
["fa", "fa-IR"],
|
||||||
|
];
|
||||||
|
|
||||||
|
const ignoreUnused = [
|
||||||
|
/^capability\..*$/,
|
||||||
|
/^status\..*$/,
|
||||||
|
/^type\..*$/,
|
||||||
|
];
|
||||||
|
|
||||||
|
const { spawnSync } = require("child_process");
|
||||||
|
const fs = require("fs");
|
||||||
|
|
||||||
|
const tmp = require("tmp");
|
||||||
|
|
||||||
|
// Parse backend errors
|
||||||
|
const BACKEND_ERRORS_FILE = "../backend/internal/errors/errors.go";
|
||||||
|
const BACKEND_ERRORS = [];
|
||||||
|
/*
|
||||||
|
try {
|
||||||
|
const backendErrorsContent = fs.readFileSync(BACKEND_ERRORS_FILE, "utf8");
|
||||||
|
const backendErrorsContentRes = [
|
||||||
|
...backendErrorsContent.matchAll(/(?:errors|eris)\.New\("([^"]+)"\)/g),
|
||||||
|
];
|
||||||
|
backendErrorsContentRes.map((item) => {
|
||||||
|
BACKEND_ERRORS.push("error." + item[1]);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
} catch (err) {
|
||||||
|
console.log("\x1b[31m%s\x1b[0m", err);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// get all translations used in frontend code
|
||||||
|
const tmpobj = tmp.fileSync({ postfix: ".json" });
|
||||||
|
spawnSync("yarn", ["locale-extract", "--out-file", tmpobj.name]);
|
||||||
|
|
||||||
|
const allLocalesInProject = require(tmpobj.name);
|
||||||
|
|
||||||
|
// get list og language names and locales
|
||||||
|
const langList = require("./src/locale/src/lang-list.json");
|
||||||
|
|
||||||
|
// store a list of all validation errors
|
||||||
|
const allErrors = [];
|
||||||
|
const allWarnings = [];
|
||||||
|
const allKeys = [];
|
||||||
|
|
||||||
|
const checkLangList = (fullCode) => {
|
||||||
|
const key = "locale-" + fullCode;
|
||||||
|
if (typeof langList[key] === "undefined") {
|
||||||
|
allErrors.push(
|
||||||
|
"ERROR: `" + key + "` language does not exist in lang-list.json",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const compareLocale = (locale) => {
|
||||||
|
const projectLocaleKeys = Object.keys(allLocalesInProject);
|
||||||
|
// Check that locale contains the items used in the codebase
|
||||||
|
projectLocaleKeys.map((key) => {
|
||||||
|
if (typeof locale.data[key] === "undefined") {
|
||||||
|
allErrors.push(
|
||||||
|
"ERROR: `" + locale[0] + "` does not contain item: `" + key + "`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
// Check that locale contains all error.* items
|
||||||
|
BACKEND_ERRORS.forEach((key) => {
|
||||||
|
if (typeof locale.data[key] === "undefined") {
|
||||||
|
allErrors.push(
|
||||||
|
"ERROR: `" + locale[0] + "` does not contain item: `" + key + "`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check that locale does not contain items not used in the codebase
|
||||||
|
const localeKeys = Object.keys(locale.data);
|
||||||
|
localeKeys.map((key) => {
|
||||||
|
let ignored = false;
|
||||||
|
ignoreUnused.map((regex) => {
|
||||||
|
if (key.match(regex)) {
|
||||||
|
ignored = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ignored && typeof allLocalesInProject[key] === "undefined") {
|
||||||
|
// ensure this key doesn't exist in the backend errors either
|
||||||
|
if (!BACKEND_ERRORS.includes(key)) {
|
||||||
|
allErrors.push(
|
||||||
|
"ERROR: `" + locale[0] + "` contains unused item: `" + key + "`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this key to allKeys
|
||||||
|
if (allKeys.indexOf(key) === -1) {
|
||||||
|
allKeys.push(key);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Checks for any keys missing from this locale, that
|
||||||
|
// have been defined in any other locales
|
||||||
|
const checkForMissing = (locale) => {
|
||||||
|
allKeys.forEach((key) => {
|
||||||
|
if (typeof locale.data[key] === "undefined") {
|
||||||
|
let ignored = false;
|
||||||
|
ignoreMissing.map((regex) => {
|
||||||
|
if (key.match(regex)) {
|
||||||
|
ignored = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!ignored) {
|
||||||
|
allWarnings.push(
|
||||||
|
"WARN: `" + locale[0] + "` does not contain item: `" + key + "`",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Local all locale data
|
||||||
|
allLocales.map((locale, idx) => {
|
||||||
|
checkLangList(locale[1]);
|
||||||
|
allLocales[idx].data = require("./src/locale/src/" + locale[0] + ".json");
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Verify all locale data
|
||||||
|
allLocales.map((locale) => {
|
||||||
|
compareLocale(locale);
|
||||||
|
checkForMissing(locale);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (allErrors.length) {
|
||||||
|
allErrors.map((err) => {
|
||||||
|
console.log("\x1b[31m%s\x1b[0m", err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (allWarnings.length) {
|
||||||
|
allWarnings.map((err) => {
|
||||||
|
console.log("\x1b[33m%s\x1b[0m", err);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allErrors.length) {
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("\x1b[32m%s\x1b[0m", "Locale check passed");
|
||||||
|
process.exit(0);
|
||||||
@@ -1 +0,0 @@
|
|||||||
../node_modules/tabler-ui/dist/assets/fonts/feather
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user