update nginx/dep updates/fix eslint/change line endings
Signed-off-by: Zoey <zoey@z0ey.de>
This commit is contained in:
parent
ef5ac4cbd8
commit
906d7ce04a
96 changed files with 2579 additions and 2859 deletions
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
* text=auto
|
6
.github/workflows/docker.yml
vendored
6
.github/workflows/docker.yml
vendored
|
@ -10,6 +10,7 @@ on:
|
||||||
- backend/**
|
- backend/**
|
||||||
- global/**
|
- global/**
|
||||||
- rootfs/**
|
- rootfs/**
|
||||||
|
- src/**
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- .github/workflows/docker.yml
|
- .github/workflows/docker.yml
|
||||||
|
@ -18,6 +19,7 @@ on:
|
||||||
- backend/**
|
- backend/**
|
||||||
- global/**
|
- global/**
|
||||||
- rootfs/**
|
- rootfs/**
|
||||||
|
- src/**
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
|
@ -68,8 +70,6 @@ jobs:
|
||||||
tags: |
|
tags: |
|
||||||
${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
|
${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
|
||||||
ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
|
ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ github.ref_name }}
|
||||||
build-args: |
|
|
||||||
"BUILD=${{ steps.rn.outputs.rn }}"
|
|
||||||
- name: show version
|
- name: show version
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
if: ${{ github.event_name != 'pull_request' }}
|
||||||
run: |
|
run: |
|
||||||
|
@ -88,8 +88,6 @@ jobs:
|
||||||
platforms: linux/amd64,linux/arm64 #,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4 #,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
|
platforms: linux/amd64,linux/arm64 #,linux/amd64/v2,linux/amd64/v3,linux/amd64/v4 #,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6
|
||||||
push: ${{ github.event_name == 'pull_request' }}
|
push: ${{ github.event_name == 'pull_request' }}
|
||||||
tags: ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }}
|
tags: ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }}
|
||||||
build-args: |
|
|
||||||
"BUILD=${{ steps.rn.outputs.rn }}"
|
|
||||||
- name: show version (PR)
|
- name: show version (PR)
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
if: ${{ github.event_name == 'pull_request' }}
|
||||||
run: docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }} -V
|
run: docker run --rm --entrypoint nginx ghcr.io/${{ steps.un.outputs.un }}/${{ steps.rn.outputs.rn }}:${{ steps.pr.outputs.pr }} -V
|
||||||
|
|
3
.github/workflows/dockerlint.yml
vendored
3
.github/workflows/dockerlint.yml
vendored
|
@ -18,9 +18,10 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
DOCKERFILES="$(find . -name "*Dockerfile*")"
|
DOCKERFILES="$(find . -name "*Dockerfile*")"
|
||||||
for file in $(echo "$DOCKERFILES" | tr " " "\n"); do
|
for file in $(echo "$DOCKERFILES" | tr " " "\n"); do
|
||||||
|
# DL3003 warning: Use WORKDIR to switch to a directory
|
||||||
# DL3018 warning: Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
|
# DL3018 warning: Pin versions in apk add. Instead of `apk add <package>` use `apk add <package>=<version>`
|
||||||
# DL3013 warning: Pin versions in pip. Instead of `pip install <package>` use `pip install <package>==<version>` or `pip install --requirement <requirements file>`
|
# DL3013 warning: Pin versions in pip. Instead of `pip install <package>` use `pip install <package>==<version>` or `pip install --requirement <requirements file>`
|
||||||
hadolint "$file" --ignore DL3013 --ignore DL3018 | tee -a hadolint.log
|
hadolint "$file" --ignore DL3003 --ignore DL3013 --ignore DL3018 | tee -a hadolint.log
|
||||||
done
|
done
|
||||||
if grep -q "DL[0-9]\+\|SC[0-9]\+" hadolint.log; then
|
if grep -q "DL[0-9]\+\|SC[0-9]\+" hadolint.log; then
|
||||||
exit 1
|
exit 1
|
||||||
|
|
2
.github/workflows/json.yml
vendored
2
.github/workflows/json.yml
vendored
|
@ -11,4 +11,4 @@ jobs:
|
||||||
- name: json-syntax-check
|
- name: json-syntax-check
|
||||||
uses: limitusus/json-syntax-check@v2
|
uses: limitusus/json-syntax-check@v2
|
||||||
with:
|
with:
|
||||||
pattern: "\\.json$*"
|
pattern: "\\.json"
|
||||||
|
|
2
.github/workflows/spellcheck.yml
vendored
2
.github/workflows/spellcheck.yml
vendored
|
@ -15,4 +15,4 @@ jobs:
|
||||||
with:
|
with:
|
||||||
check_filenames: true
|
check_filenames: true
|
||||||
check_hidden: true
|
check_hidden: true
|
||||||
skip: .gitignore,block-exploits.conf,showdown.min.js,jquery.min.js,xregexp-all.js
|
skip: .git,.gitignore,showdown.min.js,jquery.min.js,xregexp-all.js
|
||||||
|
|
10
.github/workflows/update-and-lint.yml
vendored
10
.github/workflows/update-and-lint.yml
vendored
|
@ -1,6 +1,8 @@
|
||||||
name: update-and-lint
|
name: update-and-lint
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
|
branches:
|
||||||
|
- develop
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 */6 * * *"
|
- cron: "0 */6 * * *"
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
@ -13,7 +15,7 @@ jobs:
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: 19
|
node-version: 21
|
||||||
- name: eslint
|
- name: eslint
|
||||||
run: |
|
run: |
|
||||||
cd backend
|
cd backend
|
||||||
|
@ -23,9 +25,9 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
curl -L https://unpkg.com/xregexp/xregexp-all.js -o rootfs/nftd/xregexp-all.js
|
curl -L https://unpkg.com/xregexp/xregexp-all.js -o rootfs/nftd/xregexp-all.js
|
||||||
curl -L https://unpkg.com/showdown/dist/showdown.min.js -o rootfs/nftd/showdown.min.js
|
curl -L https://unpkg.com/showdown/dist/showdown.min.js -o rootfs/nftd/showdown.min.js
|
||||||
curl -L https://code.jquery.com/jquery-"$(git ls-remote --tags https://github.com/jquery/jquery | cut -d/ -f3 | sort -V | tail -1 | sed -E "s/\^\{\}//")".min.js -o rootfs/nftd/jquery.min.js
|
curl -L https://code.jquery.com/jquery-"$(git ls-remote --tags https://github.com/jquery/jquery | cut -d/ -f3 | sort -V | tail -1)".min.js -o rootfs/nftd/jquery.min.js
|
||||||
curl -L https://cdn.jsdelivr.net/npm/bootstrap@"$(git ls-remote --tags https://github.com/twbs/bootstrap v3.3.* | cut -d/ -f3 | sort -V | tail -1 | sed -E "s/\^\{\}//")"/dist/css/bootstrap.min.css -o rootfs/html/404/bootstrap.min.css
|
curl -L https://cdn.jsdelivr.net/npm/bootstrap@"$(git ls-remote --tags https://github.com/twbs/bootstrap v3.3.* | cut -d/ -f3 | sort -V | tail -1)"/dist/css/bootstrap.min.css -o rootfs/html/404/bootstrap.min.css
|
||||||
curl -L https://cdn.jsdelivr.net/npm/bootstrap@"$(git ls-remote --tags https://github.com/twbs/bootstrap v3.3.* | cut -d/ -f3 | sort -V | tail -1 | sed -E "s/\^\{\}//")"/dist/css/bootstrap.min.css -o rootfs/html/default/bootstrap.min.css
|
curl -L https://cdn.jsdelivr.net/npm/bootstrap@"$(git ls-remote --tags https://github.com/twbs/bootstrap v3.3.* | cut -d/ -f3 | sort -V | tail -1)"/dist/css/bootstrap.min.css -o rootfs/html/default/bootstrap.min.css
|
||||||
- name: nginxbeautifier
|
- name: nginxbeautifier
|
||||||
run: |
|
run: |
|
||||||
yarn global add nginxbeautifier
|
yarn global add nginxbeautifier
|
||||||
|
|
20
.github/workflows/yq.yml
vendored
20
.github/workflows/yq.yml
vendored
|
@ -1,20 +0,0 @@
|
||||||
name: yq
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
jobs:
|
|
||||||
yq:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
token: ${{ secrets.YQ }}
|
|
||||||
- name: update workflows
|
|
||||||
run: for workflow in .github/workflows/*.yml; do yq "$workflow" | tee "$workflow".tmp && mv "$workflow".tmp "$workflow"; done
|
|
||||||
- name: push changes
|
|
||||||
run: |
|
|
||||||
git config user.name "GitHub"
|
|
||||||
git config user.email "noreply@github.com"
|
|
||||||
git add -A
|
|
||||||
git diff-index --quiet HEAD || git commit -sm "yq"
|
|
||||||
git push
|
|
10
Dockerfile
10
Dockerfile
|
@ -56,14 +56,14 @@ RUN apk upgrade --no-cache -a && \
|
||||||
echo "APPSEC_FAILURE_ACTION=deny" | tee -a /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \
|
echo "APPSEC_FAILURE_ACTION=deny" | tee -a /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf && \
|
||||||
sed -i "s|BOUNCING_ON_TYPE=all|BOUNCING_ON_TYPE=ban|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf
|
sed -i "s|BOUNCING_ON_TYPE=all|BOUNCING_ON_TYPE=ban|g" /src/crowdsec-nginx-bouncer/lua-mod/config_example.conf
|
||||||
|
|
||||||
FROM zoeyvid/nginx-quic:262
|
FROM zoeyvid/nginx-quic:271
|
||||||
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
|
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
|
||||||
|
|
||||||
ARG CRS_VER=v4.1.0
|
ARG CRS_VER=v4.1.0
|
||||||
|
|
||||||
COPY rootfs /
|
COPY rootfs /
|
||||||
COPY --from=zoeyvid/certbot-docker:27 /usr/local /usr/local
|
COPY --from=zoeyvid/certbot-docker:34 /usr/local /usr/local
|
||||||
COPY --from=zoeyvid/curl-quic:376 /usr/local/bin/curl /usr/local/bin/curl
|
COPY --from=zoeyvid/curl-quic:380 /usr/local/bin/curl /usr/local/bin/curl
|
||||||
|
|
||||||
RUN apk upgrade --no-cache -a && \
|
RUN apk upgrade --no-cache -a && \
|
||||||
apk add --no-cache ca-certificates tzdata tini \
|
apk add --no-cache ca-certificates tzdata tini \
|
||||||
|
@ -145,3 +145,7 @@ ENV PUID=0 \
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
ENTRYPOINT ["tini", "--", "entrypoint.sh"]
|
ENTRYPOINT ["tini", "--", "entrypoint.sh"]
|
||||||
HEALTHCHECK CMD healthcheck.sh
|
HEALTHCHECK CMD healthcheck.sh
|
||||||
|
EXPOSE 80/tcp
|
||||||
|
EXPOSE 81/tcp
|
||||||
|
EXPOSE 443/tcp
|
||||||
|
EXPOSE 443/udp
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
7
backend/.prettierrc
Normal file
7
backend/.prettierrc
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"useTabs": true,
|
||||||
|
"printWidth": 1000,
|
||||||
|
"singleQuote": true,
|
||||||
|
"bracketSameLine": true
|
||||||
|
}
|
|
@ -46,7 +46,7 @@ app.use(function (req, res, next) {
|
||||||
'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();
|
||||||
});
|
});
|
||||||
|
@ -58,18 +58,17 @@ app.use('/', require('./routes/api/main'));
|
||||||
// no stacktraces leaked to user
|
// no stacktraces leaked to user
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
app.use(function (err, req, res, next) {
|
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 (config.debug() || (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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,14 +76,12 @@ app.use(function (err, req, res, next) {
|
||||||
if (typeof err.stack !== 'undefined' && err.stack) {
|
if (typeof err.stack !== 'undefined' && err.stack) {
|
||||||
if (config.debug()) {
|
if (config.debug()) {
|
||||||
log.debug(err.stack);
|
log.debug(err.stack);
|
||||||
} else if (typeof err.public == 'undefined' || !err.public) {
|
} else if (typeof err.public === 'undefined' || !err.public) {
|
||||||
log.warn(err.message);
|
log.warn(err.message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res.status(err.status || 500).send(payload);
|
||||||
.status(err.status || 500)
|
|
||||||
.send(payload);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = app;
|
module.exports = app;
|
||||||
|
|
|
@ -20,8 +20,8 @@ function generateDbConfig() {
|
||||||
ssl: cfg.tls,
|
ssl: cfg.tls,
|
||||||
},
|
},
|
||||||
migrations: {
|
migrations: {
|
||||||
tableName: 'migrations'
|
tableName: 'migrations',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
5
backend/eslint.config.mjs
Normal file
5
backend/eslint.config.mjs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
import globals from 'globals';
|
||||||
|
import pluginJs from '@eslint/js';
|
||||||
|
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
||||||
|
|
||||||
|
export default [{ files: ['**/*.js'], languageOptions: { sourceType: 'commonjs' } }, { languageOptions: { globals: globals.node } }, pluginJs.configs.recommended, eslintPluginPrettierRecommended];
|
|
@ -11,7 +11,8 @@ async function appStart () {
|
||||||
const internalCertificate = require('./internal/certificate');
|
const internalCertificate = require('./internal/certificate');
|
||||||
const internalIpRanges = require('./internal/ip_ranges');
|
const internalIpRanges = require('./internal/ip_ranges');
|
||||||
|
|
||||||
return migrate.latest()
|
return migrate
|
||||||
|
.latest()
|
||||||
.then(setup)
|
.then(setup)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return apiValidator.loadSchemas;
|
return apiValidator.loadSchemas;
|
||||||
|
|
|
@ -16,14 +16,14 @@ function omissions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
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,37 +31,35 @@ 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()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
data.id = row.id;
|
data.id = row.id;
|
||||||
|
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
// 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,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -70,16 +68,21 @@ 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 (row.proxy_host_count) {
|
if (row.proxy_host_count) {
|
||||||
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
return internalNginx.bulkGenerateConfigs('proxy_host', row.proxy_hosts);
|
||||||
|
@ -91,7 +94,7 @@ const internalAccessList = {
|
||||||
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,7 +112,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -122,10 +126,7 @@ const internalAccessList = {
|
||||||
.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,
|
||||||
|
@ -135,18 +136,17 @@ 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) {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
let items_to_keep = [];
|
const items_to_keep = [];
|
||||||
|
|
||||||
data.items.map(function (item) {
|
data.items.map(function (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
|
||||||
|
@ -154,17 +154,13 @@ const internalAccessList = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let 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);
|
||||||
|
@ -175,28 +171,23 @@ 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) {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
data.clients.map(function (client) {
|
data.clients.map(function (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,
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let 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);
|
||||||
|
@ -210,23 +201,29 @@ const internalAccessList = {
|
||||||
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 (row.proxy_host_count) {
|
if (row.proxy_host_count) {
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -247,16 +244,10 @@ const internalAccessList = {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('access_lists:get', data.id)
|
return access
|
||||||
|
.can('access_lists:get', data.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = accessListModel
|
const query = accessListModel.query().select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count')).joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0').where('access_list.is_deleted', 0).andWhere('access_list.id', data.id).allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]').first();
|
||||||
.query()
|
|
||||||
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
|
|
||||||
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
|
|
||||||
.where('access_list.is_deleted', 0)
|
|
||||||
.andWhere('access_list.id', data.id)
|
|
||||||
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
|
|
||||||
.first();
|
|
||||||
|
|
||||||
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));
|
||||||
|
@ -291,7 +282,8 @@ 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'] });
|
||||||
})
|
})
|
||||||
|
@ -310,7 +302,7 @@ const internalAccessList = {
|
||||||
.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)
|
||||||
|
@ -336,11 +328,11 @@ const internalAccessList = {
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// delete the htpasswd file
|
// delete the htpasswd file
|
||||||
let htpasswd_file = internalAccessList.getFilename(row);
|
const htpasswd_file = internalAccessList.getFilename(row);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(htpasswd_file);
|
fs.unlinkSync(htpasswd_file);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -350,7 +342,7 @@ const internalAccessList = {
|
||||||
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']),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -368,16 +360,10 @@ 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) => {
|
||||||
let query = accessListModel
|
const query = accessListModel.query().select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count')).joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0').where('access_list.is_deleted', 0).groupBy('access_list.id').allowGraph('[owner,items,clients]').orderBy('access_list.name', 'ASC');
|
||||||
.query()
|
|
||||||
.select('access_list.*', accessListModel.raw('COUNT(proxy_host.id) as proxy_host_count'))
|
|
||||||
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
|
|
||||||
.where('access_list.is_deleted', 0)
|
|
||||||
.groupBy('access_list.id')
|
|
||||||
.allowGraph('[owner,items,clients]')
|
|
||||||
.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));
|
||||||
|
@ -417,17 +403,13 @@ const internalAccessList = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
let 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 parseInt(row.count, 10);
|
return parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -447,7 +429,7 @@ const internalAccessList = {
|
||||||
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 = '';
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -475,12 +457,12 @@ const internalAccessList = {
|
||||||
logger.info('Building Access file #' + list.id + ' for: ' + list.name);
|
logger.info('Building Access file #' + list.id + ' for: ' + list.name);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let htpasswd_file = internalAccessList.getFilename(list);
|
const htpasswd_file = internalAccessList.getFilename(list);
|
||||||
|
|
||||||
// 1. remove any existing access file
|
// 1. remove any existing access file
|
||||||
try {
|
try {
|
||||||
fs.unlinkSync(htpasswd_file);
|
fs.unlinkSync(htpasswd_file);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,17 +473,18 @@ const internalAccessList = {
|
||||||
} 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('htpasswd', ['-b', htpasswd_file, item.username, item.password])
|
utils
|
||||||
|
.execFile('htpasswd', ['-b', htpasswd_file, item.username, item.password])
|
||||||
.then((/* result */) => {
|
.then((/* result */) => {
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
|
@ -522,7 +505,7 @@ const internalAccessList = {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalAccessList;
|
module.exports = internalAccessList;
|
||||||
|
|
|
@ -2,7 +2,6 @@ const error = require('../lib/error');
|
||||||
const auditLogModel = require('../models/audit-log');
|
const auditLogModel = require('../models/audit-log');
|
||||||
|
|
||||||
const internalAuditLog = {
|
const internalAuditLog = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* All logs
|
* All logs
|
||||||
*
|
*
|
||||||
|
@ -12,14 +11,8 @@ 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.query().orderBy('created_on', 'DESC').orderBy('id', 'DESC').limit(100).allowGraph('[user]');
|
||||||
let query = auditLogModel
|
|
||||||
.query()
|
|
||||||
.orderBy('created_on', 'DESC')
|
|
||||||
.orderBy('id', 'DESC')
|
|
||||||
.limit(100)
|
|
||||||
.allowGraph('[user]');
|
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string') {
|
if (typeof search_query === 'string') {
|
||||||
|
@ -61,18 +54,18 @@ const internalAuditLog = {
|
||||||
reject(new error.InternalValidationError('Audit log entry must contain an Action'));
|
reject(new error.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;
|
module.exports = internalAuditLog;
|
||||||
|
|
|
@ -23,7 +23,6 @@ function omissions() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const internalCertificate = {
|
const internalCertificate = {
|
||||||
|
|
||||||
allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
|
allowedSslFiles: ['certificate', 'certificate_key', 'intermediate_certificate'],
|
||||||
intervalTimeout: 1000 * 60 * 60 * Number(process.env.CRT),
|
intervalTimeout: 1000 * 60 * 60 * Number(process.env.CRT),
|
||||||
interval: null,
|
interval: null,
|
||||||
|
@ -42,19 +41,16 @@ const internalCertificate = {
|
||||||
internalCertificate.intervalProcessing = true;
|
internalCertificate.intervalProcessing = true;
|
||||||
logger.info('Renewing TLS certs close to expiry...');
|
logger.info('Renewing TLS certs close to expiry...');
|
||||||
|
|
||||||
const cmd = certbotCommand + ' renew --quiet ' +
|
const cmd = certbotCommand + ' renew --quiet ' + '--config "' + certbotConfig + '" ' + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew';
|
||||||
'--config "' + certbotConfig + '" ' +
|
|
||||||
'--preferred-challenges "dns,http" ' +
|
|
||||||
'--no-random-sleep-on-renew';
|
|
||||||
|
|
||||||
return utils.exec(cmd)
|
return utils
|
||||||
|
.exec(cmd)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result) {
|
if (result) {
|
||||||
logger.info('Renew Result: ' + result);
|
logger.info('Renew Result: ' + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
return internalNginx.reload()
|
return internalNginx.reload().then(() => {
|
||||||
.then(() => {
|
|
||||||
logger.info('Renew Complete');
|
logger.info('Renew Complete');
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
@ -67,24 +63,25 @@ const internalCertificate = {
|
||||||
.andWhere('provider', 'letsencrypt')
|
.andWhere('provider', 'letsencrypt')
|
||||||
.then((certificates) => {
|
.then((certificates) => {
|
||||||
if (certificates && certificates.length) {
|
if (certificates && certificates.length) {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
certificates.map(function (certificate) {
|
certificates.map(function (certificate) {
|
||||||
promises.push(
|
promises.push(
|
||||||
internalCertificate.getCertificateInfoFromFile('/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem')
|
internalCertificate
|
||||||
|
.getCertificateInfoFromFile('/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem')
|
||||||
.then((cert_info) => {
|
.then((cert_info) => {
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
.where('id', certificate.id)
|
.where('id', certificate.id)
|
||||||
.andWhere('provider', 'letsencrypt')
|
.andWhere('provider', 'letsencrypt')
|
||||||
.patch({
|
.patch({
|
||||||
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
|
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
// Don't want to stop the train here, just log the error
|
// Don't want to stop the train here, just log the error
|
||||||
logger.error(err.message);
|
logger.error(err.message);
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -108,7 +105,8 @@ const internalCertificate = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
create: (access, data) => {
|
create: (access, data) => {
|
||||||
return access.can('certificates:create', data)
|
return access
|
||||||
|
.can('certificates:create', data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
|
|
||||||
|
@ -116,16 +114,14 @@ const internalCertificate = {
|
||||||
data.nice_name = data.domain_names.join(', ');
|
data.nice_name = data.domain_names.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
return certificateModel
|
return certificateModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((certificate) => {
|
.then((certificate) => {
|
||||||
if (certificate.provider === 'letsencrypt') {
|
if (certificate.provider === 'letsencrypt') {
|
||||||
// Request a new Cert using Certbot. Let the fun begin.
|
// Request a new Cert using Certbot. Let the fun begin.
|
||||||
if (certificate.meta.dns_challenge) {
|
if (certificate.meta.dns_challenge) {
|
||||||
return internalCertificate.requestLetsEncryptSslWithDnsChallenge(certificate)
|
return internalCertificate
|
||||||
|
.requestLetsEncryptSslWithDnsChallenge(certificate)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return certificate;
|
return certificate;
|
||||||
})
|
})
|
||||||
|
@ -134,7 +130,8 @@ const internalCertificate = {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return internalCertificate.requestLetsEncryptSsl(certificate)
|
return internalCertificate
|
||||||
|
.requestLetsEncryptSsl(certificate)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return certificate;
|
return certificate;
|
||||||
})
|
})
|
||||||
|
@ -152,16 +149,12 @@ const internalCertificate = {
|
||||||
// At this point, the certbot cert should exist on disk.
|
// At this point, the certbot cert should exist on disk.
|
||||||
// Lets get the expiry date from the file and update the row silently
|
// Lets get the expiry date from the file and update the row silently
|
||||||
return internalCertificate
|
return internalCertificate
|
||||||
.getCertificateInfoFromFile(
|
.getCertificateInfoFromFile('/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem')
|
||||||
'/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem'
|
|
||||||
)
|
|
||||||
.then((cert_info) => {
|
.then((cert_info) => {
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
.patchAndFetchById(certificate.id, {
|
.patchAndFetchById(certificate.id, {
|
||||||
expires_on: moment(cert_info.dates.to, 'X').format(
|
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
'YYYY-MM-DD HH:mm:ss'
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add cert data for audit log
|
// Add cert data for audit log
|
||||||
|
@ -171,7 +164,8 @@ const internalCertificate = {
|
||||||
|
|
||||||
return saved_row;
|
return saved_row;
|
||||||
});
|
});
|
||||||
}).catch(async (error) => {
|
})
|
||||||
|
.catch(async (error) => {
|
||||||
// Delete the certificate from the database if it was not created successfully
|
// Delete the certificate from the database if it was not created successfully
|
||||||
await certificateModel.query().deleteById(certificate.id);
|
await certificateModel.query().deleteById(certificate.id);
|
||||||
|
|
||||||
|
@ -182,15 +176,15 @@ const internalCertificate = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((certificate) => {
|
.then((certificate) => {
|
||||||
|
|
||||||
data.meta = _.assign({}, data.meta || {}, certificate.meta);
|
data.meta = _.assign({}, data.meta || {}, certificate.meta);
|
||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'certificate',
|
object_type: 'certificate',
|
||||||
object_id: certificate.id,
|
object_id: certificate.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return certificate;
|
return certificate;
|
||||||
|
@ -198,7 +192,6 @@ const internalCertificate = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
|
@ -208,7 +201,8 @@ const internalCertificate = {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
return access.can('certificates:update', data.id)
|
return access
|
||||||
|
.can('certificates:update', data.id)
|
||||||
.then((/* access_data */) => {
|
.then((/* access_data */) => {
|
||||||
return internalCertificate.get(access, { id: data.id });
|
return internalCertificate.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
|
@ -232,11 +226,12 @@ const internalCertificate = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'certificate',
|
object_type: 'certificate',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(data, ['expires_on']) // this prevents json circular reference because expires_on might be raw
|
meta: _.omit(data, ['expires_on']), // this prevents json circular reference because expires_on might be raw
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return saved_row;
|
return saved_row;
|
||||||
|
@ -258,14 +253,10 @@ const internalCertificate = {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('certificates:get', data.id)
|
return access
|
||||||
|
.can('certificates:get', data.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = certificateModel
|
const query = certificateModel.query().where('is_deleted', 0).andWhere('id', data.id).allowGraph('[owner]').first();
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.andWhere('id', data.id)
|
|
||||||
.allowGraph('[owner]')
|
|
||||||
.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));
|
||||||
|
@ -297,7 +288,8 @@ const internalCertificate = {
|
||||||
*/
|
*/
|
||||||
download: (access, data) => {
|
download: (access, data) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
access.can('certificates:get', data)
|
access
|
||||||
|
.can('certificates:get', data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalCertificate.get(access, data);
|
return internalCertificate.get(access, data);
|
||||||
})
|
})
|
||||||
|
@ -309,23 +301,27 @@ const internalCertificate = {
|
||||||
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
|
throw new error.ItemNotFoundError('Certificate ' + certificate.nice_name + ' does not exists');
|
||||||
}
|
}
|
||||||
|
|
||||||
let certFiles = fs.readdirSync(zipDirectory)
|
const certFiles = fs
|
||||||
|
.readdirSync(zipDirectory)
|
||||||
.filter((fn) => fn.endsWith('.pem'))
|
.filter((fn) => fn.endsWith('.pem'))
|
||||||
.map((fn) => fs.realpathSync(path.join(zipDirectory, fn)));
|
.map((fn) => fs.realpathSync(path.join(zipDirectory, fn)));
|
||||||
const downloadName = 'npm-' + data.id + '-' + `${Date.now()}.zip`;
|
const downloadName = 'npm-' + data.id + '-' + `${Date.now()}.zip`;
|
||||||
const opName = '/tmp/' + downloadName;
|
const opName = '/tmp/' + downloadName;
|
||||||
internalCertificate.zipFiles(certFiles, opName)
|
internalCertificate
|
||||||
|
.zipFiles(certFiles, opName)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.debug('zip completed : ', opName);
|
logger.debug('zip completed : ', opName);
|
||||||
const resp = {
|
const resp = {
|
||||||
fileName: opName
|
fileName: opName,
|
||||||
};
|
};
|
||||||
resolve(resp);
|
resolve(resp);
|
||||||
}).catch((err) => reject(err));
|
})
|
||||||
|
.catch((err) => reject(err));
|
||||||
} else {
|
} else {
|
||||||
throw new error.ValidationError('Only Certbot certificates can be downloaded');
|
throw new error.ValidationError('Only Certbot certificates can be downloaded');
|
||||||
}
|
}
|
||||||
}).catch((err) => reject(err));
|
})
|
||||||
|
.catch((err) => reject(err));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -339,15 +335,12 @@ const internalCertificate = {
|
||||||
const stream = fs.createWriteStream(out);
|
const stream = fs.createWriteStream(out);
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
source
|
source.map((fl) => {
|
||||||
.map((fl) => {
|
const fileName = path.basename(fl);
|
||||||
let fileName = path.basename(fl);
|
|
||||||
logger.debug(fl, 'added to certificate zip');
|
logger.debug(fl, 'added to certificate zip');
|
||||||
archive.file(fl, { name: fileName });
|
archive.file(fl, { name: fileName });
|
||||||
});
|
});
|
||||||
archive
|
archive.on('error', (err) => reject(err)).pipe(stream);
|
||||||
.on('error', (err) => reject(err))
|
|
||||||
.pipe(stream);
|
|
||||||
|
|
||||||
stream.on('close', () => resolve());
|
stream.on('close', () => resolve());
|
||||||
archive.finalize();
|
archive.finalize();
|
||||||
|
@ -362,7 +355,8 @@ const internalCertificate = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
delete: (access, data) => {
|
delete: (access, data) => {
|
||||||
return access.can('certificates:delete', data.id)
|
return access
|
||||||
|
.can('certificates:delete', data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalCertificate.get(access, { id: data.id });
|
return internalCertificate.get(access, { id: data.id });
|
||||||
})
|
})
|
||||||
|
@ -375,7 +369,7 @@ const internalCertificate = {
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where('id', row.id)
|
||||||
.patch({
|
.patch({
|
||||||
is_deleted: 1
|
is_deleted: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
|
@ -385,7 +379,7 @@ const internalCertificate = {
|
||||||
action: 'deleted',
|
action: 'deleted',
|
||||||
object_type: 'certificate',
|
object_type: 'certificate',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: _.omit(row, omissions())
|
meta: _.omit(row, omissions()),
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -409,14 +403,8 @@ const internalCertificate = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('certificates:list')
|
return access.can('certificates:list').then((access_data) => {
|
||||||
.then((access_data) => {
|
const query = certificateModel.query().where('is_deleted', 0).groupBy('id').allowGraph('[owner]').orderBy('nice_name', 'ASC');
|
||||||
let query = certificateModel
|
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.groupBy('id')
|
|
||||||
.allowGraph('[owner]')
|
|
||||||
.orderBy('nice_name', '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));
|
||||||
|
@ -445,17 +433,13 @@ const internalCertificate = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
let query = certificateModel
|
const query = certificateModel.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 parseInt(row.count, 10);
|
return parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -504,8 +488,7 @@ const internalCertificate = {
|
||||||
resolve();
|
resolve();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
}).then(() => {
|
||||||
.then(() => {
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
fs.writeFile(dir + '/privkey.pem', certificate.meta.certificate_key, function (err) {
|
fs.writeFile(dir + '/privkey.pem', certificate.meta.certificate_key, function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
@ -530,7 +513,7 @@ const internalCertificate = {
|
||||||
return internalCertificate.create(access, {
|
return internalCertificate.create(access, {
|
||||||
provider: 'letsencrypt',
|
provider: 'letsencrypt',
|
||||||
domain_names: data.domain_names,
|
domain_names: data.domain_names,
|
||||||
meta: data.meta
|
meta: data.meta,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -545,7 +528,7 @@ const internalCertificate = {
|
||||||
validate: (data) => {
|
validate: (data) => {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
// Put file contents into an object
|
// Put file contents into an object
|
||||||
let files = {};
|
const files = {};
|
||||||
_.map(data.files, (file, name) => {
|
_.map(data.files, (file, name) => {
|
||||||
if (internalCertificate.allowedSslFiles.indexOf(name) !== -1) {
|
if (internalCertificate.allowedSslFiles.indexOf(name) !== -1) {
|
||||||
files[name] = file.data.toString();
|
files[name] = file.data.toString();
|
||||||
|
@ -553,13 +536,13 @@ const internalCertificate = {
|
||||||
});
|
});
|
||||||
|
|
||||||
resolve(files);
|
resolve(files);
|
||||||
})
|
}).then((files) => {
|
||||||
.then((files) => {
|
|
||||||
// For each file, create a temp file and write the contents to it
|
// For each file, create a temp file and write the contents to it
|
||||||
// Then test it depending on the file type
|
// Then test it depending on the file type
|
||||||
let promises = [];
|
const promises = [];
|
||||||
_.map(files, (content, type) => {
|
_.map(files, (content, type) => {
|
||||||
promises.push(new Promise((resolve) => {
|
promises.push(
|
||||||
|
new Promise((resolve) => {
|
||||||
if (type === 'certificate_key') {
|
if (type === 'certificate_key') {
|
||||||
resolve(internalCertificate.checkPrivateKey(content));
|
resolve(internalCertificate.checkPrivateKey(content));
|
||||||
} else {
|
} else {
|
||||||
|
@ -568,11 +551,11 @@ const internalCertificate = {
|
||||||
}
|
}
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
return { [type]: res };
|
return { [type]: res };
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(promises)
|
return Promise.all(promises).then((files) => {
|
||||||
.then((files) => {
|
|
||||||
let data = {};
|
let data = {};
|
||||||
|
|
||||||
_.each(files, (file) => {
|
_.each(files, (file) => {
|
||||||
|
@ -592,13 +575,13 @@ const internalCertificate = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
upload: (access, data) => {
|
upload: (access, data) => {
|
||||||
return internalCertificate.get(access, {id: data.id})
|
return internalCertificate.get(access, { id: data.id }).then((row) => {
|
||||||
.then((row) => {
|
|
||||||
if (row.provider !== 'other') {
|
if (row.provider !== 'other') {
|
||||||
throw new error.ValidationError('Cannot upload certificates for this type of provider');
|
throw new error.ValidationError('Cannot upload certificates for this type of provider');
|
||||||
}
|
}
|
||||||
|
|
||||||
return internalCertificate.validate(data)
|
return internalCertificate
|
||||||
|
.validate(data)
|
||||||
.then((validations) => {
|
.then((validations) => {
|
||||||
if (typeof validations.certificate === 'undefined') {
|
if (typeof validations.certificate === 'undefined') {
|
||||||
throw new error.ValidationError('Certificate file was not provided');
|
throw new error.ValidationError('Certificate file was not provided');
|
||||||
|
@ -611,11 +594,12 @@ const internalCertificate = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO: This uses a mysql only raw function that won't translate to postgres
|
// TODO: This uses a mysql only raw function that won't translate to postgres
|
||||||
return internalCertificate.update(access, {
|
return internalCertificate
|
||||||
|
.update(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expires_on: moment(validations.certificate.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss'),
|
expires_on: moment(validations.certificate.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
domain_names: [validations.certificate.cn],
|
domain_names: [validations.certificate.cn],
|
||||||
meta: _.clone(row.meta) // Prevent the update method from changing this value that we'll use later
|
meta: _.clone(row.meta), // Prevent the update method from changing this value that we'll use later
|
||||||
})
|
})
|
||||||
.then((certificate) => {
|
.then((certificate) => {
|
||||||
certificate.meta = row.meta;
|
certificate.meta = row.meta;
|
||||||
|
@ -671,11 +655,13 @@ const internalCertificate = {
|
||||||
const randomName = crypto.randomBytes(8).toString('hex');
|
const randomName = crypto.randomBytes(8).toString('hex');
|
||||||
const filepath = path.join('/tmp', 'certificate_' + randomName);
|
const filepath = path.join('/tmp', 'certificate_' + randomName);
|
||||||
fs.writeFileSync(filepath, certificate);
|
fs.writeFileSync(filepath, certificate);
|
||||||
return internalCertificate.getCertificateInfoFromFile(filepath, throw_expired)
|
return internalCertificate
|
||||||
|
.getCertificateInfoFromFile(filepath, throw_expired)
|
||||||
.then((certData) => {
|
.then((certData) => {
|
||||||
fs.unlinkSync(filepath);
|
fs.unlinkSync(filepath);
|
||||||
return certData;
|
return certData;
|
||||||
}).catch((err) => {
|
})
|
||||||
|
.catch((err) => {
|
||||||
fs.unlinkSync(filepath);
|
fs.unlinkSync(filepath);
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
|
@ -689,9 +675,10 @@ const internalCertificate = {
|
||||||
* @param {Boolean} [throw_expired] Throw when the certificate is out of date
|
* @param {Boolean} [throw_expired] Throw when the certificate is out of date
|
||||||
*/
|
*/
|
||||||
getCertificateInfoFromFile: (certificate_file, throw_expired) => {
|
getCertificateInfoFromFile: (certificate_file, throw_expired) => {
|
||||||
let certData = {};
|
const certData = {};
|
||||||
|
|
||||||
return utils.exec('openssl x509 -in ' + certificate_file + ' -subject -noout')
|
return utils
|
||||||
|
.exec('openssl x509 -in ' + certificate_file + ' -subject -noout')
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
// subject=CN = something.example.com
|
// subject=CN = something.example.com
|
||||||
const regex = /(?:subject=)?[^=]+=\s+(\S+)/gim;
|
const regex = /(?:subject=)?[^=]+=\s+(\S+)/gim;
|
||||||
|
@ -701,7 +688,7 @@ const internalCertificate = {
|
||||||
throw new error.ValidationError('Could not determine subject from certificate: ' + result);
|
throw new error.ValidationError('Could not determine subject from certificate: ' + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
certData['cn'] = match[1];
|
certData.cn = match[1];
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout');
|
return utils.exec('openssl x509 -in ' + certificate_file + ' -issuer -noout');
|
||||||
|
@ -714,7 +701,7 @@ const internalCertificate = {
|
||||||
throw new error.ValidationError('Could not determine issuer from certificate: ' + result);
|
throw new error.ValidationError('Could not determine issuer from certificate: ' + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
certData['issuer'] = match[1];
|
certData.issuer = match[1];
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout');
|
return utils.exec('openssl x509 -in ' + certificate_file + ' -dates -noout');
|
||||||
|
@ -749,13 +736,14 @@ const internalCertificate = {
|
||||||
throw new error.ValidationError('Certificate has expired');
|
throw new error.ValidationError('Certificate has expired');
|
||||||
}
|
}
|
||||||
|
|
||||||
certData['dates'] = {
|
certData.dates = {
|
||||||
from: validFrom,
|
from: validFrom,
|
||||||
to: validTo
|
to: validTo,
|
||||||
};
|
};
|
||||||
|
|
||||||
return certData;
|
return certData;
|
||||||
}).catch((err) => {
|
})
|
||||||
|
.catch((err) => {
|
||||||
throw new error.ValidationError('Certificate is not valid (' + err.message + ')', err);
|
throw new error.ValidationError('Certificate is not valid (' + err.message + ')', err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -789,12 +777,7 @@ const internalCertificate = {
|
||||||
requestLetsEncryptSsl: (certificate) => {
|
requestLetsEncryptSsl: (certificate) => {
|
||||||
logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
|
logger.info('Requesting Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
|
||||||
|
|
||||||
let cmd = certbotCommand + ' certonly ' +
|
let cmd = certbotCommand + ' certonly ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--authenticator webroot ' + '--preferred-challenges "dns,http" ' + '--domains "' + certificate.domain_names.join(',') + '"';
|
||||||
'--config "' + certbotConfig + '" ' +
|
|
||||||
'--cert-name "npm-' + certificate.id + '" ' +
|
|
||||||
'--authenticator webroot ' +
|
|
||||||
'--preferred-challenges "dns,http" ' +
|
|
||||||
'--domains "' + certificate.domain_names.join(',') + '"';
|
|
||||||
|
|
||||||
if (certificate.meta.letsencrypt_email === '') {
|
if (certificate.meta.letsencrypt_email === '') {
|
||||||
cmd = cmd + ' --register-unsafely-without-email ';
|
cmd = cmd + ' --register-unsafely-without-email ';
|
||||||
|
@ -804,8 +787,7 @@ const internalCertificate = {
|
||||||
|
|
||||||
logger.info('Command:', cmd);
|
logger.info('Command:', cmd);
|
||||||
|
|
||||||
return utils.exec(cmd)
|
return utils.exec(cmd).then((result) => {
|
||||||
.then((result) => {
|
|
||||||
logger.success(result);
|
logger.success(result);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
@ -825,20 +807,10 @@ const internalCertificate = {
|
||||||
|
|
||||||
const credentialsLocation = '/data/tls/certbot/credentials/credentials-' + certificate.id;
|
const credentialsLocation = '/data/tls/certbot/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 credentialsCmd = `echo '${escapedCredentials}' | tee '${credentialsLocation}'`;
|
const credentialsCmd = `echo '${escapedCredentials}' | tee '${credentialsLocation}'`;
|
||||||
|
|
||||||
let mainCmd = certbotCommand + ' certonly ' +
|
let mainCmd = certbotCommand + ' certonly ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--domains "' + certificate.domain_names.join(',') + '" ' + '--authenticator ' + dnsPlugin.full_plugin_name + ' ' + '--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"' + (certificate.meta.propagation_seconds !== undefined ? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds : '');
|
||||||
'--config "' + certbotConfig + '" ' +
|
|
||||||
'--cert-name "npm-' + certificate.id + '" ' +
|
|
||||||
'--domains "' + certificate.domain_names.join(',') + '" ' +
|
|
||||||
'--authenticator ' + dnsPlugin.full_plugin_name + ' ' +
|
|
||||||
'--' + dnsPlugin.full_plugin_name + '-credentials "' + credentialsLocation + '"' +
|
|
||||||
(
|
|
||||||
certificate.meta.propagation_seconds !== undefined
|
|
||||||
? ' --' + dnsPlugin.full_plugin_name + '-propagation-seconds ' + certificate.meta.propagation_seconds
|
|
||||||
: ''
|
|
||||||
);
|
|
||||||
|
|
||||||
if (certificate.meta.letsencrypt_email === '') {
|
if (certificate.meta.letsencrypt_email === '') {
|
||||||
mainCmd = mainCmd + ' --register-unsafely-without-email ';
|
mainCmd = mainCmd + ' --register-unsafely-without-email ';
|
||||||
|
@ -861,7 +833,6 @@ const internalCertificate = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
|
@ -869,7 +840,8 @@ const internalCertificate = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
renew: (access, data) => {
|
renew: (access, data) => {
|
||||||
return access.can('certificates:update', data)
|
return access
|
||||||
|
.can('certificates:update', data)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalCertificate.get(access, data);
|
return internalCertificate.get(access, data);
|
||||||
})
|
})
|
||||||
|
@ -882,19 +854,18 @@ const internalCertificate = {
|
||||||
return internalCertificate.getCertificateInfoFromFile('/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem');
|
return internalCertificate.getCertificateInfoFromFile('/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem');
|
||||||
})
|
})
|
||||||
.then((cert_info) => {
|
.then((cert_info) => {
|
||||||
return certificateModel
|
return certificateModel.query().patchAndFetchById(certificate.id, {
|
||||||
.query()
|
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss'),
|
||||||
.patchAndFetchById(certificate.id, {
|
|
||||||
expires_on: moment(cert_info.dates.to, 'X').format('YYYY-MM-DD HH:mm:ss')
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((updated_certificate) => {
|
.then((updated_certificate) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'renewed',
|
action: 'renewed',
|
||||||
object_type: 'certificate',
|
object_type: 'certificate',
|
||||||
object_id: updated_certificate.id,
|
object_id: updated_certificate.id,
|
||||||
meta: updated_certificate
|
meta: updated_certificate,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return updated_certificate;
|
return updated_certificate;
|
||||||
|
@ -913,16 +884,11 @@ const internalCertificate = {
|
||||||
renewLetsEncryptSsl: (certificate) => {
|
renewLetsEncryptSsl: (certificate) => {
|
||||||
logger.info('Renewing Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
|
logger.info('Renewing Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
|
||||||
|
|
||||||
const cmd = certbotCommand + ' renew --force-renewal ' +
|
const cmd = certbotCommand + ' renew --force-renewal ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew';
|
||||||
'--config "' + certbotConfig + '" ' +
|
|
||||||
'--cert-name "npm-' + certificate.id + '" ' +
|
|
||||||
'--preferred-challenges "dns,http" ' +
|
|
||||||
'--no-random-sleep-on-renew';
|
|
||||||
|
|
||||||
logger.info('Command:', cmd);
|
logger.info('Command:', cmd);
|
||||||
|
|
||||||
return utils.exec(cmd)
|
return utils.exec(cmd).then((result) => {
|
||||||
.then((result) => {
|
|
||||||
logger.info(result);
|
logger.info(result);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
@ -941,16 +907,11 @@ const internalCertificate = {
|
||||||
|
|
||||||
logger.info(`Renewing Certbot certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
logger.info(`Renewing Certbot certificates via ${dnsPlugin.name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||||
|
|
||||||
let mainCmd = certbotCommand + ' renew --force-renewal ' +
|
const mainCmd = certbotCommand + ' renew --force-renewal ' + '--config "' + certbotConfig + '" ' + '--cert-name "npm-' + certificate.id + '" ' + '--preferred-challenges "dns,http" ' + '--no-random-sleep-on-renew';
|
||||||
'--config "' + certbotConfig + '" ' +
|
|
||||||
'--cert-name "npm-' + certificate.id + '" ' +
|
|
||||||
'--preferred-challenges "dns,http" ' +
|
|
||||||
'--no-random-sleep-on-renew';
|
|
||||||
|
|
||||||
logger.info('Command:', mainCmd);
|
logger.info('Command:', mainCmd);
|
||||||
|
|
||||||
return utils.exec(mainCmd)
|
return utils.exec(mainCmd).then(async (result) => {
|
||||||
.then(async (result) => {
|
|
||||||
logger.info(result);
|
logger.info(result);
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
@ -964,18 +925,15 @@ const internalCertificate = {
|
||||||
revokeLetsEncryptSsl: (certificate, throw_errors) => {
|
revokeLetsEncryptSsl: (certificate, throw_errors) => {
|
||||||
logger.info('Revoking Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
|
logger.info('Revoking Certbot certificates for Cert #' + certificate.id + ': ' + certificate.domain_names.join(', '));
|
||||||
|
|
||||||
const mainCmd = certbotCommand + ' revoke ' +
|
const mainCmd = certbotCommand + ' revoke ' + '--config "' + certbotConfig + '" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/privkey.pem" ' + '--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem" ' + '--delete-after-revoke';
|
||||||
'--config "' + certbotConfig + '" ' +
|
|
||||||
'--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/privkey.pem" ' +
|
|
||||||
'--cert-path "/data/tls/certbot/live/npm-' + certificate.id + '/fullchain.pem" ' +
|
|
||||||
'--delete-after-revoke';
|
|
||||||
|
|
||||||
// Don't fail command if file does not exist
|
// Don't fail command if file does not exist
|
||||||
const delete_credentialsCmd = `rm -f '/data/tls/certbot/credentials/credentials-${certificate.id}' || true`;
|
const delete_credentialsCmd = `rm -f '/data/tls/certbot/credentials/credentials-${certificate.id}' || true`;
|
||||||
|
|
||||||
logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd);
|
logger.info('Command:', mainCmd + '; ' + delete_credentialsCmd);
|
||||||
|
|
||||||
return utils.exec(mainCmd)
|
return utils
|
||||||
|
.exec(mainCmd)
|
||||||
.then(async (result) => {
|
.then(async (result) => {
|
||||||
await utils.exec(delete_credentialsCmd);
|
await utils.exec(delete_credentialsCmd);
|
||||||
logger.info(result);
|
logger.info(result);
|
||||||
|
@ -1009,7 +967,7 @@ const internalCertificate = {
|
||||||
*/
|
*/
|
||||||
disableInUseHosts: (in_use_result) => {
|
disableInUseHosts: (in_use_result) => {
|
||||||
if (in_use_result.total_count) {
|
if (in_use_result.total_count) {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
if (in_use_result.proxy_hosts.length) {
|
if (in_use_result.proxy_hosts.length) {
|
||||||
promises.push(internalNginx.bulkDeleteConfigs('proxy_host', in_use_result.proxy_hosts));
|
promises.push(internalNginx.bulkDeleteConfigs('proxy_host', in_use_result.proxy_hosts));
|
||||||
|
@ -1024,7 +982,6 @@ const internalCertificate = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -1039,7 +996,7 @@ const internalCertificate = {
|
||||||
*/
|
*/
|
||||||
enableInUseHosts: (in_use_result) => {
|
enableInUseHosts: (in_use_result) => {
|
||||||
if (in_use_result.total_count) {
|
if (in_use_result.total_count) {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
if (in_use_result.proxy_hosts.length) {
|
if (in_use_result.proxy_hosts.length) {
|
||||||
promises.push(internalNginx.bulkGenerateConfigs('proxy_host', in_use_result.proxy_hosts));
|
promises.push(internalNginx.bulkGenerateConfigs('proxy_host', in_use_result.proxy_hosts));
|
||||||
|
@ -1054,7 +1011,6 @@ const internalCertificate = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -1085,18 +1041,17 @@ const internalCertificate = {
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/x-www-form-urlencoded',
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
'Content-Length': Buffer.byteLength(formBody),
|
'Content-Length': Buffer.byteLength(formBody),
|
||||||
'Connection': 'keep-alive',
|
Connection: 'keep-alive',
|
||||||
'User-Agent': 'NPMplus',
|
'User-Agent': 'NPMplus',
|
||||||
'Accept': '*/*'
|
Accept: '*/*',
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await new Promise((resolve) => {
|
const result = await new Promise((resolve) => {
|
||||||
|
|
||||||
const req = https.request('https://www.site24x7.com/tools/restapi-tester', options, function (res) {
|
const req = https.request('https://www.site24x7.com/tools/restapi-tester', options, function (res) {
|
||||||
let responseBody = '';
|
let responseBody = '';
|
||||||
|
|
||||||
res.on('data', (chunk) => responseBody = responseBody + chunk);
|
res.on('data', (chunk) => (responseBody = responseBody + chunk));
|
||||||
res.on('end', function () {
|
res.on('end', function () {
|
||||||
try {
|
try {
|
||||||
const parsedBody = JSON.parse(responseBody + '');
|
const parsedBody = JSON.parse(responseBody + '');
|
||||||
|
@ -1120,8 +1075,10 @@ const internalCertificate = {
|
||||||
// Make sure to write the request body.
|
// Make sure to write the request body.
|
||||||
req.write(formBody);
|
req.write(formBody);
|
||||||
req.end();
|
req.end();
|
||||||
req.on('error', function (e) { logger.warn(`Failed to test HTTP challenge for domain ${domain}`, e);
|
req.on('error', function (e) {
|
||||||
resolve(undefined); });
|
logger.warn(`Failed to test HTTP challenge for domain ${domain}`, e);
|
||||||
|
resolve(undefined);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
|
@ -1162,7 +1119,7 @@ const internalCertificate = {
|
||||||
fs.unlinkSync(testChallengeFile);
|
fs.unlinkSync(testChallengeFile);
|
||||||
|
|
||||||
return results;
|
return results;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalCertificate;
|
module.exports = internalCertificate;
|
||||||
|
|
|
@ -12,30 +12,29 @@ function omissions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
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 create_certificate = data.certificate_id === 'new';
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
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(function (domain_name) {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
|
||||||
check_results.map(function (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 error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
@ -48,19 +47,17 @@ const internalDeadHost = {
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
data = internalHost.cleanSslHstsData(data);
|
data = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
return deadHostModel
|
return deadHostModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.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 internalDeadHost.update(access, {
|
return internalDeadHost.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -74,13 +71,12 @@ const internalDeadHost = {
|
||||||
// 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;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -88,11 +84,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
|
||||||
|
.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'dead-host',
|
object_type: 'dead-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
|
@ -107,24 +104,24 @@ const internalDeadHost = {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let 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('dead_hosts:update', data.id)
|
return access
|
||||||
|
.can('dead_hosts:update', data.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 data.domain_names !== 'undefined') {
|
||||||
data.domain_names.map(function (domain_name) {
|
data.domain_names.map(function (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 Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
|
||||||
check_results.map(function (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 error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
@ -143,9 +140,10 @@ const internalDeadHost = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, {
|
||||||
domain_names: data.domain_names || row.domain_names,
|
domain_names: data.domain_names || row.domain_names,
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
meta: _.assign({}, row.meta, data.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
|
@ -160,9 +158,13 @@ const internalDeadHost = {
|
||||||
})
|
})
|
||||||
.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({}, {
|
data = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
|
||||||
data = internalHost.cleanSslHstsData(data, row);
|
data = internalHost.cleanSslHstsData(data, row);
|
||||||
|
|
||||||
|
@ -172,11 +174,12 @@ const internalDeadHost = {
|
||||||
.patch(data)
|
.patch(data)
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'dead-host',
|
object_type: 'dead-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
|
@ -184,14 +187,14 @@ const internalDeadHost = {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalDeadHost.get(access, {
|
return internalDeadHost
|
||||||
|
.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'certificate']
|
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);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
|
@ -213,14 +216,10 @@ const internalDeadHost = {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('dead_hosts:get', data.id)
|
return access
|
||||||
|
.can('dead_hosts:get', data.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = deadHostModel
|
const query = deadHostModel.query().where('is_deleted', 0).andWhere('id', data.id).allowGraph('[owner,certificate]').first();
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.andWhere('id', data.id)
|
|
||||||
.allowGraph('[owner,certificate]')
|
|
||||||
.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));
|
||||||
|
@ -252,7 +251,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -265,12 +265,11 @@ const internalDeadHost = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -280,7 +279,7 @@ const internalDeadHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -297,11 +296,12 @@ 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) => {
|
||||||
|
@ -317,7 +317,7 @@ const internalDeadHost = {
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where('id', row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
|
@ -329,7 +329,7 @@ const internalDeadHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -346,7 +346,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -363,12 +364,11 @@ const internalDeadHost = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -378,7 +378,7 @@ const internalDeadHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -396,14 +396,10 @@ 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().where('is_deleted', 0).groupBy('id').allowGraph('[owner,certificate]').orderBy('domain_names', 'ASC');
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.groupBy('id')
|
|
||||||
.allowGraph('[owner,certificate]')
|
|
||||||
.orderBy('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));
|
||||||
|
@ -439,20 +435,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 parseInt(row.count, 10);
|
return parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalDeadHost;
|
module.exports = internalDeadHost;
|
||||||
|
|
|
@ -4,7 +4,6 @@ const redirectionHostModel = require('../models/redirection_host');
|
||||||
const deadHostModel = require('../models/dead_host');
|
const deadHostModel = require('../models/dead_host');
|
||||||
|
|
||||||
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.
|
||||||
|
@ -17,7 +16,7 @@ const internalHost = {
|
||||||
cleanSslHstsData: function (data, existing_data) {
|
cleanSslHstsData: function (data, existing_data) {
|
||||||
existing_data = existing_data === undefined ? {} : existing_data;
|
existing_data = existing_data === undefined ? {} : existing_data;
|
||||||
|
|
||||||
let combined_data = _.assign({}, existing_data, data);
|
const combined_data = _.assign({}, existing_data, data);
|
||||||
|
|
||||||
if (!combined_data.certificate_id) {
|
if (!combined_data.certificate_id) {
|
||||||
combined_data.ssl_forced = false;
|
combined_data.ssl_forced = false;
|
||||||
|
@ -69,25 +68,14 @@ const internalHost = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getHostsWithDomains: function (domain_names) {
|
getHostsWithDomains: function (domain_names) {
|
||||||
let promises = [
|
const promises = [proxyHostModel.query().where('is_deleted', 0), redirectionHostModel.query().where('is_deleted', 0), deadHostModel.query().where('is_deleted', 0)];
|
||||||
proxyHostModel
|
|
||||||
.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]) {
|
||||||
|
@ -121,7 +109,7 @@ const internalHost = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
isHostnameTaken: function (hostname, ignore_type, ignore_id) {
|
isHostnameTaken: function (hostname, ignore_type, ignore_id) {
|
||||||
let promises = [
|
const promises = [
|
||||||
proxyHostModel
|
proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
|
@ -133,11 +121,10 @@ const internalHost = {
|
||||||
deadHostModel
|
deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('domain_names', 'like', '%' + hostname + '%')
|
.andWhere('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]) {
|
||||||
|
@ -162,8 +149,8 @@ const internalHost = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
hostname: hostname,
|
hostname,
|
||||||
is_taken: is_taken
|
is_taken,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -203,7 +190,7 @@ const internalHost = {
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
_getHostsWithDomains: function (hosts, domain_names) {
|
_getHostsWithDomains: function (hosts, domain_names) {
|
||||||
let response = [];
|
const response = [];
|
||||||
|
|
||||||
if (hosts && hosts.length) {
|
if (hosts && hosts.length) {
|
||||||
hosts.map(function (host) {
|
hosts.map(function (host) {
|
||||||
|
@ -224,8 +211,7 @@ const internalHost = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalHost;
|
module.exports = internalHost;
|
||||||
|
|
|
@ -13,7 +13,6 @@ 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 * Number(process.env.IPRT),
|
interval_timeout: 1000 * 60 * 60 * Number(process.env.IPRT),
|
||||||
interval: null,
|
interval: null,
|
||||||
interval_processing: false,
|
interval_processing: false,
|
||||||
|
@ -29,7 +28,8 @@ const internalIpRanges = {
|
||||||
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
|
||||||
|
.get(url, (res) => {
|
||||||
res.setEncoding('utf8');
|
res.setEncoding('utf8');
|
||||||
let raw_data = '';
|
let raw_data = '';
|
||||||
res.on('data', (chunk) => {
|
res.on('data', (chunk) => {
|
||||||
|
@ -39,7 +39,8 @@ const internalIpRanges = {
|
||||||
res.on('end', () => {
|
res.on('end', () => {
|
||||||
resolve(raw_data);
|
resolve(raw_data);
|
||||||
});
|
});
|
||||||
}).on('error', (err) => {
|
})
|
||||||
|
.on('error', (err) => {
|
||||||
reject(err);
|
reject(err);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -55,9 +56,10 @@ const internalIpRanges = {
|
||||||
|
|
||||||
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) => {
|
||||||
|
@ -79,26 +81,25 @@ 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 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();
|
||||||
|
@ -124,7 +125,7 @@ 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 = '/data/nginx/ip_ranges.conf';
|
const filename = '/data/nginx/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) {
|
||||||
|
@ -133,7 +134,7 @@ const internalIpRanges = {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEngine
|
renderEngine
|
||||||
.parseAndRender(template, {ip_ranges: ip_ranges})
|
.parseAndRender(template, { 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);
|
||||||
|
@ -143,7 +144,7 @@ const internalIpRanges = {
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new error.ConfigurationError(err.message));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalIpRanges;
|
module.exports = internalIpRanges;
|
||||||
|
|
|
@ -8,7 +8,6 @@ const error = require('../lib/error');
|
||||||
const NgxPidFilePath = '/usr/local/nginx/logs/nginx.pid';
|
const NgxPidFilePath = '/usr/local/nginx/logs/nginx.pid';
|
||||||
|
|
||||||
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
|
||||||
|
@ -26,7 +25,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.
|
||||||
|
@ -39,19 +39,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) => {
|
||||||
|
@ -59,8 +57,8 @@ const internalNginx = {
|
||||||
// It will always look like this:
|
// It will always look like this:
|
||||||
// nginx: [alert] could not open error log file: open() "/dev/null" failed (6: No such device or address)
|
// nginx: [alert] could not open error log file: open() "/dev/null" failed (6: No such device or address)
|
||||||
|
|
||||||
let valid_lines = [];
|
const valid_lines = [];
|
||||||
let err_lines = err.message.split('\n');
|
const err_lines = err.message.split('\n');
|
||||||
err_lines.map(function (line) {
|
err_lines.map(function (line) {
|
||||||
if (line.indexOf('/dev/null') === -1) {
|
if (line.indexOf('/dev/null') === -1) {
|
||||||
valid_lines.push(line);
|
valid_lines.push(line);
|
||||||
|
@ -74,14 +72,14 @@ const internalNginx = {
|
||||||
// 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);
|
||||||
|
@ -115,8 +113,7 @@ const internalNginx = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
reload: () => {
|
reload: () => {
|
||||||
return internalNginx.test()
|
return internalNginx.test().then(() => {
|
||||||
.then(() => {
|
|
||||||
if (fs.existsSync(NgxPidFilePath)) {
|
if (fs.existsSync(NgxPidFilePath)) {
|
||||||
const ngxPID = fs.readFileSync(NgxPidFilePath, 'utf8').trim();
|
const ngxPID = fs.readFileSync(NgxPidFilePath, 'utf8').trim();
|
||||||
if (ngxPID.length > 0) {
|
if (ngxPID.length > 0) {
|
||||||
|
@ -166,11 +163,7 @@ const internalNginx = {
|
||||||
|
|
||||||
const locationRendering = async () => {
|
const locationRendering = async () => {
|
||||||
for (let i = 0; i < host.locations.length; i++) {
|
for (let i = 0; i < host.locations.length; i++) {
|
||||||
let locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
|
const locationCopy = Object.assign({}, { access_list_id: host.access_list_id }, { certificate_id: host.certificate_id }, { 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]);
|
||||||
{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 split = locationCopy.forward_host.split('/');
|
const split = locationCopy.forward_host.split('/');
|
||||||
|
@ -179,14 +172,11 @@ const internalNginx = {
|
||||||
locationCopy.forward_path = `/${split.join('/')}`;
|
locationCopy.forward_path = `/${split.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));
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -206,7 +196,7 @@ const internalNginx = {
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let 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' });
|
||||||
|
@ -239,7 +229,6 @@ const internalNginx = {
|
||||||
host.use_default_location = false;
|
host.use_default_location = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
locationsPromise = Promise.resolve();
|
locationsPromise = Promise.resolve();
|
||||||
}
|
}
|
||||||
|
@ -296,7 +285,6 @@ const internalNginx = {
|
||||||
return host_type.replace(new RegExp('-', 'g'), '_');
|
return host_type.replace(new RegExp('-', 'g'), '_');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} host_type
|
* @param {String} host_type
|
||||||
* @param {Object} [host]
|
* @param {Object} [host]
|
||||||
|
@ -342,7 +330,7 @@ const internalNginx = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
bulkGenerateConfigs: (host_type, hosts) => {
|
bulkGenerateConfigs: (host_type, hosts) => {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
hosts.map(function (host) {
|
hosts.map(function (host) {
|
||||||
promises.push(internalNginx.generateConfig(host_type, host));
|
promises.push(internalNginx.generateConfig(host_type, host));
|
||||||
});
|
});
|
||||||
|
@ -356,7 +344,7 @@ const internalNginx = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
bulkDeleteConfigs: (host_type, hosts) => {
|
bulkDeleteConfigs: (host_type, hosts) => {
|
||||||
let promises = [];
|
const promises = [];
|
||||||
hosts.map(function (host) {
|
hosts.map(function (host) {
|
||||||
promises.push(internalNginx.deleteConfig(host_type, host, true));
|
promises.push(internalNginx.deleteConfig(host_type, host, true));
|
||||||
});
|
});
|
||||||
|
@ -382,7 +370,7 @@ const internalNginx = {
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalNginx;
|
module.exports = internalNginx;
|
||||||
|
|
|
@ -12,30 +12,29 @@ function omissions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
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';
|
const create_certificate = data.certificate_id === 'new';
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
delete data.certificate_id;
|
delete data.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('proxy_hosts:create', data)
|
return access
|
||||||
|
.can('proxy_hosts:create', data)
|
||||||
.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) {
|
data.domain_names.map(function (domain_name) {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
|
||||||
check_results.map(function (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 error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
@ -48,19 +47,17 @@ const internalProxyHost = {
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
data = internalHost.cleanSslHstsData(data);
|
data = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.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 internalProxyHost.update(access, {
|
return internalProxyHost.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -74,13 +71,12 @@ const internalProxyHost = {
|
||||||
// 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;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -89,11 +85,12 @@ const internalProxyHost = {
|
||||||
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
|
||||||
|
.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'proxy-host',
|
object_type: 'proxy-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
|
@ -108,24 +105,24 @@ const internalProxyHost = {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let 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('proxy_hosts:update', data.id)
|
return access
|
||||||
|
.can('proxy_hosts:update', data.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 data.domain_names !== 'undefined') {
|
||||||
data.domain_names.map(function (domain_name) {
|
data.domain_names.map(function (domain_name) {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'proxy', data.id));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'proxy', data.id));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
|
||||||
check_results.map(function (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 error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
@ -144,9 +141,10 @@ const internalProxyHost = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, {
|
||||||
domain_names: data.domain_names || row.domain_names,
|
domain_names: data.domain_names || row.domain_names,
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
meta: _.assign({}, row.meta, data.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
|
@ -161,9 +159,13 @@ const internalProxyHost = {
|
||||||
})
|
})
|
||||||
.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({}, {
|
data = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
|
||||||
data = internalHost.cleanSslHstsData(data, row);
|
data = internalHost.cleanSslHstsData(data, row);
|
||||||
|
|
||||||
|
@ -174,11 +176,12 @@ const internalProxyHost = {
|
||||||
.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
|
||||||
|
.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'proxy-host',
|
object_type: 'proxy-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return saved_row;
|
return saved_row;
|
||||||
|
@ -186,9 +189,10 @@ const internalProxyHost = {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalProxyHost.get(access, {
|
return internalProxyHost
|
||||||
|
.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'certificate', 'access_list.[clients,items]']
|
expand: ['owner', 'certificate', 'access_list.[clients,items]'],
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (!row.enabled) {
|
if (!row.enabled) {
|
||||||
|
@ -196,8 +200,7 @@ 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);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
|
@ -219,14 +222,10 @@ const internalProxyHost = {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('proxy_hosts:get', data.id)
|
return access
|
||||||
|
.can('proxy_hosts:get', data.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = proxyHostModel
|
const query = proxyHostModel.query().where('is_deleted', 0).andWhere('id', data.id).allowGraph('[owner,access_list.[clients,items],certificate]').first();
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.andWhere('id', data.id)
|
|
||||||
.allowGraph('[owner,access_list.[clients,items],certificate]')
|
|
||||||
.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));
|
||||||
|
@ -259,7 +258,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -272,12 +272,11 @@ const internalProxyHost = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -287,7 +286,7 @@ const internalProxyHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -304,11 +303,12 @@ 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) => {
|
||||||
|
@ -324,7 +324,7 @@ const internalProxyHost = {
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where('id', row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
|
@ -336,7 +336,7 @@ const internalProxyHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -353,7 +353,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -370,12 +371,11 @@ const internalProxyHost = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -385,7 +385,7 @@ const internalProxyHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -403,14 +403,10 @@ 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().where('is_deleted', 0).groupBy('id').allowGraph('[owner,access_list,certificate]').orderBy('domain_names', 'ASC');
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.groupBy('id')
|
|
||||||
.allowGraph('[owner,access_list,certificate]')
|
|
||||||
.orderBy('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));
|
||||||
|
@ -446,20 +442,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 parseInt(row.count, 10);
|
return parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalProxyHost;
|
module.exports = internalProxyHost;
|
||||||
|
|
|
@ -12,30 +12,29 @@ function omissions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
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';
|
const create_certificate = data.certificate_id === 'new';
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
delete data.certificate_id;
|
delete data.certificate_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('redirection_hosts:create', data)
|
return access
|
||||||
|
.can('redirection_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(function (domain_name) {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
|
||||||
check_results.map(function (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 error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
@ -48,19 +47,17 @@ const internalRedirectionHost = {
|
||||||
data.owner_user_id = access.token.getUserId(1);
|
data.owner_user_id = access.token.getUserId(1);
|
||||||
data = internalHost.cleanSslHstsData(data);
|
data = internalHost.cleanSslHstsData(data);
|
||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.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 internalRedirectionHost.update(access, {
|
return internalRedirectionHost.update(access, {
|
||||||
id: row.id,
|
id: row.id,
|
||||||
certificate_id: cert.id
|
certificate_id: cert.id,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -73,13 +70,12 @@ 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;
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -87,11 +83,12 @@ const internalRedirectionHost = {
|
||||||
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
|
||||||
|
.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'redirection-host',
|
object_type: 'redirection-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
|
@ -106,24 +103,24 @@ const internalRedirectionHost = {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
let 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('redirection_hosts:update', data.id)
|
return access
|
||||||
|
.can('redirection_hosts:update', data.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 data.domain_names !== 'undefined') {
|
||||||
data.domain_names.map(function (domain_name) {
|
data.domain_names.map(function (domain_name) {
|
||||||
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'redirection', data.id));
|
domain_name_check_promises.push(internalHost.isHostnameTaken(domain_name, 'redirection', data.id));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(domain_name_check_promises)
|
return Promise.all(domain_name_check_promises).then((check_results) => {
|
||||||
.then((check_results) => {
|
|
||||||
check_results.map(function (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 error.ValidationError(result.hostname + ' is already in use');
|
||||||
|
@ -142,9 +139,10 @@ const internalRedirectionHost = {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
return internalCertificate.createQuickCertificate(access, {
|
return internalCertificate
|
||||||
|
.createQuickCertificate(access, {
|
||||||
domain_names: data.domain_names || row.domain_names,
|
domain_names: data.domain_names || row.domain_names,
|
||||||
meta: _.assign({}, row.meta, data.meta)
|
meta: _.assign({}, row.meta, data.meta),
|
||||||
})
|
})
|
||||||
.then((cert) => {
|
.then((cert) => {
|
||||||
// update host with cert id
|
// update host with cert id
|
||||||
|
@ -159,9 +157,13 @@ const internalRedirectionHost = {
|
||||||
})
|
})
|
||||||
.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({}, {
|
data = _.assign(
|
||||||
domain_names: row.domain_names
|
{},
|
||||||
}, data);
|
{
|
||||||
|
domain_names: row.domain_names,
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
);
|
||||||
|
|
||||||
data = internalHost.cleanSslHstsData(data, row);
|
data = internalHost.cleanSslHstsData(data, row);
|
||||||
|
|
||||||
|
@ -171,11 +173,12 @@ const internalRedirectionHost = {
|
||||||
.patch(data)
|
.patch(data)
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'redirection-host',
|
object_type: 'redirection-host',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return _.omit(saved_row, omissions());
|
||||||
|
@ -183,14 +186,14 @@ const internalRedirectionHost = {
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalRedirectionHost.get(access, {
|
return internalRedirectionHost
|
||||||
|
.get(access, {
|
||||||
id: data.id,
|
id: data.id,
|
||||||
expand: ['owner', 'certificate']
|
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);
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
return _.omit(row, omissions());
|
return _.omit(row, omissions());
|
||||||
|
@ -212,14 +215,10 @@ const internalRedirectionHost = {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('redirection_hosts:get', data.id)
|
return access
|
||||||
|
.can('redirection_hosts:get', data.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = redirectionHostModel
|
const query = redirectionHostModel.query().where('is_deleted', 0).andWhere('id', data.id).allowGraph('[owner,certificate]').first();
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.andWhere('id', data.id)
|
|
||||||
.allowGraph('[owner,certificate]')
|
|
||||||
.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));
|
||||||
|
@ -252,7 +251,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -265,12 +265,11 @@ const internalRedirectionHost = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -280,7 +279,7 @@ const internalRedirectionHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -297,11 +296,12 @@ 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) => {
|
||||||
|
@ -317,7 +317,7 @@ const internalRedirectionHost = {
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where('id', row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
|
@ -329,7 +329,7 @@ const internalRedirectionHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -346,7 +346,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -363,12 +364,11 @@ const internalRedirectionHost = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -378,7 +378,7 @@ const internalRedirectionHost = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -396,14 +396,10 @@ 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().where('is_deleted', 0).groupBy('id').allowGraph('[owner,certificate]').orderBy('domain_names', 'ASC');
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.groupBy('id')
|
|
||||||
.allowGraph('[owner,certificate]')
|
|
||||||
.orderBy('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));
|
||||||
|
@ -439,20 +435,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 parseInt(row.count, 10);
|
return parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalRedirectionHost;
|
module.exports = internalRedirectionHost;
|
||||||
|
|
|
@ -4,22 +4,17 @@ const internalDeadHost = require('./dead-host');
|
||||||
const internalStream = require('./stream');
|
const internalStream = require('./stream');
|
||||||
|
|
||||||
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 user_id = access.token.getUserId(1);
|
||||||
|
|
||||||
let promises = [
|
const promises = [internalProxyHost.getCount(user_id, access_data.visibility), internalRedirectionHost.getCount(user_id, access_data.visibility), internalStream.getCount(user_id, access_data.visibility), internalDeadHost.getCount(user_id, access_data.visibility)];
|
||||||
internalProxyHost.getCount(user_id, access_data.visibility),
|
|
||||||
internalRedirectionHost.getCount(user_id, access_data.visibility),
|
|
||||||
internalStream.getCount(user_id, access_data.visibility),
|
|
||||||
internalDeadHost.getCount(user_id, access_data.visibility)
|
|
||||||
];
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
})
|
})
|
||||||
|
@ -28,11 +23,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;
|
module.exports = internalReport;
|
||||||
|
|
|
@ -4,7 +4,6 @@ const settingModel = require('../models/setting');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
|
|
||||||
const internalSetting = {
|
const internalSetting = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Access} access
|
* @param {Access} access
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
|
@ -12,7 +11,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -22,14 +22,11 @@ const internalSetting = {
|
||||||
throw new error.InternalValidationError('Setting could not be updated, IDs do not match: ' + row.id + ' !== ' + data.id);
|
throw new error.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) => {
|
||||||
|
@ -40,7 +37,8 @@ const internalSetting = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.deleteConfig('default')
|
return internalNginx
|
||||||
|
.deleteConfig('default')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.generateConfig('default', row);
|
return internalNginx.generateConfig('default', row);
|
||||||
})
|
})
|
||||||
|
@ -54,7 +52,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();
|
||||||
})
|
})
|
||||||
|
@ -79,12 +78,10 @@ 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) {
|
||||||
|
@ -102,12 +99,10 @@ 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 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;
|
module.exports = internalSetting;
|
||||||
|
|
|
@ -10,14 +10,14 @@ function omissions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) => {
|
||||||
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);
|
||||||
|
@ -26,25 +26,22 @@ const internalStream = {
|
||||||
data.meta = {};
|
data.meta = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return streamModel
|
return streamModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
return internalNginx.configure(streamModel, 'stream', row)
|
return internalNginx.configure(streamModel, 'stream', row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalStream.get(access, { id: row.id, expand: ['owner'] });
|
return internalStream.get(access, { id: row.id, expand: ['owner'] });
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'stream',
|
object_type: 'stream',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
|
@ -59,7 +56,8 @@ const internalStream = {
|
||||||
* @return {Promise}
|
* @return {Promise}
|
||||||
*/
|
*/
|
||||||
update: (access, data) => {
|
update: (access, data) => {
|
||||||
return access.can('streams:update', data.id)
|
return access
|
||||||
|
.can('streams:update', data.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: data.id });
|
||||||
|
@ -75,18 +73,18 @@ const internalStream = {
|
||||||
.patchAndFetchById(row.id, data)
|
.patchAndFetchById(row.id, data)
|
||||||
.then(utils.omitRow(omissions()))
|
.then(utils.omitRow(omissions()))
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
return internalNginx.configure(streamModel, 'stream', saved_row)
|
return internalNginx.configure(streamModel, 'stream', saved_row).then(() => {
|
||||||
.then(() => {
|
|
||||||
return internalStream.get(access, { id: row.id, expand: ['owner'] });
|
return internalStream.get(access, { id: row.id, expand: ['owner'] });
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'stream',
|
object_type: 'stream',
|
||||||
object_id: row.id,
|
object_id: row.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return saved_row;
|
return saved_row;
|
||||||
|
@ -108,14 +106,10 @@ const internalStream = {
|
||||||
data = {};
|
data = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('streams:get', data.id)
|
return access
|
||||||
|
.can('streams:get', data.id)
|
||||||
.then((access_data) => {
|
.then((access_data) => {
|
||||||
let query = streamModel
|
const query = streamModel.query().where('is_deleted', 0).andWhere('id', data.id).allowGraph('[owner]').first();
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.andWhere('id', data.id)
|
|
||||||
.allowGraph('[owner]')
|
|
||||||
.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));
|
||||||
|
@ -147,7 +141,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -160,12 +155,11 @@ const internalStream = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -175,7 +169,7 @@ const internalStream = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -192,11 +186,12 @@ 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: ['owner']
|
expand: ['owner'],
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
|
@ -212,7 +207,7 @@ const internalStream = {
|
||||||
.query()
|
.query()
|
||||||
.where('id', row.id)
|
.where('id', row.id)
|
||||||
.patch({
|
.patch({
|
||||||
enabled: 1
|
enabled: 1,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
|
@ -224,7 +219,7 @@ const internalStream = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -241,7 +236,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -258,12 +254,11 @@ const internalStream = {
|
||||||
.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();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -273,7 +268,7 @@ const internalStream = {
|
||||||
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()),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -291,14 +286,8 @@ 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.query().where('is_deleted', 0).groupBy('id').allowGraph('[owner]').orderBy('incoming_port', 'ASC');
|
||||||
let query = streamModel
|
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.groupBy('id')
|
|
||||||
.allowGraph('[owner]')
|
|
||||||
.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));
|
||||||
|
@ -327,20 +316,16 @@ const internalStream = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getCount: (user_id, visibility) => {
|
getCount: (user_id, visibility) => {
|
||||||
let 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 parseInt(row.count, 10);
|
return parseInt(row.count, 10);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = internalStream;
|
module.exports = internalStream;
|
||||||
|
|
|
@ -6,7 +6,6 @@ const helpers = require('../lib/helpers');
|
||||||
const TokenModel = require('../models/token');
|
const TokenModel = require('../models/token');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} data
|
* @param {Object} data
|
||||||
* @param {String} data.identity
|
* @param {String} data.identity
|
||||||
|
@ -17,7 +16,7 @@ module.exports = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getTokenFromEmail: (data, issuer) => {
|
getTokenFromEmail: (data, issuer) => {
|
||||||
let Token = new TokenModel();
|
const Token = new TokenModel();
|
||||||
|
|
||||||
data.scope = data.scope || 'user';
|
data.scope = data.scope || 'user';
|
||||||
data.expiry = data.expiry || '1d';
|
data.expiry = data.expiry || '1d';
|
||||||
|
@ -38,10 +37,8 @@ module.exports = {
|
||||||
.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.
|
||||||
|
@ -49,7 +46,7 @@ module.exports = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a moment of the expiry expression
|
// Create a moment of the expiry expression
|
||||||
let expiry = helpers.parseDatePeriod(data.expiry);
|
const expiry = helpers.parseDatePeriod(data.expiry);
|
||||||
if (expiry === null) {
|
if (expiry === null) {
|
||||||
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
|
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
|
||||||
}
|
}
|
||||||
|
@ -57,15 +54,14 @@ module.exports = {
|
||||||
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 {
|
} else {
|
||||||
|
@ -90,21 +86,20 @@ module.exports = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getFreshToken: (access, data) => {
|
getFreshToken: (access, data) => {
|
||||||
let Token = new TokenModel();
|
const Token = new TokenModel();
|
||||||
|
|
||||||
data = data || {};
|
data = data || {};
|
||||||
data.expiry = data.expiry || '1d';
|
data.expiry = data.expiry || '1d';
|
||||||
|
|
||||||
if (access && access.token.getUserId(0)) {
|
if (access && 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 = helpers.parseDatePeriod(data.expiry);
|
||||||
if (expiry === null) {
|
if (expiry === null) {
|
||||||
throw new error.AuthError('Invalid expiry time: ' + data.expiry);
|
throw new error.AuthError('Invalid expiry time: ' + data.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
|
||||||
|
@ -119,14 +114,13 @@ module.exports = {
|
||||||
|
|
||||||
return Token.create({
|
return Token.create({
|
||||||
iss: 'api',
|
iss: 'api',
|
||||||
scope: scope,
|
scope,
|
||||||
attrs: token_attrs,
|
attrs: token_attrs,
|
||||||
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 {
|
} else {
|
||||||
|
@ -146,17 +140,16 @@ module.exports = {
|
||||||
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,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,14 +13,13 @@ function omissions () {
|
||||||
}
|
}
|
||||||
|
|
||||||
const internalUser = {
|
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 || '';
|
||||||
|
@ -30,14 +29,12 @@ const internalUser = {
|
||||||
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
|
return userModel.query().insertAndFetch(data).then(utils.omitRow(omissions()));
|
||||||
.query()
|
|
||||||
.insertAndFetch(data)
|
|
||||||
.then(utils.omitRow(omissions()));
|
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (auth) {
|
if (auth) {
|
||||||
|
@ -47,7 +44,7 @@ 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;
|
||||||
|
@ -58,7 +55,7 @@ const internalUser = {
|
||||||
})
|
})
|
||||||
.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()
|
||||||
|
@ -70,7 +67,7 @@ const internalUser = {
|
||||||
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'] });
|
||||||
|
@ -78,11 +75,12 @@ const internalUser = {
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
// Add to audit log
|
// Add to audit log
|
||||||
return internalAuditLog.add(access, {
|
return internalAuditLog
|
||||||
|
.add(access, {
|
||||||
action: 'created',
|
action: 'created',
|
||||||
object_type: 'user',
|
object_type: 'user',
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: user
|
meta: user,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return user;
|
return user;
|
||||||
|
@ -103,21 +101,18 @@ const internalUser = {
|
||||||
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 error.ValidationError('Email address already in use - ' + data.email);
|
||||||
}
|
}
|
||||||
|
@ -139,21 +134,19 @@ const internalUser = {
|
||||||
|
|
||||||
data.avatar = gravatar.url(data.email || user.email, { default: 'mm' });
|
data.avatar = gravatar.url(data.email || user.email, { default: 'mm' });
|
||||||
|
|
||||||
return userModel
|
return userModel.query().patchAndFetchById(user.id, data).then(utils.omitRow(omissions()));
|
||||||
.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
|
||||||
|
.add(access, {
|
||||||
action: 'updated',
|
action: 'updated',
|
||||||
object_type: 'user',
|
object_type: 'user',
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: data
|
meta: data,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return user;
|
return user;
|
||||||
|
@ -178,14 +171,10 @@ const internalUser = {
|
||||||
data.id = access.token.getUserId(0);
|
data.id = access.token.getUserId(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return access.can('users:get', data.id)
|
return access
|
||||||
|
.can('users:get', data.id)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
let query = userModel
|
const query = userModel.query().where('is_deleted', 0).andWhere('id', data.id).allowGraph('[permissions]').first();
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.andWhere('id', data.id)
|
|
||||||
.allowGraph('[permissions]')
|
|
||||||
.first();
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
|
@ -213,18 +202,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,7 +221,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -255,7 +240,7 @@ const internalUser = {
|
||||||
.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
|
||||||
|
@ -263,7 +248,7 @@ const internalUser = {
|
||||||
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,19 +265,15 @@ 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('user.email', 'like', '%' + search_query + '%');
|
||||||
.orWhere('user.email', 'like', '%' + search_query + '%');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,20 +293,13 @@ const internalUser = {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
getAll: (access, expand, search_query) => {
|
getAll: (access, expand, search_query) => {
|
||||||
return access.can('users:list')
|
return access.can('users:list').then(() => {
|
||||||
.then(() => {
|
const query = userModel.query().where('is_deleted', 0).groupBy('id').allowGraph('[permissions]').orderBy('name', 'ASC');
|
||||||
let query = userModel
|
|
||||||
.query()
|
|
||||||
.where('is_deleted', 0)
|
|
||||||
.groupBy('id')
|
|
||||||
.allowGraph('[permissions]')
|
|
||||||
.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('email', 'like', '%' + search_query + '%');
|
||||||
.orWhere('email', 'like', '%' + search_query + '%');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +335,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -377,9 +352,10 @@ const internalUser = {
|
||||||
throw new error.ValidationError('Current password was not supplied');
|
throw new error.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;
|
||||||
|
@ -398,23 +374,17 @@ const internalUser = {
|
||||||
.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 {
|
} 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: {},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -427,8 +397,8 @@ const internalUser = {
|
||||||
meta: {
|
meta: {
|
||||||
name: user.name,
|
name: user.name,
|
||||||
password_changed: true,
|
password_changed: true,
|
||||||
auth_type: data.type
|
auth_type: data.type,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
@ -443,7 +413,8 @@ 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 });
|
||||||
})
|
})
|
||||||
|
@ -470,9 +441,7 @@ const internalUser = {
|
||||||
.patchAndFetchById(existing_auth.id, _.assign({ user_id: user.id }, data));
|
.patchAndFetchById(existing_auth.id, _.assign({ user_id: user.id }, data));
|
||||||
} else {
|
} else {
|
||||||
// insert
|
// insert
|
||||||
return userPermissionModel
|
return userPermissionModel.query().insertAndFetch(_.assign({ user_id: user.id }, data));
|
||||||
.query()
|
|
||||||
.insertAndFetch(_.assign({user_id: user.id}, data));
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((permissions) => {
|
.then((permissions) => {
|
||||||
|
@ -483,10 +452,9 @@ const internalUser = {
|
||||||
object_id: user.id,
|
object_id: user.id,
|
||||||
meta: {
|
meta: {
|
||||||
name: user.name,
|
name: user.name,
|
||||||
permissions: permissions
|
permissions,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -500,14 +468,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;
|
module.exports = internalUser;
|
||||||
|
|
|
@ -4,8 +4,8 @@ module.exports = {
|
||||||
migrations: {
|
migrations: {
|
||||||
tableName: 'migrations',
|
tableName: 'migrations',
|
||||||
stub: 'lib/migrate_template.js',
|
stub: 'lib/migrate_template.js',
|
||||||
directory: 'migrations'
|
directory: 'migrations',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
production: {
|
production: {
|
||||||
|
@ -13,7 +13,7 @@ module.exports = {
|
||||||
migrations: {
|
migrations: {
|
||||||
tableName: 'migrations',
|
tableName: 'migrations',
|
||||||
stub: 'lib/migrate_template.js',
|
stub: 'lib/migrate_template.js',
|
||||||
directory: 'migrations'
|
directory: 'migrations',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,10 +19,10 @@ const roleSchema = require('./access/roles.json');
|
||||||
const permsSchema = require('./access/permissions.json');
|
const permsSchema = require('./access/permissions.json');
|
||||||
|
|
||||||
module.exports = function (token_string) {
|
module.exports = function (token_string) {
|
||||||
let Token = new TokenModel();
|
const Token = new TokenModel();
|
||||||
let token_data = null;
|
let token_data = null;
|
||||||
let initialized = false;
|
let initialized = 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 = {};
|
||||||
|
@ -39,8 +39,8 @@ module.exports = function (token_string) {
|
||||||
} else if (!token_string) {
|
} else if (!token_string) {
|
||||||
reject(new error.PermissionError('Permission Denied'));
|
reject(new error.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:
|
||||||
|
@ -78,7 +78,6 @@ module.exports = function (token_string) {
|
||||||
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 error.AuthError('User cannot be loaded for Token');
|
||||||
}
|
}
|
||||||
|
@ -86,7 +85,8 @@ module.exports = function (token_string) {
|
||||||
} else {
|
} else {
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -105,12 +105,11 @@ module.exports = function (token_string) {
|
||||||
if (typeof token_data.attrs.id === 'undefined' || !token_data.attrs.id) {
|
if (typeof token_data.attrs.id === 'undefined' || !token_data.attrs.id) {
|
||||||
reject(new error.AuthError('User Token supplied without a User ID'));
|
reject(new error.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] : []);
|
||||||
|
@ -118,18 +117,15 @@ module.exports = function (token_string) {
|
||||||
|
|
||||||
// Proxy Hosts
|
// Proxy Hosts
|
||||||
case 'proxy_hosts':
|
case 'proxy_hosts':
|
||||||
query = proxyHostModel
|
query = proxyHostModel.query().select('id').andWhere('is_deleted', 0);
|
||||||
.query()
|
|
||||||
.select('id')
|
|
||||||
.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 +136,7 @@ module.exports = function (token_string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -156,8 +152,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,9 +165,9 @@ 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',
|
||||||
$schema: 'http://json-schema.org/draft-07/schema#',
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
||||||
description: 'Actor Properties',
|
description: 'Actor Properties',
|
||||||
|
@ -183,29 +178,28 @@ module.exports = function (token_string) {
|
||||||
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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -214,7 +208,6 @@ module.exports = function (token_string) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
token: Token,
|
token: Token,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -249,11 +242,10 @@ module.exports = function (token_string) {
|
||||||
return this.init()
|
return this.init()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// initialized, token decoded ok
|
// initialized, token decoded ok
|
||||||
return this.getObjectSchema(permission)
|
return this.getObjectSchema(permission).then((objectSchema) => {
|
||||||
.then((objectSchema) => {
|
const data_schema = {
|
||||||
let data_schema = {
|
|
||||||
[permission]: {
|
[permission]: {
|
||||||
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,
|
||||||
|
@ -262,16 +254,16 @@ 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 = {
|
||||||
$schema: 'http://json-schema.org/draft-07/schema#',
|
$schema: 'http://json-schema.org/draft-07/schema#',
|
||||||
$async: true,
|
$async: true,
|
||||||
$id: 'permissions',
|
$id: 'permissions',
|
||||||
additionalProperties: false,
|
additionalProperties: false,
|
||||||
properties: {}
|
properties: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json');
|
permissionSchema.properties[permission] = require('./access/' + permission.replace(/:/gim, '-') + '.json');
|
||||||
|
@ -280,23 +272,17 @@ module.exports = function (token_string) {
|
||||||
// logger.info('permissionSchema', JSON.stringify(permissionSchema, null, 2));
|
// logger.info('permissionSchema', JSON.stringify(permissionSchema, null, 2));
|
||||||
// logger.info('data_schema', JSON.stringify(data_schema, null, 2));
|
// logger.info('data_schema', JSON.stringify(data_schema, null, 2));
|
||||||
|
|
||||||
let ajv = validator({
|
const ajv = validator({
|
||||||
verbose: true,
|
verbose: true,
|
||||||
allErrors: true,
|
allErrors: true,
|
||||||
format: 'full',
|
format: 'full',
|
||||||
missingRefs: 'fail',
|
missingRefs: 'fail',
|
||||||
breakOnError: true,
|
breakOnError: true,
|
||||||
coerceTypes: true,
|
coerceTypes: true,
|
||||||
schemas: [
|
schemas: [roleSchema, permsSchema, objectSchema, permissionSchema],
|
||||||
roleSchema,
|
|
||||||
permsSchema,
|
|
||||||
objectSchema,
|
|
||||||
permissionSchema
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return ajv.validate('permissions', data_schema)
|
return ajv.validate('permissions', data_schema).then(() => {
|
||||||
.then(() => {
|
|
||||||
return data_schema[permission];
|
return data_schema[permission];
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -309,6 +295,6 @@ module.exports = function (token_string) {
|
||||||
throw new error.PermissionError('Permission Denied', err);
|
throw new error.PermissionError('Permission Denied', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -5,7 +5,6 @@ const logger = require('../logger').certbot;
|
||||||
const batchflow = require('batchflow');
|
const batchflow = require('batchflow');
|
||||||
|
|
||||||
const certbot = {
|
const certbot = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {array} pluginKeys
|
* @param {array} pluginKeys
|
||||||
*/
|
*/
|
||||||
|
@ -18,9 +17,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();
|
||||||
})
|
})
|
||||||
|
@ -59,7 +60,8 @@ const certbot = {
|
||||||
logger.start(`Installing ${pluginKey}...`);
|
logger.start(`Installing ${pluginKey}...`);
|
||||||
|
|
||||||
const cmd = 'pip install --no-cache-dir ' + plugin.package_name;
|
const cmd = 'pip install --no-cache-dir ' + plugin.package_name;
|
||||||
return utils.exec(cmd)
|
return utils
|
||||||
|
.exec(cmd)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
logger.complete(`Installed ${pluginKey}`);
|
logger.complete(`Installed ${pluginKey}`);
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -14,7 +14,7 @@ const configure = () => {
|
||||||
let configData;
|
let configData;
|
||||||
try {
|
try {
|
||||||
configData = require(filename);
|
configData = require(filename);
|
||||||
} catch (err) {
|
} catch {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,10 +57,10 @@ const configure = () => {
|
||||||
knex: {
|
knex: {
|
||||||
client: 'sqlite3',
|
client: 'sqlite3',
|
||||||
connection: {
|
connection: {
|
||||||
filename: envSqliteFile
|
filename: envSqliteFile,
|
||||||
|
},
|
||||||
|
useNullAsDefault: true,
|
||||||
},
|
},
|
||||||
useNullAsDefault: true
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
keys: getKeys(),
|
keys: getKeys(),
|
||||||
};
|
};
|
||||||
|
@ -103,7 +103,6 @@ const generateKeys = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {string} key ie: 'database' or 'database.engine'
|
* @param {string} key ie: 'database' or 'database.engine'
|
||||||
|
@ -183,5 +182,5 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
useLetsencryptStaging: function () {
|
useLetsencryptStaging: function () {
|
||||||
return !!process.env.LE_STAGING;
|
return !!process.env.LE_STAGING;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,6 @@ const _ = require('lodash');
|
||||||
const util = require('util');
|
const util = require('util');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
PermissionError: function (message, 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;
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
const validator = require('../validator');
|
const validator = require('../validator');
|
||||||
|
|
||||||
module.exports = function (req, res, next) {
|
module.exports = function (req, res, next) {
|
||||||
|
|
||||||
if (req.headers.origin) {
|
if (req.headers.origin) {
|
||||||
|
|
||||||
const originSchema = {
|
const originSchema = {
|
||||||
oneOf: [
|
oneOf: [
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
pattern: '^[a-z\\-]+:\\/\\/(?:[\\w\\-\\.]+(:[0-9]+)?/?)?$'
|
pattern: '^[a-z\\-]+:\\/\\/(?:[\\w\\-\\.]+(:[0-9]+)?/?)?$',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
pattern: '^[a-z\\-]+:\\/\\/(?:\\[([a-z0-9]{0,4}\\:?)+\\])?/?(:[0-9]+)?$'
|
pattern: '^[a-z\\-]+:\\/\\/(?:\\[([a-z0-9]{0,4}\\:?)+\\])?/?(:[0-9]+)?$',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
// very relaxed validation....
|
// very relaxed validation....
|
||||||
|
@ -26,15 +24,13 @@ module.exports = function (req, res, next) {
|
||||||
'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': 'Content-Type, Cache-Control, Pragma, Expires, Authorization, X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit',
|
||||||
'Access-Control-Max-Age': 5 * 60,
|
'Access-Control-Max-Age': 5 * 60,
|
||||||
'Access-Control-Expose-Headers': 'X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit'
|
'Access-Control-Expose-Headers': 'X-Dataset-Total, X-Dataset-Offset, X-Dataset-Limit',
|
||||||
});
|
});
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// No origin
|
// No origin
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,8 +3,9 @@ const Access = require('../access');
|
||||||
module.exports = () => {
|
module.exports = () => {
|
||||||
return function (req, res, next) {
|
return function (req, 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,7 +1,7 @@
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return function (req, res, next) {
|
return function (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];
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
let _ = require('lodash');
|
const _ = require('lodash');
|
||||||
|
|
||||||
module.exports = function (default_sort, default_offset, default_limit, max_limit) {
|
module.exports = function (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
|
||||||
*
|
*
|
||||||
|
@ -12,7 +11,6 @@ module.exports = function (default_sort, default_offset, default_limit, max_limi
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return function (req, res, next) {
|
return function (req, res, next) {
|
||||||
|
|
||||||
req.query.offset = typeof req.query.limit === 'undefined' ? default_offset || 0 : parseInt(req.query.offset, 10);
|
req.query.offset = typeof req.query.limit === 'undefined' ? default_offset || 0 : 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 : parseInt(req.query.limit, 10);
|
||||||
|
|
||||||
|
@ -22,23 +20,23 @@ module.exports = function (default_sort, default_offset, default_limit, max_limi
|
||||||
|
|
||||||
// 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, function (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,7 +1,6 @@
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
|
|
||||||
module.exports = {
|
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
|
||||||
*
|
*
|
||||||
|
@ -21,12 +20,11 @@ module.exports = {
|
||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
parseDatePeriod: function (expression) {
|
parseDatePeriod: function (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;
|
||||||
}
|
},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,7 +11,6 @@ const logger = require('../logger').migrate;
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex, Promise) {
|
exports.up = function (knex, Promise) {
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
// Create Table example:
|
// Create Table example:
|
||||||
|
|
|
@ -7,8 +7,6 @@ const error = require('./error');
|
||||||
// const logger = require('../logger').global;
|
// const logger = require('../logger').global;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} cmd
|
* @param {String} cmd
|
||||||
*/
|
*/
|
||||||
|
@ -62,7 +60,7 @@ module.exports = {
|
||||||
const childProcess = spawn(cmd, {
|
const childProcess = spawn(cmd, {
|
||||||
shell: true,
|
shell: true,
|
||||||
detached: true,
|
detached: true,
|
||||||
stdio: 'inherit'
|
stdio: 'inherit',
|
||||||
});
|
});
|
||||||
|
|
||||||
childProcess.on('error', (err) => {
|
childProcess.on('error', (err) => {
|
||||||
|
@ -119,7 +117,7 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
getRenderEngine: function () {
|
getRenderEngine: function () {
|
||||||
const renderEngine = new Liquid({
|
const renderEngine = new Liquid({
|
||||||
root: __dirname + '/../templates/'
|
root: __dirname + '/../templates/',
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -136,5 +134,5 @@ module.exports = {
|
||||||
});
|
});
|
||||||
|
|
||||||
return renderEngine;
|
return renderEngine;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,7 +7,7 @@ const ajv = require('ajv')({
|
||||||
validateSchema: true,
|
validateSchema: true,
|
||||||
allErrors: false,
|
allErrors: false,
|
||||||
format: 'full',
|
format: 'full',
|
||||||
coerceTypes: true
|
coerceTypes: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -21,23 +21,21 @@ function apiValidator (schema, payload/*, description*/) {
|
||||||
reject(new error.ValidationError('Payload is undefined'));
|
reject(new error.ValidationError('Payload is undefined'));
|
||||||
}
|
}
|
||||||
|
|
||||||
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(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 error.ValidationError(message);
|
||||||
err.debug = [validate.errors, payload];
|
err.debug = [validate.errors, payload];
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
apiValidator.loadSchemas = parser
|
apiValidator.loadSchemas = parser.dereference(path.resolve('schema/index.json')).then((schema) => {
|
||||||
.dereference(path.resolve('schema/index.json'))
|
|
||||||
.then((schema) => {
|
|
||||||
ajv.addSchema(schema);
|
ajv.addSchema(schema);
|
||||||
return schema;
|
return schema;
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,9 +9,7 @@ const ajv = require('ajv')({
|
||||||
allErrors: true,
|
allErrors: true,
|
||||||
format: 'full', // strict regexes for format checks
|
format: 'full', // strict regexes for format checks
|
||||||
coerceTypes: true,
|
coerceTypes: true,
|
||||||
schemas: [
|
schemas: [definitions],
|
||||||
definitions
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,24 +24,20 @@ function validator (schema, payload) {
|
||||||
reject(new error.InternalValidationError('Payload is falsy'));
|
reject(new error.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 error.InternalValidationError(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = validator;
|
module.exports = validator;
|
||||||
|
|
|
@ -10,5 +10,5 @@ module.exports = {
|
||||||
certbot: new Signale({ scope: 'Certbot ' }),
|
certbot: new Signale({ scope: 'Certbot ' }),
|
||||||
import: new Signale({ scope: 'Importer ' }),
|
import: new Signale({ scope: 'Importer ' }),
|
||||||
setup: new Signale({ scope: 'Setup ' }),
|
setup: new Signale({ scope: 'Setup ' }),
|
||||||
ip_ranges: new Signale({scope: 'IP Ranges'})
|
ip_ranges: new Signale({ scope: 'IP Ranges' }),
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,13 +3,12 @@ const logger = require('./logger').migrate;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
latest: function () {
|
latest: function () {
|
||||||
return db.migrate.currentVersion()
|
return db.migrate.currentVersion().then((version) => {
|
||||||
.then((version) => {
|
|
||||||
logger.info('Current database version:', version);
|
logger.info('Current database version:', version);
|
||||||
return db.migrate.latest({
|
return db.migrate.latest({
|
||||||
tableName: 'migrations',
|
tableName: 'migrations',
|
||||||
directory: 'migrations'
|
directory: 'migrations',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] 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();
|
||||||
|
@ -189,7 +190,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] audit_log Table created');
|
logger.info('[' + migrate_name + '] audit_log Table created');
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -200,6 +200,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down the initial data.');
|
logger.warn('[' + migrate_name + "] You can't migrate down the initial data.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,13 +13,13 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.integer('allow_websocket_upgrade').notNull().unsigned().defaultTo(0);
|
proxy_host.integer('allow_websocket_upgrade').notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
logger.info('[' + migrate_name + '] proxy_host Table altered');
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,6 +30,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.renameColumn('forward_ip', 'forward_host');
|
proxy_host.renameColumn('forward_ip', 'forward_host');
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -29,6 +30,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
proxy_host.integer('http2_support').notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -43,7 +44,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.string('forward_scheme').notNull().defaultTo('http');
|
proxy_host.string('forward_scheme').notNull().defaultTo('http');
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -29,6 +30,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
proxy_host.integer('enabled').notNull().unsigned().defaultTo(1);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -50,6 +51,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.json('locations');
|
proxy_host.json('locations');
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -30,6 +31,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('proxy_host', function (proxy_host) {
|
return knex.schema
|
||||||
|
.table('proxy_host', function (proxy_host) {
|
||||||
proxy_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
proxy_host.integer('hsts_enabled').notNull().unsigned().defaultTo(0);
|
||||||
proxy_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
proxy_host.integer('hsts_subdomains').notNull().unsigned().defaultTo(0);
|
||||||
})
|
})
|
||||||
|
@ -46,6 +47,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.createTable('setting', (table) => {
|
return knex.schema
|
||||||
|
.createTable('setting', (table) => {
|
||||||
table.string('id').notNull().primary();
|
table.string('id').notNull().primary();
|
||||||
table.string('name', 100).notNull();
|
table.string('name', 100).notNull();
|
||||||
table.string('description', 255).notNull();
|
table.string('description', 255).notNull();
|
||||||
|
@ -33,6 +34,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down the initial data.');
|
logger.warn('[' + migrate_name + "] You can't migrate down the initial data.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,10 @@ const logger = require('../logger').migrate;
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] 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();
|
||||||
|
@ -22,7 +22,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
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(function () {
|
||||||
logger.info('[' + migrate_name + '] access_list_client Table created');
|
logger.info('[' + migrate_name + '] access_list_client Table created');
|
||||||
|
@ -46,8 +45,7 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
exports.down = function (knex /*, Promise */) {
|
exports.down = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
return knex.schema.dropTable('access_list_client')
|
return knex.schema.dropTable('access_list_client').then(() => {
|
||||||
.then(() => {
|
|
||||||
logger.info('[' + migrate_name + '] access_list_client Table dropped');
|
logger.info('[' + migrate_name + '] access_list_client Table dropped');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('access_list', function (access_list) {
|
return knex.schema
|
||||||
|
.table('access_list', function (access_list) {
|
||||||
access_list.renameColumn('satify_any', 'satisfy_any');
|
access_list.renameColumn('satify_any', 'satisfy_any');
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -29,6 +30,6 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.down = function (knex, Promise) {
|
exports.down = function (knex, Promise) {
|
||||||
logger.warn('[' + migrate_name + '] You can\'t migrate down this one.');
|
logger.warn('[' + migrate_name + "] You can't migrate down this one.");
|
||||||
return Promise.resolve(true);
|
return Promise.resolve(true);
|
||||||
};
|
};
|
||||||
|
|
|
@ -11,10 +11,10 @@ const logger = require('../logger').migrate;
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('access_list', function (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(() => {
|
||||||
|
@ -32,7 +32,8 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
exports.down = function (knex /*, Promise */) {
|
exports.down = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
return knex.schema.table('access_list', function (access_list) {
|
return knex.schema
|
||||||
|
.table('access_list', function (access_list) {
|
||||||
access_list.dropColumn('pass_auth');
|
access_list.dropColumn('pass_auth');
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
|
|
@ -11,10 +11,10 @@ const logger = require('../logger').migrate;
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] 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(function () {
|
||||||
|
@ -32,7 +32,8 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
exports.down = function (knex /*, Promise */) {
|
exports.down = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', (table) => {
|
return knex.schema
|
||||||
|
.table('redirection_host', (table) => {
|
||||||
table.dropColumn('forward_scheme');
|
table.dropColumn('forward_scheme');
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
|
|
@ -11,10 +11,10 @@ const logger = require('../logger').migrate;
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
|
|
||||||
logger.info('[' + migrate_name + '] 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(function () {
|
||||||
|
@ -32,7 +32,8 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
exports.down = function (knex /*, Promise */) {
|
exports.down = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
return knex.schema.table('redirection_host', (table) => {
|
return knex.schema
|
||||||
|
.table('redirection_host', (table) => {
|
||||||
table.dropColumn('forward_http_code');
|
table.dropColumn('forward_http_code');
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
|
|
@ -13,7 +13,8 @@ const logger = require('../logger').migrate;
|
||||||
exports.up = function (knex /*, Promise */) {
|
exports.up = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Up...');
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
return knex.schema.table('stream', (table) => {
|
return knex.schema
|
||||||
|
.table('stream', (table) => {
|
||||||
table.renameColumn('forward_ip', 'forwarding_host');
|
table.renameColumn('forward_ip', 'forwarding_host');
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
@ -31,7 +32,8 @@ exports.up = function (knex/*, Promise*/) {
|
||||||
exports.down = function (knex /*, Promise */) {
|
exports.down = function (knex /*, Promise */) {
|
||||||
logger.info('[' + migrate_name + '] Migrating Down...');
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
return knex.schema.table('stream', (table) => {
|
return knex.schema
|
||||||
|
.table('stream', (table) => {
|
||||||
table.renameColumn('forwarding_host', 'forward_ip');
|
table.renameColumn('forwarding_host', 'forward_ip');
|
||||||
})
|
})
|
||||||
.then(function () {
|
.then(function () {
|
||||||
|
|
|
@ -9,7 +9,8 @@ async function regenerateDefaultHost(knex) {
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
|
|
@ -46,39 +46,39 @@ class AccessList extends Model {
|
||||||
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
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: ProxyHost,
|
||||||
join: {
|
join: {
|
||||||
from: 'access_list.id',
|
from: 'access_list.id',
|
||||||
to: 'proxy_host.access_list_id'
|
to: 'proxy_host.access_list_id',
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('proxy_host.is_deleted', 0);
|
qb.where('proxy_host.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,12 @@ class AccessListAuth extends Model {
|
||||||
modelClass: require('./access_list'),
|
modelClass: require('./access_list'),
|
||||||
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('access_list.is_deleted', 0);
|
qb.where('access_list.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,12 @@ class AccessListClient extends Model {
|
||||||
modelClass: require('./access_list'),
|
modelClass: require('./access_list'),
|
||||||
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('access_list.is_deleted', 0);
|
qb.where('access_list.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,9 @@ class AuditLog extends Model {
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'audit_log.user_id',
|
from: 'audit_log.user_id',
|
||||||
to: 'user.id'
|
to: 'user.id',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,10 @@ Model.knex(db);
|
||||||
|
|
||||||
function encryptPassword() {
|
function encryptPassword() {
|
||||||
/* jshint -W040 */
|
/* jshint -W040 */
|
||||||
let _this = this;
|
const _this = this;
|
||||||
|
|
||||||
if (_this.type === 'password' && _this.secret) {
|
if (_this.type === 'password' && _this.secret) {
|
||||||
return bcrypt.hash(_this.secret, 13)
|
return bcrypt.hash(_this.secret, 13).then(function (hash) {
|
||||||
.then(function (hash) {
|
|
||||||
_this.secret = hash;
|
_this.secret = hash;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -70,12 +69,12 @@ class Auth extends Model {
|
||||||
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,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,12 +52,12 @@ class Certificate extends Model {
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'certificate.owner_user_id',
|
from: 'certificate.owner_user_id',
|
||||||
to: 'user.id'
|
to: 'user.id',
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,23 +48,23 @@ class DeadHost extends Model {
|
||||||
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('certificate.is_deleted', 0);
|
qb.where('certificate.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ Model.knex(db);
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
if (config.isSqlite()) {
|
if (config.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()');
|
||||||
|
|
|
@ -49,34 +49,34 @@ class ProxyHost extends Model {
|
||||||
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('access_list.is_deleted', 0);
|
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('certificate.is_deleted', 0);
|
qb.where('certificate.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
|
@ -51,23 +50,23 @@ class RedirectionHost extends Model {
|
||||||
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
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: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('certificate.is_deleted', 0);
|
qb.where('certificate.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,12 @@ class Stream extends Model {
|
||||||
modelClass: User,
|
modelClass: User,
|
||||||
join: {
|
join: {
|
||||||
from: 'stream.owner_user_id',
|
from: 'stream.owner_user_id',
|
||||||
to: 'user.id'
|
to: 'user.id',
|
||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ const logger = require('../logger').global;
|
||||||
const ALGO = 'RS256';
|
const ALGO = 'RS256';
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
|
|
||||||
let token_data = {};
|
let token_data = {};
|
||||||
|
|
||||||
const self = {
|
const self = {
|
||||||
|
@ -27,12 +26,10 @@ module.exports = function () {
|
||||||
// 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, config.getPrivateKey(), options, (err, token) => {
|
||||||
|
@ -41,8 +38,8 @@ module.exports = function () {
|
||||||
} else {
|
} else {
|
||||||
token_data = payload;
|
token_data = payload;
|
||||||
resolve({
|
resolve({
|
||||||
token: token,
|
token,
|
||||||
payload: payload
|
payload,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -64,13 +61,11 @@ module.exports = function () {
|
||||||
} else {
|
} else {
|
||||||
jwt.verify(token, config.getPublicKey(), { ignoreExpiration: false, algorithms: [ALGO] }, (err, result) => {
|
jwt.verify(token, config.getPublicKey(), { ignoreExpiration: false, algorithms: [ALGO] }, (err, result) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
||||||
if (err.name === 'TokenExpiredError') {
|
if (err.name === 'TokenExpiredError') {
|
||||||
reject(new error.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;
|
||||||
resolve(token_data);
|
resolve(token_data);
|
||||||
|
@ -81,7 +76,6 @@ module.exports = function () {
|
||||||
reject(err);
|
reject(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,7 +119,7 @@ module.exports = function () {
|
||||||
}
|
}
|
||||||
|
|
||||||
return default_value || 0;
|
return default_value || 0;
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
|
|
|
@ -42,12 +42,11 @@ class User extends Model {
|
||||||
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;
|
module.exports = User;
|
||||||
|
|
|
@ -4,19 +4,19 @@
|
||||||
"description": "A beautiful interface for creating Nginx endpoints",
|
"description": "A beautiful interface for creating Nginx endpoints",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/json-schema-ref-parser": "11.5.4",
|
"@apidevtools/json-schema-ref-parser": "11.5.5",
|
||||||
"ajv": "6.12.6",
|
"ajv": "6.12.6",
|
||||||
"archiver": "7.0.1",
|
"archiver": "7.0.1",
|
||||||
"batchflow": "0.4.0",
|
"batchflow": "0.4.0",
|
||||||
"bcrypt": "5.1.1",
|
"bcrypt": "5.1.1",
|
||||||
"body-parser": "1.20.2",
|
"body-parser": "1.20.2",
|
||||||
"compression": "1.7.4",
|
"compression": "1.7.4",
|
||||||
"express": "4.19.1",
|
"express": "4.19.2",
|
||||||
"express-fileupload": "1.5.0",
|
"express-fileupload": "1.5.0",
|
||||||
"gravatar": "1.8.2",
|
"gravatar": "1.8.2",
|
||||||
"jsonwebtoken": "9.0.2",
|
"jsonwebtoken": "9.0.2",
|
||||||
"knex": "3.1.0",
|
"knex": "3.1.0",
|
||||||
"liquidjs": "10.10.2",
|
"liquidjs": "10.11.0",
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"moment": "2.30.1",
|
"moment": "2.30.1",
|
||||||
"mysql": "2.18.1",
|
"mysql": "2.18.1",
|
||||||
|
@ -29,7 +29,11 @@
|
||||||
"author": "Jamie Curnow <jc@jc21.com> and ZoeyVid <zoeyvid@zvcdn.de>",
|
"author": "Jamie Curnow <jc@jc21.com> and ZoeyVid <zoeyvid@zvcdn.de>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "8.57.0",
|
"@eslint/js": "9.0.0",
|
||||||
"eslint-plugin-align-assignments": "1.1.2"
|
"eslint": "9.0.0",
|
||||||
|
"eslint-config-prettier": "9.1.0",
|
||||||
|
"eslint-plugin-prettier": "5.1.3",
|
||||||
|
"globals": "15.0.0",
|
||||||
|
"prettier": "3.2.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@ if (fs.existsSync(process.env.DB_SQLITE_FILE)) {
|
||||||
|
|
||||||
console.log(`Password for user ${USER_EMAIL} has been reset.`);
|
console.log(`Password for user ${USER_EMAIL} has been reset.`);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ const validator = require('../../lib/validator');
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
const jwtdecode = require('../../lib/express/jwt-decode');
|
||||||
const internalAuditLog = require('../../internal/audit-log');
|
const internalAuditLog = require('../../internal/audit-log');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,26 +25,28 @@ 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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,10 @@ const express = require('express');
|
||||||
const pjson = require('../../package.json');
|
const pjson = require('../../package.json');
|
||||||
const error = require('../../lib/error');
|
const error = require('../../lib/error');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,15 +13,15 @@ let router = express.Router({
|
||||||
* GET /api
|
* GET /api
|
||||||
*/
|
*/
|
||||||
router.get('/', (req, res /*, next */) => {
|
router.get('/', (req, 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: parseInt(version.shift(), 10),
|
||||||
minor: parseInt(version.shift(), 10),
|
minor: parseInt(version.shift(), 10),
|
||||||
revision: parseInt(version.shift(), 10)
|
revision: parseInt(version.shift(), 10),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
const internalAccessList = require('../../../internal/access-list');
|
const internalAccessList = require('../../../internal/access-list');
|
||||||
const apiValidator = require('../../../lib/validator/api');
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,26 +26,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
})
|
})
|
||||||
|
@ -61,8 +63,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -85,30 +86,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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: 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);
|
||||||
})
|
})
|
||||||
|
@ -125,8 +128,7 @@ router
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -137,10 +139,10 @@ 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: parseInt(req.params.list_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
const internalCertificate = require('../../../internal/certificate');
|
const internalCertificate = require('../../../internal/certificate');
|
||||||
const apiValidator = require('../../../lib/validator/api');
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,26 +26,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
})
|
})
|
||||||
|
@ -62,8 +64,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -86,10 +87,10 @@ router
|
||||||
* Test HTTP challenge for domains
|
* Test HTTP challenge for domains
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, res, next) => {
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -112,30 +113,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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: 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);
|
||||||
})
|
})
|
||||||
|
@ -152,8 +155,7 @@ router
|
||||||
return internalCertificate.update(res.locals.access, payload);
|
return internalCertificate.update(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
|
@ -164,10 +166,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: parseInt(req.params.certificate_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -191,16 +193,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
|
||||||
|
.upload(res.locals.access, {
|
||||||
id: parseInt(req.params.certificate_id, 10),
|
id: parseInt(req.params.certificate_id, 10),
|
||||||
files: req.files
|
files: req.files,
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
}
|
}
|
||||||
|
@ -225,12 +226,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: parseInt(req.params.certificate_id, 10),
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -253,12 +254,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: 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);
|
||||||
});
|
});
|
||||||
|
@ -282,15 +283,14 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
const internalDeadHost = require('../../../internal/dead-host');
|
const internalDeadHost = require('../../../internal/dead-host');
|
||||||
const apiValidator = require('../../../lib/validator/api');
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,26 +26,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
})
|
})
|
||||||
|
@ -61,8 +63,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -85,30 +86,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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: 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);
|
||||||
})
|
})
|
||||||
|
@ -125,8 +128,7 @@ router
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -137,10 +139,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -161,10 +163,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -185,10 +187,10 @@ 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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
const internalProxyHost = require('../../../internal/proxy-host');
|
const internalProxyHost = require('../../../internal/proxy-host');
|
||||||
const apiValidator = require('../../../lib/validator/api');
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,26 +26,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
})
|
})
|
||||||
|
@ -61,8 +63,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -85,30 +86,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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: 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);
|
||||||
})
|
})
|
||||||
|
@ -125,8 +128,7 @@ router
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -137,10 +139,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -161,10 +163,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -185,10 +187,10 @@ 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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
const internalRedirectionHost = require('../../../internal/redirection-host');
|
const internalRedirectionHost = require('../../../internal/redirection-host');
|
||||||
const apiValidator = require('../../../lib/validator/api');
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,26 +26,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
})
|
})
|
||||||
|
@ -61,8 +63,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -85,30 +86,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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: 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);
|
||||||
})
|
})
|
||||||
|
@ -125,8 +128,7 @@ router
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -137,10 +139,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -161,10 +163,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -185,10 +187,10 @@ 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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../../lib/express/jwt-decode');
|
||||||
const internalStream = require('../../../internal/stream');
|
const internalStream = require('../../../internal/stream');
|
||||||
const apiValidator = require('../../../lib/validator/api');
|
const apiValidator = require('../../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,26 +26,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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);
|
||||||
})
|
})
|
||||||
|
@ -61,8 +63,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -85,30 +86,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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: 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);
|
||||||
})
|
})
|
||||||
|
@ -125,8 +128,7 @@ router
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -137,10 +139,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: parseInt(req.params.stream_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -161,10 +163,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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -185,10 +187,10 @@ 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: parseInt(req.params.host_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(200)
|
res.status(200).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,10 @@ const express = require('express');
|
||||||
const jwtdecode = require('../../lib/express/jwt-decode');
|
const jwtdecode = require('../../lib/express/jwt-decode');
|
||||||
const internalReport = require('../../internal/report');
|
const internalReport = require('../../internal/report');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
router
|
router
|
||||||
|
@ -18,10 +18,10 @@ router
|
||||||
* GET /reports/hosts
|
* GET /reports/hosts
|
||||||
*/
|
*/
|
||||||
.get(jwtdecode(), (req, res, next) => {
|
.get(jwtdecode(), (req, 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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,10 +2,10 @@ const express = require('express');
|
||||||
const swaggerJSON = require('../../doc/api.swagger.json');
|
const swaggerJSON = require('../../doc/api.swagger.json');
|
||||||
const PACKAGE = require('../../package.json');
|
const PACKAGE = require('../../package.json');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
router
|
router
|
||||||
|
|
|
@ -4,10 +4,10 @@ const jwtdecode = require('../../lib/express/jwt-decode');
|
||||||
const internalSetting = require('../../internal/setting');
|
const internalSetting = require('../../internal/setting');
|
||||||
const apiValidator = require('../../lib/validator/api');
|
const apiValidator = require('../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,10 +26,10 @@ router
|
||||||
* Retrieve all settings
|
* Retrieve all settings
|
||||||
*/
|
*/
|
||||||
.get((req, res, next) => {
|
.get((req, 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);
|
||||||
});
|
});
|
||||||
|
@ -52,25 +52,27 @@ 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: {
|
||||||
$ref: 'definitions#/definitions/setting_id'
|
$ref: 'definitions#/definitions/setting_id',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}, {
|
},
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -87,8 +89,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,10 +3,10 @@ const jwtdecode = require('../../lib/express/jwt-decode');
|
||||||
const internalToken = require('../../internal/token');
|
const internalToken = require('../../internal/token');
|
||||||
const apiValidator = require('../../lib/validator/api');
|
const apiValidator = require('../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
router
|
router
|
||||||
|
@ -23,13 +23,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);
|
||||||
})
|
})
|
||||||
|
@ -45,8 +45,7 @@ router
|
||||||
return internalToken.getTokenFromEmail(payload);
|
return internalToken.getTokenFromEmail(payload);
|
||||||
})
|
})
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
res.status(200)
|
res.status(200).send(data);
|
||||||
.send(data);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,10 +5,10 @@ const userIdFromMe = require('../../lib/express/user-id-from-me');
|
||||||
const internalUser = require('../../internal/user');
|
const internalUser = require('../../internal/user');
|
||||||
const apiValidator = require('../../lib/validator/api');
|
const apiValidator = require('../../lib/validator/api');
|
||||||
|
|
||||||
let router = express.Router({
|
const router = express.Router({
|
||||||
caseSensitive: true,
|
caseSensitive: true,
|
||||||
strict: true,
|
strict: true,
|
||||||
mergeParams: true
|
mergeParams: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,26 +27,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: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/expand',
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
$ref: 'definitions#/definitions/query'
|
$ref: 'definitions#/definitions/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(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
|
@ -62,8 +64,7 @@ router
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@ -87,31 +88,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: 'definitions#/definitions/id'
|
$ref: 'definitions#/definitions/id',
|
||||||
},
|
},
|
||||||
expand: {
|
expand: {
|
||||||
$ref: 'definitions#/definitions/expand'
|
$ref: 'definitions#/definitions/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(next);
|
.catch(next);
|
||||||
})
|
})
|
||||||
|
@ -128,8 +131,7 @@ router
|
||||||
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);
|
||||||
})
|
})
|
||||||
|
@ -140,10 +142,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);
|
||||||
});
|
});
|
||||||
|
@ -173,8 +175,7 @@ router
|
||||||
return internalUser.setPassword(res.locals.access, payload);
|
return internalUser.setPassword(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -204,8 +205,7 @@ router
|
||||||
return internalUser.setPermissions(res.locals.access, payload);
|
return internalUser.setPermissions(res.locals.access, payload);
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
@ -228,10 +228,10 @@ 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: parseInt(req.params.user_id, 10) })
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
res.status(201)
|
res.status(201).send(result);
|
||||||
.send(result);
|
|
||||||
})
|
})
|
||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
|
@ -24,7 +24,7 @@ const setupDefaultUser = () => {
|
||||||
// Create a new user and set password
|
// Create a new user and set password
|
||||||
logger.info('Creating a new user: admin@example.com with password: iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi');
|
logger.info('Creating a new user: admin@example.com with password: iArhP1j7p1P6TA92FA2FMbbUGYqwcYzxC4AVEe12Wbi94FY9gNN62aKyF1shrvG4NycjjX9KfmDQiwkLZH1ZDR9xMjiG2QmoHXi');
|
||||||
|
|
||||||
let data = {
|
const data = {
|
||||||
is_deleted: 0,
|
is_deleted: 0,
|
||||||
email: 'admin@example.com',
|
email: 'admin@example.com',
|
||||||
name: 'Administrator',
|
name: 'Administrator',
|
||||||
|
@ -111,8 +111,8 @@ const setupCertbotPlugins = () => {
|
||||||
.andWhere('provider', 'letsencrypt')
|
.andWhere('provider', 'letsencrypt')
|
||||||
.then((certificates) => {
|
.then((certificates) => {
|
||||||
if (certificates && certificates.length) {
|
if (certificates && certificates.length) {
|
||||||
let plugins = [];
|
const plugins = [];
|
||||||
let promises = [];
|
const promises = [];
|
||||||
|
|
||||||
certificates.map(function (certificate) {
|
certificates.map(function (certificate) {
|
||||||
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
||||||
|
@ -123,17 +123,15 @@ const setupCertbotPlugins = () => {
|
||||||
// Make sure credentials file exists
|
// Make sure credentials file exists
|
||||||
const credentials_loc = '/data/tls/certbot/credentials/credentials-' + certificate.id;
|
const credentials_loc = '/data/tls/certbot/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 /data/tls/certbot/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
|
const credentials_cmd = "[ -f '" + credentials_loc + "' ] || { mkdir -p /data/tls/certbot/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 certbot.installPlugins(plugins)
|
return certbot.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(', '));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -143,7 +141,5 @@ const setupCertbotPlugins = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
return setupDefaultUser()
|
return setupDefaultUser().then(setupDefaultSettings).then(setupCertbotPlugins);
|
||||||
.then(setupDefaultSettings)
|
|
||||||
.then(setupCertbotPlugins);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"description": "A beautiful interface for creating Nginx endpoints",
|
"description": "A beautiful interface for creating Nginx endpoints",
|
||||||
"main": "js/index.js",
|
"main": "js/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/core": "7.24.3",
|
"@babel/core": "7.24.4",
|
||||||
"babel-core": "6.26.3",
|
"babel-core": "6.26.3",
|
||||||
"babel-loader": "8.3.0",
|
"babel-loader": "8.3.0",
|
||||||
"babel-preset-env": "1.7.0",
|
"babel-preset-env": "1.7.0",
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
"nodemon": "3.1.0",
|
"nodemon": "3.1.0",
|
||||||
"numeral": "2.0.6",
|
"numeral": "2.0.6",
|
||||||
"sass-loader": "10.5.2",
|
"sass-loader": "10.5.2",
|
||||||
"style-loader": "3.3.4",
|
"style-loader": "4.0.0",
|
||||||
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
|
"tabler-ui": "git+https://github.com/tabler/tabler.git#00f78ad823311bc3ad974ac3e5b0126198f0a813",
|
||||||
"underscore": "1.13.6",
|
"underscore": "1.13.6",
|
||||||
"webpack": "4.47.0",
|
"webpack": "4.47.0",
|
||||||
|
|
|
@ -40,6 +40,7 @@ http {
|
||||||
gzip_types *;
|
gzip_types *;
|
||||||
gzip_proxied any;
|
gzip_proxied any;
|
||||||
gzip_comp_level 1;
|
gzip_comp_level 1;
|
||||||
|
gzip_http_version 1.0;
|
||||||
gunzip on;
|
gunzip on;
|
||||||
gzip_static on;
|
gzip_static on;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue