mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge pull request #1352 from bunkerity/dev
Merge branch "dev" into branch "staging"
This commit is contained in:
commit
e3bc7150f1
32 changed files with 243 additions and 228 deletions
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
|
|
@ -21,7 +21,7 @@ jobs:
|
|||
- name: Checkout repository
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up Python 3.9
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
|
||||
if: matrix.language == 'python'
|
||||
with:
|
||||
python-version: "3.9"
|
||||
|
|
|
|||
2
.github/workflows/container-build.yml
vendored
2
.github/workflows/container-build.yml
vendored
|
|
@ -117,7 +117,7 @@ jobs:
|
|||
# Check OS vulnerabilities
|
||||
- name: Check OS vulnerabilities
|
||||
if: ${{ inputs.CACHE_SUFFIX != 'arm' }}
|
||||
uses: aquasecurity/trivy-action@7c2007bcb556501da015201bcba5aa14069b74e2 # v0.23.0
|
||||
uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # v0.24.0
|
||||
with:
|
||||
vuln-type: os
|
||||
skip-dirs: /root/.cargo
|
||||
|
|
|
|||
4
.github/workflows/doc-to-pdf.yml
vendored
4
.github/workflows/doc-to-pdf.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
- name: Checkout source code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install doc dependencies
|
||||
|
|
@ -23,7 +23,7 @@ jobs:
|
|||
- name: Install chromium
|
||||
run: sudo apt install chromium-browser
|
||||
- name: Install node
|
||||
uses: actions/setup-node@60edb5dd545a775178f52524783378180af0d1f8 # v4.0.2
|
||||
uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3
|
||||
with:
|
||||
node-version: 18
|
||||
- name: Install puppeteer
|
||||
|
|
|
|||
6
.github/workflows/linux-build.yml
vendored
6
.github/workflows/linux-build.yml
vendored
|
|
@ -123,9 +123,9 @@ jobs:
|
|||
if: startsWith(env.ARCH, 'arm') == true
|
||||
run: |
|
||||
docker save local/bunkerweb-${{ inputs.LINUX }}:latest | ssh -C root@arm docker load
|
||||
scp ./src/linux/package.sh root@arm:/opt
|
||||
ssh root@arm chmod +x /opt/package.sh
|
||||
ssh root@arm /opt/package.sh ${{ inputs.LINUX }} ${{ env.LARCH }} "$(cat src/VERSION | tr -d '\n')"
|
||||
scp ./src/linux/package.sh root@arm:/opt/package_${{ inputs.LINUX }}.sh
|
||||
ssh root@arm chmod +x /opt/package_${{ inputs.LINUX }}.sh
|
||||
ssh root@arm /opt/package_${{ inputs.LINUX }}.sh ${{ inputs.LINUX }} ${{ env.LARCH }} "$(cat src/VERSION | tr -d '\n')"
|
||||
scp -r root@arm:/root/package-${{ inputs.LINUX }} ./package-${{ inputs.LINUX }}
|
||||
env:
|
||||
LARCH: ${{ env.LARCH }}
|
||||
|
|
|
|||
2
.github/workflows/push-doc.yml
vendored
2
.github/workflows/push-doc.yml
vendored
|
|
@ -29,7 +29,7 @@ jobs:
|
|||
run: |
|
||||
git config --global user.name "BunkerBot"
|
||||
git config --global user.email "bunkerbot@bunkerity.com"
|
||||
- uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
- uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
|
||||
with:
|
||||
python-version: "3.10"
|
||||
- name: Install doc dependencies
|
||||
|
|
|
|||
2
.github/workflows/push-packagecloud.yml
vendored
2
.github/workflows/push-packagecloud.yml
vendored
|
|
@ -42,7 +42,7 @@ jobs:
|
|||
- name: Check out repository code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Install ruby
|
||||
uses: ruby/setup-ruby@3a77c29278ae80936b4cb030fefc7d21c96c786f # v1.185.0
|
||||
uses: ruby/setup-ruby@161cd54b698f1fb3ea539faab2e036d409550e3c # v1.187.0
|
||||
with:
|
||||
ruby-version: "3.0"
|
||||
- name: Install packagecloud
|
||||
|
|
|
|||
2
.github/workflows/staging-create-infra.yml
vendored
2
.github/workflows/staging-create-infra.yml
vendored
|
|
@ -30,7 +30,7 @@ jobs:
|
|||
with:
|
||||
version: "v1.29.1"
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
|
||||
if: inputs.TYPE != 'k8s'
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
|
|
|||
2
.github/workflows/test-core-linux.yml
vendored
2
.github/workflows/test-core-linux.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
- name: Checkout source code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Install Firefox manually and dependencies
|
||||
|
|
|
|||
2
.github/workflows/tests-ui-linux.yml
vendored
2
.github/workflows/tests-ui-linux.yml
vendored
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
- name: Checkout source code
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
|
||||
- name: Set up Python 3.12
|
||||
uses: actions/setup-python@82c7e631bb3cdc910f68e0081d67478d79c6982d # v5.1.0
|
||||
uses: actions/setup-python@39cd14951b08e74b54015e9e001cdefcf80e669f # v5.1.1
|
||||
with:
|
||||
python-version: "3.12"
|
||||
- name: Install Firefox manually and dependencies
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ repos:
|
|||
- id: codespell
|
||||
name: Codespell Spell Checker
|
||||
exclude: (^src/(ui/templates|common/core/.+/files|bw/loading)/.+.html|modsecurity-rules.conf.*|src/ui/static/js/lottie-web.min.js)$
|
||||
entry: codespell --ignore-regex="(tabEl|Widgits)" --skip src/ui/static/js/utils/flatpickr.js,src/ui/static/css/style.css,CHANGELOG.md
|
||||
entry: codespell --ignore-regex="(tabEl|Widgits)" --skip src/ui/static/js/utils/flatpickr.js,src/ui/static/css/style.css,CHANGELOG.md,CODE_OF_CONDUCT.md
|
||||
language: python
|
||||
types: [text]
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
- [BUGFIX] Fix issues with kubernetes integration when were setting a global multisite setting it was not applied to the services
|
||||
- [UI] Update web UI setup wizard to handle when a reverse proxy already exists but no admin user is configured
|
||||
- [UI] Fix issues with multiple settings on the global_config not being able to be deleted in specific cases
|
||||
- [AUTOCONF] Fix issues with globally set settings overridden by default values not being saved correctly in database
|
||||
- [SECURITY] Update security headers in default pages and error pages for improved security
|
||||
- [DEPS] Updated LuaJIT version to v2.1-20240626
|
||||
- [DEPS] Updated coreruleset-v4 version to v4.4.0
|
||||
|
|
|
|||
14
README.md
14
README.md
|
|
@ -371,13 +371,13 @@ Here is the list of "official" plugins that we maintain (see the [bunkerweb-plug
|
|||
|
||||
| Name | Version | Description | Link |
|
||||
| :------------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------: |
|
||||
| **ClamAV** | 1.5 | Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. | [bunkerweb-plugins/clamav](https://github.com/bunkerity/bunkerweb-plugins/tree/main/clamav) |
|
||||
| **Coraza** | 1.5 | Inspect requests using a the Coraza WAF (alternative of ModSecurity). | [bunkerweb-plugins/coraza](https://github.com/bunkerity/bunkerweb-plugins/tree/main/coraza) |
|
||||
| **CrowdSec** | 1.5 | CrowdSec bouncer for BunkerWeb. | [bunkerweb-plugins/crowdsec](https://github.com/bunkerity/bunkerweb-plugins/tree/main/crowdsec) |
|
||||
| **Discord** | 1.5 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
|
||||
| **Slack** | 1.5 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
|
||||
| **VirusTotal** | 1.5 | Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. | [bunkerweb-plugins/virustotal](https://github.com/bunkerity/bunkerweb-plugins/tree/main/virustotal) |
|
||||
| **WebHook** | 1.5 | Send security notifications to a custom HTTP endpoint using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/webhook) |
|
||||
| **ClamAV** | 1.6 | Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. | [bunkerweb-plugins/clamav](https://github.com/bunkerity/bunkerweb-plugins/tree/main/clamav) |
|
||||
| **Coraza** | 1.6 | Inspect requests using a the Coraza WAF (alternative of ModSecurity). | [bunkerweb-plugins/coraza](https://github.com/bunkerity/bunkerweb-plugins/tree/main/coraza) |
|
||||
| **CrowdSec** | 1.6 | CrowdSec bouncer for BunkerWeb. | [bunkerweb-plugins/crowdsec](https://github.com/bunkerity/bunkerweb-plugins/tree/main/crowdsec) |
|
||||
| **Discord** | 1.6 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
|
||||
| **Slack** | 1.6 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
|
||||
| **VirusTotal** | 1.6 | Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. | [bunkerweb-plugins/virustotal](https://github.com/bunkerity/bunkerweb-plugins/tree/main/virustotal) |
|
||||
| **WebHook** | 1.6 | Send security notifications to a custom HTTP endpoint using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/webhook) |
|
||||
|
||||
You will find more information in the [plugins section](https://docs.bunkerweb.io/1.5.9/plugins/?utm_campaign=self&utm_source=github) of the documentation.
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ Here is the list of "official" plugins that we maintain (see the [bunkerweb-plug
|
|||
|
||||
| Name | Version | Description | Link |
|
||||
| :------------: | :-----: | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------: |
|
||||
| **ClamAV** | 1.5 | Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. | [bunkerweb-plugins/clamav](https://github.com/bunkerity/bunkerweb-plugins/tree/main/clamav) |
|
||||
| **Coraza** | 1.5 | Inspect requests using a the Coraza WAF (alternative of ModSecurity). | [bunkerweb-plugins/coraza](https://github.com/bunkerity/bunkerweb-plugins/tree/main/coraza) |
|
||||
| **CrowdSec** | 1.5 | CrowdSec bouncer for BunkerWeb. | [bunkerweb-plugins/crowdsec](https://github.com/bunkerity/bunkerweb-plugins/tree/main/crowdsec) |
|
||||
| **Discord** | 1.5 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
|
||||
| **Slack** | 1.5 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
|
||||
| **VirusTotal** | 1.5 | Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. | [bunkerweb-plugins/virustotal](https://github.com/bunkerity/bunkerweb-plugins/tree/main/virustotal) |
|
||||
| **WebHook** | 1.5 | Send security notifications to a custom HTTP endpoint using a Webhook. | [bunkerweb-plugins/webhook](https://github.com/bunkerity/bunkerweb-plugins/tree/main/webhook) |
|
||||
| **ClamAV** | 1.6 | Automatically scans uploaded files with the ClamAV antivirus engine and denies the request when a file is detected as malicious. | [bunkerweb-plugins/clamav](https://github.com/bunkerity/bunkerweb-plugins/tree/main/clamav) |
|
||||
| **Coraza** | 1.6 | Inspect requests using a the Coraza WAF (alternative of ModSecurity). | [bunkerweb-plugins/coraza](https://github.com/bunkerity/bunkerweb-plugins/tree/main/coraza) |
|
||||
| **CrowdSec** | 1.6 | CrowdSec bouncer for BunkerWeb. | [bunkerweb-plugins/crowdsec](https://github.com/bunkerity/bunkerweb-plugins/tree/main/crowdsec) |
|
||||
| **Discord** | 1.6 | Send security notifications to a Discord channel using a Webhook. | [bunkerweb-plugins/discord](https://github.com/bunkerity/bunkerweb-plugins/tree/main/discord) |
|
||||
| **Slack** | 1.6 | Send security notifications to a Slack channel using a Webhook. | [bunkerweb-plugins/slack](https://github.com/bunkerity/bunkerweb-plugins/tree/main/slack) |
|
||||
| **VirusTotal** | 1.6 | Automatically scans uploaded files with the VirusTotal API and denies the request when a file is detected as malicious. | [bunkerweb-plugins/virustotal](https://github.com/bunkerity/bunkerweb-plugins/tree/main/virustotal) |
|
||||
| **WebHook** | 1.6 | Send security notifications to a custom HTTP endpoint using a Webhook. | [bunkerweb-plugins/webhook](https://github.com/bunkerity/bunkerweb-plugins/tree/main/webhook) |
|
||||
|
||||
## How to use a plugin
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ Here is the list of "official" plugins that we maintain (see the [bunkerweb-plug
|
|||
|
||||
If you want to quickly install external plugins, you can use the `EXTERNAL_PLUGIN_URLS` setting. It takes a list of URLs, separated with space, pointing to compressed (zip format) archive containing one or more plugin(s).
|
||||
|
||||
You can use the following value if you want to automatically install the official plugins : `EXTERNAL_PLUGIN_URLS=https://github.com/bunkerity/bunkerweb-plugins/archive/refs/tags/v1.5.zip`
|
||||
You can use the following value if you want to automatically install the official plugins : `EXTERNAL_PLUGIN_URLS=https://github.com/bunkerity/bunkerweb-plugins/archive/refs/tags/v1.6.zip`
|
||||
|
||||
### Manual
|
||||
|
||||
|
|
|
|||
|
|
@ -619,9 +619,9 @@ requests==2.32.3 \
|
|||
# importlib-resources
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==70.2.0 \
|
||||
--hash=sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05 \
|
||||
--hash=sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1
|
||||
setuptools==70.3.0 \
|
||||
--hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \
|
||||
--hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc
|
||||
# via mkdocs-material
|
||||
six==1.16.0 \
|
||||
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
ansible==9.5.1
|
||||
ansible==10.1.0
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
#
|
||||
# pip-compile --allow-unsafe --generate-hashes --strip-extras requirements-ansible.in
|
||||
#
|
||||
ansible==9.5.1 \
|
||||
--hash=sha256:3c278bc9642b97fc953b2ba05b99cd80801e75bf3567dfaa1cb5131fe0ec1ecd \
|
||||
--hash=sha256:aed2f4208a75836a27c13555ec5d8d942fe3b089a8b1fc44e8234fadd9e649fd
|
||||
ansible==10.1.0 \
|
||||
--hash=sha256:05b761c4628a0fc216478a5e3c111613c61fd13280846fa84843a63c36c7b1b6 \
|
||||
--hash=sha256:7d8c44557f570687306e19d0e3296ad230593cb12bda35dcfc9274a6063af22a
|
||||
# via -r requirements-ansible.in
|
||||
ansible-core==2.16.6 \
|
||||
--hash=sha256:111e55d358c2297ec0ce03ba98e6c5ce95947fdf50d878215eb8c183d0c275e4 \
|
||||
--hash=sha256:f9dea5044a86fd95cc27099f4f5c3ae9beb23acf7c3b6331455726c47825922b
|
||||
ansible-core==2.17.1 \
|
||||
--hash=sha256:46449d71bbd17c3ce85fe379721d88d333fd23637b5c3798e83fae5fa38def00 \
|
||||
--hash=sha256:aaaccf6a9fe05968821a02079c5ec4c33a7fe5f02d9f5d94f7c3a69f71eab675
|
||||
# via ansible
|
||||
cffi==1.16.0 \
|
||||
--hash=sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc \
|
||||
|
|
@ -66,43 +66,43 @@ cffi==1.16.0 \
|
|||
--hash=sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956 \
|
||||
--hash=sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357
|
||||
# via cryptography
|
||||
cryptography==42.0.5 \
|
||||
--hash=sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee \
|
||||
--hash=sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576 \
|
||||
--hash=sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d \
|
||||
--hash=sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30 \
|
||||
--hash=sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413 \
|
||||
--hash=sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb \
|
||||
--hash=sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da \
|
||||
--hash=sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4 \
|
||||
--hash=sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd \
|
||||
--hash=sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc \
|
||||
--hash=sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8 \
|
||||
--hash=sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1 \
|
||||
--hash=sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc \
|
||||
--hash=sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e \
|
||||
--hash=sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8 \
|
||||
--hash=sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940 \
|
||||
--hash=sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400 \
|
||||
--hash=sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7 \
|
||||
--hash=sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16 \
|
||||
--hash=sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278 \
|
||||
--hash=sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74 \
|
||||
--hash=sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec \
|
||||
--hash=sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1 \
|
||||
--hash=sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2 \
|
||||
--hash=sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c \
|
||||
--hash=sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922 \
|
||||
--hash=sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a \
|
||||
--hash=sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6 \
|
||||
--hash=sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1 \
|
||||
--hash=sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e \
|
||||
--hash=sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac \
|
||||
--hash=sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7
|
||||
cryptography==42.0.8 \
|
||||
--hash=sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad \
|
||||
--hash=sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583 \
|
||||
--hash=sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b \
|
||||
--hash=sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c \
|
||||
--hash=sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1 \
|
||||
--hash=sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648 \
|
||||
--hash=sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949 \
|
||||
--hash=sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba \
|
||||
--hash=sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c \
|
||||
--hash=sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9 \
|
||||
--hash=sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d \
|
||||
--hash=sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c \
|
||||
--hash=sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e \
|
||||
--hash=sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2 \
|
||||
--hash=sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d \
|
||||
--hash=sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7 \
|
||||
--hash=sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70 \
|
||||
--hash=sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2 \
|
||||
--hash=sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7 \
|
||||
--hash=sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14 \
|
||||
--hash=sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe \
|
||||
--hash=sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e \
|
||||
--hash=sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71 \
|
||||
--hash=sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961 \
|
||||
--hash=sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7 \
|
||||
--hash=sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c \
|
||||
--hash=sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28 \
|
||||
--hash=sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842 \
|
||||
--hash=sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902 \
|
||||
--hash=sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801 \
|
||||
--hash=sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a \
|
||||
--hash=sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e
|
||||
# via ansible-core
|
||||
jinja2==3.1.3 \
|
||||
--hash=sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa \
|
||||
--hash=sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90
|
||||
jinja2==3.1.4 \
|
||||
--hash=sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369 \
|
||||
--hash=sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d
|
||||
# via ansible-core
|
||||
markupsafe==2.1.5 \
|
||||
--hash=sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf \
|
||||
|
|
@ -166,9 +166,9 @@ markupsafe==2.1.5 \
|
|||
--hash=sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd \
|
||||
--hash=sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68
|
||||
# via jinja2
|
||||
packaging==24.0 \
|
||||
--hash=sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5 \
|
||||
--hash=sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9
|
||||
packaging==24.1 \
|
||||
--hash=sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002 \
|
||||
--hash=sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124
|
||||
# via ansible-core
|
||||
pycparser==2.22 \
|
||||
--hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \
|
||||
|
|
|
|||
|
|
@ -80,9 +80,15 @@ class Config:
|
|||
i = 0
|
||||
while i < 60:
|
||||
curr_changes = self._db.check_changes()
|
||||
first_config_saved = self._db.is_first_config_saved()
|
||||
if isinstance(curr_changes, str):
|
||||
if not startup:
|
||||
self.__logger.error(f"An error occurred when checking for changes in the database : {curr_changes}")
|
||||
elif isinstance(first_config_saved, str):
|
||||
if not startup:
|
||||
self.__logger.error(f"An error occurred when checking if the first config is saved in the database : {first_config_saved}")
|
||||
elif not first_config_saved:
|
||||
self.__logger.warning("First configuration is not saved yet, retrying in 5 seconds ...")
|
||||
elif not any(curr_changes.values()):
|
||||
break
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -1250,6 +1250,10 @@ class Database:
|
|||
changed_plugins.add(session.query(Settings).with_entities(Settings.plugin_id).filter_by(id=db_service_config.setting_id).first().plugin_id)
|
||||
|
||||
if config:
|
||||
db_global_config = {}
|
||||
if method == "autoconf":
|
||||
db_global_config = self.get_non_default_settings(global_only=True)
|
||||
|
||||
config.pop("DATABASE_URI", None)
|
||||
db_services = session.query(Services).with_entities(Services.id, Services.method, Services.is_draft).all()
|
||||
db_ids: Dict[str, dict] = {service.id: {"method": service.method, "is_draft": service.is_draft} for service in db_services}
|
||||
|
|
@ -1338,7 +1342,9 @@ class Database:
|
|||
|
||||
if not service_setting:
|
||||
if key != "SERVER_NAME" and (
|
||||
(original_key not in config and value == setting.default) or (original_key in config and value == config[original_key])
|
||||
(original_key not in config and original_key not in db_global_config and value == setting.default)
|
||||
or (original_key in config and value == config[original_key])
|
||||
or (original_key in db_global_config and value == db_global_config[original_key])
|
||||
):
|
||||
continue
|
||||
|
||||
|
|
@ -1355,7 +1361,9 @@ class Database:
|
|||
)
|
||||
|
||||
if key != "SERVER_NAME" and (
|
||||
(original_key not in config and value == setting.default) or (original_key in config and value == config[original_key])
|
||||
(original_key not in config and original_key not in db_global_config and value == setting.default)
|
||||
or (original_key in config and value == config[original_key])
|
||||
or (original_key in db_global_config and value == db_global_config[original_key])
|
||||
):
|
||||
query.delete()
|
||||
continue
|
||||
|
|
@ -1386,7 +1394,7 @@ class Database:
|
|||
query.delete()
|
||||
continue
|
||||
query.update({Global_values.value: value, Global_values.method: method})
|
||||
else:
|
||||
elif method != "autoconf":
|
||||
if (
|
||||
config.get("SERVER_NAME", "www.example.com")
|
||||
and not session.query(Services)
|
||||
|
|
|
|||
|
|
@ -114,9 +114,9 @@ docker==7.1.0 \
|
|||
--hash=sha256:ad8c70e6e3f8926cb8a92619b832b4ea5299e2831c14284663184e200546fa6c \
|
||||
--hash=sha256:c96b93b7f0a746f9e77d325bcfb87422a3d8bd4f03136ae8a85b37f1898d5fc0
|
||||
# via -r requirements.in
|
||||
google-auth==2.31.0 \
|
||||
--hash=sha256:042c4702efa9f7d3c48d3a69341c209381b125faa6dbf3ebe56bc7e40ae05c23 \
|
||||
--hash=sha256:87805c36970047247c8afe614d4e3af8eceafc1ebba0c679fe75ddd1d575e871
|
||||
google-auth==2.32.0 \
|
||||
--hash=sha256:49315be72c55a6a37d62819e3573f6b416aca00721f7e3e31a008d928bf64022 \
|
||||
--hash=sha256:53326ea2ebec768070a94bee4e1b9194c9646ea0c2bd72422785bd0f9abfad7b
|
||||
# via kubernetes
|
||||
idna==3.7 \
|
||||
--hash=sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc \
|
||||
|
|
|
|||
|
|
@ -2,6 +2,6 @@ pip==24.1.2
|
|||
pip-compile-multi==2.6.4
|
||||
pip-tools==7.4.1
|
||||
pip-upgrader==1.4.15
|
||||
setuptools==70.2.0
|
||||
setuptools==70.3.0
|
||||
tomli==2.0.1
|
||||
wheel==0.43.0
|
||||
|
|
|
|||
|
|
@ -163,9 +163,9 @@ requests==2.32.3 \
|
|||
# via
|
||||
# -r requirements-deps.in
|
||||
# pip-tools
|
||||
setuptools==70.2.0 \
|
||||
--hash=sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05 \
|
||||
--hash=sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1
|
||||
setuptools==70.3.0 \
|
||||
--hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \
|
||||
--hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc
|
||||
# via pip-upgrader
|
||||
terminaltables==3.1.10 \
|
||||
--hash=sha256:ba6eca5cb5ba02bba4c9f4f985af80c54ec3dccf94cfcd190154386255e47543 \
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
pip==24.1.2
|
||||
pip-tools==7.4.1
|
||||
setuptools==70.2.0
|
||||
setuptools==70.3.0
|
||||
wheel==0.43.0
|
||||
|
|
|
|||
|
|
@ -36,9 +36,9 @@ pyproject-hooks==1.1.0 \
|
|||
# via
|
||||
# -r requirements.in
|
||||
# pip-tools
|
||||
setuptools==70.2.0 \
|
||||
--hash=sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05 \
|
||||
--hash=sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1
|
||||
setuptools==70.3.0 \
|
||||
--hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \
|
||||
--hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc
|
||||
# via
|
||||
# build
|
||||
# pip-tools
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:22.04@sha256:2af372c1e2645779643284c7dc38775e3dbbc417b2d784a27c5a9eb784014fb8 AS builder
|
||||
FROM ubuntu:22.04@sha256:340d9b015b194dc6e2a13938944e0d016e57b9679963fdeb9ce021daac430221 as builder
|
||||
|
||||
ENV OS=ubuntu
|
||||
ENV NGINX_VERSION=1.26.1
|
||||
|
|
@ -58,7 +58,7 @@ COPY src/scheduler scheduler
|
|||
COPY src/ui ui
|
||||
COPY src/VERSION VERSION
|
||||
|
||||
FROM ubuntu:22.04@sha256:2af372c1e2645779643284c7dc38775e3dbbc417b2d784a27c5a9eb784014fb8
|
||||
FROM ubuntu:22.04@sha256:340d9b015b194dc6e2a13938944e0d016e57b9679963fdeb9ce021daac430221
|
||||
|
||||
# Set default umask to prevent huge recursive chmod increasing the final image size
|
||||
RUN umask 027
|
||||
|
|
|
|||
|
|
@ -343,9 +343,9 @@ schedule==1.2.2 \
|
|||
# via importlib-metadata
|
||||
|
||||
# The following packages are considered to be unsafe in a requirements file:
|
||||
setuptools==70.2.0 \
|
||||
--hash=sha256:b8b8060bb426838fbe942479c90296ce976249451118ef566a5a0b7d8b78fb05 \
|
||||
--hash=sha256:bd63e505105011b25c3c11f753f7e3b8465ea739efddaccef8f0efac2137bac1
|
||||
setuptools==70.3.0 \
|
||||
--hash=sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5 \
|
||||
--hash=sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc
|
||||
# via -r requirements.in
|
||||
six==1.16.0 \
|
||||
--hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 \
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ COPY --from=builder --chown=0:101 /usr/share/bunkerweb /usr/share/bunkerweb
|
|||
WORKDIR /usr/share/bunkerweb
|
||||
|
||||
# Add ui user, install runtime dependencies, create data folders and set permissions
|
||||
RUN apk add --no-cache bash unzip libmagic mariadb-client postgresql-client sqlite && \
|
||||
RUN apk add --no-cache bash unzip libmagic mariadb-connector-c mariadb-client postgresql-client sqlite && \
|
||||
addgroup -g 101 ui && \
|
||||
adduser -h /var/cache/nginx -g ui -s /bin/sh -G ui -D -H -u 101 ui && \
|
||||
echo "Docker" > INTEGRATION && \
|
||||
|
|
|
|||
|
|
@ -59,11 +59,11 @@ class Multiple {
|
|||
//get plugin from btn
|
||||
const btn = e.target.closest("button");
|
||||
const attName = btn.getAttribute(
|
||||
`data-${this.prefix}-multiple-add`
|
||||
`data-${this.prefix}-multiple-add`,
|
||||
);
|
||||
//get all multiple groups
|
||||
const multipleEls = document.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple*="${attName}"]`
|
||||
`[data-${this.prefix}-settings-multiple*="${attName}"]`,
|
||||
);
|
||||
//case no schema
|
||||
if (multipleEls.length <= 0) return;
|
||||
|
|
@ -75,7 +75,7 @@ class Multiple {
|
|||
//and keep the highest num
|
||||
multipleEls.forEach((container) => {
|
||||
const ctnrName = container.getAttribute(
|
||||
`data-${this.prefix}-settings-multiple`
|
||||
`data-${this.prefix}-settings-multiple`,
|
||||
);
|
||||
const num = this.getSuffixNumOrFalse(ctnrName);
|
||||
if (!isNaN(num) && num > topNum) topNum = num;
|
||||
|
|
@ -86,7 +86,7 @@ class Multiple {
|
|||
const setNum = +currNum === 0 ? `` : `_${currNum}`;
|
||||
//the default (schema) group is the last group
|
||||
const schema = document.querySelector(
|
||||
`[data-${this.prefix}-settings-multiple="${attName}_SCHEMA"]`
|
||||
`[data-${this.prefix}-settings-multiple="${attName}_SCHEMA"]`,
|
||||
);
|
||||
//clone schema to create a group with new num
|
||||
const schemaClone = schema.cloneNode(true);
|
||||
|
|
@ -129,12 +129,12 @@ class Multiple {
|
|||
// We are not removing it really, just hiding it and update values to default
|
||||
// By setting default value, group will be send to server and delete (because a setting with default value is useless to keep)
|
||||
const multContainer = e.target.closest(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multContainer.classList.add("hidden-multiple");
|
||||
// get setting container
|
||||
const settings = multContainer.querySelectorAll(
|
||||
`[data-setting-container]`
|
||||
`[data-setting-container]`,
|
||||
);
|
||||
settings.forEach((setting) => {
|
||||
// for regular input
|
||||
|
|
@ -161,7 +161,7 @@ class Multiple {
|
|||
// for select
|
||||
try {
|
||||
const selects = setting.querySelectorAll(
|
||||
"button[data-setting-select]"
|
||||
"button[data-setting-select]",
|
||||
);
|
||||
selects.forEach((select) => {
|
||||
const defaultVal = select.getAttribute("data-default") || "";
|
||||
|
|
@ -172,8 +172,8 @@ class Multiple {
|
|||
defaultVal;
|
||||
const dropdown = document.querySelector(
|
||||
`[data-setting-select-dropdown="${select.getAttribute(
|
||||
"data-setting-select"
|
||||
)}"]`
|
||||
"data-setting-select",
|
||||
)}"]`,
|
||||
);
|
||||
dropdown.querySelector(`button[value=${defaultVal}]`).click();
|
||||
});
|
||||
|
|
@ -187,7 +187,7 @@ class Multiple {
|
|||
|
||||
setMultStateActions() {
|
||||
const multiplesGroup = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multiplesGroup.forEach((group) => {
|
||||
// Check if at least one data-method isn't ui, default or manual
|
||||
|
|
@ -205,7 +205,7 @@ class Multiple {
|
|||
if (!isDisabled) return;
|
||||
// Case need to disabled
|
||||
const removeBtn = group.querySelector(
|
||||
`[data-${this.prefix}-multiple-delete]`
|
||||
`[data-${this.prefix}-multiple-delete]`,
|
||||
);
|
||||
removeBtn.setAttribute("disabled", "");
|
||||
});
|
||||
|
|
@ -237,13 +237,13 @@ class Multiple {
|
|||
? name.replace(`_${splitName[splitName.length - 1]}`, "").trim()
|
||||
: name.trim();
|
||||
const relateSetting = document.querySelector(
|
||||
`[data-setting-container=${nameSuffixLess}_SCHEMA]`
|
||||
`[data-setting-container=${nameSuffixLess}_SCHEMA]`,
|
||||
);
|
||||
const relateCtnr = relateSetting.closest(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
const relateCtnrName = relateCtnr.getAttribute(
|
||||
`data-${this.prefix}-settings-multiple`
|
||||
`data-${this.prefix}-settings-multiple`,
|
||||
);
|
||||
//then we sort the setting on the right container name by suffixe number
|
||||
if (!(relateCtnrName in sortMultiples)) {
|
||||
|
|
@ -261,7 +261,7 @@ class Multiple {
|
|||
addOneMultGroup() {
|
||||
const settings = document.querySelector(`[data-${this.prefix}-modal-form]`);
|
||||
const multAddBtns = settings.querySelectorAll(
|
||||
`[data-${this.prefix}-multiple-add]`
|
||||
`[data-${this.prefix}-multiple-add]`,
|
||||
);
|
||||
multAddBtns.forEach((btn) => {
|
||||
//check if already one (SCHEMA exclude so length >= 2)
|
||||
|
|
@ -277,7 +277,7 @@ class Multiple {
|
|||
|
||||
showMultByAtt(att) {
|
||||
const multContainers = document.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`,
|
||||
);
|
||||
multContainers.forEach((container) => {
|
||||
if (
|
||||
|
|
@ -291,7 +291,7 @@ class Multiple {
|
|||
|
||||
toggleMultByAtt(att) {
|
||||
const multContainers = document.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`,
|
||||
);
|
||||
multContainers.forEach((container) => {
|
||||
if (
|
||||
|
|
@ -307,7 +307,7 @@ class Multiple {
|
|||
//get schema settings
|
||||
const multiples = {};
|
||||
const schemaSettings = document.querySelectorAll(
|
||||
`[data-setting-container$="SCHEMA"]`
|
||||
`[data-setting-container$="SCHEMA"]`,
|
||||
);
|
||||
// loop on every schema settings
|
||||
schemaSettings.forEach((schema) => {
|
||||
|
|
@ -333,11 +333,11 @@ class Multiple {
|
|||
setMultipleToDOM(sortMultObj) {
|
||||
//we loop on each multiple that contains values to render to DOM
|
||||
for (const [schemaCtnrName, multGroupBySuffix] of Object.entries(
|
||||
sortMultObj
|
||||
sortMultObj,
|
||||
)) {
|
||||
//we need to access the DOM schema container
|
||||
const schemaCtnr = document.querySelector(
|
||||
`[data-${this.prefix}-settings-multiple="${schemaCtnrName}"]`
|
||||
`[data-${this.prefix}-settings-multiple="${schemaCtnrName}"]`,
|
||||
);
|
||||
//now we have to loop on each multiple settings group
|
||||
for (const [suffix, settings] of Object.entries(multGroupBySuffix)) {
|
||||
|
|
@ -353,14 +353,14 @@ class Multiple {
|
|||
for (const [name, data] of Object.entries(settings)) {
|
||||
//get setting container of clone container
|
||||
const settingContainer = schemaCtnrClone.querySelector(
|
||||
`[data-setting-container="${name}"]`
|
||||
`[data-setting-container="${name}"]`,
|
||||
);
|
||||
//replace input info and disabled state
|
||||
this.setSetting(
|
||||
data["value"],
|
||||
data["method"],
|
||||
data["global"],
|
||||
settingContainer
|
||||
settingContainer,
|
||||
);
|
||||
}
|
||||
//send schema clone to DOM and show it
|
||||
|
|
@ -375,7 +375,7 @@ class Multiple {
|
|||
`data-${this.prefix}-settings-multiple`,
|
||||
schemaCtnrClone
|
||||
.getAttribute(`data-${this.prefix}-settings-multiple`)
|
||||
.replace("_SCHEMA", suffix)
|
||||
.replace("_SCHEMA", suffix),
|
||||
);
|
||||
|
||||
//rename title
|
||||
|
|
@ -389,18 +389,18 @@ class Multiple {
|
|||
|
||||
//rename setting container
|
||||
const settingCtnrs = schemaCtnrClone.querySelectorAll(
|
||||
"[data-setting-container]"
|
||||
"[data-setting-container]",
|
||||
);
|
||||
settingCtnrs.forEach((settingCtnr) => {
|
||||
settingCtnr.setAttribute(
|
||||
"data-setting-container",
|
||||
settingCtnr
|
||||
.getAttribute("data-setting-container")
|
||||
.replace("_SCHEMA", suffix)
|
||||
.replace("_SCHEMA", suffix),
|
||||
);
|
||||
settingCtnr.setAttribute(
|
||||
"id",
|
||||
settingCtnr.getAttribute("id").replace("_SCHEMA", suffix)
|
||||
settingCtnr.getAttribute("id").replace("_SCHEMA", suffix),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -409,7 +409,7 @@ class Multiple {
|
|||
labelEls.forEach((label) => {
|
||||
label.setAttribute(
|
||||
"for",
|
||||
label.getAttribute("for").replace("_SCHEMA", suffix)
|
||||
label.getAttribute("for").replace("_SCHEMA", suffix),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -418,19 +418,19 @@ class Multiple {
|
|||
popoverBtns.forEach((popoverBtn) => {
|
||||
popoverBtn.setAttribute(
|
||||
"data-popover-btn",
|
||||
popoverBtn.getAttribute("data-popover-btn").replace("_SCHEMA", suffix)
|
||||
popoverBtn.getAttribute("data-popover-btn").replace("_SCHEMA", suffix),
|
||||
);
|
||||
});
|
||||
|
||||
const popoverContents = schemaCtnrClone.querySelectorAll(
|
||||
"[data-popover-content]"
|
||||
"[data-popover-content]",
|
||||
);
|
||||
popoverContents.forEach((popoverContent) => {
|
||||
popoverContent.setAttribute(
|
||||
"data-popover-content",
|
||||
popoverContent
|
||||
.getAttribute("data-popover-content")
|
||||
.replace("_SCHEMA", suffix)
|
||||
.replace("_SCHEMA", suffix),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -439,7 +439,7 @@ class Multiple {
|
|||
invalidEls.forEach((invalidEl) => {
|
||||
invalidEl.setAttribute(
|
||||
"data-invalid",
|
||||
invalidEl.getAttribute("data-invalid").replace("_SCHEMA", suffix)
|
||||
invalidEl.getAttribute("data-invalid").replace("_SCHEMA", suffix),
|
||||
);
|
||||
});
|
||||
|
||||
|
|
@ -517,15 +517,15 @@ class Multiple {
|
|||
//click the custom select dropdown btn value to update select value
|
||||
select.parentElement
|
||||
.querySelector(
|
||||
`button[data-setting-select-dropdown-btn][value='${defaultVal}']`
|
||||
`button[data-setting-select-dropdown-btn][value='${defaultVal}']`,
|
||||
)
|
||||
.click();
|
||||
|
||||
//set state to custom visible el
|
||||
const btnCustom = document.querySelector(
|
||||
`[data-setting-select=${select.getAttribute(
|
||||
"data-setting-select-default"
|
||||
)}]`
|
||||
"data-setting-select-default",
|
||||
)}]`,
|
||||
);
|
||||
|
||||
this.setDisabledMultServ(btnCustom, method, global);
|
||||
|
|
@ -561,10 +561,10 @@ class Multiple {
|
|||
selects.forEach((select) => {
|
||||
const method = select.getAttribute("data-default-method");
|
||||
const name = select.getAttribute(
|
||||
`data-${this.prefix}-setting-select-default`
|
||||
`data-${this.prefix}-setting-select-default`,
|
||||
);
|
||||
const selDOM = document.querySelector(
|
||||
`button[data-${this.prefix}-setting-select='${name}']`
|
||||
`button[data-${this.prefix}-setting-select='${name}']`,
|
||||
);
|
||||
if (method === "ui" || method === "default") {
|
||||
selDOM.removeAttribute("disabled", "");
|
||||
|
|
@ -607,7 +607,7 @@ class Multiple {
|
|||
hiddenIfNoMultiples() {
|
||||
//hide multiple btn if no multiple exist on a plugin
|
||||
const multiples = document.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multiples.forEach((container) => {
|
||||
if (container.querySelectorAll(`[data-setting-container]`).length <= 0)
|
||||
|
|
@ -619,7 +619,7 @@ class Multiple {
|
|||
|
||||
removePrevMultiples() {
|
||||
const multiPlugins = document.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multiPlugins.forEach((multiGrp) => {
|
||||
if (
|
||||
|
|
@ -655,7 +655,7 @@ const setPopover = new Popover("main", "global-config");
|
|||
const setDrop = new Dropdown("global-config");
|
||||
const setTabsSelect = new TabsSelect(
|
||||
document.querySelector("[data-global-config-tabs-select-container]"),
|
||||
document.querySelector("[data-global-config-plugins-container]")
|
||||
document.querySelector("[data-global-config-plugins-container]"),
|
||||
);
|
||||
const setInvalid = new showInvalid();
|
||||
const format = new FormatValue();
|
||||
|
|
@ -663,7 +663,7 @@ const format = new FormatValue();
|
|||
const setFilterGlobal = new FilterSettings(
|
||||
"keyword",
|
||||
document.querySelector("[data-global-config-tabs-select-container]"),
|
||||
document.querySelector("[data-global-config-plugins-container]")
|
||||
document.querySelector("[data-global-config-plugins-container]"),
|
||||
);
|
||||
|
||||
const setMultiple = new Multiple("global-config");
|
||||
|
|
@ -675,19 +675,19 @@ const checkServiceModalKeyword = new CheckNoMatchFilter(
|
|||
.querySelector("[data-global-config-plugins-container]")
|
||||
.querySelectorAll("[data-plugin-item]"),
|
||||
document.querySelector("[data-global-config-form]"),
|
||||
document.querySelector("[data-global-config-nomatch]")
|
||||
document.querySelector("[data-global-config-nomatch]"),
|
||||
);
|
||||
|
||||
try {
|
||||
const checkServiceCardSelect = new CheckNoMatchFilter(
|
||||
document.querySelectorAll(
|
||||
"button[data-global-config-setting-select-dropdown-btn]"
|
||||
"button[data-global-config-setting-select-dropdown-btn]",
|
||||
),
|
||||
"select",
|
||||
document
|
||||
.querySelector("[data-global-config-plugins-container]")
|
||||
.querySelectorAll("[data-plugin-item]"),
|
||||
document.querySelector("[data-global-config-form]"),
|
||||
document.querySelector("[data-global-config-nomatch]")
|
||||
document.querySelector("[data-global-config-nomatch]"),
|
||||
);
|
||||
} catch (e) {}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class Popover {
|
|||
this.hidePopover(this.relateBtn);
|
||||
} catch (e) {}
|
||||
},
|
||||
true
|
||||
true,
|
||||
);
|
||||
|
||||
window.addEventListener("pointerover", (e) => {
|
||||
|
|
@ -48,7 +48,7 @@ class Popover {
|
|||
const popoverName = btn.getAttribute("data-popover-btn");
|
||||
//toggle curr popover
|
||||
const popover = btn.parentElement.querySelector(
|
||||
`[data-popover-content=${popoverName}]`
|
||||
`[data-popover-content=${popoverName}]`,
|
||||
);
|
||||
|
||||
popover.classList.add("transition-all", "delay-200", "opacity-0");
|
||||
|
|
@ -70,7 +70,7 @@ class Popover {
|
|||
const popoverName = btn.getAttribute("data-popover-btn");
|
||||
//toggle curr popover
|
||||
const popover = btn.parentElement.querySelector(
|
||||
`[data-popover-content=${popoverName}]`
|
||||
`[data-popover-content=${popoverName}]`,
|
||||
);
|
||||
popover.classList.add("hidden");
|
||||
popover.classList.remove("transition-all", "delay-200");
|
||||
|
|
@ -127,7 +127,7 @@ class TabsSelect {
|
|||
window.history.replaceState(
|
||||
null,
|
||||
"",
|
||||
`${window.location.pathname}#${tabAtt}`
|
||||
`${window.location.pathname}#${tabAtt}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ class TabsSelect {
|
|||
const fragment = window.location.hash.substring(1);
|
||||
if (fragment) {
|
||||
const tab = this.tabContainer.querySelector(
|
||||
`button[data-tab-select-handler='${fragment}']`
|
||||
`button[data-tab-select-handler='${fragment}']`,
|
||||
);
|
||||
tab.click();
|
||||
// Scroll to the top of the page (with a delay to ensure the tab is clicked first)
|
||||
|
|
@ -167,7 +167,7 @@ class TabsSelect {
|
|||
|
||||
resetTabsStyle() {
|
||||
const tabsEl = this.tabContainer.querySelectorAll(
|
||||
"button[data-tab-select-handler]"
|
||||
"button[data-tab-select-handler]",
|
||||
);
|
||||
tabsEl.forEach((tab) => {
|
||||
tab.classList.remove("active");
|
||||
|
|
@ -176,7 +176,7 @@ class TabsSelect {
|
|||
|
||||
highlightClicked(tabAtt) {
|
||||
const tabMobile = this.tabContainer.querySelector(
|
||||
`button[data-tab-select-handler='${tabAtt}']`
|
||||
`button[data-tab-select-handler='${tabAtt}']`,
|
||||
);
|
||||
tabMobile.classList.add("active");
|
||||
}
|
||||
|
|
@ -191,14 +191,14 @@ class TabsSelect {
|
|||
|
||||
showSettingClicked(tabAtt) {
|
||||
const plugin = this.contentContainer.querySelector(
|
||||
`[data-plugin-item='${tabAtt}']`
|
||||
`[data-plugin-item='${tabAtt}']`,
|
||||
);
|
||||
plugin.classList.remove("hidden");
|
||||
}
|
||||
|
||||
setDropBtnText(tabAtt, text) {
|
||||
const dropBtn = this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown-btn]"
|
||||
"[data-tab-select-dropdown-btn]",
|
||||
);
|
||||
dropBtn.setAttribute("data-tab-id", tabAtt);
|
||||
dropBtn.querySelector("span").textContent = text;
|
||||
|
|
@ -206,7 +206,7 @@ class TabsSelect {
|
|||
|
||||
closeDropdown() {
|
||||
const dropdown = this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown]"
|
||||
"[data-tab-select-dropdown]",
|
||||
);
|
||||
dropdown.classList.add("hidden");
|
||||
dropdown.classList.remove("flex");
|
||||
|
|
@ -216,7 +216,7 @@ class TabsSelect {
|
|||
|
||||
toggleDropdown() {
|
||||
const dropdown = this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown]"
|
||||
"[data-tab-select-dropdown]",
|
||||
);
|
||||
const combobox = dropdown.querySelector("[data-combobox]");
|
||||
if (combobox) {
|
||||
|
|
@ -241,7 +241,7 @@ class TabsSelect {
|
|||
|
||||
updateTabArrow() {
|
||||
const dropdown = this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown]"
|
||||
"[data-tab-select-dropdown]",
|
||||
);
|
||||
|
||||
if (dropdown.classList.contains("hidden")) {
|
||||
|
|
@ -275,24 +275,24 @@ class FilterSettings {
|
|||
inputID,
|
||||
tabContainer,
|
||||
contentContainer,
|
||||
prefix = "global-config"
|
||||
prefix = "global-config",
|
||||
) {
|
||||
this.input = document.querySelector(`input#${inputID}`);
|
||||
this.prefix = prefix;
|
||||
this.contextTxtEl = document.querySelector(
|
||||
`span[data-${this.prefix}-setting-select-text="context"]`
|
||||
`span[data-${this.prefix}-setting-select-text="context"]`,
|
||||
);
|
||||
this.typeTxtEl = document.querySelector(
|
||||
`span[data-${this.prefix}-setting-select-text="type"]`
|
||||
`span[data-${this.prefix}-setting-select-text="type"]`,
|
||||
);
|
||||
this.comboboxEl = document.querySelector(
|
||||
`[data-${this.prefix}-tabs-select] [data-combobox]`
|
||||
`[data-${this.prefix}-tabs-select] [data-combobox]`,
|
||||
);
|
||||
this.isComboCheck = false;
|
||||
this.tabContainer = tabContainer;
|
||||
this.contentContainer = contentContainer;
|
||||
this.tabsEls = this.tabContainer.querySelectorAll(
|
||||
`[data-tab-select-handler]`
|
||||
`[data-tab-select-handler]`,
|
||||
);
|
||||
this.comboboxEl = this.tabContainer
|
||||
.querySelector("[data-tab-select-dropdown]")
|
||||
|
|
@ -325,16 +325,16 @@ class FilterSettings {
|
|||
try {
|
||||
if (
|
||||
(e.target.hasAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) &&
|
||||
e.target.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) === `context`) ||
|
||||
(e.target.hasAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) &&
|
||||
e.target.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
) === `type`)
|
||||
) {
|
||||
return this.runFilter();
|
||||
|
|
@ -531,7 +531,7 @@ class FilterSettings {
|
|||
const multGroups = this.contentContainer
|
||||
.querySelector(`[data-plugin-item=${tabName}]`)
|
||||
.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^="${multHandlerName}"]`
|
||||
`[data-${this.prefix}-settings-multiple^="${multHandlerName}"]`,
|
||||
);
|
||||
// check for each if all settings are hidden
|
||||
|
||||
|
|
@ -539,7 +539,7 @@ class FilterSettings {
|
|||
const multGroup = multGroups[j];
|
||||
let isAllMultSettingHidden = true;
|
||||
const settings = multGroup.querySelectorAll(
|
||||
`[data-setting-container]`
|
||||
`[data-setting-container]`,
|
||||
);
|
||||
for (let k = 0; k < settings.length; k++) {
|
||||
if (!settings[k].classList.contains("hidden")) {
|
||||
|
|
@ -632,7 +632,7 @@ class FilterSettings {
|
|||
.querySelector("[data-tab-select-dropdown-btn]")
|
||||
.setAttribute("data-tab-id", "no-match");
|
||||
this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown-btn] span"
|
||||
"[data-tab-select-dropdown-btn] span",
|
||||
).textContent = "No match";
|
||||
// we want to close dropdown in case open previously
|
||||
this.toggleDropdown(true, true, false);
|
||||
|
|
@ -641,7 +641,7 @@ class FilterSettings {
|
|||
|
||||
// case at least one match
|
||||
const currTabBtn = this.tabContainer.querySelector(
|
||||
`[data-tab-select-handler='${tabNameBeforeFilter}']`
|
||||
`[data-tab-select-handler='${tabNameBeforeFilter}']`,
|
||||
);
|
||||
|
||||
// case the previous plugin is still visible, set is as active by clicking it again
|
||||
|
|
@ -661,7 +661,7 @@ class FilterSettings {
|
|||
return;
|
||||
|
||||
const hiddenTabsEl = this.tabContainer.querySelectorAll(
|
||||
`[data-tab-select-handler][class*="!hidden"]`
|
||||
`[data-tab-select-handler][class*="!hidden"]`,
|
||||
);
|
||||
|
||||
if (hiddenTabsEl.length < this.tabsEls.length - 1)
|
||||
|
|
@ -672,15 +672,15 @@ class FilterSettings {
|
|||
toggleDropdown(
|
||||
avoidComboFocus = false,
|
||||
disableOpen = false,
|
||||
disableClose = false
|
||||
disableClose = false,
|
||||
) {
|
||||
// avoid this on mobile
|
||||
if (window.innerWidth < 768) return;
|
||||
const dropdownEl = this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown]"
|
||||
"[data-tab-select-dropdown]",
|
||||
);
|
||||
const dropdownBtn = this.tabContainer.querySelector(
|
||||
"[data-tab-select-dropdown-btn]"
|
||||
"[data-tab-select-dropdown-btn]",
|
||||
);
|
||||
if (this.comboboxEl && avoidComboFocus)
|
||||
this.comboboxEl.setAttribute("data-focus", "false");
|
||||
|
|
@ -736,7 +736,7 @@ class FilterSettings {
|
|||
const multGroups = this.contentContainer
|
||||
.querySelector(`[data-plugin-item=${tabName}]`)
|
||||
.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^="${multHandlerName}"]`
|
||||
`[data-${this.prefix}-settings-multiple^="${multHandlerName}"]`,
|
||||
);
|
||||
// check for each if all settings are hidden
|
||||
for (let j = 0; j < multGroups.length; j++) {
|
||||
|
|
@ -751,7 +751,7 @@ class FilterSettings {
|
|||
multGroup.classList.remove("hidden");
|
||||
|
||||
const settings = multGroup.querySelectorAll(
|
||||
`[data-setting-container]`
|
||||
`[data-setting-container]`,
|
||||
);
|
||||
for (let k = 0; k < settings.length; k++) {
|
||||
settings[k].classList.remove("hidden");
|
||||
|
|
@ -768,7 +768,7 @@ class FilterSettings {
|
|||
.querySelector(`[data-plugin-item="${tabName}"]`)
|
||||
.querySelector(`[data-plugin-settings]`);
|
||||
const settings = settingContainer.querySelectorAll(
|
||||
"[data-setting-container]"
|
||||
"[data-setting-container]",
|
||||
);
|
||||
return settings;
|
||||
}
|
||||
|
|
@ -790,7 +790,7 @@ class FilterSettings {
|
|||
)
|
||||
continue;
|
||||
const settingsContainer = settingMultipleGroup.querySelectorAll(
|
||||
`[data-setting-container]`
|
||||
`[data-setting-container]`,
|
||||
);
|
||||
|
||||
settingsContainer.forEach((setting) => {
|
||||
|
|
@ -859,7 +859,7 @@ class CheckNoMatchFilter {
|
|||
elsToCheck,
|
||||
elContainer,
|
||||
noMatchEl,
|
||||
classToCheck = "hidden"
|
||||
classToCheck = "hidden",
|
||||
) {
|
||||
this.input = input;
|
||||
this.type = type;
|
||||
|
|
@ -989,11 +989,11 @@ class Settings {
|
|||
this.mode = mode;
|
||||
|
||||
this.serverNameInps = this.container.querySelectorAll(
|
||||
'input[name="SERVER_NAME"][data-setting-input]'
|
||||
'input[name="SERVER_NAME"][data-setting-input]',
|
||||
);
|
||||
|
||||
this.submitBtn = this.container.querySelector(
|
||||
`button[data-${this.prefix}-modal-submit]`
|
||||
`button[data-${this.prefix}-modal-submit]`,
|
||||
);
|
||||
this.currAction = "";
|
||||
this.currMethod = "";
|
||||
|
|
@ -1092,7 +1092,7 @@ class Settings {
|
|||
parentEl = this.container,
|
||||
attMethodName = "data-default-method",
|
||||
attValueName = "data-default-value",
|
||||
avoidMultiple = true
|
||||
avoidMultiple = true,
|
||||
) {
|
||||
// Start with input-like (input, checkbox)
|
||||
const inps = avoidMultiple
|
||||
|
|
@ -1123,7 +1123,7 @@ class Settings {
|
|||
"select",
|
||||
select,
|
||||
select.getAttribute("name"),
|
||||
parentEl
|
||||
parentEl,
|
||||
)
|
||||
)
|
||||
return;
|
||||
|
|
@ -1133,15 +1133,15 @@ class Settings {
|
|||
//click the custom select dropdown to update select value
|
||||
select.parentElement
|
||||
.querySelector(
|
||||
`button[data-setting-select-dropdown-btn][value='${defaultVal}']`
|
||||
`button[data-setting-select-dropdown-btn][value='${defaultVal}']`,
|
||||
)
|
||||
.click();
|
||||
|
||||
//set state to custom visible el
|
||||
const btnCustom = document.querySelector(
|
||||
`[data-setting-select=${select.getAttribute(
|
||||
"data-setting-select-default"
|
||||
)}]`
|
||||
"data-setting-select-default",
|
||||
)}]`,
|
||||
);
|
||||
|
||||
this.setDisabledByMethod(btnCustom, defaultMethod);
|
||||
|
|
@ -1171,7 +1171,7 @@ class Settings {
|
|||
setMethodUI,
|
||||
forceEnabled,
|
||||
emptyServerName,
|
||||
forceDisabled
|
||||
forceDisabled,
|
||||
) {
|
||||
// Get global needed data
|
||||
this.currAction = action;
|
||||
|
|
@ -1189,7 +1189,7 @@ class Settings {
|
|||
|
||||
updateOldNameValue() {
|
||||
const oldNameInps = this.container.querySelectorAll(
|
||||
'input[name="OLD_SERVER_NAME"]'
|
||||
'input[name="OLD_SERVER_NAME"]',
|
||||
);
|
||||
|
||||
oldNameInps.forEach((inp) => {
|
||||
|
|
@ -1201,7 +1201,7 @@ class Settings {
|
|||
updateOperation() {
|
||||
// update operation and other hidden inputs for all mode in modal
|
||||
const operationInps = this.container.querySelectorAll(
|
||||
'input[name="operation"]'
|
||||
'input[name="operation"]',
|
||||
);
|
||||
operationInps.forEach((inp) => {
|
||||
inp.setAttribute("value", this.operation);
|
||||
|
|
@ -1273,7 +1273,7 @@ class Settings {
|
|||
if (inp.tagName === "SELECT") {
|
||||
inp.parentElement
|
||||
.querySelector(
|
||||
`button[data-setting-select-dropdown-btn][value='${value}']`
|
||||
`button[data-setting-select-dropdown-btn][value='${value}']`,
|
||||
)
|
||||
.click();
|
||||
inp.setAttribute("data-method", method);
|
||||
|
|
@ -1350,7 +1350,7 @@ class SettingsMultiple extends Settings {
|
|||
const attName = btn.getAttribute(`data-${this.prefix}-multiple-add`);
|
||||
//get all multiple groups
|
||||
const multipleEls = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple*="${attName}"]`
|
||||
`[data-${this.prefix}-settings-multiple*="${attName}"]`,
|
||||
);
|
||||
//case no schema
|
||||
if (multipleEls.length <= 0) return;
|
||||
|
|
@ -1362,7 +1362,7 @@ class SettingsMultiple extends Settings {
|
|||
//and keep the highest num
|
||||
multipleEls.forEach((container) => {
|
||||
const ctnrName = container.getAttribute(
|
||||
`data-${this.prefix}-settings-multiple`
|
||||
`data-${this.prefix}-settings-multiple`,
|
||||
);
|
||||
const [containerSuffix, containerIsNum, containerName] =
|
||||
this.getSuffixData(ctnrName);
|
||||
|
|
@ -1375,7 +1375,7 @@ class SettingsMultiple extends Settings {
|
|||
const setNum = +currNum === 0 ? `` : `_${currNum}`;
|
||||
//the default (schema) group is the last group
|
||||
const schema = this.container.querySelector(
|
||||
`[data-${this.prefix}-settings-multiple="${attName}_SCHEMA"]`
|
||||
`[data-${this.prefix}-settings-multiple="${attName}_SCHEMA"]`,
|
||||
);
|
||||
//clone schema to create a group with new num
|
||||
const schemaClone = schema.cloneNode(true);
|
||||
|
|
@ -1416,12 +1416,12 @@ class SettingsMultiple extends Settings {
|
|||
// We are not removing it really, just hiding it and update values to default
|
||||
// By setting default value, group will be send to server and delete (because a setting with default value is useless to keep)
|
||||
const multContainer = e.target.closest(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multContainer.classList.add("hidden-multiple");
|
||||
// get setting container
|
||||
const settings = multContainer.querySelectorAll(
|
||||
`[data-setting-container]`
|
||||
`[data-setting-container]`,
|
||||
);
|
||||
settings.forEach((setting) => {
|
||||
// for regular input
|
||||
|
|
@ -1450,7 +1450,7 @@ class SettingsMultiple extends Settings {
|
|||
// for select
|
||||
try {
|
||||
const selects = setting.querySelectorAll(
|
||||
"button[data-setting-select]"
|
||||
"button[data-setting-select]",
|
||||
);
|
||||
selects.forEach((select) => {
|
||||
const defaultVal =
|
||||
|
|
@ -1462,8 +1462,8 @@ class SettingsMultiple extends Settings {
|
|||
defaultVal;
|
||||
const dropdown = this.container.querySelector(
|
||||
`[data-setting-select-dropdown="${select.getAttribute(
|
||||
"data-setting-select"
|
||||
)}"]`
|
||||
"data-setting-select",
|
||||
)}"]`,
|
||||
);
|
||||
dropdown.querySelector(`button[value=${defaultVal}]`).click();
|
||||
});
|
||||
|
|
@ -1491,7 +1491,7 @@ class SettingsMultiple extends Settings {
|
|||
|
||||
removePrevMultiples() {
|
||||
const multiPlugins = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multiPlugins.forEach((multiGrp) => {
|
||||
if (
|
||||
|
|
@ -1522,7 +1522,7 @@ class SettingsMultiple extends Settings {
|
|||
|
||||
setMultStateActions() {
|
||||
const multiplesGroup = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multiplesGroup.forEach((group) => {
|
||||
// Check if at least one data-method isn't ui, default or manual
|
||||
|
|
@ -1540,7 +1540,7 @@ class SettingsMultiple extends Settings {
|
|||
if (!isDisabled) return;
|
||||
// Case need to disabled
|
||||
const removeBtn = group.querySelector(
|
||||
`[data-${this.prefix}-multiple-delete]`
|
||||
`[data-${this.prefix}-multiple-delete]`,
|
||||
);
|
||||
removeBtn.setAttribute("disabled", "");
|
||||
});
|
||||
|
|
@ -1550,11 +1550,11 @@ class SettingsMultiple extends Settings {
|
|||
setMultipleToDOM(sortMultObj) {
|
||||
// We want to loop on each schema container
|
||||
for (const [schemaCtnrName, multGroupBySuffix] of Object.entries(
|
||||
sortMultObj
|
||||
sortMultObj,
|
||||
)) {
|
||||
//we need to access the DOM schema container
|
||||
const schemaCtnr = this.container.querySelector(
|
||||
`[data-${this.prefix}-settings-multiple="${schemaCtnrName}"]`
|
||||
`[data-${this.prefix}-settings-multiple="${schemaCtnrName}"]`,
|
||||
);
|
||||
//now we have to loop on each multiple settings group
|
||||
for (const [suffix, settings] of Object.entries(multGroupBySuffix)) {
|
||||
|
|
@ -1570,7 +1570,7 @@ class SettingsMultiple extends Settings {
|
|||
for (const [name, data] of Object.entries(settings)) {
|
||||
//get setting container of clone container
|
||||
const settingContainer = schemaCtnrClone.querySelector(
|
||||
`[data-setting-container="${name}"]`
|
||||
`[data-setting-container="${name}"]`,
|
||||
);
|
||||
}
|
||||
//send schema clone to DOM and show it
|
||||
|
|
@ -1593,7 +1593,7 @@ class SettingsMultiple extends Settings {
|
|||
const multiples = {};
|
||||
|
||||
const schemaSettings = this.container.querySelectorAll(
|
||||
`[data-setting-container$="SCHEMA"]`
|
||||
`[data-setting-container$="SCHEMA"]`,
|
||||
);
|
||||
|
||||
// loop on every schema settings
|
||||
|
|
@ -1620,13 +1620,13 @@ class SettingsMultiple extends Settings {
|
|||
|
||||
addOneMultGroup() {
|
||||
const multAddBtns = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-multiple-add]`
|
||||
`[data-${this.prefix}-multiple-add]`,
|
||||
);
|
||||
multAddBtns.forEach((btn) => {
|
||||
const att = btn.getAttribute(`data-${this.prefix}-multiple-add`);
|
||||
//check if already one (SCHEMA exclude so length >= 2)
|
||||
const multGroups = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^="${att}"]`
|
||||
`[data-${this.prefix}-settings-multiple^="${att}"]`,
|
||||
);
|
||||
if (multGroups.length >= 2) return;
|
||||
|
||||
|
|
@ -1643,7 +1643,7 @@ class SettingsMultiple extends Settings {
|
|||
hiddenIfNoMultiples() {
|
||||
//hide multiple btn if no multiple exist on a plugin
|
||||
const multiples = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
multiples.forEach((container) => {
|
||||
if (container.querySelectorAll(`[data-setting-container]`).length <= 0)
|
||||
|
|
@ -1655,7 +1655,7 @@ class SettingsMultiple extends Settings {
|
|||
|
||||
showMultByAtt(att) {
|
||||
const multContainers = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`,
|
||||
);
|
||||
multContainers.forEach((container) => {
|
||||
if (
|
||||
|
|
@ -1669,7 +1669,7 @@ class SettingsMultiple extends Settings {
|
|||
|
||||
toggleMultByAtt(att) {
|
||||
const multContainers = this.container.querySelectorAll(
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`
|
||||
`[data-${this.prefix}-settings-multiple^=${att}]`,
|
||||
);
|
||||
multContainers.forEach((container) => {
|
||||
if (
|
||||
|
|
@ -1704,10 +1704,10 @@ class SettingsMultiple extends Settings {
|
|||
selects.forEach((select) => {
|
||||
const method = select.getAttribute("data-default-method");
|
||||
const name = select.getAttribute(
|
||||
`data-${this.prefix}-setting-select-default`
|
||||
`data-${this.prefix}-setting-select-default`,
|
||||
);
|
||||
const selDOM = this.container.querySelector(
|
||||
`button[data-${this.prefix}-setting-select='${name}']`
|
||||
`button[data-${this.prefix}-setting-select='${name}']`,
|
||||
);
|
||||
if (method === "ui" || method === "default") {
|
||||
selDOM.removeAttribute("disabled", "");
|
||||
|
|
@ -1732,14 +1732,14 @@ class SettingsMultiple extends Settings {
|
|||
? name.replace(`_${splitName[splitName.length - 1]}`, "").trim()
|
||||
: name.trim();
|
||||
const relateSetting = this.container.querySelector(
|
||||
`[data-setting-container=${nameSuffixLess}_SCHEMA]`
|
||||
`[data-setting-container=${nameSuffixLess}_SCHEMA]`,
|
||||
);
|
||||
if (!relateSetting) continue;
|
||||
const relateCtnr = relateSetting.closest(
|
||||
`[data-${this.prefix}-settings-multiple]`
|
||||
`[data-${this.prefix}-settings-multiple]`,
|
||||
);
|
||||
const relateCtnrName = relateCtnr.getAttribute(
|
||||
`data-${this.prefix}-settings-multiple`
|
||||
`data-${this.prefix}-settings-multiple`,
|
||||
);
|
||||
//then we sort the setting on the right container name by suffixe number
|
||||
if (!(relateCtnrName in sortMultiples)) {
|
||||
|
|
@ -1760,7 +1760,7 @@ class SettingsMultiple extends Settings {
|
|||
`data-${this.prefix}-settings-multiple`,
|
||||
schemaCtnrClone
|
||||
.getAttribute(`data-${this.prefix}-settings-multiple`)
|
||||
.replace("_SCHEMA", suffix)
|
||||
.replace("_SCHEMA", suffix),
|
||||
);
|
||||
|
||||
// Get all elemennts by attribute to update _SCHEMA by suffix
|
||||
|
|
@ -1779,7 +1779,7 @@ class SettingsMultiple extends Settings {
|
|||
attEls.forEach((attEl) => {
|
||||
attEl.setAttribute(
|
||||
att,
|
||||
attEl.getAttribute(att).replace("_SCHEMA", suffix)
|
||||
attEl.getAttribute(att).replace("_SCHEMA", suffix),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -1866,7 +1866,7 @@ class SettingsEditor extends SettingsMultiple {
|
|||
addDefaultEditorIfNone() {
|
||||
// get containers with _SCHEMA
|
||||
const editorContainers = this.container.querySelectorAll(
|
||||
"[data-editor-container$='_SCHEMA']"
|
||||
"[data-editor-container$='_SCHEMA']",
|
||||
);
|
||||
editorContainers.forEach((editorContainer) => {
|
||||
// Check if others editor exists with same base name
|
||||
|
|
@ -1874,7 +1874,7 @@ class SettingsEditor extends SettingsMultiple {
|
|||
.getAttribute("data-editor-container")
|
||||
.replace("_SCHEMA", "");
|
||||
const otherEditors = this.container.querySelectorAll(
|
||||
`[data-editor-container*='${editorName}']`
|
||||
`[data-editor-container*='${editorName}']`,
|
||||
);
|
||||
if (otherEditors.length > 1) return;
|
||||
// Add default editor
|
||||
|
|
@ -1892,7 +1892,7 @@ class SettingsEditor extends SettingsMultiple {
|
|||
// reset previous editors
|
||||
this.editorEls.forEach((editor) => {
|
||||
const editorContainer = editor.container.closest(
|
||||
"[data-editor-container]"
|
||||
"[data-editor-container]",
|
||||
);
|
||||
editorContainer.remove();
|
||||
editor.destroy();
|
||||
|
|
@ -1901,7 +1901,7 @@ class SettingsEditor extends SettingsMultiple {
|
|||
this.editorEls = [];
|
||||
// get only container ending with _SCHEMA
|
||||
const editorContainers = this.container.querySelectorAll(
|
||||
"[data-editor-container$='_SCHEMA']"
|
||||
"[data-editor-container$='_SCHEMA']",
|
||||
);
|
||||
const configsSettings = this.getEditorSettings();
|
||||
// Create instances on the right containers
|
||||
|
|
@ -1922,7 +1922,7 @@ class SettingsEditor extends SettingsMultiple {
|
|||
editorType,
|
||||
editorName,
|
||||
num,
|
||||
editorValue
|
||||
editorValue,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -1941,11 +1941,11 @@ class SettingsEditor extends SettingsMultiple {
|
|||
editor.setAttribute("name", `${contName}_${num}`);
|
||||
}
|
||||
const filenameInp = containerClone.querySelector(
|
||||
`input[data-editor-filename]`
|
||||
`input[data-editor-filename]`,
|
||||
);
|
||||
if (filenameInp) filenameInp.value = name;
|
||||
const hiddenInp = containerClone.querySelector(
|
||||
`textarea[data-editor-input]`
|
||||
`textarea[data-editor-input]`,
|
||||
);
|
||||
if (hiddenInp) {
|
||||
hiddenInp.setAttribute("data-config-type", type);
|
||||
|
|
@ -2005,7 +2005,7 @@ class SettingsAdvanced extends SettingsEditor {
|
|||
setMethodUI = false,
|
||||
forceEnabled = false,
|
||||
emptyServerName = false,
|
||||
forceDisabled = false
|
||||
forceDisabled = false,
|
||||
) {
|
||||
this.updateData(
|
||||
action,
|
||||
|
|
@ -2015,7 +2015,7 @@ class SettingsAdvanced extends SettingsEditor {
|
|||
setMethodUI,
|
||||
forceEnabled,
|
||||
emptyServerName,
|
||||
forceDisabled
|
||||
forceDisabled,
|
||||
);
|
||||
this.setSettingsAdvanced();
|
||||
this.resetServerName();
|
||||
|
|
@ -2031,7 +2031,7 @@ class SettingsAdvanced extends SettingsEditor {
|
|||
checkVisibleInpsValidity() {
|
||||
try {
|
||||
const inps = this.container.querySelectorAll(
|
||||
"[data-plugin-item]:not(.hidden) input[data-setting-input], [data-plugin-item][class*='hidden'] input[data-setting-input]"
|
||||
"[data-plugin-item]:not(.hidden) input[data-setting-input], [data-plugin-item][class*='hidden'] input[data-setting-input]",
|
||||
);
|
||||
|
||||
// merge input with visible and not visible
|
||||
|
|
@ -2057,7 +2057,7 @@ class SettingsAdvanced extends SettingsEditor {
|
|||
) {
|
||||
// Case conflict with another server name
|
||||
const serverNames = document.querySelectorAll(
|
||||
"[data-services-service]"
|
||||
"[data-services-service]",
|
||||
);
|
||||
const serverNameValue = inps[i].getAttribute("value");
|
||||
serverNames.forEach((serverName) => {
|
||||
|
|
@ -2072,7 +2072,7 @@ class SettingsAdvanced extends SettingsEditor {
|
|||
}
|
||||
|
||||
const errMsg = this.container.querySelector(
|
||||
"[data-services-modal-error-msg]"
|
||||
"[data-services-modal-error-msg]",
|
||||
);
|
||||
if (!isAllValid) {
|
||||
invalidInp.classList.add("invalid");
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ version: "3.5"
|
|||
|
||||
services:
|
||||
bw-db:
|
||||
image: mariadb:10.10
|
||||
image: mariadb
|
||||
environment:
|
||||
- MYSQL_RANDOM_ROOT_PASSWORD=yes
|
||||
- MYSQL_DATABASE=db
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ version: "3.5"
|
|||
|
||||
services:
|
||||
bw-db:
|
||||
image: mysql:8.0
|
||||
image: mysql
|
||||
environment:
|
||||
- MYSQL_RANDOM_ROOT_PASSWORD=yes
|
||||
- MYSQL_DATABASE=db
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ version: "3.5"
|
|||
|
||||
services:
|
||||
bw-db:
|
||||
image: postgres:15.1
|
||||
image: postgres
|
||||
environment:
|
||||
- POSTGRES_USER=bunkerweb
|
||||
- POSTGRES_PASSWORD=secret
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e57fd7aec21dd0d1b0761bbfb2
|
||||
FROM ubuntu:22.04@sha256:340d9b015b194dc6e2a13938944e0d016e57b9679963fdeb9ce021daac430221
|
||||
|
||||
ENV container docker
|
||||
ENV LC_ALL C
|
||||
|
|
|
|||
Loading…
Reference in a new issue