Merge pull request #1352 from bunkerity/dev

Merge branch "dev" into branch "staging"
This commit is contained in:
Théophile Diot 2024-07-11 21:26:53 +01:00 committed by GitHub
commit e3bc7150f1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
32 changed files with 243 additions and 228 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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 }}

View file

@ -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

View file

@ -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

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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]

View file

@ -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

View file

@ -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.

View file

@ -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

View file

@ -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 \

View file

@ -1 +1 @@
ansible==9.5.1
ansible==10.1.0

View file

@ -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 \

View file

@ -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:

View file

@ -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)

View file

@ -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 \

View file

@ -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

View file

@ -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 \

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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 \

View file

@ -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 && \

View file

@ -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) {}

View file

@ -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");

View file

@ -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

View file

@ -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

View file

@ -2,7 +2,7 @@ version: "3.5"
services:
bw-db:
image: postgres:15.1
image: postgres
environment:
- POSTGRES_USER=bunkerweb
- POSTGRES_PASSWORD=secret

View file

@ -1,4 +1,4 @@
FROM ubuntu:22.04@sha256:a6d2b38300ce017add71440577d5b0a90460d0e57fd7aec21dd0d1b0761bbfb2
FROM ubuntu:22.04@sha256:340d9b015b194dc6e2a13938944e0d016e57b9679963fdeb9ce021daac430221
ENV container docker
ENV LC_ALL C