mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2025-06-18 10:06:26 +00:00
Compare commits
244 Commits
Author | SHA1 | Date | |
---|---|---|---|
095bc8f676 | |||
8c15340b83 | |||
a13f7c3792 | |||
6748985669 | |||
e2957f070b | |||
fccbde1371 | |||
fec36834f7 | |||
00aeef75b6 | |||
5b7682f13c | |||
b30fcb50c8 | |||
100c56ad10 | |||
44bebf366a | |||
6a28701242 | |||
09d1d3744c | |||
84e0b30f8d | |||
546ce8d4bc | |||
9b40bb288d | |||
c812b674b6 | |||
86e63197f6 | |||
c371b2e953 | |||
2142e25029 | |||
30076a0e66 | |||
42bd39163a | |||
cc4891d9ec | |||
40c26839f5 | |||
2ff66ee238 | |||
9d60b4a756 | |||
d2becc0681 | |||
579c32a724 | |||
b08ef17894 | |||
589ab8757e | |||
abdaac8584 | |||
d5c950a231 | |||
d9a1701927 | |||
6e500c35dc | |||
a06e96061f | |||
f0513d34f9 | |||
09349efbbe | |||
06453e9668 | |||
b1e904df84 | |||
5f435b6325 | |||
7b48488c29 | |||
3f6ad0d807 | |||
edba369ae8 | |||
b77d916bdd | |||
2706454635 | |||
32a3bb1d6d | |||
95665ca378 | |||
09d6cf7c48 | |||
2addc48a9b | |||
ebf07a7912 | |||
abe6493244 | |||
9f192ab275 | |||
52e013d289 | |||
331da3841e | |||
e227f4177b | |||
88fa7cdfff | |||
f3b3072711 | |||
cf6cc7dcc5 | |||
448c8a2dd5 | |||
634cfe13f1 | |||
7597515c20 | |||
93f57aece5 | |||
ef6da1bbe1 | |||
4ad9e68886 | |||
9b35e7c188 | |||
2aa6e55d6b | |||
1ac28410ff | |||
b0fd976b97 | |||
7fe7e94fbd | |||
8864960eb4 | |||
23326895b2 | |||
d2f707b76d | |||
a7f0c3b730 | |||
a9e84f1750 | |||
7ca3a9e7a6 | |||
c80d099193 | |||
35aba13122 | |||
b69e493c54 | |||
99d73a2da8 | |||
3c23aa935e | |||
8dee139810 | |||
6349cb6094 | |||
452838b04a | |||
fd30cfe98b | |||
6f281fef42 | |||
5920b0cf5e | |||
41bbfcf165 | |||
80a93e17fa | |||
4a1eebc54b | |||
264ba71462 | |||
e229fa89f8 | |||
d3b72ae07d | |||
b62b6b5112 | |||
c44f8c6155 | |||
0dfa3d9ca3 | |||
8c7c84906b | |||
662143cf21 | |||
c60fc7926e | |||
cfbdc6c340 | |||
2f6d8257ec | |||
b9a6b5d4f5 | |||
32f77dbcee | |||
052cb8f12d | |||
03b544023b | |||
5070499cfd | |||
e77b13d36e | |||
4bb237d7c2 | |||
aa5a7faa94 | |||
837f4dcbd4 | |||
d73a246b66 | |||
f85e82973d | |||
84afec567c | |||
e1525e5d56 | |||
d2688cf08c | |||
7372319568 | |||
60ffec5c64 | |||
23c88f6955 | |||
dd14207b63 | |||
103adfbb57 | |||
b673ebe2ca | |||
0e0c3df0cd | |||
8dbd482e08 | |||
ab5f7c0f26 | |||
191f493eb9 | |||
d1f4640a9c | |||
3d97f4578d | |||
fb0ef08fd8 | |||
0de78205b5 | |||
e0821bd927 | |||
e5966b54a8 | |||
d2f6b09901 | |||
5c8aa8517b | |||
1e5916db28 | |||
a3ae6956e2 | |||
518b84b38b | |||
932dc4bf02 | |||
bdc3a555b6 | |||
d4dcb61ee6 | |||
cce73beb2d | |||
4db34f5894 | |||
063ac4619f | |||
d1a338107b | |||
0d0b7e117f | |||
3538f9719f | |||
feaafdc559 | |||
edf369a3d4 | |||
eb148eb8f0 | |||
4251157ffa | |||
9866eec21c | |||
e879d41ee4 | |||
bb26f5b2c7 | |||
8e61d3eadf | |||
749ab36b1a | |||
c68874743d | |||
1a76f4ebfc | |||
59238d1dc1 | |||
661f3d6899 | |||
14b889a85f | |||
ac25171420 | |||
7281ed5968 | |||
dc541b2c72 | |||
9a854fd8fe | |||
8eb44c404d | |||
61b25e1213 | |||
d3a5a3d0d6 | |||
366fcf0bed | |||
29c0fcbad6 | |||
de84d5d463 | |||
078114ee67 | |||
49f350fb00 | |||
e141b5ff20 | |||
181f163cb5 | |||
30a9d3ae8d | |||
83e09ad5a7 | |||
8e5255a275 | |||
e4f06368bb | |||
0edd87324c | |||
96e034aa75 | |||
821432263a | |||
5edb16f36e | |||
a233bc0045 | |||
eed40d095e | |||
0d0e5295f4 | |||
51ac4bc688 | |||
4f97592965 | |||
be5a763d39 | |||
c435ce0224 | |||
67d8ede247 | |||
5e98ce32b7 | |||
a2c01655f0 | |||
3a71281937 | |||
f235ec8b5a | |||
fa7df05b92 | |||
1f3ac7a9ec | |||
5bd002a568 | |||
5fb0cc5fab | |||
818b9595aa | |||
c78f641e85 | |||
081380c8d5 | |||
7e451bce0b | |||
a082ec0604 | |||
973a10a9d1 | |||
1ec95096d5 | |||
e81cc45405 | |||
b9ef11e8bf | |||
0d8dd03c3d | |||
74d610d9ad | |||
9146ca6c63 | |||
d7e0ae0fa0 | |||
29ee48530c | |||
abe53a4bdd | |||
2d23bedf12 | |||
4e17fb476b | |||
c803ec7e26 | |||
7e67f33766 | |||
9dd5644183 | |||
5a8028a72d | |||
747de511d4 | |||
7800938fd2 | |||
ab80fe13e9 | |||
5d106c4064 | |||
2ac1026e4b | |||
b78c7e1c53 | |||
849bdcda7b | |||
5aae8cd0e3 | |||
adc5a2020a | |||
40b1521f72 | |||
ac23c66659 | |||
84bc33db8a | |||
6392df36c3 | |||
c82843279c | |||
b394eb8e55 | |||
bb422d4454 | |||
3dfe23836c | |||
d45f39aae3 | |||
cb091040a8 | |||
ddd538944a | |||
1f879f67a9 | |||
ee89dedd0f | |||
38ec0f9f95 | |||
9efe6cfb39 | |||
c86a1a50bd | |||
c55476b196 |
89
Jenkinsfile
vendored
89
Jenkinsfile
vendored
@ -1,3 +1,9 @@
|
|||||||
|
import groovy.transform.Field
|
||||||
|
|
||||||
|
@Field
|
||||||
|
def shOutput = ""
|
||||||
|
def buildxPushTags = ""
|
||||||
|
|
||||||
pipeline {
|
pipeline {
|
||||||
agent {
|
agent {
|
||||||
label 'docker-multiarch'
|
label 'docker-multiarch'
|
||||||
@ -16,6 +22,8 @@ pipeline {
|
|||||||
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
|
COMPOSE_FILE = 'docker/docker-compose.ci.yml'
|
||||||
COMPOSE_INTERACTIVE_NO_CLI = 1
|
COMPOSE_INTERACTIVE_NO_CLI = 1
|
||||||
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
|
BUILDX_NAME = "${COMPOSE_PROJECT_NAME}"
|
||||||
|
DOCS_BUCKET = 'jc21-npm-site'
|
||||||
|
DOCS_CDN = 'EN1G6DEWZUTDT'
|
||||||
}
|
}
|
||||||
stages {
|
stages {
|
||||||
stage('Environment') {
|
stage('Environment') {
|
||||||
@ -26,7 +34,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest"
|
buildxPushTags = "-t docker.io/jc21/${IMAGE}:${BUILD_VERSION} -t docker.io/jc21/${IMAGE}:${MAJOR_VERSION} -t docker.io/jc21/${IMAGE}:latest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,7 +47,7 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
// Defaults to the Branch name, which is applies to all branches AND pr's
|
// Defaults to the Branch name, which is applies to all branches AND pr's
|
||||||
env.BUILDX_PUSH_TAGS = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}"
|
buildxPushTags = "-t docker.io/jc21/${IMAGE}:github-${BRANCH_LOWER}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,34 +62,28 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Frontend') {
|
stage('Build and Test') {
|
||||||
steps {
|
steps {
|
||||||
sh './scripts/frontend-build'
|
script {
|
||||||
|
// Frontend and Backend
|
||||||
|
def shStatusCode = sh(label: 'Checking and Building', returnStatus: true, script: '''
|
||||||
|
set -e
|
||||||
|
./scripts/ci/frontend-build > ${WORKSPACE}/tmp-sh-build 2>&1
|
||||||
|
./scripts/ci/test-and-build > ${WORKSPACE}/tmp-sh-build 2>&1
|
||||||
|
''')
|
||||||
|
shOutput = readFile "${env.WORKSPACE}/tmp-sh-build"
|
||||||
|
if (shStatusCode != 0) {
|
||||||
|
error "${shOutput}"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
post {
|
||||||
stage('Backend') {
|
always {
|
||||||
steps {
|
sh 'rm -f ${WORKSPACE}/tmp-sh-build'
|
||||||
echo 'Checking Syntax ...'
|
}
|
||||||
// See: https://github.com/yarnpkg/yarn/issues/3254
|
failure {
|
||||||
sh '''docker run --rm \\
|
npmGithubPrComment("CI Error:\n\n```\n${shOutput}\n```", true)
|
||||||
-v "$(pwd)/backend:/app" \\
|
}
|
||||||
-v "$(pwd)/global:/app/global" \\
|
|
||||||
-w /app \\
|
|
||||||
node:latest \\
|
|
||||||
sh -c "yarn install && yarn eslint . && rm -rf node_modules"
|
|
||||||
'''
|
|
||||||
|
|
||||||
echo 'Docker Build ...'
|
|
||||||
sh '''docker build --pull --no-cache --squash --compress \\
|
|
||||||
-t "${IMAGE}:ci-${BUILD_NUMBER}" \\
|
|
||||||
-f docker/Dockerfile \\
|
|
||||||
--build-arg TARGETPLATFORM=linux/amd64 \\
|
|
||||||
--build-arg BUILDPLATFORM=linux/amd64 \\
|
|
||||||
--build-arg BUILD_VERSION="${BUILD_VERSION}" \\
|
|
||||||
--build-arg BUILD_COMMIT="${BUILD_COMMIT}" \\
|
|
||||||
--build-arg BUILD_DATE="$(date '+%Y-%m-%d %T %Z')" \\
|
|
||||||
.
|
|
||||||
'''
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('Integration Tests Sqlite') {
|
stage('Integration Tests Sqlite') {
|
||||||
@ -163,10 +165,8 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
withCredentials([usernamePassword(credentialsId: 'jc21-dockerhub', passwordVariable: 'dpass', usernameVariable: 'duser')]) {
|
||||||
// Docker Login
|
sh 'docker login -u "${duser}" -p "${dpass}"'
|
||||||
sh "docker login -u '${duser}' -p '${dpass}'"
|
sh "./scripts/buildx --push ${buildxPushTags}"
|
||||||
// Buildx with push from cache
|
|
||||||
sh "./scripts/buildx --push ${BUILDX_PUSH_TAGS}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -180,26 +180,7 @@ pipeline {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
withCredentials([[$class: 'AmazonWebServicesCredentialsBinding', accessKeyVariable: 'AWS_ACCESS_KEY_ID', credentialsId: 'npm-s3-docs', secretKeyVariable: 'AWS_SECRET_ACCESS_KEY']]) {
|
npmDocsRelease("$DOCS_BUCKET", "$DOCS_CDN")
|
||||||
sh """docker run --rm \\
|
|
||||||
--name \${COMPOSE_PROJECT_NAME}-docs-upload \\
|
|
||||||
-e S3_BUCKET=jc21-npm-site \\
|
|
||||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
|
|
||||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
|
|
||||||
-v \$(pwd):/app \\
|
|
||||||
-w /app \\
|
|
||||||
jc21/ci-tools \\
|
|
||||||
scripts/docs-upload /app/docs/.vuepress/dist/
|
|
||||||
"""
|
|
||||||
|
|
||||||
sh """docker run --rm \\
|
|
||||||
--name \${COMPOSE_PROJECT_NAME}-docs-invalidate \\
|
|
||||||
-e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \\
|
|
||||||
-e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \\
|
|
||||||
jc21/ci-tools \\
|
|
||||||
aws cloudfront create-invalidation --distribution-id EN1G6DEWZUTDT --paths '/*'
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('PR Comment') {
|
stage('PR Comment') {
|
||||||
@ -213,14 +194,14 @@ pipeline {
|
|||||||
}
|
}
|
||||||
steps {
|
steps {
|
||||||
script {
|
script {
|
||||||
def comment = pullRequest.comment("This is an automated message from CI:\n\nDocker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.")
|
npmGithubPrComment("Docker Image for build ${BUILD_NUMBER} is available on [DockerHub](https://cloud.docker.com/repository/docker/jc21/${IMAGE}) as `jc21/${IMAGE}:github-${BRANCH_LOWER}`\n\n**Note:** ensure you backup your NPM instance before testing this PR image! Especially if this PR contains database changes.", true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
always {
|
always {
|
||||||
sh 'docker-compose down --rmi all --remove-orphans --volumes -t 30'
|
sh 'docker-compose down --remove-orphans --volumes -t 30'
|
||||||
sh 'echo Reverting ownership'
|
sh 'echo Reverting ownership'
|
||||||
sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
|
sh 'docker run --rm -v $(pwd):/data jc21/ci-tools chown -R $(id -u):$(id -g) /data'
|
||||||
}
|
}
|
||||||
|
414
README.md
414
README.md
@ -1,22 +1,13 @@
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img src="https://nginxproxymanager.com/github.png">
|
<img src="https://nginxproxymanager.com/github.png">
|
||||||
<br><br>
|
<br><br>
|
||||||
<img src="https://img.shields.io/badge/version-2.9.12-green.svg?style=for-the-badge">
|
<img src="https://img.shields.io/badge/version-2.9.19-green.svg?style=for-the-badge">
|
||||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
||||||
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
<img src="https://img.shields.io/docker/stars/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
<a href="https://hub.docker.com/repository/docker/jc21/nginx-proxy-manager">
|
||||||
<img src="https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
<img src="https://img.shields.io/docker/pulls/jc21/nginx-proxy-manager.svg?style=for-the-badge">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://ci.nginxproxymanager.com/blue/organizations/jenkins/nginx-proxy-manager/branches/">
|
|
||||||
<img src="https://img.shields.io/jenkins/build?jobUrl=https%3A%2F%2Fci.nginxproxymanager.com%2Fjob%2Fnginx-proxy-manager%2Fjob%2Fmaster&style=for-the-badge">
|
|
||||||
</a>
|
|
||||||
<a href="https://gitter.im/nginx-proxy-manager/community">
|
|
||||||
<img alt="Gitter" src="https://img.shields.io/gitter/room/nginx-proxy-manager/community?style=for-the-badge">
|
|
||||||
</a>
|
|
||||||
<a href="https://reddit.com/r/nginxproxymanager">
|
|
||||||
<img alt="Reddit" src="https://img.shields.io/reddit/subreddit-subscribers/nginxproxymanager?label=Reddit%20Community&style=for-the-badge">
|
|
||||||
</a>
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
This project comes as a pre-built docker image that enables you to easily forward to your websites
|
||||||
@ -83,6 +74,10 @@ services:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker-compose up -d
|
docker-compose up -d
|
||||||
|
|
||||||
|
# If using docker-compose-plugin
|
||||||
|
docker compose up -d
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
4. Log in to the Admin UI
|
4. Log in to the Admin UI
|
||||||
@ -103,395 +98,12 @@ Immediately after logging in with this default user you will be asked to modify
|
|||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
Special thanks to the following contributors:
|
Special thanks to [all of our contributors](https://github.com/NginxProxyManager/nginx-proxy-manager/graphs/contributors).
|
||||||
|
|
||||||
<!-- prettier-ignore-start -->
|
|
||||||
<!-- markdownlint-disable -->
|
## Getting Support
|
||||||
<table>
|
|
||||||
<tr>
|
1. [Found a bug?](https://github.com/NginxProxyManager/nginx-proxy-manager/issues)
|
||||||
<td align="center">
|
2. [Discussions](https://github.com/NginxProxyManager/nginx-proxy-manager/discussions)
|
||||||
<a href="https://github.com/Subv">
|
3. [Development Gitter](https://gitter.im/nginx-proxy-manager/community)
|
||||||
<img src="https://avatars1.githubusercontent.com/u/357072?s=460&u=d8adcdc91d749ae53e177973ed9b6bb6c4c894a3&v=4" width="80" alt=""/>
|
4. [Reddit](https://reddit.com/r/nginxproxymanager)
|
||||||
<br /><sub><b>Sebastian Valle</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Indemnity83">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/35218?s=460&u=7082004ff35138157c868d7d9c683ccebfce5968&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Kyle Klaus</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/theraw">
|
|
||||||
<img src="https://avatars1.githubusercontent.com/u/32969774?s=460&u=6b359971e15685fb0359e6a8c065a399b40dc228&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>ƬHE ЯAW</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/spalger">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/1329312?s=400&u=565223e38f1c052afb4c5dcca3fcf1c63ba17ae7&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Spencer</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Xantios">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/1507836?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Xantios Krugor</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/dpanesso">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/2687121?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>David Panesso</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/IronTooch">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/27360514?s=460&u=69bf854a6647c55725f62ecb8d39249c6c0b2602&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>IronTooch</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/damianog">
|
|
||||||
<img src="https://avatars1.githubusercontent.com/u/2786682?s=460&u=76c6136fae797abb76b951cd8a246dcaecaf21af&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Damiano</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/tfmm">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/6880538?s=460&u=ce0160821cc4aa802df8395200f2d4956a5bc541&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Russ</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/margaale">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/20794934?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Marcelo Castagna</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Steven-Harris">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/7720242?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Steven Harris</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/jlesage">
|
|
||||||
<img src="https://avatars0.githubusercontent.com/u/1791123?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Jocelyn Le Sage</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/cmer">
|
|
||||||
<img src="https://avatars0.githubusercontent.com/u/412?s=460&u=67dd8b2e3661bfd6f68ec1eaa5b9821bd8a321cd&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Carl Mercier</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/the1ts">
|
|
||||||
<img src="https://avatars1.githubusercontent.com/u/84956?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Paul Mansfield</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/OhHeyAlan">
|
|
||||||
<img src="https://avatars0.githubusercontent.com/u/11955126?s=460&u=fbaa5a1a4f73ef8960132c703349bfd037fe2630&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>OhHeyAlan</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/dogmatic69">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/94674?s=460&u=ca7647de53145c6283b6373ade5dc94ba99347db&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Carl Sutton</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/tg44">
|
|
||||||
<img src="https://avatars0.githubusercontent.com/u/31839?s=460&u=ad32f4cadfef5e5fb09cdfa4b7b7b36a99ba6811&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Gergő Törcsvári</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/vrenjith">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/2093241?s=460&u=96ce93a9bebabdd0a60a2dc96cd093a41d5edaba&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>vrenjith</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/duhruh">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/1133969?s=460&u=c0691e6131ec6d516416c1c6fcedb5034f877bbe&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>David Rivera</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/jipjan">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/1384618?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Jaap-Jan de Wit</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/jmwebslave">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/6118262?s=460&u=7db409c47135b1e141c366bbb03ed9fae6ac2638&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>James Morgan</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/chaptergy">
|
|
||||||
<img src="https://avatars2.githubusercontent.com/u/26956711?s=460&u=7d9adebabb6b4e7af7cb05d98d751087a372304b&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>chaptergy</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Philip-Mooney">
|
|
||||||
<img src="https://avatars0.githubusercontent.com/u/48624631?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Philip Mooney</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/WaterCalm">
|
|
||||||
<img src="https://avatars1.githubusercontent.com/u/23502129?s=400&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>WaterCalm</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/lebrou34">
|
|
||||||
<img src="https://avatars1.githubusercontent.com/u/16373103?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>lebrou34</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/lightglitch">
|
|
||||||
<img src="https://avatars0.githubusercontent.com/u/196953?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Mário Franco</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/klutchell">
|
|
||||||
<img src="https://avatars3.githubusercontent.com/u/20458272?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Kyle Harding</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/ahgraber">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/24922003?s=460&u=8376c9f00af9b6057ba4d2fb03b4f1b20a75277f&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Alex Graber</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/MooBaloo">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/9493496?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>MooBaloo</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Shuro">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/944030?s=460&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Shuro</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/lorisbergeron">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/51918567?s=460&u=778e4ff284b7d7304450f98421c99f79298371fb&v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Loris Bergeron</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/hepelayo">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/8243119?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>hepelayo</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/jonasled">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/46790650?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Jonas Leder</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/stegmannb">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/12850482?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Bastian Stegmann</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Stealthii">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/998920?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Stealthii</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/thegamingninja">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/8020534?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>THEGamingninja</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/italobb">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/1801687?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Italo Borssatto</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/GurjinderSingh">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/3470709?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Gurjinder Singh</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/phantomski77">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/69464125?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>David Dosoudil</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/ijaron">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/5156472?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>ijaron</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/nielscil">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/9073152?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Niels Bouma</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/ogarai">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/2949572?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Orko Garai</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/baruffaldi">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/36949?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Filippo Baruffaldi</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/bikram990">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/6782131?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Bikramjeet Singh</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/razvanstoica89">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/28236583?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Razvan Stoica</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/psharma04">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/22587474?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>RBXII3</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/demize">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/264914?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>demize</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/PUP-Loki">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/75944209?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>PUP-Loki</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/DSorlov">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/8133650?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Daniel Sörlöv</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Theyooo">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/58510131?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Theyooo</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/mrdink">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/514751?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Justin Peacock</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/ChrisTracy">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/58871574?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Chris Tracy</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/Fuechslein">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/15112818?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Fuechslein</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/nightah">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/3339418?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Amir Zarrinkafsh</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/gabbe">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/156397?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>gabbe</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/bmbvenom">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/20530371?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>bmbvenom</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/FMeinicke">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/42121639?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Florian Meinicke</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/ssrahul96">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/15570570?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Rahul Somasundaram</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/BjoernAkAManf">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/833043?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Björn Heinrichs</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/realJoshByrnes">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/204185?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>Josh Byrnes</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td align="center">
|
|
||||||
<a href="https://github.com/bergi9">
|
|
||||||
<img src="https://avatars.githubusercontent.com/u/5556750?v=4" width="80" alt=""/>
|
|
||||||
<br /><sub><b>bergi9</b></sub>
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
<!-- markdownlint-enable -->
|
|
||||||
<!-- prettier-ignore-end -->
|
|
||||||
|
@ -3,13 +3,13 @@ const fs = require('fs');
|
|||||||
const batchflow = require('batchflow');
|
const batchflow = require('batchflow');
|
||||||
const logger = require('../logger').access;
|
const logger = require('../logger').access;
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const accessListModel = require('../models/access_list');
|
const accessListModel = require('../models/access_list');
|
||||||
const accessListAuthModel = require('../models/access_list_auth');
|
const accessListAuthModel = require('../models/access_list_auth');
|
||||||
const accessListClientModel = require('../models/access_list_client');
|
const accessListClientModel = require('../models/access_list_client');
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
const internalAuditLog = require('./audit-log');
|
const internalAuditLog = require('./audit-log');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const utils = require('../lib/utils');
|
|
||||||
|
|
||||||
function omissions () {
|
function omissions () {
|
||||||
return ['is_deleted'];
|
return ['is_deleted'];
|
||||||
@ -27,13 +27,13 @@ const internalAccessList = {
|
|||||||
.then((/*access_data*/) => {
|
.then((/*access_data*/) => {
|
||||||
return accessListModel
|
return accessListModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
|
||||||
.insertAndFetch({
|
.insertAndFetch({
|
||||||
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((row) => {
|
.then((row) => {
|
||||||
data.id = row.id;
|
data.id = row.id;
|
||||||
@ -218,7 +218,7 @@ const internalAccessList = {
|
|||||||
// 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.[certificate,access_list.[clients,items]]']
|
||||||
}, true /* <- skip masking */);
|
}, true /* <- skip masking */);
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
@ -256,35 +256,31 @@ const internalAccessList = {
|
|||||||
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
|
.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)
|
.where('access_list.is_deleted', 0)
|
||||||
.andWhere('access_list.id', data.id)
|
.andWhere('access_list.id', data.id)
|
||||||
.allowEager('[owner,items,clients,proxy_hosts.[*, access_list.[clients,items]]]')
|
.allowGraph('[owner,items,clients,proxy_hosts.[certificate,access_list.[clients,items]]]')
|
||||||
.omit(['access_list.is_deleted'])
|
|
||||||
.first();
|
.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));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
if (!skip_masking && typeof row.items !== 'undefined' && row.items) {
|
|
||||||
row = internalAccessList.maskItems(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
if (!skip_masking && typeof row.items !== 'undefined' && row.items) {
|
||||||
|
row = internalAccessList.maskItems(row);
|
||||||
|
}
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -381,8 +377,7 @@ const internalAccessList = {
|
|||||||
.joinRaw('LEFT JOIN `proxy_host` ON `proxy_host`.`access_list_id` = `access_list`.`id` AND `proxy_host`.`is_deleted` = 0')
|
.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)
|
.where('access_list.is_deleted', 0)
|
||||||
.groupBy('access_list.id')
|
.groupBy('access_list.id')
|
||||||
.omit(['access_list.is_deleted'])
|
.allowGraph('[owner,items,clients]')
|
||||||
.allowEager('[owner,items,clients]')
|
|
||||||
.orderBy('access_list.name', 'ASC');
|
.orderBy('access_list.name', 'ASC');
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
@ -397,10 +392,10 @@ const internalAccessList = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (rows) {
|
if (rows) {
|
||||||
@ -507,7 +502,7 @@ const internalAccessList = {
|
|||||||
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.exec('/usr/bin/htpasswd -b "' + htpasswd_file + '" "' + item.username + '" "' + item.password + '"')
|
utils.execFile('/usr/bin/htpasswd', ['-b', htpasswd_file, item.username, item.password])
|
||||||
.then((/*result*/) => {
|
.then((/*result*/) => {
|
||||||
next();
|
next();
|
||||||
})
|
})
|
||||||
|
@ -19,7 +19,7 @@ const internalAuditLog = {
|
|||||||
.orderBy('created_on', 'DESC')
|
.orderBy('created_on', 'DESC')
|
||||||
.orderBy('id', 'DESC')
|
.orderBy('id', 'DESC')
|
||||||
.limit(100)
|
.limit(100)
|
||||||
.allowEager('[user]');
|
.allowGraph('[user]');
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
if (typeof search_query === 'string') {
|
if (typeof search_query === 'string') {
|
||||||
@ -29,7 +29,7 @@ const internalAuditLog = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
const https = require('https');
|
||||||
const tempWrite = require('temp-write');
|
const tempWrite = require('temp-write');
|
||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const logger = require('../logger').ssl;
|
const logger = require('../logger').ssl;
|
||||||
@ -15,6 +16,7 @@ const letsencryptConfig = '/etc/letsencrypt.ini';
|
|||||||
const certbotCommand = 'certbot';
|
const certbotCommand = 'certbot';
|
||||||
const archiver = require('archiver');
|
const archiver = require('archiver');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const { isArray } = require('lodash');
|
||||||
|
|
||||||
function omissions() {
|
function omissions() {
|
||||||
return ['is_deleted'];
|
return ['is_deleted'];
|
||||||
@ -119,8 +121,8 @@ const internalCertificate = {
|
|||||||
|
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.insertAndFetch(data)
|
||||||
.insertAndFetch(data);
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((certificate) => {
|
.then((certificate) => {
|
||||||
if (certificate.provider === 'letsencrypt') {
|
if (certificate.provider === 'letsencrypt') {
|
||||||
@ -169,6 +171,7 @@ const internalCertificate = {
|
|||||||
// 3. Generate the LE config
|
// 3. Generate the LE config
|
||||||
return internalNginx.generateLetsEncryptRequestConfig(certificate)
|
return internalNginx.generateLetsEncryptRequestConfig(certificate)
|
||||||
.then(internalNginx.reload)
|
.then(internalNginx.reload)
|
||||||
|
.then(async() => await new Promise((r) => setTimeout(r, 5000)))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// 4. Request cert
|
// 4. Request cert
|
||||||
return internalCertificate.requestLetsEncryptSsl(certificate);
|
return internalCertificate.requestLetsEncryptSsl(certificate);
|
||||||
@ -266,8 +269,8 @@ const internalCertificate = {
|
|||||||
|
|
||||||
return certificateModel
|
return certificateModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
|
||||||
.patchAndFetchById(row.id, data)
|
.patchAndFetchById(row.id, data)
|
||||||
|
.then(utils.omitRow(omissions()))
|
||||||
.then((saved_row) => {
|
.then((saved_row) => {
|
||||||
saved_row.meta = internalCertificate.cleanMeta(saved_row.meta);
|
saved_row.meta = internalCertificate.cleanMeta(saved_row.meta);
|
||||||
data.meta = internalCertificate.cleanMeta(data.meta);
|
data.meta = internalCertificate.cleanMeta(data.meta);
|
||||||
@ -285,7 +288,7 @@ const internalCertificate = {
|
|||||||
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 _.omit(saved_row, omissions());
|
return saved_row;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -310,30 +313,28 @@ const internalCertificate = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowEager('[owner]')
|
.allowGraph('[owner]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -385,7 +386,7 @@ const internalCertificate = {
|
|||||||
zipFiles(source, out) {
|
zipFiles(source, out) {
|
||||||
const archive = archiver('zip', { zlib: { level: 9 } });
|
const archive = archiver('zip', { zlib: { level: 9 } });
|
||||||
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) => {
|
||||||
@ -396,7 +397,7 @@ const internalCertificate = {
|
|||||||
archive
|
archive
|
||||||
.on('error', (err) => reject(err))
|
.on('error', (err) => reject(err))
|
||||||
.pipe(stream);
|
.pipe(stream);
|
||||||
|
|
||||||
stream.on('close', () => resolve());
|
stream.on('close', () => resolve());
|
||||||
archive.finalize();
|
archive.finalize();
|
||||||
});
|
});
|
||||||
@ -463,8 +464,7 @@ const internalCertificate = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.groupBy('id')
|
.groupBy('id')
|
||||||
.omit(['is_deleted'])
|
.allowGraph('[owner]')
|
||||||
.allowEager('[owner]')
|
|
||||||
.orderBy('nice_name', 'ASC');
|
.orderBy('nice_name', 'ASC');
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
@ -474,15 +474,15 @@ const internalCertificate = {
|
|||||||
// 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('nice_name', 'like', '%' + search_query + '%');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -659,7 +659,6 @@ const internalCertificate = {
|
|||||||
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) => {
|
||||||
console.log('ROWMETA:', row.meta);
|
|
||||||
certificate.meta = row.meta;
|
certificate.meta = row.meta;
|
||||||
return internalCertificate.writeCustomCert(certificate);
|
return internalCertificate.writeCustomCert(certificate);
|
||||||
});
|
});
|
||||||
@ -868,8 +867,11 @@ const internalCertificate = {
|
|||||||
logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
logger.info(`Requesting Let'sEncrypt certificates via ${dns_plugin.display_name} for Cert #${certificate.id}: ${certificate.domain_names.join(', ')}`);
|
||||||
|
|
||||||
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentialsLocation = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
// Escape single quotes and backslashes
|
||||||
const prepareCmd = 'pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies;
|
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
||||||
|
const credentialsCmd = 'mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentialsLocation + '\' && chmod 600 \'' + credentialsLocation + '\'';
|
||||||
|
// we call `. /opt/certbot/bin/activate` (`.` is alternative to `source` in dash) to access certbot venv
|
||||||
|
let prepareCmd = '. /opt/certbot/bin/activate && pip install ' + dns_plugin.package_name + (dns_plugin.version_requirement || '') + ' ' + dns_plugin.dependencies + ' && deactivate';
|
||||||
|
|
||||||
// Whether the plugin has a --<name>-credentials argument
|
// Whether the plugin has a --<name>-credentials argument
|
||||||
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
const hasConfigArg = certificate.meta.dns_provider !== 'route53';
|
||||||
@ -1124,6 +1126,94 @@ const internalCertificate = {
|
|||||||
} else {
|
} else {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
testHttpsChallenge: async (access, domains) => {
|
||||||
|
await access.can('certificates:list');
|
||||||
|
|
||||||
|
if (!isArray(domains)) {
|
||||||
|
throw new error.InternalValidationError('Domains must be an array of strings');
|
||||||
|
}
|
||||||
|
if (domains.length === 0) {
|
||||||
|
throw new error.InternalValidationError('No domains provided');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a test challenge file
|
||||||
|
const testChallengeDir = '/data/letsencrypt-acme-challenge/.well-known/acme-challenge';
|
||||||
|
const testChallengeFile = testChallengeDir + '/test-challenge';
|
||||||
|
fs.mkdirSync(testChallengeDir, {recursive: true});
|
||||||
|
fs.writeFileSync(testChallengeFile, 'Success', {encoding: 'utf8'});
|
||||||
|
|
||||||
|
async function performTestForDomain (domain) {
|
||||||
|
logger.info('Testing http challenge for ' + domain);
|
||||||
|
const url = `http://${domain}/.well-known/acme-challenge/test-challenge`;
|
||||||
|
const formBody = `method=G&url=${encodeURI(url)}&bodytype=T&requestbody=&headername=User-Agent&headervalue=None&locationid=1&ch=false&cc=false`;
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'Content-Length': Buffer.byteLength(formBody)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = await new Promise((resolve) => {
|
||||||
|
|
||||||
|
const req = https.request('https://www.site24x7.com/tools/restapi-tester', options, function (res) {
|
||||||
|
let responseBody = '';
|
||||||
|
|
||||||
|
res.on('data', (chunk) => responseBody = responseBody + chunk);
|
||||||
|
res.on('end', function () {
|
||||||
|
const parsedBody = JSON.parse(responseBody + '');
|
||||||
|
if (res.statusCode !== 200) {
|
||||||
|
logger.warn(`Failed to test HTTP challenge for domain ${domain}`, res);
|
||||||
|
resolve(undefined);
|
||||||
|
}
|
||||||
|
resolve(parsedBody);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Make sure to write the request body.
|
||||||
|
req.write(formBody);
|
||||||
|
req.end();
|
||||||
|
req.on('error', function (e) { logger.warn(`Failed to test HTTP challenge for domain ${domain}`, e);
|
||||||
|
resolve(undefined); });
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
// Some error occurred while trying to get the data
|
||||||
|
return 'failed';
|
||||||
|
} else if (`${result.responsecode}` === '200' && result.htmlresponse === 'Success') {
|
||||||
|
// Server exists and has responded with the correct data
|
||||||
|
return 'ok';
|
||||||
|
} else if (`${result.responsecode}` === '200') {
|
||||||
|
// Server exists but has responded with wrong data
|
||||||
|
logger.info(`HTTP challenge test failed for domain ${domain} because of invalid returned data:`, result.htmlresponse);
|
||||||
|
return 'wrong-data';
|
||||||
|
} else if (`${result.responsecode}` === '404') {
|
||||||
|
// Server exists but responded with a 404
|
||||||
|
logger.info(`HTTP challenge test failed for domain ${domain} because code 404 was returned`);
|
||||||
|
return '404';
|
||||||
|
} else if (`${result.responsecode}` === '0' || (typeof result.reason === 'string' && result.reason.toLowerCase() === 'host unavailable')) {
|
||||||
|
// Server does not exist at domain
|
||||||
|
logger.info(`HTTP challenge test failed for domain ${domain} the host was not found`);
|
||||||
|
return 'no-host';
|
||||||
|
} else {
|
||||||
|
// Other errors
|
||||||
|
logger.info(`HTTP challenge test failed for domain ${domain} because code ${result.responsecode} was returned`);
|
||||||
|
return `other:${result.responsecode}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = {};
|
||||||
|
|
||||||
|
for (const domain of domains){
|
||||||
|
results[domain] = await performTestForDomain(domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the test challenge file
|
||||||
|
fs.unlinkSync(testChallengeFile);
|
||||||
|
|
||||||
|
return results;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const deadHostModel = require('../models/dead_host');
|
const deadHostModel = require('../models/dead_host');
|
||||||
const internalHost = require('./host');
|
const internalHost = require('./host');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
@ -49,8 +50,8 @@ const internalDeadHost = {
|
|||||||
|
|
||||||
return deadHostModel
|
return deadHostModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.insertAndFetch(data)
|
||||||
.insertAndFetch(data);
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
@ -218,31 +219,28 @@ const internalDeadHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowEager('[owner,certificate]')
|
.allowGraph('[owner,certificate]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -404,8 +402,7 @@ const internalDeadHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.groupBy('id')
|
.groupBy('id')
|
||||||
.omit(['is_deleted'])
|
.allowGraph('[owner,certificate]')
|
||||||
.allowEager('[owner,certificate]')
|
|
||||||
.orderBy('domain_names', 'ASC');
|
.orderBy('domain_names', 'ASC');
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
@ -420,10 +417,10 @@ const internalDeadHost = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
||||||
|
@ -2,13 +2,16 @@ const https = require('https');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const logger = require('../logger').ip_ranges;
|
const logger = require('../logger').ip_ranges;
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const { Liquid } = require('liquidjs');
|
|
||||||
|
|
||||||
const CLOUDFRONT_URL = 'https://ip-ranges.amazonaws.com/ip-ranges.json';
|
const CLOUDFRONT_URL = 'https://ip-ranges.amazonaws.com/ip-ranges.json';
|
||||||
const CLOUDFARE_V4_URL = 'https://www.cloudflare.com/ips-v4';
|
const CLOUDFARE_V4_URL = 'https://www.cloudflare.com/ips-v4';
|
||||||
const CLOUDFARE_V6_URL = 'https://www.cloudflare.com/ips-v6';
|
const CLOUDFARE_V6_URL = 'https://www.cloudflare.com/ips-v6';
|
||||||
|
|
||||||
|
const regIpV4 = /^(\d+\.?){4}\/\d+/;
|
||||||
|
const regIpV6 = /^(([\da-fA-F]+)?:)+\/\d+/;
|
||||||
|
|
||||||
const internalIpRanges = {
|
const internalIpRanges = {
|
||||||
|
|
||||||
interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
|
interval_timeout: 1000 * 60 * 60 * 6, // 6 hours
|
||||||
@ -74,14 +77,14 @@ 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');
|
let 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');
|
let items = cloudfare_data.split('\n').filter((line) => regIpV6.test(line));
|
||||||
ip_ranges = [... ip_ranges, ... items];
|
ip_ranges = [... ip_ranges, ... items];
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
@ -116,10 +119,7 @@ const internalIpRanges = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
generateConfig: (ip_ranges) => {
|
generateConfig: (ip_ranges) => {
|
||||||
let renderEngine = new Liquid({
|
const renderEngine = utils.getRenderEngine();
|
||||||
root: __dirname + '/../templates/'
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let filename = '/etc/nginx/conf.d/include/ip_ranges.conf';
|
let filename = '/etc/nginx/conf.d/include/ip_ranges.conf';
|
||||||
|
@ -3,7 +3,6 @@ const fs = require('fs');
|
|||||||
const logger = require('../logger').nginx;
|
const logger = require('../logger').nginx;
|
||||||
const utils = require('../lib/utils');
|
const utils = require('../lib/utils');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
const { Liquid } = require('liquidjs');
|
|
||||||
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
|
const debug_mode = process.env.NODE_ENV !== 'production' || !!process.env.DEBUG;
|
||||||
|
|
||||||
const internalNginx = {
|
const internalNginx = {
|
||||||
@ -29,7 +28,9 @@ const internalNginx = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
// Nginx is OK
|
// Nginx is OK
|
||||||
// We're deleting this config regardless.
|
// We're deleting this config regardless.
|
||||||
return internalNginx.deleteConfig(host_type, host); // Don't throw errors, as the file may not exist at all
|
// Don't throw errors, as the file may not exist at all
|
||||||
|
// Delete the .err file too
|
||||||
|
return internalNginx.deleteConfig(host_type, host, false, true);
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.generateConfig(host_type, host);
|
return internalNginx.generateConfig(host_type, host);
|
||||||
@ -80,6 +81,9 @@ const internalNginx = {
|
|||||||
.patch({
|
.patch({
|
||||||
meta: combined_meta
|
meta: combined_meta
|
||||||
})
|
})
|
||||||
|
.then(() => {
|
||||||
|
internalNginx.renameConfigAsError(host_type, host);
|
||||||
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalNginx.deleteConfig(host_type, host, true);
|
return internalNginx.deleteConfig(host_type, host, true);
|
||||||
});
|
});
|
||||||
@ -121,13 +125,10 @@ const internalNginx = {
|
|||||||
* @returns {String}
|
* @returns {String}
|
||||||
*/
|
*/
|
||||||
getConfigName: (host_type, host_id) => {
|
getConfigName: (host_type, host_id) => {
|
||||||
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
|
||||||
|
|
||||||
if (host_type === 'default') {
|
if (host_type === 'default') {
|
||||||
return '/data/nginx/default_host/site.conf';
|
return '/data/nginx/default_host/site.conf';
|
||||||
}
|
}
|
||||||
|
return '/data/nginx/' + internalNginx.getFileFriendlyHostType(host_type) + '/' + host_id + '.conf';
|
||||||
return '/data/nginx/' + host_type + '/' + host_id + '.conf';
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,8 +137,6 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
renderLocations: (host) => {
|
renderLocations: (host) => {
|
||||||
|
|
||||||
//logger.info('host = ' + JSON.stringify(host, null, 2));
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template;
|
let template;
|
||||||
|
|
||||||
@ -148,19 +147,17 @@ const internalNginx = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let renderer = new Liquid({
|
const renderEngine = utils.getRenderEngine();
|
||||||
root: __dirname + '/../templates/'
|
|
||||||
});
|
|
||||||
let renderedLocations = '';
|
let renderedLocations = '';
|
||||||
|
|
||||||
const locationRendering = async () => {
|
const locationRendering = async () => {
|
||||||
for (let i = 0; i < host.locations.length; i++) {
|
for (let i = 0; i < host.locations.length; i++) {
|
||||||
let locationCopy = Object.assign({}, {access_list_id: host.access_list_id}, {certificate_id: host.certificate_id},
|
let 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},
|
{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},
|
{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},
|
{hsts_enabled: host.hsts_enabled}, {hsts_subdomains: host.hsts_subdomains}, {access_list: host.access_list},
|
||||||
{certificate: host.certificate}, host.locations[i]);
|
{certificate: host.certificate}, host.locations[i]);
|
||||||
|
|
||||||
if (locationCopy.forward_host.indexOf('/') > -1) {
|
if (locationCopy.forward_host.indexOf('/') > -1) {
|
||||||
const splitted = locationCopy.forward_host.split('/');
|
const splitted = locationCopy.forward_host.split('/');
|
||||||
|
|
||||||
@ -168,16 +165,14 @@ const internalNginx = {
|
|||||||
locationCopy.forward_path = `/${splitted.join('/')}`;
|
locationCopy.forward_path = `/${splitted.join('/')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
//logger.info('locationCopy = ' + JSON.stringify(locationCopy, null, 2));
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
renderedLocations += await renderer.parseAndRender(template, locationCopy);
|
renderedLocations += await renderEngine.parseAndRender(template, locationCopy);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
locationRendering().then(() => resolve(renderedLocations));
|
locationRendering().then(() => resolve(renderedLocations));
|
||||||
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -187,24 +182,20 @@ const internalNginx = {
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
generateConfig: (host_type, host) => {
|
generateConfig: (host_type, host) => {
|
||||||
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
const nice_host_type = internalNginx.getFileFriendlyHostType(host_type);
|
||||||
|
|
||||||
if (debug_mode) {
|
if (debug_mode) {
|
||||||
logger.info('Generating ' + host_type + ' Config:', host);
|
logger.info('Generating ' + nice_host_type + ' Config:', JSON.stringify(host, null, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
// logger.info('host = ' + JSON.stringify(host, null, 2));
|
const renderEngine = utils.getRenderEngine();
|
||||||
|
|
||||||
let renderEngine = new Liquid({
|
|
||||||
root: __dirname + '/../templates/'
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
let filename = internalNginx.getConfigName(host_type, host.id);
|
let filename = internalNginx.getConfigName(nice_host_type, host.id);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template = fs.readFileSync(__dirname + '/../templates/' + host_type + '.conf', {encoding: 'utf8'});
|
template = fs.readFileSync(__dirname + '/../templates/' + nice_host_type + '.conf', {encoding: 'utf8'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
reject(new error.ConfigurationError(err.message));
|
reject(new error.ConfigurationError(err.message));
|
||||||
return;
|
return;
|
||||||
@ -214,7 +205,7 @@ const internalNginx = {
|
|||||||
let origLocations;
|
let origLocations;
|
||||||
|
|
||||||
// Manipulate the data a bit before sending it to the template
|
// Manipulate the data a bit before sending it to the template
|
||||||
if (host_type !== 'default') {
|
if (nice_host_type !== 'default') {
|
||||||
host.use_default_location = true;
|
host.use_default_location = true;
|
||||||
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
|
if (typeof host.advanced_config !== 'undefined' && host.advanced_config) {
|
||||||
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
host.use_default_location = !internalNginx.advancedConfigHasDefaultLocation(host.advanced_config);
|
||||||
@ -281,9 +272,7 @@ const internalNginx = {
|
|||||||
logger.info('Generating LetsEncrypt Request Config:', certificate);
|
logger.info('Generating LetsEncrypt Request Config:', certificate);
|
||||||
}
|
}
|
||||||
|
|
||||||
let renderEngine = new Liquid({
|
const renderEngine = utils.getRenderEngine();
|
||||||
root: __dirname + '/../templates/'
|
|
||||||
});
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let template = null;
|
let template = null;
|
||||||
@ -319,33 +308,39 @@ const internalNginx = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple wrapper around unlinkSync that writes to the logger
|
||||||
|
*
|
||||||
|
* @param {String} filename
|
||||||
|
*/
|
||||||
|
deleteFile: (filename) => {
|
||||||
|
logger.debug('Deleting file: ' + filename);
|
||||||
|
try {
|
||||||
|
fs.unlinkSync(filename);
|
||||||
|
} catch (err) {
|
||||||
|
logger.debug('Could not delete file:', JSON.stringify(err, null, 2));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {String} host_type
|
||||||
|
* @returns String
|
||||||
|
*/
|
||||||
|
getFileFriendlyHostType: (host_type) => {
|
||||||
|
return host_type.replace(new RegExp('-', 'g'), '_');
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This removes the temporary nginx config file generated by `generateLetsEncryptRequestConfig`
|
* This removes the temporary nginx config file generated by `generateLetsEncryptRequestConfig`
|
||||||
*
|
*
|
||||||
* @param {Object} certificate
|
* @param {Object} certificate
|
||||||
* @param {Boolean} [throw_errors]
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
deleteLetsEncryptRequestConfig: (certificate, throw_errors) => {
|
deleteLetsEncryptRequestConfig: (certificate) => {
|
||||||
return new Promise((resolve, reject) => {
|
const config_file = '/data/nginx/temp/letsencrypt_' + certificate.id + '.conf';
|
||||||
try {
|
return new Promise((resolve/*, reject*/) => {
|
||||||
let config_file = '/data/nginx/temp/letsencrypt_' + certificate.id + '.conf';
|
internalNginx.deleteFile(config_file);
|
||||||
|
|
||||||
if (debug_mode) {
|
|
||||||
logger.warn('Deleting nginx config: ' + config_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.unlinkSync(config_file);
|
|
||||||
} catch (err) {
|
|
||||||
if (debug_mode) {
|
|
||||||
logger.warn('Could not delete config:', err.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (throw_errors) {
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -353,35 +348,42 @@ const internalNginx = {
|
|||||||
/**
|
/**
|
||||||
* @param {String} host_type
|
* @param {String} host_type
|
||||||
* @param {Object} [host]
|
* @param {Object} [host]
|
||||||
* @param {Boolean} [throw_errors]
|
* @param {Boolean} [delete_err_file]
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
deleteConfig: (host_type, host, throw_errors) => {
|
deleteConfig: (host_type, host, delete_err_file) => {
|
||||||
host_type = host_type.replace(new RegExp('-', 'g'), '_');
|
const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id);
|
||||||
|
const config_file_err = config_file + '.err';
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve/*, reject*/) => {
|
||||||
try {
|
internalNginx.deleteFile(config_file);
|
||||||
let config_file = internalNginx.getConfigName(host_type, typeof host === 'undefined' ? 0 : host.id);
|
if (delete_err_file) {
|
||||||
|
internalNginx.deleteFile(config_file_err);
|
||||||
if (debug_mode) {
|
|
||||||
logger.warn('Deleting nginx config: ' + config_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.unlinkSync(config_file);
|
|
||||||
} catch (err) {
|
|
||||||
if (debug_mode) {
|
|
||||||
logger.warn('Could not delete config:', err.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (throw_errors) {
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} host_type
|
||||||
|
* @param {Object} [host]
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
renameConfigAsError: (host_type, host) => {
|
||||||
|
const config_file = internalNginx.getConfigName(internalNginx.getFileFriendlyHostType(host_type), typeof host === 'undefined' ? 0 : host.id);
|
||||||
|
const config_file_err = config_file + '.err';
|
||||||
|
|
||||||
|
return new Promise((resolve/*, reject*/) => {
|
||||||
|
fs.unlink(config_file, () => {
|
||||||
|
// ignore result, continue
|
||||||
|
fs.rename(config_file, config_file_err, () => {
|
||||||
|
// also ignore result, as this is a debugging informative file anyway
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {String} host_type
|
* @param {String} host_type
|
||||||
* @param {Array} hosts
|
* @param {Array} hosts
|
||||||
@ -399,13 +401,12 @@ const internalNginx = {
|
|||||||
/**
|
/**
|
||||||
* @param {String} host_type
|
* @param {String} host_type
|
||||||
* @param {Array} hosts
|
* @param {Array} hosts
|
||||||
* @param {Boolean} [throw_errors]
|
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
bulkDeleteConfigs: (host_type, hosts, throw_errors) => {
|
bulkDeleteConfigs: (host_type, hosts) => {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
hosts.map(function (host) {
|
hosts.map(function (host) {
|
||||||
promises.push(internalNginx.deleteConfig(host_type, host, throw_errors));
|
promises.push(internalNginx.deleteConfig(host_type, host, true));
|
||||||
});
|
});
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const proxyHostModel = require('../models/proxy_host');
|
const proxyHostModel = require('../models/proxy_host');
|
||||||
const internalHost = require('./host');
|
const internalHost = require('./host');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
@ -49,8 +50,8 @@ const internalProxyHost = {
|
|||||||
|
|
||||||
return proxyHostModel
|
return proxyHostModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.insertAndFetch(data)
|
||||||
.insertAndFetch(data);
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
@ -170,6 +171,7 @@ const internalProxyHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where({id: data.id})
|
.where({id: data.id})
|
||||||
.patch(data)
|
.patch(data)
|
||||||
|
.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, {
|
||||||
@ -179,7 +181,7 @@ const internalProxyHost = {
|
|||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return saved_row;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
@ -223,31 +225,29 @@ const internalProxyHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowEager('[owner,access_list,access_list.[clients,items],certificate]')
|
.allowGraph('[owner,access_list,access_list.[clients,items],certificate]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -409,8 +409,7 @@ const internalProxyHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.groupBy('id')
|
.groupBy('id')
|
||||||
.omit(['is_deleted'])
|
.allowGraph('[owner,access_list,certificate]')
|
||||||
.allowEager('[owner,access_list,certificate]')
|
|
||||||
.orderBy('domain_names', 'ASC');
|
.orderBy('domain_names', 'ASC');
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
@ -425,10 +424,10 @@ const internalProxyHost = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const redirectionHostModel = require('../models/redirection_host');
|
const redirectionHostModel = require('../models/redirection_host');
|
||||||
const internalHost = require('./host');
|
const internalHost = require('./host');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
@ -49,8 +50,8 @@ const internalRedirectionHost = {
|
|||||||
|
|
||||||
return redirectionHostModel
|
return redirectionHostModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.insertAndFetch(data)
|
||||||
.insertAndFetch(data);
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (create_certificate) {
|
if (create_certificate) {
|
||||||
@ -65,9 +66,8 @@ const internalRedirectionHost = {
|
|||||||
.then(() => {
|
.then(() => {
|
||||||
return row;
|
return row;
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
return row;
|
|
||||||
}
|
}
|
||||||
|
return row;
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// re-fetch with cert
|
// re-fetch with cert
|
||||||
@ -218,31 +218,29 @@ const internalRedirectionHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowEager('[owner,certificate]')
|
.allowGraph('[owner,certificate]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
row = internalHost.cleanRowCertificateMeta(row);
|
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
row = internalHost.cleanRowCertificateMeta(row);
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -404,8 +402,7 @@ const internalRedirectionHost = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.groupBy('id')
|
.groupBy('id')
|
||||||
.omit(['is_deleted'])
|
.allowGraph('[owner,certificate]')
|
||||||
.allowEager('[owner,certificate]')
|
|
||||||
.orderBy('domain_names', 'ASC');
|
.orderBy('domain_names', 'ASC');
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
@ -420,10 +417,10 @@ const internalRedirectionHost = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
})
|
})
|
||||||
.then((rows) => {
|
.then((rows) => {
|
||||||
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
if (typeof expand !== 'undefined' && expand !== null && expand.indexOf('certificate') !== -1) {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const streamModel = require('../models/stream');
|
const streamModel = require('../models/stream');
|
||||||
const internalNginx = require('./nginx');
|
const internalNginx = require('./nginx');
|
||||||
const internalAuditLog = require('./audit-log');
|
const internalAuditLog = require('./audit-log');
|
||||||
@ -27,8 +28,8 @@ const internalStream = {
|
|||||||
|
|
||||||
return streamModel
|
return streamModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.insertAndFetch(data)
|
||||||
.insertAndFetch(data);
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
// Configure nginx
|
// Configure nginx
|
||||||
@ -71,8 +72,8 @@ const internalStream = {
|
|||||||
|
|
||||||
return streamModel
|
return streamModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
|
||||||
.patchAndFetchById(row.id, data)
|
.patchAndFetchById(row.id, data)
|
||||||
|
.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(() => {
|
||||||
@ -88,7 +89,7 @@ const internalStream = {
|
|||||||
meta: data
|
meta: data
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return _.omit(saved_row, omissions());
|
return saved_row;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -113,30 +114,28 @@ const internalStream = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowEager('[owner]')
|
.allowGraph('[owner]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
query.andWhere('owner_user_id', access.token.getUserId(1));
|
query.andWhere('owner_user_id', access.token.getUserId(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -298,8 +297,7 @@ const internalStream = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.groupBy('id')
|
.groupBy('id')
|
||||||
.omit(['is_deleted'])
|
.allowGraph('[owner]')
|
||||||
.allowEager('[owner]')
|
|
||||||
.orderBy('incoming_port', 'ASC');
|
.orderBy('incoming_port', 'ASC');
|
||||||
|
|
||||||
if (access_data.permission_visibility !== 'all') {
|
if (access_data.permission_visibility !== 'all') {
|
||||||
@ -314,10 +312,10 @@ const internalStream = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ module.exports = {
|
|||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.where('email', data.identity)
|
.where('email', data.identity.toLowerCase().trim())
|
||||||
.andWhere('is_deleted', 0)
|
.andWhere('is_deleted', 0)
|
||||||
.andWhere('is_disabled', 0)
|
.andWhere('is_disabled', 0)
|
||||||
.first()
|
.first()
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const error = require('../lib/error');
|
const error = require('../lib/error');
|
||||||
|
const utils = require('../lib/utils');
|
||||||
const userModel = require('../models/user');
|
const userModel = require('../models/user');
|
||||||
const userPermissionModel = require('../models/user_permission');
|
const userPermissionModel = require('../models/user_permission');
|
||||||
const authModel = require('../models/auth');
|
const authModel = require('../models/auth');
|
||||||
@ -35,8 +36,8 @@ const internalUser = {
|
|||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
.insertAndFetch(data)
|
||||||
.insertAndFetch(data);
|
.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (auth) {
|
if (auth) {
|
||||||
@ -140,11 +141,8 @@ const internalUser = {
|
|||||||
|
|
||||||
return userModel
|
return userModel
|
||||||
.query()
|
.query()
|
||||||
.omit(omissions())
|
|
||||||
.patchAndFetchById(user.id, data)
|
.patchAndFetchById(user.id, data)
|
||||||
.then((saved_user) => {
|
.then(utils.omitRow(omissions()));
|
||||||
return _.omit(saved_user, omissions());
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
return internalUser.get(access, {id: data.id});
|
return internalUser.get(access, {id: data.id});
|
||||||
@ -186,26 +184,24 @@ const internalUser = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.andWhere('id', data.id)
|
.andWhere('id', data.id)
|
||||||
.allowEager('[permissions]')
|
.allowGraph('[permissions]')
|
||||||
.first();
|
.first();
|
||||||
|
|
||||||
// Custom omissions
|
|
||||||
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
|
||||||
query.omit(data.omit);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
if (typeof data.expand !== 'undefined' && data.expand !== null) {
|
||||||
query.eager('[' + data.expand.join(', ') + ']');
|
query.withGraphFetched('[' + data.expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRow(omissions()));
|
||||||
})
|
})
|
||||||
.then((row) => {
|
.then((row) => {
|
||||||
if (row) {
|
if (!row) {
|
||||||
return _.omit(row, omissions());
|
|
||||||
} else {
|
|
||||||
throw new error.ItemNotFoundError(data.id);
|
throw new error.ItemNotFoundError(data.id);
|
||||||
}
|
}
|
||||||
|
// Custom omissions
|
||||||
|
if (typeof data.omit !== 'undefined' && data.omit !== null) {
|
||||||
|
row = _.omit(row, data.omit);
|
||||||
|
}
|
||||||
|
return row;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -322,8 +318,7 @@ const internalUser = {
|
|||||||
.query()
|
.query()
|
||||||
.where('is_deleted', 0)
|
.where('is_deleted', 0)
|
||||||
.groupBy('id')
|
.groupBy('id')
|
||||||
.omit(['is_deleted'])
|
.allowGraph('[permissions]')
|
||||||
.allowEager('[permissions]')
|
|
||||||
.orderBy('name', 'ASC');
|
.orderBy('name', 'ASC');
|
||||||
|
|
||||||
// Query is used for searching
|
// Query is used for searching
|
||||||
@ -335,10 +330,10 @@ const internalUser = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (typeof expand !== 'undefined' && expand !== null) {
|
if (typeof expand !== 'undefined' && expand !== null) {
|
||||||
query.eager('[' + expand.join(', ') + ']');
|
query.withGraphFetched('[' + expand.join(', ') + ']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return query;
|
return query.then(utils.omitRows(omissions()));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -55,8 +55,8 @@ module.exports = function (token_string) {
|
|||||||
.where('id', token_data.attrs.id)
|
.where('id', token_data.attrs.id)
|
||||||
.andWhere('is_deleted', 0)
|
.andWhere('is_deleted', 0)
|
||||||
.andWhere('is_disabled', 0)
|
.andWhere('is_disabled', 0)
|
||||||
.allowEager('[permissions]')
|
.allowGraph('[permissions]')
|
||||||
.eager('[permissions]')
|
.withGraphFetched('[permissions]')
|
||||||
.first()
|
.first()
|
||||||
.then((user) => {
|
.then((user) => {
|
||||||
if (user) {
|
if (user) {
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
const exec = require('child_process').exec;
|
const _ = require('lodash');
|
||||||
|
const exec = require('child_process').exec;
|
||||||
|
const execFile = require('child_process').execFile;
|
||||||
|
const { Liquid } = require('liquidjs');
|
||||||
|
const logger = require('../logger').global;
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
@ -16,5 +20,82 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} cmd
|
||||||
|
* @param {Array} args
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
execFile: function (cmd, args) {
|
||||||
|
logger.debug('CMD: ' + cmd + ' ' + (args ? args.join(' ') : ''));
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
execFile(cmd, args, function (err, stdout, /*stderr*/) {
|
||||||
|
if (err && typeof err === 'object') {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
resolve(stdout.trim());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in objection query builder
|
||||||
|
*
|
||||||
|
* @param {Array} omissions
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
omitRow: function (omissions) {
|
||||||
|
/**
|
||||||
|
* @param {Object} row
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
return (row) => {
|
||||||
|
return _.omit(row, omissions);
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used in objection query builder
|
||||||
|
*
|
||||||
|
* @param {Array} omissions
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
omitRows: function (omissions) {
|
||||||
|
/**
|
||||||
|
* @param {Array} rows
|
||||||
|
* @returns {Object}
|
||||||
|
*/
|
||||||
|
return (rows) => {
|
||||||
|
rows.forEach((row, idx) => {
|
||||||
|
rows[idx] = _.omit(row, omissions);
|
||||||
|
});
|
||||||
|
return rows;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Object} Liquid render engine
|
||||||
|
*/
|
||||||
|
getRenderEngine: function () {
|
||||||
|
const renderEngine = new Liquid({
|
||||||
|
root: __dirname + '/../templates/'
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nginxAccessRule expects the object given to have 2 properties:
|
||||||
|
*
|
||||||
|
* directive string
|
||||||
|
* address string
|
||||||
|
*/
|
||||||
|
renderEngine.registerFilter('nginxAccessRule', (v) => {
|
||||||
|
if (typeof v.directive !== 'undefined' && typeof v.address !== 'undefined' && v.directive && v.address) {
|
||||||
|
return `${v.directive} ${v.address};`;
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
|
||||||
|
return renderEngine;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
50
backend/migrations/20211108145214_regenerate_default_host.js
Normal file
50
backend/migrations/20211108145214_regenerate_default_host.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
const migrate_name = 'stream_domain';
|
||||||
|
const logger = require('../logger').migrate;
|
||||||
|
const internalNginx = require('../internal/nginx');
|
||||||
|
|
||||||
|
async function regenerateDefaultHost(knex) {
|
||||||
|
const row = await knex('setting').select('*').where('id', 'default-site').first();
|
||||||
|
|
||||||
|
if (!row) {
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
return internalNginx.deleteConfig('default')
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.generateConfig('default', row);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.test();
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
return internalNginx.reload();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrate
|
||||||
|
*
|
||||||
|
* @see http://knexjs.org/#Schema
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.up = function (knex) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Up...');
|
||||||
|
|
||||||
|
return regenerateDefaultHost(knex);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Undo Migrate
|
||||||
|
*
|
||||||
|
* @param {Object} knex
|
||||||
|
* @param {Promise} Promise
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
exports.down = function (knex) {
|
||||||
|
logger.info('[' + migrate_name + '] Migrating Down...');
|
||||||
|
|
||||||
|
return regenerateDefaultHost(knex);
|
||||||
|
};
|
@ -50,7 +50,6 @@ class AccessList extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
items: {
|
items: {
|
||||||
@ -59,9 +58,6 @@ class AccessList extends Model {
|
|||||||
join: {
|
join: {
|
||||||
from: 'access_list.id',
|
from: 'access_list.id',
|
||||||
to: 'access_list_auth.access_list_id'
|
to: 'access_list_auth.access_list_id'
|
||||||
},
|
|
||||||
modify: function (qb) {
|
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'access_list_id', 'meta']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
clients: {
|
clients: {
|
||||||
@ -70,9 +66,6 @@ class AccessList extends Model {
|
|||||||
join: {
|
join: {
|
||||||
from: 'access_list.id',
|
from: 'access_list.id',
|
||||||
to: 'access_list_client.access_list_id'
|
to: 'access_list_client.access_list_id'
|
||||||
},
|
|
||||||
modify: function (qb) {
|
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'access_list_id', 'meta']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
proxy_hosts: {
|
proxy_hosts: {
|
||||||
@ -84,19 +77,10 @@ class AccessList extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('proxy_host.is_deleted', 0);
|
qb.where('proxy_host.is_deleted', 0);
|
||||||
qb.omit(['is_deleted', 'meta']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get satisfy() {
|
|
||||||
return this.satisfy_any ? 'satisfy any' : 'satisfy all';
|
|
||||||
}
|
|
||||||
|
|
||||||
get passauth() {
|
|
||||||
return this.pass_auth ? '' : 'proxy_set_header Authorization "";';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AccessList;
|
module.exports = AccessList;
|
||||||
|
@ -45,7 +45,6 @@ class AccessListAuth extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('access_list.is_deleted', 0);
|
qb.where('access_list.is_deleted', 0);
|
||||||
qb.omit(['created_on', 'modified_on', 'is_deleted', 'access_list_id']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -45,15 +45,10 @@ class AccessListClient extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('access_list.is_deleted', 0);
|
qb.where('access_list.is_deleted', 0);
|
||||||
qb.omit(['created_on', 'modified_on', 'is_deleted', 'access_list_id']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get rule() {
|
|
||||||
return `${this.directive} ${this.address}`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = AccessListClient;
|
module.exports = AccessListClient;
|
||||||
|
@ -43,9 +43,6 @@ class AuditLog extends Model {
|
|||||||
join: {
|
join: {
|
||||||
from: 'audit_log.user_id',
|
from: 'audit_log.user_id',
|
||||||
to: 'user.id'
|
to: 'user.id'
|
||||||
},
|
|
||||||
modify: function (qb) {
|
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'roles']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -74,9 +74,6 @@ class Auth extends Model {
|
|||||||
},
|
},
|
||||||
filter: {
|
filter: {
|
||||||
is_deleted: 0
|
is_deleted: 0
|
||||||
},
|
|
||||||
modify: function (qb) {
|
|
||||||
qb.omit(['is_deleted']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -63,7 +63,6 @@ class Certificate extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -59,7 +59,6 @@ class DeadHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
@ -71,7 +70,6 @@ class DeadHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('certificate.is_deleted', 0);
|
qb.where('certificate.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,8 +6,8 @@ Model.knex(db);
|
|||||||
|
|
||||||
module.exports = function () {
|
module.exports = function () {
|
||||||
if (config.database.knex && config.database.knex.client === 'sqlite3') {
|
if (config.database.knex && config.database.knex.client === 'sqlite3') {
|
||||||
return Model.raw('datetime(\'now\',\'localtime\')');
|
// eslint-disable-next-line
|
||||||
} else {
|
return Model.raw("datetime('now','localtime')");
|
||||||
return Model.raw('NOW()');
|
|
||||||
}
|
}
|
||||||
|
return Model.raw('NOW()');
|
||||||
};
|
};
|
||||||
|
@ -60,7 +60,6 @@ class ProxyHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
access_list: {
|
access_list: {
|
||||||
@ -72,7 +71,6 @@ class ProxyHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('access_list.is_deleted', 0);
|
qb.where('access_list.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
@ -84,7 +82,6 @@ class ProxyHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('certificate.is_deleted', 0);
|
qb.where('certificate.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
// Objection Docs:
|
// Objection Docs:
|
||||||
// http://vincit.github.io/objection.js/
|
// http://vincit.github.io/objection.js/
|
||||||
|
|
||||||
@ -59,7 +60,6 @@ class RedirectionHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
certificate: {
|
certificate: {
|
||||||
@ -71,7 +71,6 @@ class RedirectionHost extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('certificate.is_deleted', 0);
|
qb.where('certificate.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -46,7 +46,6 @@ class Stream extends Model {
|
|||||||
},
|
},
|
||||||
modify: function (qb) {
|
modify: function (qb) {
|
||||||
qb.where('user.is_deleted', 0);
|
qb.where('user.is_deleted', 0);
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'is_deleted', 'email', 'roles']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -83,8 +83,6 @@ module.exports = function () {
|
|||||||
// Hack: some tokens out in the wild have a scope of 'all' instead of 'user'.
|
// Hack: some tokens out in the wild have a scope of 'all' instead of 'user'.
|
||||||
// For 30 days at least, we need to replace 'all' with user.
|
// For 30 days at least, we need to replace 'all' with user.
|
||||||
if ((typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, 'all') !== -1)) {
|
if ((typeof token_data.scope !== 'undefined' && _.indexOf(token_data.scope, 'all') !== -1)) {
|
||||||
//console.log('Warning! Replacing "all" scope with "user"');
|
|
||||||
|
|
||||||
token_data.scope = ['user'];
|
token_data.scope = ['user'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,9 +43,6 @@ class User extends Model {
|
|||||||
join: {
|
join: {
|
||||||
from: 'user.id',
|
from: 'user.id',
|
||||||
to: 'user_permission.user_id'
|
to: 'user_permission.user_id'
|
||||||
},
|
|
||||||
modify: function (qb) {
|
|
||||||
qb.omit(['id', 'created_on', 'modified_on', 'user_id']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -11,22 +11,22 @@
|
|||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"config": "^3.3.1",
|
"config": "^3.3.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.3",
|
||||||
"express-fileupload": "^1.1.9",
|
"express-fileupload": "^1.1.9",
|
||||||
"gravatar": "^1.8.0",
|
"gravatar": "^1.8.0",
|
||||||
"json-schema-ref-parser": "^8.0.0",
|
"json-schema-ref-parser": "^8.0.0",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^9.0.0",
|
||||||
"knex": "^0.20.13",
|
"knex": "2.4.2",
|
||||||
"liquidjs": "^9.11.10",
|
"liquidjs": "10.6.1",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.29.4",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"node-rsa": "^1.0.8",
|
"node-rsa": "^1.0.8",
|
||||||
"nodemon": "^2.0.2",
|
"nodemon": "^2.0.2",
|
||||||
"objection": "^2.2.16",
|
"objection": "3.0.1",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"signale": "^1.4.0",
|
"signale": "1.4.0",
|
||||||
"sqlite3": "^4.1.1",
|
"sqlite3": "5.1.6",
|
||||||
"temp-write": "^4.0.0"
|
"temp-write": "^4.0.0"
|
||||||
},
|
},
|
||||||
"signale": {
|
"signale": {
|
||||||
|
@ -68,6 +68,32 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test HTTP challenge for domains
|
||||||
|
*
|
||||||
|
* /api/nginx/certificates/test-http
|
||||||
|
*/
|
||||||
|
router
|
||||||
|
.route('/test-http')
|
||||||
|
.options((req, res) => {
|
||||||
|
res.sendStatus(204);
|
||||||
|
})
|
||||||
|
.all(jwtdecode())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GET /api/nginx/certificates/test-http
|
||||||
|
*
|
||||||
|
* Test HTTP challenge for domains
|
||||||
|
*/
|
||||||
|
.get((req, res, next) => {
|
||||||
|
internalCertificate.testHttpsChallenge(res.locals.access, JSON.parse(req.query.domains))
|
||||||
|
.then((result) => {
|
||||||
|
res.status(200)
|
||||||
|
.send(result);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specific certificate
|
* Specific certificate
|
||||||
*
|
*
|
||||||
@ -209,7 +235,6 @@ router
|
|||||||
.catch(next);
|
.catch(next);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download LE Certs
|
* Download LE Certs
|
||||||
*
|
*
|
||||||
|
@ -157,6 +157,17 @@
|
|||||||
"targetSchema": {
|
"targetSchema": {
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"title": "Test HTTP Challenge",
|
||||||
|
"description": "Tests whether the HTTP challenge should work",
|
||||||
|
"href": "/nginx/certificates/{definitions.identity.example}/test-http",
|
||||||
|
"access": "private",
|
||||||
|
"method": "GET",
|
||||||
|
"rel": "info",
|
||||||
|
"http_header": {
|
||||||
|
"$ref": "../examples.json#/definitions/auth_header"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -174,27 +174,29 @@ const setupCertbotPlugins = () => {
|
|||||||
|
|
||||||
certificates.map(function (certificate) {
|
certificates.map(function (certificate) {
|
||||||
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
if (certificate.meta && certificate.meta.dns_challenge === true) {
|
||||||
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
|
const dns_plugin = dns_plugins[certificate.meta.dns_provider];
|
||||||
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
|
|
||||||
|
|
||||||
|
const packages_to_install = `${dns_plugin.package_name}${dns_plugin.version_requirement || ''} ${dns_plugin.dependencies}`;
|
||||||
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
|
if (plugins.indexOf(packages_to_install) === -1) plugins.push(packages_to_install);
|
||||||
|
|
||||||
// Make sure credentials file exists
|
// Make sure credentials file exists
|
||||||
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
const credentials_loc = '/etc/letsencrypt/credentials/credentials-' + certificate.id;
|
||||||
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + certificate.meta.dns_provider_credentials.replace('\'', '\\\'') + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
|
// Escape single quotes and backslashes
|
||||||
|
const escapedCredentials = certificate.meta.dns_provider_credentials.replaceAll('\'', '\\\'').replaceAll('\\', '\\\\');
|
||||||
|
const credentials_cmd = '[ -f \'' + credentials_loc + '\' ] || { mkdir -p /etc/letsencrypt/credentials 2> /dev/null; echo \'' + escapedCredentials + '\' > \'' + credentials_loc + '\' && chmod 600 \'' + credentials_loc + '\'; }';
|
||||||
promises.push(utils.exec(credentials_cmd));
|
promises.push(utils.exec(credentials_cmd));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (plugins.length) {
|
if (plugins.length) {
|
||||||
const install_cmd = 'pip install ' + plugins.join(' ');
|
const install_cmd = '. /opt/certbot/bin/activate && pip install ' + plugins.join(' ') + ' && deactivate';
|
||||||
promises.push(utils.exec(install_cmd));
|
promises.push(utils.exec(install_cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
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(', '));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
backend/templates/_access.conf
Normal file
25
backend/templates/_access.conf
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{% if access_list_id > 0 %}
|
||||||
|
{% if access_list.items.length > 0 %}
|
||||||
|
# Authorization
|
||||||
|
auth_basic "Authorization required";
|
||||||
|
auth_basic_user_file /data/access/{{ access_list_id }};
|
||||||
|
|
||||||
|
{% if access_list.pass_auth == 0 %}
|
||||||
|
proxy_set_header Authorization "";
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
# Access Rules: {{ access_list.clients | size }} total
|
||||||
|
{% for client in access_list.clients %}
|
||||||
|
{{client | nginxAccessRule}}
|
||||||
|
{% endfor %}
|
||||||
|
deny all;
|
||||||
|
|
||||||
|
# Access checks must...
|
||||||
|
{% if access_list.satisfy_any == 1 %}
|
||||||
|
satisfy any;
|
||||||
|
{% else %}
|
||||||
|
satisfy all;
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
@ -1,41 +1,14 @@
|
|||||||
location {{ path }} {
|
location {{ path }} {
|
||||||
set $targetUri {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
|
|
||||||
{% unless path contains "~" and path contains "(" and path contains ")" %}
|
|
||||||
if ($request_uri != /){
|
|
||||||
set $targetUri $targetUri$request_uri;
|
|
||||||
}
|
|
||||||
{% endunless %}
|
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_pass $targetUri;
|
proxy_pass {{ forward_scheme }}://{{ forward_host }}:{{ forward_port }}{{ forward_path }};
|
||||||
|
|
||||||
{% if access_list_id > 0 %}
|
|
||||||
{% if access_list.items.length > 0 %}
|
|
||||||
# Authorization
|
|
||||||
auth_basic "Authorization required";
|
|
||||||
auth_basic_user_file /data/access/{{ access_list_id }};
|
|
||||||
|
|
||||||
{{ access_list.passauth }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
# Access Rules
|
|
||||||
{% for client in access_list.clients %}
|
|
||||||
{{- client.rule -}};
|
|
||||||
{% endfor %}deny all;
|
|
||||||
|
|
||||||
# Access checks must...
|
|
||||||
{% if access_list.satisfy %}
|
|
||||||
{{ access_list.satisfy }};
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
|
{% include "_access.conf" %}
|
||||||
{% include "_assets.conf" %}
|
{% include "_assets.conf" %}
|
||||||
{% include "_exploits.conf" %}
|
{% include "_exploits.conf" %}
|
||||||
|
|
||||||
{% include "_forced_ssl.conf" %}
|
{% include "_forced_ssl.conf" %}
|
||||||
{% include "_hsts.conf" %}
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
|
@ -7,9 +7,9 @@
|
|||||||
server {
|
server {
|
||||||
listen 80 default;
|
listen 80 default;
|
||||||
{% if ipv6 -%}
|
{% if ipv6 -%}
|
||||||
listen [::]:80;
|
listen [::]:80 default;
|
||||||
{% else -%}
|
{% else -%}
|
||||||
#listen [::]:80;
|
#listen [::]:80 default;
|
||||||
{% endif %}
|
{% endif %}
|
||||||
server_name default-host.localhost;
|
server_name default-host.localhost;
|
||||||
access_log /data/logs/default-host_access.log combined;
|
access_log /data/logs/default-host_access.log combined;
|
||||||
|
@ -30,27 +30,7 @@ proxy_http_version 1.1;
|
|||||||
|
|
||||||
location / {
|
location / {
|
||||||
|
|
||||||
{% if access_list_id > 0 %}
|
{% include "_access.conf" %}
|
||||||
{% if access_list.items.length > 0 %}
|
|
||||||
# Authorization
|
|
||||||
auth_basic "Authorization required";
|
|
||||||
auth_basic_user_file /data/access/{{ access_list_id }};
|
|
||||||
|
|
||||||
{{ access_list.passauth }}
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
# Access Rules
|
|
||||||
{% for client in access_list.clients %}
|
|
||||||
{{- client.rule -}};
|
|
||||||
{% endfor %}deny all;
|
|
||||||
|
|
||||||
# Access checks must...
|
|
||||||
{% if access_list.satisfy %}
|
|
||||||
{{ access_list.satisfy }};
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
{% include "_hsts.conf" %}
|
{% include "_hsts.conf" %}
|
||||||
|
|
||||||
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
{% if allow_websocket_upgrade == 1 or allow_websocket_upgrade == true %}
|
||||||
|
1864
backend/yarn.lock
1864
backend/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
# This file assumes that the frontend has been built using ./scripts/frontend-build
|
||||||
|
|
||||||
FROM nginxproxymanager/nginx-full:node
|
FROM jc21/nginx-full:certbot-node
|
||||||
|
|
||||||
ARG TARGETPLATFORM
|
ARG TARGETPLATFORM
|
||||||
ARG BUILD_VERSION
|
ARG BUILD_VERSION
|
||||||
@ -25,7 +25,7 @@ RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
|||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# s6 overlay
|
# s6 overlay
|
||||||
COPY scripts/install-s6 /tmp/install-s6
|
COPY docker/scripts/install-s6 /tmp/install-s6
|
||||||
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
EXPOSE 80 81 443
|
||||||
@ -46,6 +46,11 @@ RUN rm -rf /etc/services.d/frontend /etc/nginx/conf.d/dev.conf
|
|||||||
# Change permission of logrotate config file
|
# Change permission of logrotate config file
|
||||||
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
||||||
|
|
||||||
|
# fix for pip installs
|
||||||
|
# https://github.com/NginxProxyManager/nginx-proxy-manager/issues/1769
|
||||||
|
RUN pip uninstall --yes setuptools \
|
||||||
|
&& pip install "setuptools==58.0.0"
|
||||||
|
|
||||||
VOLUME [ "/data", "/etc/letsencrypt" ]
|
VOLUME [ "/data", "/etc/letsencrypt" ]
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM nginxproxymanager/nginx-full:node
|
FROM jc21/nginx-full:certbot-node
|
||||||
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
LABEL maintainer="Jamie Curnow <jc@jc21.com>"
|
||||||
|
|
||||||
ENV S6_LOGGING=0 \
|
ENV S6_LOGGING=0 \
|
||||||
@ -7,7 +7,7 @@ ENV S6_LOGGING=0 \
|
|||||||
|
|
||||||
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
RUN echo "fs.file-max = 65535" > /etc/sysctl.conf \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install -y certbot jq python3-pip logrotate \
|
&& apt-get install -y jq python3-pip logrotate \
|
||||||
&& apt-get clean \
|
&& apt-get clean \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
@ -21,9 +21,8 @@ RUN rm -f /etc/nginx/conf.d/production.conf
|
|||||||
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
RUN chmod 644 /etc/logrotate.d/nginx-proxy-manager
|
||||||
|
|
||||||
# s6 overlay
|
# s6 overlay
|
||||||
RUN curl -L -o /tmp/s6-overlay-amd64.tar.gz "https://github.com/just-containers/s6-overlay/releases/download/v1.22.1.0/s6-overlay-amd64.tar.gz" \
|
COPY scripts/install-s6 /tmp/install-s6
|
||||||
&& tar -xzf /tmp/s6-overlay-amd64.tar.gz -C /
|
RUN /tmp/install-s6 "${TARGETPLATFORM}" && rm -f /tmp/install-s6
|
||||||
|
|
||||||
EXPOSE 80 81 443
|
EXPOSE 80 81 443
|
||||||
ENTRYPOINT [ "/init" ]
|
ENTRYPOINT [ "/init" ]
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
# ref: https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/cont-init.d/01-envfile
|
# ref: https://github.com/linuxserver/docker-baseimage-alpine/blob/master/root/etc/cont-init.d/01-envfile
|
||||||
|
|
||||||
# in s6, environmental variables are written as text files for s6 to monitor
|
# in s6, environmental variables are written as text files for s6 to monitor
|
||||||
# seach through full-path filenames for files ending in "__FILE"
|
# search through full-path filenames for files ending in "__FILE"
|
||||||
for FILENAME in $(find /var/run/s6/container_environment/ | grep "__FILE$"); do
|
for FILENAME in $(find /var/run/s6/container_environment/ | grep "__FILE$"); do
|
||||||
echo "[secret-init] Evaluating ${FILENAME##*/} ..."
|
echo "[secret-init] Evaluating ${FILENAME##*/} ..."
|
||||||
|
|
||||||
|
@ -30,11 +30,9 @@ server {
|
|||||||
set $port "443";
|
set $port "443";
|
||||||
|
|
||||||
server_name localhost;
|
server_name localhost;
|
||||||
access_log /data/logs/fallback-access.log standard;
|
access_log /data/logs/fallback_access.log standard;
|
||||||
error_log /dev/null crit;
|
error_log /dev/null crit;
|
||||||
ssl_certificate /data/nginx/dummycert.pem;
|
ssl_reject_handshake on;
|
||||||
ssl_certificate_key /data/nginx/dummykey.pem;
|
|
||||||
include conf.d/include/ssl-ciphers.conf;
|
|
||||||
|
|
||||||
return 444;
|
return 444;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
location ~* ^.*\.(css|js|jpe?g|gif|png|woff|eot|ttf|svg|ico|css\.map|js\.map)$ {
|
location ~* ^.*\.(css|js|jpe?g|gif|png|webp|woff|eot|ttf|svg|ico|css\.map|js\.map)$ {
|
||||||
if_modified_since off;
|
if_modified_since off;
|
||||||
|
|
||||||
# use the public cache
|
# use the public cache
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
set $targetUri $forward_scheme://$server:$port$request_uri;
|
|
||||||
add_header X-Served-By $host;
|
add_header X-Served-By $host;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-Scheme $scheme;
|
proxy_set_header X-Forwarded-Scheme $scheme;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_pass $targetUri;
|
proxy_pass $forward_scheme://$server:$port$request_uri;
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ error_log /data/logs/fallback_error.log warn;
|
|||||||
include /etc/nginx/modules/*.conf;
|
include /etc/nginx/modules/*.conf;
|
||||||
|
|
||||||
events {
|
events {
|
||||||
worker_connections 1024;
|
include /data/nginx/custom/events[.]conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
http {
|
http {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/command/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
mkdir -p /data/letsencrypt-acme-challenge
|
set -e
|
||||||
|
|
||||||
cd /app || echo
|
|
||||||
|
|
||||||
|
echo "❯ Starting backend ..."
|
||||||
if [ "$DEVELOPMENT" == "true" ]; then
|
if [ "$DEVELOPMENT" == "true" ]; then
|
||||||
cd /app || exit 1
|
cd /app || exit 1
|
||||||
# If yarn install fails: add --verbose --network-concurrency 1
|
# If yarn install fails: add --verbose --network-concurrency 1
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/backend/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/backend/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
longrun
|
@ -1,4 +1,7 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
#!/command/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
# This service is DEVELOPMENT only.
|
# This service is DEVELOPMENT only.
|
||||||
|
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/frontend/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/frontend/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
longrun
|
7
docker/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
Executable file
7
docker/rootfs/etc/s6-overlay/s6-rc.d/nginx/run
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/command/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "❯ Starting nginx ..."
|
||||||
|
exec nginx
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/nginx/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/nginx/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
longrun
|
63
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/script.sh
Executable file
63
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/script.sh
Executable file
@ -0,0 +1,63 @@
|
|||||||
|
#!/command/with-contenv bash
|
||||||
|
# shellcheck shell=bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DATA_PATH=/data
|
||||||
|
|
||||||
|
# Ensure /data is mounted
|
||||||
|
if [ ! -d "$DATA_PATH" ]; then
|
||||||
|
echo '--------------------------------------'
|
||||||
|
echo "ERROR: $DATA_PATH is not mounted! Check your docker configuration."
|
||||||
|
echo '--------------------------------------'
|
||||||
|
/run/s6/basedir/bin/halt
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "❯ Checking folder structure ..."
|
||||||
|
|
||||||
|
# Create required folders
|
||||||
|
mkdir -p /tmp/nginx/body \
|
||||||
|
/run/nginx \
|
||||||
|
/var/log/nginx \
|
||||||
|
/data/nginx \
|
||||||
|
/data/custom_ssl \
|
||||||
|
/data/logs \
|
||||||
|
/data/access \
|
||||||
|
/data/nginx/default_host \
|
||||||
|
/data/nginx/default_www \
|
||||||
|
/data/nginx/proxy_host \
|
||||||
|
/data/nginx/redirection_host \
|
||||||
|
/data/nginx/stream \
|
||||||
|
/data/nginx/dead_host \
|
||||||
|
/data/nginx/temp \
|
||||||
|
/var/lib/nginx/cache/public \
|
||||||
|
/var/lib/nginx/cache/private \
|
||||||
|
/var/cache/nginx/proxy_temp \
|
||||||
|
/data/letsencrypt-acme-challenge
|
||||||
|
|
||||||
|
touch /var/log/nginx/error.log && chmod 777 /var/log/nginx/error.log && chmod -R 777 /var/cache/nginx
|
||||||
|
chown root /tmp/nginx
|
||||||
|
|
||||||
|
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
|
||||||
|
# thanks @tfmm
|
||||||
|
if [ "$DISABLE_IPV6" == "true" ] || [ "$DISABLE_IPV6" == "on" ] || [ "$DISABLE_IPV6" == "1" ] || [ "$DISABLE_IPV6" == "yes" ];
|
||||||
|
then
|
||||||
|
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) ipv6=off valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf
|
||||||
|
else
|
||||||
|
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" { sub(/%.*$/,"",$2); print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf) valid=10s;" > /etc/nginx/conf.d/include/resolvers.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Handle IPV6 settings
|
||||||
|
/bin/handle-ipv6-setting /etc/nginx/conf.d
|
||||||
|
/bin/handle-ipv6-setting /data/nginx
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "-------------------------------------
|
||||||
|
_ _ ____ __ __
|
||||||
|
| \ | | _ \| \/ |
|
||||||
|
| \| | |_) | |\/| |
|
||||||
|
| |\ | __/| | | |
|
||||||
|
|_| \_|_| |_| |_|
|
||||||
|
-------------------------------------
|
||||||
|
"
|
1
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/type
Normal file
1
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/type
Normal file
@ -0,0 +1 @@
|
|||||||
|
oneshot
|
2
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/up
Normal file
2
docker/rootfs/etc/s6-overlay/s6-rc.d/prepare/up
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# shellcheck shell=bash
|
||||||
|
/etc/s6-overlay/s6-rc.d/prepare/script.sh
|
@ -1,6 +0,0 @@
|
|||||||
#!/usr/bin/execlineb -S1
|
|
||||||
if { s6-test ${1} -ne 0 }
|
|
||||||
if { s6-test ${1} -ne 256 }
|
|
||||||
|
|
||||||
s6-svscanctl -t /var/run/s6/services
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
s6-svscanctl -t /var/run/s6/services
|
|
@ -1 +0,0 @@
|
|||||||
/bin/true
|
|
@ -1,49 +0,0 @@
|
|||||||
#!/usr/bin/with-contenv bash
|
|
||||||
|
|
||||||
# Create required folders
|
|
||||||
mkdir -p /tmp/nginx/body \
|
|
||||||
/run/nginx \
|
|
||||||
/var/log/nginx \
|
|
||||||
/data/nginx \
|
|
||||||
/data/custom_ssl \
|
|
||||||
/data/logs \
|
|
||||||
/data/access \
|
|
||||||
/data/nginx/default_host \
|
|
||||||
/data/nginx/default_www \
|
|
||||||
/data/nginx/proxy_host \
|
|
||||||
/data/nginx/redirection_host \
|
|
||||||
/data/nginx/stream \
|
|
||||||
/data/nginx/dead_host \
|
|
||||||
/data/nginx/temp \
|
|
||||||
/var/lib/nginx/cache/public \
|
|
||||||
/var/lib/nginx/cache/private \
|
|
||||||
/var/cache/nginx/proxy_temp
|
|
||||||
|
|
||||||
touch /var/log/nginx/error.log && chmod 777 /var/log/nginx/error.log && chmod -R 777 /var/cache/nginx
|
|
||||||
chown root /tmp/nginx
|
|
||||||
|
|
||||||
# Dynamically generate resolvers file, if resolver is IPv6, enclose in `[]`
|
|
||||||
# thanks @tfmm
|
|
||||||
echo resolver "$(awk 'BEGIN{ORS=" "} $1=="nameserver" {print ($2 ~ ":")? "["$2"]": $2}' /etc/resolv.conf);" > /etc/nginx/conf.d/include/resolvers.conf
|
|
||||||
|
|
||||||
# Generate dummy self-signed certificate.
|
|
||||||
if [ ! -f /data/nginx/dummycert.pem ] || [ ! -f /data/nginx/dummykey.pem ]
|
|
||||||
then
|
|
||||||
echo "Generating dummy SSL certificate..."
|
|
||||||
openssl req \
|
|
||||||
-new \
|
|
||||||
-newkey rsa:2048 \
|
|
||||||
-days 3650 \
|
|
||||||
-nodes \
|
|
||||||
-x509 \
|
|
||||||
-subj '/O=localhost/OU=localhost/CN=localhost' \
|
|
||||||
-keyout /data/nginx/dummykey.pem \
|
|
||||||
-out /data/nginx/dummycert.pem
|
|
||||||
echo "Complete"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Handle IPV6 settings
|
|
||||||
/bin/handle-ipv6-setting /etc/nginx/conf.d
|
|
||||||
/bin/handle-ipv6-setting /data/nginx
|
|
||||||
|
|
||||||
exec nginx
|
|
@ -8,8 +8,8 @@ BLUE='\E[1;34m'
|
|||||||
GREEN='\E[1;32m'
|
GREEN='\E[1;32m'
|
||||||
RESET='\E[0m'
|
RESET='\E[0m'
|
||||||
|
|
||||||
S6_OVERLAY_VERSION=1.22.1.0
|
S6_OVERLAY_VERSION=3.1.4.1
|
||||||
TARGETPLATFORM=$1
|
TARGETPLATFORM=${1:unspecified}
|
||||||
|
|
||||||
# Determine the correct binary file for the architecture given
|
# Determine the correct binary file for the architecture given
|
||||||
case $TARGETPLATFORM in
|
case $TARGETPLATFORM in
|
||||||
@ -22,13 +22,17 @@ case $TARGETPLATFORM in
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
S6_ARCH=amd64
|
S6_ARCH=x86_64
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
echo -e "${BLUE}❯ ${CYAN}Installing S6-overlay v${S6_OVERLAY_VERSION} for ${YELLOW}${TARGETPLATFORM} (${S6_ARCH})${RESET}"
|
echo -e "${BLUE}❯ ${CYAN}Installing S6-overlay v${S6_OVERLAY_VERSION} for ${YELLOW}${TARGETPLATFORM} (${S6_ARCH})${RESET}"
|
||||||
|
|
||||||
curl -L -o "/tmp/s6-overlay-${S6_ARCH}.tar.gz" "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.gz" \
|
curl -L -o '/tmp/s6-overlay-noarch.tar.xz' "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-noarch.tar.xz"
|
||||||
&& tar -xzf "/tmp/s6-overlay-${S6_ARCH}.tar.gz" -C /
|
curl -L -o "/tmp/s6-overlay-${S6_ARCH}.tar.xz" "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${S6_ARCH}.tar.xz"
|
||||||
|
tar -C / -Jxpf '/tmp/s6-overlay-noarch.tar.xz'
|
||||||
|
tar -C / -Jxpf "/tmp/s6-overlay-${S6_ARCH}.tar.xz"
|
||||||
|
|
||||||
|
rm -rf "/tmp/s6-overlay-${S6_ARCH}.tar.xz"
|
||||||
|
|
||||||
echo -e "${BLUE}❯ ${GREEN}S6-overlay install Complete${RESET}"
|
echo -e "${BLUE}❯ ${GREEN}S6-overlay install Complete${RESET}"
|
@ -18,8 +18,8 @@ services running on this Docker host:
|
|||||||
```yml
|
```yml
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external:
|
external: true
|
||||||
name: scoobydoo
|
name: scoobydoo
|
||||||
```
|
```
|
||||||
|
|
||||||
Let's look at a Portainer example:
|
Let's look at a Portainer example:
|
||||||
@ -38,8 +38,8 @@ services:
|
|||||||
|
|
||||||
networks:
|
networks:
|
||||||
default:
|
default:
|
||||||
external:
|
external: true
|
||||||
name: scoobydoo
|
name: scoobydoo
|
||||||
```
|
```
|
||||||
|
|
||||||
Now in the NPM UI you can create a proxy host with `portainer` as the hostname,
|
Now in the NPM UI you can create a proxy host with `portainer` as the hostname,
|
||||||
@ -151,6 +151,7 @@ You can add your custom configuration snippet files at `/data/nginx/custom` as f
|
|||||||
- `/data/nginx/custom/root.conf`: Included at the very end of nginx.conf
|
- `/data/nginx/custom/root.conf`: Included at the very end of nginx.conf
|
||||||
- `/data/nginx/custom/http_top.conf`: Included at the top of the main http block
|
- `/data/nginx/custom/http_top.conf`: Included at the top of the main http block
|
||||||
- `/data/nginx/custom/http.conf`: Included at the end of the main http block
|
- `/data/nginx/custom/http.conf`: Included at the end of the main http block
|
||||||
|
- `/data/nginx/custom/events.conf`: Included at the end of the events block
|
||||||
- `/data/nginx/custom/stream.conf`: Included at the end of the main stream block
|
- `/data/nginx/custom/stream.conf`: Included at the end of the main stream block
|
||||||
- `/data/nginx/custom/server_proxy.conf`: Included at the end of every proxy server block
|
- `/data/nginx/custom/server_proxy.conf`: Included at the end of every proxy server block
|
||||||
- `/data/nginx/custom/server_redirect.conf`: Included at the end of every redirection server block
|
- `/data/nginx/custom/server_redirect.conf`: Included at the end of every redirection server block
|
||||||
|
@ -21,3 +21,6 @@ Your best bet is to ask the [Reddit community for support](https://www.reddit.co
|
|||||||
|
|
||||||
Gitter is best left for anyone contributing to the project to ask for help about internals, code reviews etc.
|
Gitter is best left for anyone contributing to the project to ask for help about internals, code reviews etc.
|
||||||
|
|
||||||
|
## When adding username and password access control to a proxy host, I can no longer login into the app.
|
||||||
|
|
||||||
|
Having an Access Control List (ACL) with username and password requires the browser to always send this username and password in the `Authorization` header on each request. If your proxied app also requires authentication (like Nginx Proxy Manager itself), most likely the app will also use the `Authorization` header to transmit this information, as this is the standardized header meant for this kind of information. However having multiples of the same headers is not allowed in the [internet standard](https://www.rfc-editor.org/rfc/rfc7230#section-3.2.2) and almost all apps do not support multiple values in the `Authorization` header. Hence one of the two logins will be broken. This can only be fixed by either removing one of the logins or by changing the app to use other non-standard headers for authorization.
|
@ -16,7 +16,7 @@
|
|||||||
"alphanum-sort": "^1.0.2",
|
"alphanum-sort": "^1.0.2",
|
||||||
"ansi-colors": "^4.1.1",
|
"ansi-colors": "^4.1.1",
|
||||||
"ansi-escapes": "^4.3.1",
|
"ansi-escapes": "^4.3.1",
|
||||||
"ansi-html": "^0.0.7",
|
"ansi-html": "^0.0.8",
|
||||||
"ansi-regex": "^5.0.0",
|
"ansi-regex": "^5.0.0",
|
||||||
"ansi-styles": "^4.2.1",
|
"ansi-styles": "^4.2.1",
|
||||||
"anymatch": "^3.1.1",
|
"anymatch": "^3.1.1",
|
||||||
@ -213,7 +213,7 @@
|
|||||||
"etag": "^1.8.1",
|
"etag": "^1.8.1",
|
||||||
"eventemitter3": "^4.0.4",
|
"eventemitter3": "^4.0.4",
|
||||||
"events": "^3.2.0",
|
"events": "^3.2.0",
|
||||||
"eventsource": "^1.0.7",
|
"eventsource": "^2.0.2",
|
||||||
"evp_bytestokey": "^1.0.3",
|
"evp_bytestokey": "^1.0.3",
|
||||||
"execa": "^4.0.3",
|
"execa": "^4.0.3",
|
||||||
"expand-brackets": "^4.0.0",
|
"expand-brackets": "^4.0.0",
|
||||||
@ -357,7 +357,7 @@
|
|||||||
"jsbn": "^1.1.0",
|
"jsbn": "^1.1.0",
|
||||||
"jsesc": "^3.0.1",
|
"jsesc": "^3.0.1",
|
||||||
"json-parse-better-errors": "^1.0.2",
|
"json-parse-better-errors": "^1.0.2",
|
||||||
"json-schema": "^0.2.5",
|
"json-schema": "^0.4.0",
|
||||||
"json-schema-traverse": "^0.4.1",
|
"json-schema-traverse": "^0.4.1",
|
||||||
"json-stringify-safe": "^5.0.1",
|
"json-stringify-safe": "^5.0.1",
|
||||||
"json3": "^3.3.3",
|
"json3": "^3.3.3",
|
||||||
@ -394,7 +394,7 @@
|
|||||||
"map-age-cleaner": "^0.1.3",
|
"map-age-cleaner": "^0.1.3",
|
||||||
"map-cache": "^0.2.2",
|
"map-cache": "^0.2.2",
|
||||||
"map-visit": "^1.0.0",
|
"map-visit": "^1.0.0",
|
||||||
"markdown-it": "^11.0.0",
|
"markdown-it": "^12.3.2",
|
||||||
"markdown-it-anchor": "^5.3.0",
|
"markdown-it-anchor": "^5.3.0",
|
||||||
"markdown-it-chain": "^1.3.0",
|
"markdown-it-chain": "^1.3.0",
|
||||||
"markdown-it-container": "^3.0.0",
|
"markdown-it-container": "^3.0.0",
|
||||||
@ -434,7 +434,7 @@
|
|||||||
"neo-async": "^2.6.2",
|
"neo-async": "^2.6.2",
|
||||||
"nice-try": "^2.0.1",
|
"nice-try": "^2.0.1",
|
||||||
"no-case": "^3.0.3",
|
"no-case": "^3.0.3",
|
||||||
"node-forge": "^0.10.0",
|
"node-forge": "^1.0.0",
|
||||||
"node-libs-browser": "^2.2.1",
|
"node-libs-browser": "^2.2.1",
|
||||||
"node-releases": "^1.1.60",
|
"node-releases": "^1.1.60",
|
||||||
"nopt": "^4.0.3",
|
"nopt": "^4.0.3",
|
||||||
|
@ -107,7 +107,7 @@ you don't have to worry about doing anything special and you can follow the comm
|
|||||||
|
|
||||||
Check out the [dockerhub tags](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags)
|
Check out the [dockerhub tags](https://hub.docker.com/r/jc21/nginx-proxy-manager/tags)
|
||||||
for a list of supported architectures and if you want one that doesn't exist,
|
for a list of supported architectures and if you want one that doesn't exist,
|
||||||
[create a feature request](https://github.com/jc21/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
|
[create a feature request](https://github.com/NginxProxyManager/nginx-proxy-manager/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=).
|
||||||
|
|
||||||
Also, if you don't know how to already, follow [this guide to install docker and docker-compose](https://manre-universe.net/how-to-run-docker-and-docker-compose-on-raspbian/)
|
Also, if you don't know how to already, follow [this guide to install docker and docker-compose](https://manre-universe.net/how-to-run-docker-and-docker-compose-on-raspbian/)
|
||||||
on Raspbian.
|
on Raspbian.
|
||||||
|
2
docs/third-party/README.md
vendored
2
docs/third-party/README.md
vendored
@ -1,6 +1,6 @@
|
|||||||
# Third Party
|
# Third Party
|
||||||
|
|
||||||
As this software gains popularity it's common to see it integrated with other platforms. Please be aware that unless specifically mentioned in the documenation of those
|
As this software gains popularity it's common to see it integrated with other platforms. Please be aware that unless specifically mentioned in the documentation of those
|
||||||
integrations, they are *not supported* by me.
|
integrations, they are *not supported* by me.
|
||||||
|
|
||||||
Known integrations:
|
Known integrations:
|
||||||
|
463
docs/yarn.lock
463
docs/yarn.lock
@ -967,6 +967,51 @@
|
|||||||
lodash "^4.17.19"
|
lodash "^4.17.19"
|
||||||
to-fast-properties "^2.0.0"
|
to-fast-properties "^2.0.0"
|
||||||
|
|
||||||
|
"@jridgewell/gen-mapping@^0.3.0":
|
||||||
|
version "0.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9"
|
||||||
|
integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/set-array" "^1.0.1"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
|
"@jridgewell/resolve-uri@^3.0.3":
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||||
|
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||||
|
|
||||||
|
"@jridgewell/set-array@^1.0.1":
|
||||||
|
version "1.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||||
|
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||||
|
|
||||||
|
"@jridgewell/source-map@^0.3.2":
|
||||||
|
version "0.3.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
|
||||||
|
integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/gen-mapping" "^0.3.0"
|
||||||
|
"@jridgewell/trace-mapping" "^0.3.9"
|
||||||
|
|
||||||
|
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||||
|
version "1.4.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||||
|
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||||
|
|
||||||
|
"@jridgewell/trace-mapping@^0.3.9":
|
||||||
|
version "0.3.14"
|
||||||
|
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed"
|
||||||
|
integrity sha512-bJWEfQ9lPTvm3SneWwRFVLzrh6nhjwqw7TUFFBEMzwvg7t7PCDenf2lDwqo4NQXzdpgBXyFgDWnQA+2vkruksQ==
|
||||||
|
dependencies:
|
||||||
|
"@jridgewell/resolve-uri" "^3.0.3"
|
||||||
|
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||||
|
|
||||||
|
"@leichtgewicht/ip-codec@^2.0.1":
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b"
|
||||||
|
integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==
|
||||||
|
|
||||||
"@mrmlnc/readdir-enhanced@^2.2.1":
|
"@mrmlnc/readdir-enhanced@^2.2.1":
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde"
|
||||||
@ -1478,13 +1523,13 @@ abbrev@1, abbrev@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
|
||||||
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
|
||||||
|
|
||||||
accepts@^1.3.7, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7:
|
accepts@^1.3.7, accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8:
|
||||||
version "1.3.7"
|
version "1.3.8"
|
||||||
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd"
|
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
|
||||||
integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==
|
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-types "~2.1.24"
|
mime-types "~2.1.34"
|
||||||
negotiator "0.6.2"
|
negotiator "0.6.3"
|
||||||
|
|
||||||
acorn@^6.4.1:
|
acorn@^6.4.1:
|
||||||
version "6.4.1"
|
version "6.4.1"
|
||||||
@ -1496,6 +1541,11 @@ acorn@^7.4.0:
|
|||||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c"
|
||||||
integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
|
integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==
|
||||||
|
|
||||||
|
acorn@^8.5.0:
|
||||||
|
version "8.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.1.tgz#0197122c843d1bf6d0a5e83220a788f278f63c30"
|
||||||
|
integrity sha512-Xx54uLJQZ19lKygFXOWsscKUbsBZW0CPykPhVQdhIeIwrbPmJzqeASDInc8nKBnp/JT6igTs82qPXz069H8I/A==
|
||||||
|
|
||||||
agentkeepalive@^2.2.0:
|
agentkeepalive@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
|
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef"
|
||||||
@ -1608,11 +1658,16 @@ ansi-escapes@^4.1.0, ansi-escapes@^4.2.1, ansi-escapes@^4.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.11.0"
|
type-fest "^0.11.0"
|
||||||
|
|
||||||
ansi-html@0.0.7, ansi-html@^0.0.7:
|
ansi-html@0.0.7:
|
||||||
version "0.0.7"
|
version "0.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
|
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e"
|
||||||
integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
|
integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4=
|
||||||
|
|
||||||
|
ansi-html@^0.0.8:
|
||||||
|
version "0.0.8"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.8.tgz#e969db193b12bcdfa6727b29ffd8882dc13cc501"
|
||||||
|
integrity sha512-QROYz1I1Kj+8bTYgx0IlMBpRSCIU+7GjbE0oH+KF7QKc+qSF8YAlIutN59Db17tXN70Ono9upT9Ht0iG93W7ug==
|
||||||
|
|
||||||
ansi-regex@^2.0.0:
|
ansi-regex@^2.0.0:
|
||||||
version "2.1.1"
|
version "2.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||||
@ -1686,6 +1741,11 @@ argparse@^1.0.10, argparse@^1.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
sprintf-js "~1.0.2"
|
sprintf-js "~1.0.2"
|
||||||
|
|
||||||
|
argparse@^2.0.1:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||||
|
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||||
|
|
||||||
arr-diff@^4.0.0:
|
arr-diff@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
|
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520"
|
||||||
@ -1830,9 +1890,9 @@ async@^2.6.2:
|
|||||||
lodash "^4.17.14"
|
lodash "^4.17.14"
|
||||||
|
|
||||||
async@^3.2.0:
|
async@^3.2.0:
|
||||||
version "3.2.0"
|
version "3.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720"
|
resolved "https://registry.yarnpkg.com/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd"
|
||||||
integrity sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw==
|
integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g==
|
||||||
|
|
||||||
asynckit@^0.4.0:
|
asynckit@^0.4.0:
|
||||||
version "0.4.0"
|
version "0.4.0"
|
||||||
@ -2010,21 +2070,21 @@ bn.js@^5.1.1, bn.js@^5.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0"
|
resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.2.tgz#c9686902d3c9a27729f43ab10f9d79c2004da7b0"
|
||||||
integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==
|
integrity sha512-40rZaf3bUNKTVYu9sIeeEGOg7g14Yvnj9kH7b50EiwX0Q7A6umbvfI5tvHaOERH0XigqKkfLkFQxzb4e6CIXnA==
|
||||||
|
|
||||||
body-parser@1.19.0, body-parser@^1.19.0:
|
body-parser@1.19.2, body-parser@^1.19.0:
|
||||||
version "1.19.0"
|
version "1.19.2"
|
||||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.2.tgz#4714ccd9c157d44797b8b5607d72c0b89952f26e"
|
||||||
integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==
|
integrity sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes "3.1.0"
|
bytes "3.1.2"
|
||||||
content-type "~1.0.4"
|
content-type "~1.0.4"
|
||||||
debug "2.6.9"
|
debug "2.6.9"
|
||||||
depd "~1.1.2"
|
depd "~1.1.2"
|
||||||
http-errors "1.7.2"
|
http-errors "1.8.1"
|
||||||
iconv-lite "0.4.24"
|
iconv-lite "0.4.24"
|
||||||
on-finished "~2.3.0"
|
on-finished "~2.3.0"
|
||||||
qs "6.7.0"
|
qs "6.9.7"
|
||||||
raw-body "2.4.0"
|
raw-body "2.4.3"
|
||||||
type-is "~1.6.17"
|
type-is "~1.6.18"
|
||||||
|
|
||||||
bonjour@^3.5.0:
|
bonjour@^3.5.0:
|
||||||
version "3.5.0"
|
version "3.5.0"
|
||||||
@ -2224,6 +2284,11 @@ bytes@3.1.0, bytes@^3.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||||
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
||||||
|
|
||||||
|
bytes@3.1.2:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
|
||||||
|
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||||
|
|
||||||
cac@^6.5.6, cac@^6.6.1:
|
cac@^6.5.6, cac@^6.6.1:
|
||||||
version "6.6.1"
|
version "6.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/cac/-/cac-6.6.1.tgz#3dde3f6943f45d42a56729ea3573c08b3e7b6a6d"
|
resolved "https://registry.yarnpkg.com/cac/-/cac-6.6.1.tgz#3dde3f6943f45d42a56729ea3573c08b3e7b6a6d"
|
||||||
@ -2339,6 +2404,14 @@ cacheable-request@^6.0.0:
|
|||||||
normalize-url "^4.1.0"
|
normalize-url "^4.1.0"
|
||||||
responselike "^1.0.2"
|
responselike "^1.0.2"
|
||||||
|
|
||||||
|
call-bind@^1.0.0:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||||
|
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
get-intrinsic "^1.0.2"
|
||||||
|
|
||||||
call-me-maybe@^1.0.1:
|
call-me-maybe@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
|
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
|
||||||
@ -2791,12 +2864,12 @@ constants-browserify@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
|
resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75"
|
||||||
integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
|
integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=
|
||||||
|
|
||||||
content-disposition@0.5.3, content-disposition@^0.5.3:
|
content-disposition@0.5.4, content-disposition@^0.5.3:
|
||||||
version "0.5.3"
|
version "0.5.4"
|
||||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe"
|
||||||
integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==
|
integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "5.1.2"
|
safe-buffer "5.2.1"
|
||||||
|
|
||||||
content-type@^1.0.4, content-type@~1.0.4:
|
content-type@^1.0.4, content-type@~1.0.4:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
@ -2820,15 +2893,10 @@ cookie-signature@^1.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.1.0.tgz#cc94974f91fb9a9c1bb485e95fc2b7f4b120aff2"
|
resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.1.0.tgz#cc94974f91fb9a9c1bb485e95fc2b7f4b120aff2"
|
||||||
integrity sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==
|
integrity sha512-Alvs19Vgq07eunykd3Xy2jF0/qSNv2u7KDbAek9H5liV1UMijbqFs5cycZvv5dVsvseT/U4H8/7/w8Koh35C4A==
|
||||||
|
|
||||||
cookie@0.4.0:
|
cookie@0.4.2, cookie@^0.4.1:
|
||||||
version "0.4.0"
|
version "0.4.2"
|
||||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba"
|
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432"
|
||||||
integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==
|
integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==
|
||||||
|
|
||||||
cookie@^0.4.1:
|
|
||||||
version "0.4.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1"
|
|
||||||
integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==
|
|
||||||
|
|
||||||
copy-concurrently@^1.0.0, copy-concurrently@^1.0.5:
|
copy-concurrently@^1.0.0, copy-concurrently@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
@ -3279,9 +3347,9 @@ decamelize@^4.0.0:
|
|||||||
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
|
integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
|
||||||
|
|
||||||
decode-uri-component@^0.2.0:
|
decode-uri-component@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.1.tgz#e9d7afd716fc1a7ec6ae7cc0aa3e540a1eac2e9d"
|
||||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
integrity sha512-XZHyaFJ6QMWhYmlz+UcmtaLeecNiXwkTGzCqG5WByt+1P1HnU6Siwf0TeP3OsZmlnGqQRSEMIxue0LLCaGY3dw==
|
||||||
|
|
||||||
decompress-response@^3.3.0:
|
decompress-response@^3.3.0:
|
||||||
version "3.3.0"
|
version "3.3.0"
|
||||||
@ -3501,11 +3569,11 @@ dns-packet@^4.0.0:
|
|||||||
safe-buffer "^5.1.1"
|
safe-buffer "^5.1.1"
|
||||||
|
|
||||||
dns-packet@^5.2.1:
|
dns-packet@^5.2.1:
|
||||||
version "5.2.2"
|
version "5.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.2.2.tgz#e4c7d12974cc320b0c0d4b9bbbf68ac151cfe81e"
|
resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b"
|
||||||
integrity sha512-sQN+vLwC3PvOXiCH/oHcdzML2opFeIdVh8gjjMZrM45n4dR80QF6o3AzInQy6F9Eoc0VJYog4JpQTilt4RFLYQ==
|
integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g==
|
||||||
dependencies:
|
dependencies:
|
||||||
ip "^1.1.5"
|
"@leichtgewicht/ip-codec" "^2.0.1"
|
||||||
|
|
||||||
dns-txt@^2.0.2:
|
dns-txt@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
@ -3744,10 +3812,10 @@ entities@^1.1.1, entities@~1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
|
||||||
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
|
integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==
|
||||||
|
|
||||||
entities@^2.0.0, entities@^2.0.3, entities@~2.0.0:
|
entities@^2.0.0, entities@^2.0.3, entities@~2.1.0:
|
||||||
version "2.0.3"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f"
|
resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5"
|
||||||
integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==
|
integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w==
|
||||||
|
|
||||||
envify@^4.0.0, envify@^4.1.0:
|
envify@^4.0.0, envify@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
@ -3925,6 +3993,11 @@ eventsource@^1.0.7:
|
|||||||
dependencies:
|
dependencies:
|
||||||
original "^1.0.0"
|
original "^1.0.0"
|
||||||
|
|
||||||
|
eventsource@^2.0.2:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-2.0.2.tgz#76dfcc02930fb2ff339520b6d290da573a9e8508"
|
||||||
|
integrity sha512-IzUmBGPR3+oUG9dUeXynyNmf91/3zUSJg1lCktzKw47OXuhco54U3r9B7O4XX+Rb1Itm9OZ2b0RkTs10bICOxA==
|
||||||
|
|
||||||
evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
|
evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
|
resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02"
|
||||||
@ -3985,16 +4058,16 @@ expand-brackets@^4.0.0:
|
|||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
express@^4.17.1:
|
express@^4.17.1:
|
||||||
version "4.17.1"
|
version "4.17.3"
|
||||||
resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134"
|
resolved "https://registry.yarnpkg.com/express/-/express-4.17.3.tgz#f6c7302194a4fb54271b73a1fe7a06478c8f85a1"
|
||||||
integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==
|
integrity sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==
|
||||||
dependencies:
|
dependencies:
|
||||||
accepts "~1.3.7"
|
accepts "~1.3.8"
|
||||||
array-flatten "1.1.1"
|
array-flatten "1.1.1"
|
||||||
body-parser "1.19.0"
|
body-parser "1.19.2"
|
||||||
content-disposition "0.5.3"
|
content-disposition "0.5.4"
|
||||||
content-type "~1.0.4"
|
content-type "~1.0.4"
|
||||||
cookie "0.4.0"
|
cookie "0.4.2"
|
||||||
cookie-signature "1.0.6"
|
cookie-signature "1.0.6"
|
||||||
debug "2.6.9"
|
debug "2.6.9"
|
||||||
depd "~1.1.2"
|
depd "~1.1.2"
|
||||||
@ -4008,13 +4081,13 @@ express@^4.17.1:
|
|||||||
on-finished "~2.3.0"
|
on-finished "~2.3.0"
|
||||||
parseurl "~1.3.3"
|
parseurl "~1.3.3"
|
||||||
path-to-regexp "0.1.7"
|
path-to-regexp "0.1.7"
|
||||||
proxy-addr "~2.0.5"
|
proxy-addr "~2.0.7"
|
||||||
qs "6.7.0"
|
qs "6.9.7"
|
||||||
range-parser "~1.2.1"
|
range-parser "~1.2.1"
|
||||||
safe-buffer "5.1.2"
|
safe-buffer "5.2.1"
|
||||||
send "0.17.1"
|
send "0.17.2"
|
||||||
serve-static "1.14.1"
|
serve-static "1.14.2"
|
||||||
setprototypeof "1.1.1"
|
setprototypeof "1.2.0"
|
||||||
statuses "~1.5.0"
|
statuses "~1.5.0"
|
||||||
type-is "~1.6.18"
|
type-is "~1.6.18"
|
||||||
utils-merge "1.0.1"
|
utils-merge "1.0.1"
|
||||||
@ -4112,6 +4185,13 @@ fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||||
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
|
||||||
|
|
||||||
|
fast-xml-parser@^3.19.0:
|
||||||
|
version "3.21.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-3.21.1.tgz#152a1d51d445380f7046b304672dd55d15c9e736"
|
||||||
|
integrity sha512-FTFVjYoBOZTJekiUsawGsSYV9QL0A+zDYCRj7y34IO6Jg+2IMYEtQa+bbictpdpV8dHxXywqU7C0gRDEOFtBFg==
|
||||||
|
dependencies:
|
||||||
|
strnum "^1.0.4"
|
||||||
|
|
||||||
fastq@^1.6.0:
|
fastq@^1.6.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481"
|
resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481"
|
||||||
@ -4254,9 +4334,9 @@ flush-write-stream@^2.0.0:
|
|||||||
readable-stream "^3.1.1"
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
follow-redirects@^1.0.0, follow-redirects@^1.12.1:
|
follow-redirects@^1.0.0, follow-redirects@^1.12.1:
|
||||||
version "1.12.1"
|
version "1.14.8"
|
||||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.12.1.tgz#de54a6205311b93d60398ebc01cf7015682312b6"
|
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.8.tgz#016996fb9a11a100566398b1c6839337d7bfa8fc"
|
||||||
integrity sha512-tmRv0AVuR7ZyouUHLeNSiO6pqulF7dYa3s19c6t+wz9LD69/uSzdMxJ2S91nTI9U3rt/IldxpzMOFejp6f0hjg==
|
integrity sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==
|
||||||
|
|
||||||
for-in@^1.0.2:
|
for-in@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@ -4291,7 +4371,12 @@ form-data@~2.3.2:
|
|||||||
combined-stream "^1.0.6"
|
combined-stream "^1.0.6"
|
||||||
mime-types "^2.1.12"
|
mime-types "^2.1.12"
|
||||||
|
|
||||||
forwarded@^0.1.2, forwarded@~0.1.2:
|
forwarded@0.2.0:
|
||||||
|
version "0.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
|
||||||
|
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
|
||||||
|
|
||||||
|
forwarded@^0.1.2:
|
||||||
version "0.1.2"
|
version "0.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84"
|
||||||
integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
|
integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=
|
||||||
@ -4385,6 +4470,15 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
|
||||||
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
|
||||||
|
|
||||||
|
get-intrinsic@^1.0.2:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.0.tgz#7ad1dc0535f3a2904bba075772763e5051f6d05f"
|
||||||
|
integrity sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==
|
||||||
|
dependencies:
|
||||||
|
function-bind "^1.1.1"
|
||||||
|
has "^1.0.3"
|
||||||
|
has-symbols "^1.0.3"
|
||||||
|
|
||||||
get-stream@^4.0.0, get-stream@^4.1.0:
|
get-stream@^4.0.0, get-stream@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||||
@ -4638,6 +4732,11 @@ has-symbols@^1.0.0, has-symbols@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
|
||||||
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
|
||||||
|
|
||||||
|
has-symbols@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
|
||||||
|
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
|
||||||
|
|
||||||
has-value@^0.3.1:
|
has-value@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||||
@ -4839,27 +4938,16 @@ htmlparser2@^4.1.0:
|
|||||||
entities "^2.0.0"
|
entities "^2.0.0"
|
||||||
|
|
||||||
http-cache-semantics@^4.0.0:
|
http-cache-semantics@^4.0.0:
|
||||||
version "4.1.0"
|
version "4.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a"
|
||||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==
|
||||||
|
|
||||||
http-deceiver@^1.2.7:
|
http-deceiver@^1.2.7:
|
||||||
version "1.2.7"
|
version "1.2.7"
|
||||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||||
integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
|
integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=
|
||||||
|
|
||||||
http-errors@1.7.2:
|
http-errors@1.7.3:
|
||||||
version "1.7.2"
|
|
||||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
|
|
||||||
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
|
|
||||||
dependencies:
|
|
||||||
depd "~1.1.2"
|
|
||||||
inherits "2.0.3"
|
|
||||||
setprototypeof "1.1.1"
|
|
||||||
statuses ">= 1.5.0 < 2"
|
|
||||||
toidentifier "1.0.0"
|
|
||||||
|
|
||||||
http-errors@1.7.3, http-errors@~1.7.2:
|
|
||||||
version "1.7.3"
|
version "1.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
|
||||||
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
|
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
|
||||||
@ -4870,6 +4958,17 @@ http-errors@1.7.3, http-errors@~1.7.2:
|
|||||||
statuses ">= 1.5.0 < 2"
|
statuses ">= 1.5.0 < 2"
|
||||||
toidentifier "1.0.0"
|
toidentifier "1.0.0"
|
||||||
|
|
||||||
|
http-errors@1.8.1:
|
||||||
|
version "1.8.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.1.tgz#7c3f28577cbc8a207388455dbd62295ed07bd68c"
|
||||||
|
integrity sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==
|
||||||
|
dependencies:
|
||||||
|
depd "~1.1.2"
|
||||||
|
inherits "2.0.4"
|
||||||
|
setprototypeof "1.2.0"
|
||||||
|
statuses ">= 1.5.0 < 2"
|
||||||
|
toidentifier "1.0.1"
|
||||||
|
|
||||||
http-errors@^1.8.0:
|
http-errors@^1.8.0:
|
||||||
version "1.8.0"
|
version "1.8.0"
|
||||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507"
|
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.8.0.tgz#75d1bbe497e1044f51e4ee9e704a62f28d336507"
|
||||||
@ -5530,11 +5629,11 @@ is-svg@^3.0.0:
|
|||||||
html-comment-regex "^1.1.0"
|
html-comment-regex "^1.1.0"
|
||||||
|
|
||||||
is-svg@^4.2.1:
|
is-svg@^4.2.1:
|
||||||
version "4.2.2"
|
version "4.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.2.2.tgz#a4ea0f3f78dada7085db88f1e85b6f845626cfae"
|
resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-4.3.0.tgz#3e46a45dcdb2780e42a3c8538154d7f7bfc07216"
|
||||||
integrity sha512-JlA7Mc7mfWjdxxTkJ094oUK9amGD7gQaj5xA/NCY0vlVvZ1stmj4VX+bRuwOMN93IHRZ2ctpPH/0FO6DqvQ5Rw==
|
integrity sha512-Np3TOGLVr0J27VDaS/gVE7bT45ZcSmX4pMmMTsPjqO8JY383fuPIcWmZr3QsHVWhqhZWxSdmW+tkkl3PWOB0Nw==
|
||||||
dependencies:
|
dependencies:
|
||||||
html-comment-regex "^1.1.2"
|
fast-xml-parser "^3.19.0"
|
||||||
|
|
||||||
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
is-symbol@^1.0.2, is-symbol@^1.0.3:
|
||||||
version "1.0.3"
|
version "1.0.3"
|
||||||
@ -5714,10 +5813,10 @@ json-schema@0.2.3:
|
|||||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||||
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||||
|
|
||||||
json-schema@^0.2.5:
|
json-schema@^0.4.0:
|
||||||
version "0.2.5"
|
version "0.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.5.tgz#97997f50972dd0500214e208c407efa4b5d7063b"
|
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
|
||||||
integrity sha512-gWJOWYFrhQ8j7pVm0EM8Slr+EPVq1Phf6lvzvD/WCeqkrx/f2xBI0xOsRRS9xCn3I4vKtP519dvs3TP09r24wQ==
|
integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
|
||||||
|
|
||||||
json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
|
json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
@ -5742,11 +5841,9 @@ json5@^1.0.1:
|
|||||||
minimist "^1.2.0"
|
minimist "^1.2.0"
|
||||||
|
|
||||||
json5@^2.1.2, json5@^2.1.3:
|
json5@^2.1.2, json5@^2.1.3:
|
||||||
version "2.1.3"
|
version "2.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43"
|
resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.2.tgz#64471c5bdcc564c18f7c1d4df2e2297f2457c5ab"
|
||||||
integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==
|
integrity sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ==
|
||||||
dependencies:
|
|
||||||
minimist "^1.2.5"
|
|
||||||
|
|
||||||
jsonfile@^4.0.0:
|
jsonfile@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
@ -5915,9 +6012,9 @@ loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3, loader-utils@^1.4
|
|||||||
json5 "^1.0.1"
|
json5 "^1.0.1"
|
||||||
|
|
||||||
loader-utils@^2.0.0:
|
loader-utils@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.0.tgz#e4cace5b816d425a166b5f097e10cd12b36064b0"
|
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c"
|
||||||
integrity sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==
|
integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==
|
||||||
dependencies:
|
dependencies:
|
||||||
big.js "^5.2.2"
|
big.js "^5.2.2"
|
||||||
emojis-list "^3.0.0"
|
emojis-list "^3.0.0"
|
||||||
@ -6135,13 +6232,13 @@ markdown-it-table-of-contents@^0.4.0, markdown-it-table-of-contents@^0.4.4:
|
|||||||
resolved "https://registry.yarnpkg.com/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz#3dc7ce8b8fc17e5981c77cc398d1782319f37fbc"
|
resolved "https://registry.yarnpkg.com/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz#3dc7ce8b8fc17e5981c77cc398d1782319f37fbc"
|
||||||
integrity sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==
|
integrity sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==
|
||||||
|
|
||||||
markdown-it@^11.0.0:
|
markdown-it@^12.3.2:
|
||||||
version "11.0.0"
|
version "12.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-11.0.0.tgz#dbfc30363e43d756ebc52c38586b91b90046b876"
|
resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.3.2.tgz#bf92ac92283fe983fe4de8ff8abfb5ad72cd0c90"
|
||||||
integrity sha512-+CvOnmbSubmQFSA9dKz1BRiaSMV7rhexl3sngKqFyXSagoA3fBdJQ8oZWtRy2knXdpDXaBw44euz37DeJQ9asg==
|
integrity sha512-TchMembfxfNVpHkbtriWltGWc+m3xszaRD0CZup7GFFhzIgQqxIfn3eGj1yZpfuflzPvfkt611B2Q/Bsk1YnGg==
|
||||||
dependencies:
|
dependencies:
|
||||||
argparse "^1.0.7"
|
argparse "^2.0.1"
|
||||||
entities "~2.0.0"
|
entities "~2.1.0"
|
||||||
linkify-it "^3.0.1"
|
linkify-it "^3.0.1"
|
||||||
mdurl "^1.0.1"
|
mdurl "^1.0.1"
|
||||||
uc.micro "^1.0.5"
|
uc.micro "^1.0.5"
|
||||||
@ -6296,6 +6393,11 @@ mime-db@1.44.0, "mime-db@>= 1.43.0 < 2", mime-db@^1.44.0:
|
|||||||
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92"
|
||||||
integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
|
integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==
|
||||||
|
|
||||||
|
mime-db@1.52.0:
|
||||||
|
version "1.52.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
|
||||||
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
|
mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24:
|
||||||
version "2.1.27"
|
version "2.1.27"
|
||||||
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f"
|
||||||
@ -6303,6 +6405,13 @@ mime-types@^2.1.12, mime-types@^2.1.26, mime-types@^2.1.27, mime-types@~2.1.17,
|
|||||||
dependencies:
|
dependencies:
|
||||||
mime-db "1.44.0"
|
mime-db "1.44.0"
|
||||||
|
|
||||||
|
mime-types@~2.1.34:
|
||||||
|
version "2.1.35"
|
||||||
|
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
|
||||||
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
|
dependencies:
|
||||||
|
mime-db "1.52.0"
|
||||||
|
|
||||||
mime@1.6.0:
|
mime@1.6.0:
|
||||||
version "1.6.0"
|
version "1.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
|
||||||
@ -6373,9 +6482,9 @@ minimatch@^3.0.4:
|
|||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
minimist@^1.2.0, minimist@^1.2.5:
|
minimist@^1.2.0, minimist@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.6"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
|
||||||
|
|
||||||
minipass-collect@^1.0.2:
|
minipass-collect@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
@ -6492,10 +6601,10 @@ ms@2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
|
||||||
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
|
||||||
|
|
||||||
ms@2.1.1:
|
ms@2.1.3:
|
||||||
version "2.1.1"
|
version "2.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
|
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
|
||||||
integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
ms@^2.0.0, ms@^2.1.1, ms@^2.1.2:
|
ms@^2.0.0, ms@^2.1.1, ms@^2.1.2:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
@ -6555,7 +6664,12 @@ nanomatch@^1.2.13, nanomatch@^1.2.9:
|
|||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
negotiator@0.6.2, negotiator@^0.6.2:
|
negotiator@0.6.3:
|
||||||
|
version "0.6.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
|
||||||
|
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
|
||||||
|
|
||||||
|
negotiator@^0.6.2:
|
||||||
version "0.6.2"
|
version "0.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb"
|
||||||
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==
|
||||||
@ -6595,10 +6709,10 @@ node-forge@0.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579"
|
||||||
integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
|
integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==
|
||||||
|
|
||||||
node-forge@^0.10.0:
|
node-forge@^1.0.0:
|
||||||
version "0.10.0"
|
version "1.3.0"
|
||||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
|
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2"
|
||||||
integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
|
integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA==
|
||||||
|
|
||||||
node-libs-browser@^2.2.1:
|
node-libs-browser@^2.2.1:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
@ -6776,6 +6890,11 @@ object-inspect@^1.7.0, object-inspect@^1.8.0:
|
|||||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0"
|
||||||
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
|
integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==
|
||||||
|
|
||||||
|
object-inspect@^1.9.0:
|
||||||
|
version "1.12.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
|
||||||
|
integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
|
||||||
|
|
||||||
object-is@^1.0.1, object-is@^1.1.2:
|
object-is@^1.0.1, object-is@^1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6"
|
resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.2.tgz#c5d2e87ff9e119f78b7a088441519e2eec1573b6"
|
||||||
@ -7659,9 +7778,9 @@ postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.26, postcss@^7.0.2
|
|||||||
supports-color "^6.1.0"
|
supports-color "^6.1.0"
|
||||||
|
|
||||||
postcss@^8.2.10:
|
postcss@^8.2.10:
|
||||||
version "8.2.10"
|
version "8.2.13"
|
||||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.10.tgz#ca7a042aa8aff494b334d0ff3e9e77079f6f702b"
|
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.13.tgz#dbe043e26e3c068e45113b1ed6375d2d37e2129f"
|
||||||
integrity sha512-b/h7CPV7QEdrqIxtAf2j31U5ef05uBDuvoXv6L51Q4rcS1jdlXAVKJv+atCFdUXYl9dyTHGyoMzIepwowRJjFw==
|
integrity sha512-FCE5xLH+hjbzRdpbRb1IMCvPv9yZx2QnDarBEYSN0N0HYk+TcXsEhwdFcFb+SRWOKzKGErhIEbBK2ogyLdTtfQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
colorette "^1.2.2"
|
colorette "^1.2.2"
|
||||||
nanoid "^3.1.22"
|
nanoid "^3.1.22"
|
||||||
@ -7706,9 +7825,9 @@ pretty-time@^1.1.0:
|
|||||||
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
|
integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
|
||||||
|
|
||||||
prismjs@^1.13.0, prismjs@^1.20.0:
|
prismjs@^1.13.0, prismjs@^1.20.0:
|
||||||
version "1.25.0"
|
version "1.27.0"
|
||||||
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756"
|
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057"
|
||||||
integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg==
|
integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA==
|
||||||
|
|
||||||
private@^0.1.8:
|
private@^0.1.8:
|
||||||
version "0.1.8"
|
version "0.1.8"
|
||||||
@ -7730,12 +7849,12 @@ promise-inflight@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
|
||||||
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
|
||||||
|
|
||||||
proxy-addr@^2.0.6, proxy-addr@~2.0.5:
|
proxy-addr@^2.0.6, proxy-addr@~2.0.7:
|
||||||
version "2.0.6"
|
version "2.0.7"
|
||||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf"
|
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025"
|
||||||
integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==
|
integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==
|
||||||
dependencies:
|
dependencies:
|
||||||
forwarded "~0.1.2"
|
forwarded "0.2.0"
|
||||||
ipaddr.js "1.9.1"
|
ipaddr.js "1.9.1"
|
||||||
|
|
||||||
prr@^1.0.1, prr@~1.0.1:
|
prr@^1.0.1, prr@~1.0.1:
|
||||||
@ -7826,15 +7945,17 @@ q@^1.1.2, q@^1.5.1:
|
|||||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||||
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=
|
||||||
|
|
||||||
qs@6.7.0:
|
qs@6.9.7:
|
||||||
version "6.7.0"
|
version "6.9.7"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.7.tgz#4610846871485e1e048f44ae3b94033f0e675afe"
|
||||||
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
|
integrity sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==
|
||||||
|
|
||||||
qs@^6.9.4:
|
qs@^6.9.4:
|
||||||
version "6.9.4"
|
version "6.10.3"
|
||||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687"
|
resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e"
|
||||||
integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ==
|
integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ==
|
||||||
|
dependencies:
|
||||||
|
side-channel "^1.0.4"
|
||||||
|
|
||||||
qs@~6.5.2:
|
qs@~6.5.2:
|
||||||
version "6.5.2"
|
version "6.5.2"
|
||||||
@ -7902,13 +8023,13 @@ range-parser@^1.2.1, range-parser@~1.2.1:
|
|||||||
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031"
|
||||||
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==
|
||||||
|
|
||||||
raw-body@2.4.0:
|
raw-body@2.4.3:
|
||||||
version "2.4.0"
|
version "2.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332"
|
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.3.tgz#8f80305d11c2a0a545c2d9d89d7a0286fcead43c"
|
||||||
integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==
|
integrity sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==
|
||||||
dependencies:
|
dependencies:
|
||||||
bytes "3.1.0"
|
bytes "3.1.2"
|
||||||
http-errors "1.7.2"
|
http-errors "1.8.1"
|
||||||
iconv-lite "0.4.24"
|
iconv-lite "0.4.24"
|
||||||
unpipe "1.0.0"
|
unpipe "1.0.0"
|
||||||
|
|
||||||
@ -8261,7 +8382,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||||
|
|
||||||
safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
|
safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
@ -8360,10 +8481,10 @@ semver@^7.3.2:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938"
|
||||||
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==
|
||||||
|
|
||||||
send@0.17.1, send@^0.17.1:
|
send@0.17.2, send@^0.17.1:
|
||||||
version "0.17.1"
|
version "0.17.2"
|
||||||
resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8"
|
resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820"
|
||||||
integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==
|
integrity sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==
|
||||||
dependencies:
|
dependencies:
|
||||||
debug "2.6.9"
|
debug "2.6.9"
|
||||||
depd "~1.1.2"
|
depd "~1.1.2"
|
||||||
@ -8372,9 +8493,9 @@ send@0.17.1, send@^0.17.1:
|
|||||||
escape-html "~1.0.3"
|
escape-html "~1.0.3"
|
||||||
etag "~1.8.1"
|
etag "~1.8.1"
|
||||||
fresh "0.5.2"
|
fresh "0.5.2"
|
||||||
http-errors "~1.7.2"
|
http-errors "1.8.1"
|
||||||
mime "1.6.0"
|
mime "1.6.0"
|
||||||
ms "2.1.1"
|
ms "2.1.3"
|
||||||
on-finished "~2.3.0"
|
on-finished "~2.3.0"
|
||||||
range-parser "~1.2.1"
|
range-parser "~1.2.1"
|
||||||
statuses "~1.5.0"
|
statuses "~1.5.0"
|
||||||
@ -8411,15 +8532,15 @@ serve-index@^1.9.1:
|
|||||||
mime-types "~2.1.17"
|
mime-types "~2.1.17"
|
||||||
parseurl "~1.3.2"
|
parseurl "~1.3.2"
|
||||||
|
|
||||||
serve-static@1.14.1, serve-static@^1.14.1:
|
serve-static@1.14.2, serve-static@^1.14.1:
|
||||||
version "1.14.1"
|
version "1.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9"
|
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa"
|
||||||
integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==
|
integrity sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
encodeurl "~1.0.2"
|
encodeurl "~1.0.2"
|
||||||
escape-html "~1.0.3"
|
escape-html "~1.0.3"
|
||||||
parseurl "~1.3.3"
|
parseurl "~1.3.3"
|
||||||
send "0.17.1"
|
send "0.17.2"
|
||||||
|
|
||||||
set-blocking@^2.0.0:
|
set-blocking@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
@ -8516,13 +8637,14 @@ shebang-regex@^3.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
|
||||||
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
|
||||||
|
|
||||||
side-channel@^1.0.2:
|
side-channel@^1.0.2, side-channel@^1.0.4:
|
||||||
version "1.0.2"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947"
|
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
|
||||||
integrity sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==
|
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
|
||||||
dependencies:
|
dependencies:
|
||||||
es-abstract "^1.17.0-next.1"
|
call-bind "^1.0.0"
|
||||||
object-inspect "^1.7.0"
|
get-intrinsic "^1.0.2"
|
||||||
|
object-inspect "^1.9.0"
|
||||||
|
|
||||||
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
|
signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
|
||||||
version "3.0.3"
|
version "3.0.3"
|
||||||
@ -8754,10 +8876,10 @@ source-map-resolve@^0.6.0:
|
|||||||
atob "^2.1.2"
|
atob "^2.1.2"
|
||||||
decode-uri-component "^0.2.0"
|
decode-uri-component "^0.2.0"
|
||||||
|
|
||||||
source-map-support@^0.5.19, source-map-support@~0.5.12:
|
source-map-support@^0.5.19, source-map-support@~0.5.12, source-map-support@~0.5.20:
|
||||||
version "0.5.19"
|
version "0.5.21"
|
||||||
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61"
|
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
|
||||||
integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==
|
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
|
||||||
dependencies:
|
dependencies:
|
||||||
buffer-from "^1.0.0"
|
buffer-from "^1.0.0"
|
||||||
source-map "^0.6.0"
|
source-map "^0.6.0"
|
||||||
@ -9080,6 +9202,11 @@ strip-json-comments@~2.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||||
|
|
||||||
|
strnum@^1.0.4:
|
||||||
|
version "1.0.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db"
|
||||||
|
integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==
|
||||||
|
|
||||||
stylehacks@^4.0.0, stylehacks@^4.0.3:
|
stylehacks@^4.0.0, stylehacks@^4.0.3:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
|
resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5"
|
||||||
@ -9224,13 +9351,14 @@ terser@^4.1.2:
|
|||||||
source-map-support "~0.5.12"
|
source-map-support "~0.5.12"
|
||||||
|
|
||||||
terser@^5.0.0:
|
terser@^5.0.0:
|
||||||
version "5.0.0"
|
version "5.14.2"
|
||||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.0.0.tgz#269640e4e92f15d628de1e5f01c4c61e1ba3d765"
|
resolved "https://registry.yarnpkg.com/terser/-/terser-5.14.2.tgz#9ac9f22b06994d736174f4091aa368db896f1c10"
|
||||||
integrity sha512-olH2DwGINoSuEpSGd+BsPuAQaA3OrHnHnFL/rDB2TVNc3srUbz/rq/j2BlF4zDXI+JqAvGr86bIm1R2cJgZ3FA==
|
integrity sha512-oL0rGeM/WFQCUd0y2QrWxYnq7tfSuKBiqTjRPWrRgB46WD/kiwHwF8T23z78H6Q6kGCuuHcPB+KULHRdxvVGQA==
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@jridgewell/source-map" "^0.3.2"
|
||||||
|
acorn "^8.5.0"
|
||||||
commander "^2.20.0"
|
commander "^2.20.0"
|
||||||
source-map "~0.6.1"
|
source-map-support "~0.5.20"
|
||||||
source-map-support "~0.5.12"
|
|
||||||
|
|
||||||
text-table@^0.2.0:
|
text-table@^0.2.0:
|
||||||
version "0.2.0"
|
version "0.2.0"
|
||||||
@ -9349,6 +9477,11 @@ toidentifier@1.0.0, toidentifier@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553"
|
||||||
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
|
||||||
|
|
||||||
|
toidentifier@1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
|
||||||
|
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
|
||||||
|
|
||||||
toml@^3.0.0:
|
toml@^3.0.0:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
|
resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee"
|
||||||
@ -9447,7 +9580,7 @@ type-fest@^0.8.1:
|
|||||||
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
|
||||||
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
|
||||||
|
|
||||||
type-is@^1.6.18, type-is@~1.6.17, type-is@~1.6.18:
|
type-is@^1.6.18, type-is@~1.6.18:
|
||||||
version "1.6.18"
|
version "1.6.18"
|
||||||
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
|
||||||
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
|
||||||
@ -9664,9 +9797,9 @@ url-parse-lax@^3.0.0:
|
|||||||
prepend-http "^2.0.0"
|
prepend-http "^2.0.0"
|
||||||
|
|
||||||
url-parse@^1.4.3, url-parse@^1.4.7:
|
url-parse@^1.4.3, url-parse@^1.4.7:
|
||||||
version "1.5.2"
|
version "1.5.9"
|
||||||
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.2.tgz#a4eff6fd5ff9fe6ab98ac1f79641819d13247cda"
|
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.9.tgz#05ff26484a0b5e4040ac64dcee4177223d74675e"
|
||||||
integrity sha512-6bTUPERy1muxxYClbzoRo5qtQuyoGEbzbQvi0SW4/8U8UyVkAQhWFBlnigqJkRm4su4x1zDQfNbEzWkt+vchcg==
|
integrity sha512-HpOvhKBvre8wYez+QhHcYiVvVmeF6DVnuSOOPhe3cTum3BnqHhvKaZm8FU5yTiOu/Jut2ZpB2rA/SbBA1JIGlQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
querystringify "^2.1.1"
|
querystringify "^2.1.1"
|
||||||
requires-port "^1.0.0"
|
requires-port "^1.0.0"
|
||||||
|
@ -685,6 +685,16 @@ module.exports = {
|
|||||||
return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
|
return fetch('post', 'nginx/certificates/' + id + '/renew', undefined, {timeout});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Number} id
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
testHttpChallenge: function (domains) {
|
||||||
|
return fetch('get', 'nginx/certificates/test-http?' + new URLSearchParams({
|
||||||
|
domains: JSON.stringify(domains),
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Number} id
|
* @param {Number} id
|
||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
|
@ -2,6 +2,16 @@
|
|||||||
<div class="card-status bg-teal"></div>
|
<div class="card-status bg-teal"></div>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><%- i18n('audit-log', 'title') %></h3>
|
<h3 class="card-title"><%- i18n('audit-log', 'title') %></h3>
|
||||||
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('audit-log', 'search') %>" aria-label="<%- i18n('audit-log', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body no-padding min-100">
|
<div class="card-body no-padding min-100">
|
||||||
<div class="dimmer active">
|
<div class="dimmer active">
|
||||||
|
@ -12,39 +12,68 @@ module.exports = Mn.View.extend({
|
|||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.AuditLog.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new AuditLogModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showAuditLog();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('audit-log', 'empty'),
|
||||||
|
subtitle: App.i18n('audit-log', 'empty-subtitle')
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
list_region: '@ui.list_region'
|
list_region: '@ui.list_region'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['user'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.AuditLog.getAll(['user'])
|
view.fetch(['user'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed() && response && response.length) {
|
if (!view.isDestroyed() && response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new AuditLogModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
view.showChildView('list_region', new EmptyView({
|
view.showEmpty();
|
||||||
title: App.i18n('audit-log', 'empty'),
|
|
||||||
subtitle: App.i18n('audit-log', 'empty-subtitle')
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showAuditLog();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
@ -366,6 +366,19 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Certificate Test Reachability
|
||||||
|
*
|
||||||
|
* @param model
|
||||||
|
*/
|
||||||
|
showNginxCertificateTestReachability: function (model) {
|
||||||
|
if (Cache.User.isAdmin() || Cache.User.canManage('certificates')) {
|
||||||
|
require(['./main', './nginx/certificates/test'], function (App, View) {
|
||||||
|
App.UI.showModalDialog(new View({model: model}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Audit Log
|
* Audit Log
|
||||||
*/
|
*/
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><%- i18n('access-lists', 'title') %></h3>
|
<h3 class="card-title"><%- i18n('access-lists', 'title') %></h3>
|
||||||
<div class="card-options">
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('access-lists', 'search') %>" aria-label="<%- i18n('access-lists', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
<% if (showAddButton) { %>
|
<% if (showAddButton) { %>
|
||||||
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-item"><%- i18n('access-lists', 'add') %></a>
|
<a href="#" class="btn btn-outline-teal btn-sm ml-2 add-item"><%- i18n('access-lists', 'add') %></a>
|
||||||
|
@ -14,7 +14,44 @@ module.exports = Mn.View.extend({
|
|||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add: '.add-item',
|
add: '.add-item',
|
||||||
help: '.help',
|
help: '.help',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.Nginx.AccessLists.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new AccessListModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxAccess();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
let manage = App.Cache.User.canManage('access_lists');
|
||||||
|
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('access-lists', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('access-lists', 'add') : null,
|
||||||
|
btn_color: 'teal',
|
||||||
|
permission: 'access_lists',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxAccessListForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
@ -30,6 +67,17 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.help': function (e) {
|
'click @ui.help': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showHelp(App.i18n('access-lists', 'help-title'), App.i18n('access-lists', 'help-content'));
|
App.Controller.showHelp(App.i18n('access-lists', 'help-title'), App.i18n('access-lists', 'help-content'));
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['owner', 'items', 'clients'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -40,39 +88,18 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.Nginx.AccessLists.getAll(['owner', 'items', 'clients'])
|
view.fetch(['owner', 'items', 'clients'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed()) {
|
if (!view.isDestroyed()) {
|
||||||
if (response && response.length) {
|
if (response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new AccessListModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
let manage = App.Cache.User.canManage('access_lists');
|
view.showEmpty();
|
||||||
|
|
||||||
view.showChildView('list_region', new EmptyView({
|
|
||||||
title: App.i18n('access-lists', 'empty'),
|
|
||||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
|
||||||
link: manage ? App.i18n('access-lists', 'add') : null,
|
|
||||||
btn_color: 'teal',
|
|
||||||
permission: 'access_lists',
|
|
||||||
action: function () {
|
|
||||||
App.Controller.showNginxAccessListForm();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showNginxAccess();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
@ -18,6 +18,14 @@
|
|||||||
<input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>" required>
|
<input type="text" name="domain_names" class="form-control" id="input-domains" value="<%- domain_names.join(',') %>" required>
|
||||||
<div class="text-blue"><i class="fe fe-alert-triangle"></i> <%- i18n('ssl', 'hosts-warning') %></div>
|
<div class="text-blue"><i class="fe fe-alert-triangle"></i> <%- i18n('ssl', 'hosts-warning') %></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="mb-3 test-domains-container">
|
||||||
|
<button type="button" class="btn btn-secondary test-domains col-sm-12"><%- i18n('certificates', 'test-reachability') %></button>
|
||||||
|
<div class="text-secondary small">
|
||||||
|
<i class="fe fe-info"></i>
|
||||||
|
<%- i18n('certificates', 'reachability-info') %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -29,6 +29,8 @@ module.exports = Mn.View.extend({
|
|||||||
non_loader_content: '.non-loader-content',
|
non_loader_content: '.non-loader-content',
|
||||||
le_error_info: '#le-error-info',
|
le_error_info: '#le-error-info',
|
||||||
domain_names: 'input[name="domain_names"]',
|
domain_names: 'input[name="domain_names"]',
|
||||||
|
test_domains_container: '.test-domains-container',
|
||||||
|
test_domains_button: '.test-domains',
|
||||||
buttons: '.modal-footer button',
|
buttons: '.modal-footer button',
|
||||||
cancel: 'button.cancel',
|
cancel: 'button.cancel',
|
||||||
save: 'button.save',
|
save: 'button.save',
|
||||||
@ -56,10 +58,12 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.dns_provider_credentials.prop('required', 'required');
|
this.ui.dns_provider_credentials.prop('required', 'required');
|
||||||
}
|
}
|
||||||
this.ui.dns_challenge_content.show();
|
this.ui.dns_challenge_content.show();
|
||||||
|
this.ui.test_domains_container.hide();
|
||||||
} else {
|
} else {
|
||||||
this.ui.dns_provider.prop('required', false);
|
this.ui.dns_provider.prop('required', false);
|
||||||
this.ui.dns_provider_credentials.prop('required', false);
|
this.ui.dns_provider_credentials.prop('required', false);
|
||||||
this.ui.dns_challenge_content.hide();
|
this.ui.dns_challenge_content.hide();
|
||||||
|
this.ui.test_domains_container.show();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -205,6 +209,23 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.non_loader_content.show();
|
this.ui.non_loader_content.show();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
'click @ui.test_domains_button': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
const domainNames = this.ui.domain_names[0].value.split(',');
|
||||||
|
if (domainNames && domainNames.length > 0) {
|
||||||
|
this.model.set('domain_names', domainNames);
|
||||||
|
this.model.set('back_to_add', true);
|
||||||
|
App.Controller.showNginxCertificateTestReachability(this.model);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'change @ui.domain_names': function(e){
|
||||||
|
const domainNames = e.target.value.split(',');
|
||||||
|
if (domainNames && domainNames.length > 0) {
|
||||||
|
this.ui.test_domains_button.prop('disabled', false);
|
||||||
|
} else {
|
||||||
|
this.ui.test_domains_button.prop('disabled', true);
|
||||||
|
}
|
||||||
|
},
|
||||||
'change @ui.other_certificate_key': function(e){
|
'change @ui.other_certificate_key': function(e){
|
||||||
this.setFileName("other_certificate_key_label", e)
|
this.setFileName("other_certificate_key_label", e)
|
||||||
},
|
},
|
||||||
@ -257,6 +278,12 @@ module.exports = Mn.View.extend({
|
|||||||
this.ui.credentials_file_content.hide();
|
this.ui.credentials_file_content.hide();
|
||||||
this.ui.loader_content.hide();
|
this.ui.loader_content.hide();
|
||||||
this.ui.le_error_info.hide();
|
this.ui.le_error_info.hide();
|
||||||
|
if (this.ui.domain_names[0]) {
|
||||||
|
const domainNames = this.ui.domain_names[0].value.split(',');
|
||||||
|
if (!domainNames || domainNames.length === 0 || (domainNames.length === 1 && domainNames[0] === "")) {
|
||||||
|
this.ui.test_domains_button.prop('disabled', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
|
@ -42,6 +42,9 @@
|
|||||||
<% if (provider === 'letsencrypt') { %>
|
<% if (provider === 'letsencrypt') { %>
|
||||||
<a href="#" class="renew dropdown-item"><i class="dropdown-icon fe fe-refresh-cw"></i> <%- i18n('certificates', 'force-renew') %></a>
|
<a href="#" class="renew dropdown-item"><i class="dropdown-icon fe fe-refresh-cw"></i> <%- i18n('certificates', 'force-renew') %></a>
|
||||||
<a href="#" class="download dropdown-item"><i class="dropdown-icon fe fe-download"></i> <%- i18n('certificates', 'download') %></a>
|
<a href="#" class="download dropdown-item"><i class="dropdown-icon fe fe-download"></i> <%- i18n('certificates', 'download') %></a>
|
||||||
|
<% if (meta.dns_challenge === false) { %>
|
||||||
|
<a href="#" class="test dropdown-item"><i class="dropdown-icon fe fe-globe"></i> <%- i18n('certificates', 'test-reachability') %></a>
|
||||||
|
<% } %>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<% } %>
|
<% } %>
|
||||||
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
<a href="#" class="delete dropdown-item"><i class="dropdown-icon fe fe-trash-2"></i> <%- i18n('str', 'delete') %></a>
|
||||||
|
@ -2,7 +2,7 @@ const Mn = require('backbone.marionette');
|
|||||||
const moment = require('moment');
|
const moment = require('moment');
|
||||||
const App = require('../../../main');
|
const App = require('../../../main');
|
||||||
const template = require('./item.ejs');
|
const template = require('./item.ejs');
|
||||||
const dns_providers = require('../../../../../../global/certbot-dns-plugins')
|
const dns_providers = require('../../../../../../global/certbot-dns-plugins');
|
||||||
|
|
||||||
module.exports = Mn.View.extend({
|
module.exports = Mn.View.extend({
|
||||||
template: template,
|
template: template,
|
||||||
@ -12,7 +12,8 @@ module.exports = Mn.View.extend({
|
|||||||
host_link: '.host-link',
|
host_link: '.host-link',
|
||||||
renew: 'a.renew',
|
renew: 'a.renew',
|
||||||
delete: 'a.delete',
|
delete: 'a.delete',
|
||||||
download: 'a.download'
|
download: 'a.download',
|
||||||
|
test: 'a.test'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
@ -31,11 +32,16 @@ module.exports = Mn.View.extend({
|
|||||||
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
let win = window.open($(e.currentTarget).attr('rel'), '_blank');
|
||||||
win.focus();
|
win.focus();
|
||||||
},
|
},
|
||||||
|
|
||||||
'click @ui.download': function (e) {
|
'click @ui.download': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Api.Nginx.Certificates.download(this.model.get('id'))
|
App.Api.Nginx.Certificates.download(this.model.get('id'));
|
||||||
}
|
},
|
||||||
|
|
||||||
|
'click @ui.test': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
App.Controller.showNginxCertificateTestReachability(this.model);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
templateContext: {
|
templateContext: {
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><%- i18n('certificates', 'title') %></h3>
|
<h3 class="card-title"><%- i18n('certificates', 'title') %></h3>
|
||||||
<div class="card-options">
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('certificates', 'search') %>" aria-label="<%- i18n('certificates', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
<% if (showAddButton) { %>
|
<% if (showAddButton) { %>
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
|
@ -14,7 +14,44 @@ module.exports = Mn.View.extend({
|
|||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add: '.add-item',
|
add: '.add-item',
|
||||||
help: '.help',
|
help: '.help',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.Nginx.Certificates.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new CertificateModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxCertificates();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
let manage = App.Cache.User.canManage('certificates');
|
||||||
|
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('certificates', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('certificates', 'add') : null,
|
||||||
|
btn_color: 'pink',
|
||||||
|
permission: 'certificates',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxCertificateForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
@ -31,6 +68,17 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.help': function (e) {
|
'click @ui.help': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showHelp(App.i18n('certificates', 'help-title'), App.i18n('certificates', 'help-content'));
|
App.Controller.showHelp(App.i18n('certificates', 'help-title'), App.i18n('certificates', 'help-content'));
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['owner'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -41,39 +89,18 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.Nginx.Certificates.getAll(['owner'])
|
view.fetch(['owner'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed()) {
|
if (!view.isDestroyed()) {
|
||||||
if (response && response.length) {
|
if (response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new CertificateModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
let manage = App.Cache.User.canManage('certificates');
|
view.showEmpty();
|
||||||
|
|
||||||
view.showChildView('list_region', new EmptyView({
|
|
||||||
title: App.i18n('certificates', 'empty'),
|
|
||||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
|
||||||
link: manage ? App.i18n('certificates', 'add') : null,
|
|
||||||
btn_color: 'pink',
|
|
||||||
permission: 'certificates',
|
|
||||||
action: function () {
|
|
||||||
App.Controller.showNginxCertificateForm();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showNginxCertificates();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
15
frontend/js/app/nginx/certificates/test.ejs
Normal file
15
frontend/js/app/nginx/certificates/test.ejs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title"><%- i18n('certificates', 'reachability-title') %></h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div class="waiting text-center">
|
||||||
|
<%= i18n('str', 'please-wait') %>
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-danger error" role="alert"></div>
|
||||||
|
<div class="alert alert-success success" role="alert"></div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary cancel" disabled><%- i18n('str', 'close') %></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
75
frontend/js/app/nginx/certificates/test.js
Normal file
75
frontend/js/app/nginx/certificates/test.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
const Mn = require('backbone.marionette');
|
||||||
|
const App = require('../../main');
|
||||||
|
const template = require('./test.ejs');
|
||||||
|
|
||||||
|
module.exports = Mn.View.extend({
|
||||||
|
template: template,
|
||||||
|
className: 'modal-dialog',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
waiting: '.waiting',
|
||||||
|
error: '.error',
|
||||||
|
success: '.success',
|
||||||
|
close: 'button.cancel'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'click @ui.close': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
if (this.model.get('back_to_add')) {
|
||||||
|
App.Controller.showNginxCertificateForm(this.model);
|
||||||
|
} else {
|
||||||
|
App.UI.closeModal();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.ui.error.hide();
|
||||||
|
this.ui.success.hide();
|
||||||
|
|
||||||
|
App.Api.Nginx.Certificates.testHttpChallenge(this.model.get('domain_names'))
|
||||||
|
.then((result) => {
|
||||||
|
let allOk = true;
|
||||||
|
let text = '';
|
||||||
|
|
||||||
|
for (const domain in result) {
|
||||||
|
const status = result[domain];
|
||||||
|
if (status === 'ok') {
|
||||||
|
text += `<p><strong>${domain}:</strong> ${App.i18n('certificates', 'reachability-ok')}</p>`;
|
||||||
|
} else {
|
||||||
|
allOk = false;
|
||||||
|
if (status === 'no-host') {
|
||||||
|
text += `<p><strong>${domain}:</strong> ${App.i18n('certificates', 'reachability-not-resolved')}</p>`;
|
||||||
|
} else if (status === 'failed') {
|
||||||
|
text += `<p><strong>${domain}:</strong> ${App.i18n('certificates', 'reachability-failed-to-check')}</p>`;
|
||||||
|
} else if (status === '404') {
|
||||||
|
text += `<p><strong>${domain}:</strong> ${App.i18n('certificates', 'reachability-404')}</p>`;
|
||||||
|
} else if (status === 'wrong-data') {
|
||||||
|
text += `<p><strong>${domain}:</strong> ${App.i18n('certificates', 'reachability-wrong-data')}</p>`;
|
||||||
|
} else if (status.startsWith('other:')) {
|
||||||
|
const code = status.substring(6);
|
||||||
|
text += `<p><strong>${domain}:</strong> ${App.i18n('certificates', 'reachability-other', {code})}</p>`;
|
||||||
|
} else {
|
||||||
|
// This should never happen
|
||||||
|
text += `<p><strong>${domain}:</strong> ?</p>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.ui.waiting.hide();
|
||||||
|
if (allOk) {
|
||||||
|
this.ui.success.html(text).show();
|
||||||
|
} else {
|
||||||
|
this.ui.error.html(text).show();
|
||||||
|
}
|
||||||
|
this.ui.close.prop('disabled', false);
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
console.error(e);
|
||||||
|
this.ui.waiting.hide();
|
||||||
|
this.ui.error.text(App.i18n('certificates', 'reachability-failed-to-reach-api')).show();
|
||||||
|
this.ui.close.prop('disabled', false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
@ -7,7 +7,7 @@
|
|||||||
<form>
|
<form>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<%= i18n('dead-hosts', 'delete-confirm', {domains: domain_names.join(', ')}) %>
|
<%= i18n('dead-hosts', 'delete-confirm', {domains: domain_names.join(', ').toHtmlEntities()}) %>
|
||||||
<% if (certificate_id) { %>
|
<% if (certificate_id) { %>
|
||||||
<br><br>
|
<br><br>
|
||||||
<%- i18n('ssl', 'delete-ssl') %>
|
<%- i18n('ssl', 'delete-ssl') %>
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><%- i18n('dead-hosts', 'title') %></h3>
|
<h3 class="card-title"><%- i18n('dead-hosts', 'title') %></h3>
|
||||||
<div class="card-options">
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('dead-hosts', 'search') %>" aria-label="<%- i18n('dead-hosts', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
<% if (showAddButton) { %>
|
<% if (showAddButton) { %>
|
||||||
<a href="#" class="btn btn-outline-danger btn-sm ml-2 add-item"><%- i18n('dead-hosts', 'add') %></a>
|
<a href="#" class="btn btn-outline-danger btn-sm ml-2 add-item"><%- i18n('dead-hosts', 'add') %></a>
|
||||||
|
@ -14,7 +14,44 @@ module.exports = Mn.View.extend({
|
|||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add: '.add-item',
|
add: '.add-item',
|
||||||
help: '.help',
|
help: '.help',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.Nginx.DeadHosts.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new DeadHostModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxDead();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
let manage = App.Cache.User.canManage('dead_hosts');
|
||||||
|
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('dead-hosts', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('dead-hosts', 'add') : null,
|
||||||
|
btn_color: 'danger',
|
||||||
|
permission: 'dead_hosts',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxDeadForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
@ -30,6 +67,17 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.help': function (e) {
|
'click @ui.help': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showHelp(App.i18n('dead-hosts', 'help-title'), App.i18n('dead-hosts', 'help-content'));
|
App.Controller.showHelp(App.i18n('dead-hosts', 'help-title'), App.i18n('dead-hosts', 'help-content'));
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['owner', 'certificate'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -40,39 +88,18 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.Nginx.DeadHosts.getAll(['owner', 'certificate'])
|
view.fetch(['owner', 'certificate'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed()) {
|
if (!view.isDestroyed()) {
|
||||||
if (response && response.length) {
|
if (response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new DeadHostModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
let manage = App.Cache.User.canManage('dead_hosts');
|
view.showEmpty();
|
||||||
|
|
||||||
view.showChildView('list_region', new EmptyView({
|
|
||||||
title: App.i18n('dead-hosts', 'empty'),
|
|
||||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
|
||||||
link: manage ? App.i18n('dead-hosts', 'add') : null,
|
|
||||||
btn_color: 'danger',
|
|
||||||
permission: 'dead_hosts',
|
|
||||||
action: function () {
|
|
||||||
App.Controller.showNginxDeadForm();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showNginxDead();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<form>
|
<form>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<%= i18n('proxy-hosts', 'delete-confirm', {domains: domain_names.join(', ')}) %>
|
<%= i18n('proxy-hosts', 'delete-confirm', {domains: domain_names.join(', ').toHtmlEntities()}) %>
|
||||||
<% if (certificate_id) { %>
|
<% if (certificate_id) { %>
|
||||||
<br><br>
|
<br><br>
|
||||||
<%- i18n('ssl', 'delete-ssl') %>
|
<%- i18n('ssl', 'delete-ssl') %>
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><%- i18n('proxy-hosts', 'title') %></h3>
|
<h3 class="card-title"><%- i18n('proxy-hosts', 'title') %></h3>
|
||||||
<div class="card-options">
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('proxy-hosts', 'search') %>" aria-label="<%- i18n('proxy-hosts', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
<% if (showAddButton) { %>
|
<% if (showAddButton) { %>
|
||||||
<a href="#" class="btn btn-outline-success btn-sm ml-2 add-item"><%- i18n('proxy-hosts', 'add') %></a>
|
<a href="#" class="btn btn-outline-success btn-sm ml-2 add-item"><%- i18n('proxy-hosts', 'add') %></a>
|
||||||
|
@ -14,7 +14,44 @@ module.exports = Mn.View.extend({
|
|||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add: '.add-item',
|
add: '.add-item',
|
||||||
help: '.help',
|
help: '.help',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.Nginx.ProxyHosts.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new ProxyHostModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxProxy();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
let manage = App.Cache.User.canManage('proxy_hosts');
|
||||||
|
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('proxy-hosts', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('proxy-hosts', 'add') : null,
|
||||||
|
btn_color: 'success',
|
||||||
|
permission: 'proxy_hosts',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxProxyForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
@ -30,6 +67,17 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.help': function (e) {
|
'click @ui.help': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showHelp(App.i18n('proxy-hosts', 'help-title'), App.i18n('proxy-hosts', 'help-content'));
|
App.Controller.showHelp(App.i18n('proxy-hosts', 'help-title'), App.i18n('proxy-hosts', 'help-content'));
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['owner', 'access_list', 'certificate'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -40,39 +88,18 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.Nginx.ProxyHosts.getAll(['owner', 'access_list', 'certificate'])
|
view.fetch(['owner', 'access_list', 'certificate'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed()) {
|
if (!view.isDestroyed()) {
|
||||||
if (response && response.length) {
|
if (response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new ProxyHostModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
let manage = App.Cache.User.canManage('proxy_hosts');
|
view.showEmpty();
|
||||||
|
|
||||||
view.showChildView('list_region', new EmptyView({
|
|
||||||
title: App.i18n('proxy-hosts', 'empty'),
|
|
||||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
|
||||||
link: manage ? App.i18n('proxy-hosts', 'add') : null,
|
|
||||||
btn_color: 'success',
|
|
||||||
permission: 'proxy_hosts',
|
|
||||||
action: function () {
|
|
||||||
App.Controller.showNginxProxyForm();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showNginxProxy();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<form>
|
<form>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 col-md-12">
|
<div class="col-sm-12 col-md-12">
|
||||||
<%= i18n('redirection-hosts', 'delete-confirm', {domains: domain_names.join(', ')}) %>
|
<%= i18n('redirection-hosts', 'delete-confirm', {domains: domain_names.join(', ').toHtmlEntities()}) %>
|
||||||
<% if (certificate_id) { %>
|
<% if (certificate_id) { %>
|
||||||
<br><br>
|
<br><br>
|
||||||
<%- i18n('ssl', 'delete-ssl') %>
|
<%- i18n('ssl', 'delete-ssl') %>
|
||||||
|
@ -1,11 +1,19 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-status bg-yellow"></div>
|
<div class="card-status bg-yellow"></div>
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title">Redirection Hosts</h3>
|
<h3 class="card-title"><%- i18n('redirection-hosts', 'title') %></h3>
|
||||||
<div class="card-options">
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('redirection-hosts', 'search') %>" aria-label="<%- i18n('redirection-hosts', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
<% if (showAddButton) { %>
|
<% if (showAddButton) { %>
|
||||||
<a href="#" class="btn btn-outline-yellow btn-sm ml-2 add-item">Add Redirection Host</a>
|
<a href="#" class="btn btn-outline-yellow btn-sm ml-2 add-item"><%- i18n('redirection-hosts', 'add') %></a>
|
||||||
<% } %>
|
<% } %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -14,7 +14,43 @@ module.exports = Mn.View.extend({
|
|||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add: '.add-item',
|
add: '.add-item',
|
||||||
help: '.help',
|
help: '.help',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.Nginx.RedirectionHosts.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new RedirectionHostModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxRedirection();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
let manage = App.Cache.User.canManage('redirection_hosts');
|
||||||
|
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('redirection-hosts', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('redirection-hosts', 'add') : null,
|
||||||
|
btn_color: 'yellow',
|
||||||
|
permission: 'redirection_hosts',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxRedirectionForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
@ -30,6 +66,17 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.help': function (e) {
|
'click @ui.help': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showHelp(App.i18n('redirection-hosts', 'help-title'), App.i18n('redirection-hosts', 'help-content'));
|
App.Controller.showHelp(App.i18n('redirection-hosts', 'help-title'), App.i18n('redirection-hosts', 'help-content'));
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['owner', 'certificate'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -40,39 +87,18 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.Nginx.RedirectionHosts.getAll(['owner', 'certificate'])
|
view.fetch(['owner', 'certificate'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed()) {
|
if (!view.isDestroyed()) {
|
||||||
if (response && response.length) {
|
if (response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new RedirectionHostModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
let manage = App.Cache.User.canManage('redirection_hosts');
|
view.showEmpty();
|
||||||
|
|
||||||
view.showChildView('list_region', new EmptyView({
|
|
||||||
title: App.i18n('redirection-hosts', 'empty'),
|
|
||||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
|
||||||
link: manage ? App.i18n('redirection-hosts', 'add') : null,
|
|
||||||
btn_color: 'yellow',
|
|
||||||
permission: 'redirection_hosts',
|
|
||||||
action: function () {
|
|
||||||
App.Controller.showNginxRedirectionForm();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showNginxRedirection();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
@ -3,6 +3,14 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title"><%- i18n('streams', 'title') %></h3>
|
<h3 class="card-title"><%- i18n('streams', 'title') %></h3>
|
||||||
<div class="card-options">
|
<div class="card-options">
|
||||||
|
<form class="search-form" role="search">
|
||||||
|
<div class="input-icon">
|
||||||
|
<span class="input-icon-addon">
|
||||||
|
<i class="fe fe-search"></i>
|
||||||
|
</span>
|
||||||
|
<input name="source-query" type="text" value="" class="form-control form-control-sm" placeholder="<%- i18n('streams', 'search') %>" aria-label="<%- i18n('streams', 'search') %>">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
<a href="#" class="btn btn-outline-secondary btn-sm ml-2 help"><i class="fe fe-help-circle"></i></a>
|
||||||
<% if (showAddButton) { %>
|
<% if (showAddButton) { %>
|
||||||
<a href="#" class="btn btn-outline-blue btn-sm ml-2 add-item"><%- i18n('streams', 'add') %></a>
|
<a href="#" class="btn btn-outline-blue btn-sm ml-2 add-item"><%- i18n('streams', 'add') %></a>
|
||||||
|
@ -14,7 +14,44 @@ module.exports = Mn.View.extend({
|
|||||||
list_region: '.list-region',
|
list_region: '.list-region',
|
||||||
add: '.add-item',
|
add: '.add-item',
|
||||||
help: '.help',
|
help: '.help',
|
||||||
dimmer: '.dimmer'
|
dimmer: '.dimmer',
|
||||||
|
search: '.search-form',
|
||||||
|
query: 'input[name="source-query"]'
|
||||||
|
},
|
||||||
|
|
||||||
|
fetch: App.Api.Nginx.Streams.getAll,
|
||||||
|
|
||||||
|
showData: function(response) {
|
||||||
|
this.showChildView('list_region', new ListView({
|
||||||
|
collection: new StreamModel.Collection(response)
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
showError: function(err) {
|
||||||
|
this.showChildView('list_region', new ErrorView({
|
||||||
|
code: err.code,
|
||||||
|
message: err.message,
|
||||||
|
retry: function () {
|
||||||
|
App.Controller.showNginxStream();
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
|
},
|
||||||
|
|
||||||
|
showEmpty: function() {
|
||||||
|
let manage = App.Cache.User.canManage('streams');
|
||||||
|
|
||||||
|
this.showChildView('list_region', new EmptyView({
|
||||||
|
title: App.i18n('streams', 'empty'),
|
||||||
|
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
||||||
|
link: manage ? App.i18n('streams', 'add') : null,
|
||||||
|
btn_color: 'blue',
|
||||||
|
permission: 'streams',
|
||||||
|
action: function () {
|
||||||
|
App.Controller.showNginxStreamForm();
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
@ -30,6 +67,17 @@ module.exports = Mn.View.extend({
|
|||||||
'click @ui.help': function (e) {
|
'click @ui.help': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
App.Controller.showHelp(App.i18n('streams', 'help-title'), App.i18n('streams', 'help-content'));
|
App.Controller.showHelp(App.i18n('streams', 'help-title'), App.i18n('streams', 'help-content'));
|
||||||
|
},
|
||||||
|
|
||||||
|
'submit @ui.search': function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
let query = this.ui.query.val();
|
||||||
|
|
||||||
|
this.fetch(['owner'], query)
|
||||||
|
.then(response => this.showData(response))
|
||||||
|
.catch(err => {
|
||||||
|
this.showError(err);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -40,39 +88,18 @@ module.exports = Mn.View.extend({
|
|||||||
onRender: function () {
|
onRender: function () {
|
||||||
let view = this;
|
let view = this;
|
||||||
|
|
||||||
App.Api.Nginx.Streams.getAll(['owner'])
|
view.fetch(['owner'])
|
||||||
.then(response => {
|
.then(response => {
|
||||||
if (!view.isDestroyed()) {
|
if (!view.isDestroyed()) {
|
||||||
if (response && response.length) {
|
if (response && response.length) {
|
||||||
view.showChildView('list_region', new ListView({
|
view.showData(response);
|
||||||
collection: new StreamModel.Collection(response)
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
let manage = App.Cache.User.canManage('streams');
|
view.showEmpty();
|
||||||
|
|
||||||
view.showChildView('list_region', new EmptyView({
|
|
||||||
title: App.i18n('streams', 'empty'),
|
|
||||||
subtitle: App.i18n('all-hosts', 'empty-subtitle', {manage: manage}),
|
|
||||||
link: manage ? App.i18n('streams', 'add') : null,
|
|
||||||
btn_color: 'blue',
|
|
||||||
permission: 'streams',
|
|
||||||
action: function () {
|
|
||||||
App.Controller.showNginxStreamForm();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
view.showChildView('list_region', new ErrorView({
|
view.showError(err);
|
||||||
code: err.code,
|
|
||||||
message: err.message,
|
|
||||||
retry: function () {
|
|
||||||
App.Controller.showNginxStream();
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.error(err);
|
|
||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
view.ui.dimmer.removeClass('active');
|
view.ui.dimmer.removeClass('active');
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<div class="row align-items-center">
|
<div class="row align-items-center">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<ul class="list-inline list-inline-dots mb-0">
|
<ul class="list-inline list-inline-dots mb-0">
|
||||||
<li class="list-inline-item"><a href="https://github.com/jc21/nginx-proxy-manager?utm_source=nginx-proxy-manager"><%- i18n('footer', 'fork-me') %></a></li>
|
<li class="list-inline-item"><a href="https://github.com/jc21/nginx-proxy-manager?utm_source=nginx-proxy-manager" target="_blank"><%- i18n('footer', 'fork-me') %></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user