mirror of
https://github.com/bunkerity/bunkerweb
synced 2026-05-24 09:28:37 +00:00
Merge branch 'dev' of github.com:bunkerity/bunkerweb into dev
This commit is contained in:
commit
0eb18cb31e
47 changed files with 284 additions and 232 deletions
|
|
@ -3,7 +3,7 @@
|
|||
exclude: (^LICENSE.md$|^src/VERSION$|^src/(bw/misc/root-ca.pem$|deps/src/|common/core/modsecurity/files|ui/static/js/(editor/|utils/purify/|tsparticles\.bundle\.min\.js))|\.(svg|drawio|patch\d?|ascii|tf|tftpl)$)
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.4.0
|
||||
rev: f71fa2c1f9cf5cb705f73dffe4b21f7c61470ba9 # frozen: v4.4.0
|
||||
hooks:
|
||||
- id: requirements-txt-fixer
|
||||
- id: trailing-whitespace
|
||||
|
|
@ -14,25 +14,41 @@ repos:
|
|||
- id: check-case-conflict
|
||||
|
||||
- repo: https://github.com/ambv/black
|
||||
rev: 23.9.1
|
||||
rev: e87737140f32d3cd7c44ede75f02dcd58e55820e # frozen: 23.9.1
|
||||
hooks:
|
||||
- id: black
|
||||
name: Black Python Formatter
|
||||
language_version: python3.9
|
||||
|
||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||
rev: fc260393cc4ec09f8fc0a5ba4437f481c8b55dc1 # frozen: v3.0.3
|
||||
hooks:
|
||||
- id: prettier
|
||||
name: Prettier Code Formatter
|
||||
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 6.1.0
|
||||
rev: 10f4af6dbcf93456ba7df762278ae61ba3120dc6 # frozen: 6.1.0
|
||||
hooks:
|
||||
- id: flake8
|
||||
name: Flake8 Python Linter
|
||||
args: ["--max-line-length=250", "--ignore=E266,E402,E722,W503"]
|
||||
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: 6e41aba91fb32e9feb741a6258eefeb9c6e4a482 # frozen: v2.2.6
|
||||
hooks:
|
||||
- id: codespell
|
||||
name: Codespell Spell Checker
|
||||
exclude: (^src/(common/core/.+/files|bw/loading)/.+.html|modsecurity-rules.conf.*)$
|
||||
entry: codespell --ignore-regex="(tabEl|Widgits)" --skip src/ui/static/js/utils/flatpickr.js,CHANGELOG.md
|
||||
language: python
|
||||
types: [text]
|
||||
|
||||
- repo: https://github.com/gitleaks/gitleaks
|
||||
rev: v8.18.0
|
||||
rev: b813e6fe08b87541cb77296359ba1b7a50a00c98 # frozen: v8.18.0
|
||||
hooks:
|
||||
- id: gitleaks
|
||||
|
||||
- repo: https://github.com/koalaman/shellcheck-precommit
|
||||
rev: v0.9.0
|
||||
rev: 3f77b826548d8dc2d26675f077361c92773b50a7 # frozen: v0.9.0
|
||||
hooks:
|
||||
- id: shellcheck
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ src/deps/src/
|
|||
mkdocs.yml
|
||||
CHANGELOG.md
|
||||
CONTRIBUTING.md
|
||||
CODE_OF_CONDUCT.md
|
||||
LICENSE.md
|
||||
README.md
|
||||
SECURITY.md
|
||||
|
|
|
|||
|
|
@ -335,10 +335,10 @@ Please contact us at [contact@bunkerity.com](mailto:contact@bunkerity.com) if yo
|
|||
|
||||
## Community
|
||||
|
||||
To get free community support you can use the following medias :
|
||||
To get free community support you can use the following media :
|
||||
|
||||
* The #help channel of BunkerWeb in the [Discord server](https://discord.com/invite/fTf46FmtyD)
|
||||
* The help category of [GitHub dicussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
* The help category of [GitHub discussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
* The [/r/BunkerWeb](https://www.reddit.com/r/BunkerWeb) subreddit
|
||||
* The [Server Fault](https://serverfault.com/) and [Super User](https://superuser.com/) forums
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ Please contact us at [contact@bunkerity.com](mailto:contact@bunkerity.com) if yo
|
|||
|
||||
## Where to get community support ?
|
||||
|
||||
To get free community support, you can use the following medias :
|
||||
To get free community support, you can use the following media :
|
||||
|
||||
- The #help channel of BunkerWeb in the [Discord server](https://discord.com/invite/fTf46FmtyD)
|
||||
- The help category of [GitHub dicussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
- The help category of [GitHub discussions](https://github.com/bunkerity/bunkerweb/discussions)
|
||||
- The [/r/BunkerWeb](https://www.reddit.com/r/BunkerWeb) subreddit
|
||||
- The [Server Fault](https://serverfault.com/) and [Super User](https://superuser.com/) forums
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# Concepts
|
||||
|
||||
<figure markdown>
|
||||
{ align=center, width="600" }
|
||||
{ align=center, width="600" }
|
||||
</figure>
|
||||
|
||||
## Integrations
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ The first step is to install the plugin by putting the plugin files inside the c
|
|||
When using the [Swarm integration](integrations.md#swarm), plugins must be written to the volume mounted on `/data/plugins` into the scheduler container.
|
||||
|
||||
!!! info "Swarm volume"
|
||||
Configuring a Swarm volume that will persist when the scheduler service is running on different nodes is not covered is in this documentation. We will assume that you have a shared folder mounted on `/shared` accross all nodes.
|
||||
Configuring a Swarm volume that will persist when the scheduler service is running on different nodes is not covered is in this documentation. We will assume that you have a shared folder mounted on `/shared` across all nodes.
|
||||
|
||||
The first thing to do is to create the plugins folder :
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ Some helpers modules provide common helpful helpers :
|
|||
- `self.logger` : print logs
|
||||
- `bunkerweb.utils` : various useful functions
|
||||
- `bunkerweb.datastore` : access the global shared data on one instance (key/value store)
|
||||
- `bunkerweb.clusterstore` : access a Redis data store shared beetween BunkerWeb instances (key/value store)
|
||||
- `bunkerweb.clusterstore` : access a Redis data store shared between BunkerWeb instances (key/value store)
|
||||
|
||||
To access the functions, you first need to **require** the modules :
|
||||
|
||||
|
|
|
|||
|
|
@ -2322,7 +2322,7 @@ BunkerWeb supports PHP using external or remote [PHP-FPM](https://www.php.net/ma
|
|||
!!! warning "Feature is in beta"
|
||||
This feature is not production-ready. Feel free to test it and report us any bug using [issues](https://github.com/bunkerity/bunkerweb/issues) in the GitHub repository.
|
||||
|
||||
By default, BunkerWeb will only listen on IPv4 adresses and won't use IPv6 for network communications. If you want to enable IPv6 support, you need to set `USE_IPV6=yes`. Please note that IPv6 configuration of your network and environment is out-of-the-scope of this documentation.
|
||||
By default, BunkerWeb will only listen on IPv4 addresses and won't use IPv6 for network communications. If you want to enable IPv6 support, you need to set `USE_IPV6=yes`. Please note that IPv6 configuration of your network and environment is out-of-the-scope of this documentation.
|
||||
|
||||
=== "Docker"
|
||||
|
||||
|
|
|
|||
|
|
@ -284,4 +284,4 @@ If you have bots that need to access your website, the recommended way to avoid
|
|||
|
||||
## Timezone
|
||||
|
||||
When using container-based integrations, the timezone of the container may not match the one of the host machine. To resolve that, you can set the `TZ` environment variable to the timezone of your choice on your containers (e.g. `TZ=Europe/Paris`). You will find the list of timezone identifers [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List).
|
||||
When using container-based integrations, the timezone of the container may not match the one of the host machine. To resolve that, you can set the `TZ` environment variable to the timezone of your choice on your containers (e.g. `TZ=Europe/Paris`). You will find the list of timezone identifiers [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List).
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ services:
|
|||
REVERSE_PROXY_URL: "/"
|
||||
REVERSE_PROXY_HOST: "http://mydrupal"
|
||||
CUSTOM_CONF_MODSEC_CRS_drupal: 'SecAction "id:900130,phase:1,nolog,pass,t:none,setvar:tx.crs_exclusions_drupal=1"'
|
||||
# Onces the installation is done, you can remove these lines
|
||||
# Once the installation is done, you can remove these lines
|
||||
LIMIT_REQ_URL_1: "/core/install.php"
|
||||
LIMIT_REQ_RATE_1: "5r/s"
|
||||
labels:
|
||||
|
|
@ -75,6 +75,7 @@ volumes:
|
|||
bw-data:
|
||||
db-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
ipam:
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ services:
|
|||
USE_REVERSE_PROXY: "yes"
|
||||
REVERSE_PROXY_URL: "/"
|
||||
REVERSE_PROXY_HOST: "http://myps"
|
||||
# Onces the installation is done, you can remove these lines
|
||||
# Once the installation is done, you can remove these lines
|
||||
LIMIT_REQ_URL_1: "/install/index.php"
|
||||
LIMIT_REQ_RATE_1: "8r/s"
|
||||
labels:
|
||||
|
|
@ -85,6 +85,7 @@ volumes:
|
|||
ps-data:
|
||||
db-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
ipam:
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ class IngressController(Controller):
|
|||
locked = False
|
||||
continue
|
||||
self._logger.info(
|
||||
f"Catched kubernetes event ({watch_type}), deploying new configuration ...",
|
||||
f"Caught kubernetes event ({watch_type}), deploying new configuration ...",
|
||||
)
|
||||
try:
|
||||
ret = self.apply_config()
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ class SwarmController(Controller):
|
|||
self.__internal_lock.release()
|
||||
locked = False
|
||||
continue
|
||||
self._logger.info(f"Catched Swarm event ({event_type}), deploying new configuration ...")
|
||||
self._logger.info(f"Caught Swarm event ({event_type}), deploying new configuration ...")
|
||||
if not self.apply_config():
|
||||
self._logger.error("Error while deploying new configuration")
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ log "ENTRYPOINT" "ℹ️" "Starting BunkerWeb v$(cat /usr/share/bunkerweb/VERSIO
|
|||
# trap SIGTERM and SIGINT
|
||||
function trap_exit() {
|
||||
# shellcheck disable=SC2317
|
||||
log "ENTRYPOINT" "ℹ️" "Catched stop operation, stopping nginx ..."
|
||||
log "ENTRYPOINT" "ℹ️" "Caught stop operation, stopping nginx ..."
|
||||
# shellcheck disable=SC2317
|
||||
nginx -s stop
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ trap "trap_exit" TERM INT QUIT
|
|||
# trap SIGHUP
|
||||
function trap_reload() {
|
||||
# shellcheck disable=SC2317
|
||||
log "ENTRYPOINT" "ℹ️" "Catched reload operation"
|
||||
log "ENTRYPOINT" "ℹ️" "Caught reload operation"
|
||||
# shellcheck disable=SC2317
|
||||
if [ -f /var/run/bunkerweb/nginx.pid ] ; then
|
||||
# shellcheck disable=SC2317
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -20,7 +20,7 @@ function plugin:initialize(id, ctx)
|
|||
end
|
||||
end
|
||||
self.is_request = multisite
|
||||
-- Store common objets
|
||||
-- Store common objects
|
||||
self.logger = logger:new(self.id)
|
||||
local use_redis, err = utils.get_variable("USE_REDIS", false)
|
||||
if not use_redis then
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{-raw-}
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ try:
|
|||
blacklist_path.joinpath(f"{kind}.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db(f"{kind}.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete {kind}.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete {kind}.list from cache : {err}")
|
||||
if all_fresh:
|
||||
_exit(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ try:
|
|||
greylist_path.joinpath(f"{kind}.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db(f"{kind}.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete {kind}.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete {kind}.list from cache : {err}")
|
||||
if all_fresh:
|
||||
_exit(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ try:
|
|||
tmp_realip_path.joinpath("combined.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db("combined.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete combined.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete combined.list from cache : {err}")
|
||||
logger.info("RealIP list is already in cache, skipping download...")
|
||||
_exit(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@ try:
|
|||
whitelist_path.joinpath(f"{kind}.list").unlink(missing_ok=True)
|
||||
deleted, err = del_file_in_db(f"{kind}.list", db)
|
||||
if not deleted:
|
||||
logger.warning(f"Coudn't delete {kind}.list from cache : {err}")
|
||||
logger.warning(f"Couldn't delete {kind}.list from cache : {err}")
|
||||
if all_fresh:
|
||||
_exit(0)
|
||||
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ class Database:
|
|||
with suppress(FileExistsError):
|
||||
Path(dirname(sqlalchemy_string.split("///")[1])).mkdir(parents=True, exist_ok=True)
|
||||
elif "+" in sqlalchemy_string and "+pymysql" not in sqlalchemy_string:
|
||||
splitted = sqlalchemy_string.split("+")
|
||||
sqlalchemy_string = f"{splitted[0]}:{':'.join(splitted[1].split(':')[1:])}"
|
||||
split = sqlalchemy_string.split("+")
|
||||
sqlalchemy_string = f"{split[0]}:{':'.join(split[1].split(':')[1:])}"
|
||||
|
||||
self.database_uri = sqlalchemy_string
|
||||
error = False
|
||||
|
|
|
|||
|
|
@ -162,8 +162,8 @@ class Configurator:
|
|||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
splitted = line.split("=", 1)
|
||||
variables[splitted[0]] = splitted[1]
|
||||
split = line.split("=", 1)
|
||||
variables[split[0]] = split[1]
|
||||
return variables
|
||||
|
||||
def get_config(self) -> Dict[str, Any]:
|
||||
|
|
|
|||
|
|
@ -32,12 +32,12 @@ def get_instance_configs_and_apis(instance: Any, db, _type="Docker"):
|
|||
apis = []
|
||||
|
||||
for var in instance.attrs["Config"]["Env"] if _type == "Docker" else instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"]:
|
||||
splitted = var.split("=", 1)
|
||||
if custom_confs_rx.match(splitted[0]):
|
||||
custom_conf = custom_confs_rx.search(splitted[0]).groups()
|
||||
split = var.split("=", 1)
|
||||
if custom_confs_rx.match(split[0]):
|
||||
custom_conf = custom_confs_rx.search(split[0]).groups()
|
||||
custom_confs.append(
|
||||
{
|
||||
"value": f"# CREATED BY ENV\n{splitted[1]}",
|
||||
"value": f"# CREATED BY ENV\n{split[1]}",
|
||||
"exploded": (
|
||||
custom_conf[0],
|
||||
custom_conf[1],
|
||||
|
|
@ -47,14 +47,14 @@ def get_instance_configs_and_apis(instance: Any, db, _type="Docker"):
|
|||
)
|
||||
logger.info(f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}")
|
||||
else:
|
||||
tmp_config[splitted[0]] = splitted[1]
|
||||
tmp_config[split[0]] = split[1]
|
||||
|
||||
if not db and splitted[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=splitted[1], pool=False)
|
||||
elif splitted[0] == "API_HTTP_PORT":
|
||||
api_http_port = splitted[1]
|
||||
elif splitted[0] == "API_SERVER_NAME":
|
||||
api_server_name = splitted[1]
|
||||
if not db and split[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=split[1], pool=False)
|
||||
elif split[0] == "API_HTTP_PORT":
|
||||
api_http_port = split[1]
|
||||
elif split[0] == "API_SERVER_NAME":
|
||||
api_server_name = split[1]
|
||||
|
||||
apis.append(
|
||||
API(
|
||||
|
|
@ -222,12 +222,12 @@ if __name__ == "__main__":
|
|||
|
||||
for instance in docker_client.containers.list(filters={"label": "bunkerweb.INSTANCE"}):
|
||||
for var in instance.attrs["Config"]["Env"]:
|
||||
splitted = var.split("=", 1)
|
||||
if custom_confs_rx.match(splitted[0]):
|
||||
custom_conf = custom_confs_rx.search(splitted[0]).groups()
|
||||
split = var.split("=", 1)
|
||||
if custom_confs_rx.match(split[0]):
|
||||
custom_conf = custom_confs_rx.search(split[0]).groups()
|
||||
custom_confs.append(
|
||||
{
|
||||
"value": f"# CREATED BY ENV\n{splitted[1]}",
|
||||
"value": f"# CREATED BY ENV\n{split[1]}",
|
||||
"exploded": (
|
||||
custom_conf[0],
|
||||
custom_conf[1],
|
||||
|
|
@ -237,14 +237,14 @@ if __name__ == "__main__":
|
|||
)
|
||||
logger.info(f"Found custom conf env var {'for service ' + custom_conf[0] if custom_conf[0] else 'without service'} with type {custom_conf[1]} and name {custom_conf[2]}")
|
||||
else:
|
||||
tmp_config[splitted[0]] = splitted[1]
|
||||
tmp_config[split[0]] = split[1]
|
||||
|
||||
if not db and splitted[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=splitted[1], pool=False)
|
||||
elif splitted[0] == "API_HTTP_PORT":
|
||||
api_http_port = splitted[1]
|
||||
elif splitted[0] == "API_SERVER_NAME":
|
||||
api_server_name = splitted[1]
|
||||
if not db and split[0] == "DATABASE_URI":
|
||||
db = Database(logger, sqlalchemy_string=split[1], pool=False)
|
||||
elif split[0] == "API_HTTP_PORT":
|
||||
api_http_port = split[1]
|
||||
elif split[0] == "API_SERVER_NAME":
|
||||
api_server_name = split[1]
|
||||
|
||||
apis.append(
|
||||
API(
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ function reload()
|
|||
log "SYSTEMCTL" "ℹ️" "BunkerWeb service reloaded ..."
|
||||
}
|
||||
|
||||
# List of differents args
|
||||
# List of different args
|
||||
case $1 in
|
||||
"start")
|
||||
start
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
# trap SIGTERM and SIGINT
|
||||
function trap_exit() {
|
||||
# shellcheck disable=SC2317
|
||||
log "ENTRYPOINT" "ℹ️ " "Catched stop operation"
|
||||
log "ENTRYPOINT" "ℹ️ " "Caught stop operation"
|
||||
# shellcheck disable=SC2317
|
||||
if [ -f "/var/run/bunkerweb/scheduler.pid" ] ; then
|
||||
# shellcheck disable=SC2317
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ def stop(status, _stop=True):
|
|||
|
||||
|
||||
def handle_stop(signum, frame):
|
||||
app.logger.info("Catched stop operation")
|
||||
app.logger.info("Caught stop operation")
|
||||
app.logger.info("Stopping web ui ...")
|
||||
stop(0, False)
|
||||
|
||||
|
|
@ -1330,13 +1330,13 @@ def logs_container(container_id):
|
|||
)
|
||||
|
||||
for log in tmp_logs:
|
||||
splitted = log.split(" ")
|
||||
timestamp = splitted[0]
|
||||
split = log.split(" ")
|
||||
timestamp = split[0]
|
||||
|
||||
if to_date is not None and dateutil_parse(timestamp).timestamp() > to_date:
|
||||
break
|
||||
|
||||
log = " ".join(splitted[1:])
|
||||
log = " ".join(split[1:])
|
||||
log_lower = log.lower()
|
||||
|
||||
if "[48;2" in log or not log.strip():
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ class News {
|
|||
excerpt,
|
||||
tags,
|
||||
date,
|
||||
lastUpdate
|
||||
lastUpdate,
|
||||
);
|
||||
let cleanHTML = DOMPurify.sanitize(cardHTML);
|
||||
//add to DOM
|
||||
|
|
@ -191,7 +191,7 @@ class darkMode {
|
|||
};
|
||||
const send = await fetch(
|
||||
`${location.href.split("/").slice(0, -1).join("/")}/darkmode`,
|
||||
data
|
||||
data,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -231,7 +231,7 @@ class FlashMsg {
|
|||
flashEl.remove();
|
||||
//update count
|
||||
this.flashCount.textContent = document.querySelectorAll(
|
||||
"[data-flash-message]"
|
||||
"[data-flash-message]",
|
||||
).length;
|
||||
}
|
||||
} catch (err) {}
|
||||
|
|
@ -300,7 +300,7 @@ const setMenu = new Menu();
|
|||
const setNewsSidebar = new Sidebar(
|
||||
"[data-sidebar-info]",
|
||||
"[data-sidebar-info-open]",
|
||||
"[data-sidebar-info-close]"
|
||||
"[data-sidebar-info-close]",
|
||||
);
|
||||
|
||||
const setCheckbox = new Checkbox();
|
||||
|
|
@ -311,7 +311,7 @@ const setDisabledPop = new DisabledPop();
|
|||
const setFlashSidebar = new Sidebar(
|
||||
"[data-flash-sidebar]",
|
||||
"[data-flash-sidebar-open]",
|
||||
"[data-flash-sidebar-close]"
|
||||
"[data-flash-sidebar-close]",
|
||||
);
|
||||
const setNews = new News();
|
||||
const setDarkM = new darkMode();
|
||||
|
|
|
|||
|
|
@ -133,15 +133,15 @@ class Dropdown {
|
|||
}
|
||||
|
||||
toggleSelectBtn(e) {
|
||||
const attribut = e.target
|
||||
const attribute = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`data-${this.prefix}-setting-select`);
|
||||
//toggle dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribut}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
|
||||
);
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${attribut}"]`,
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`,
|
||||
);
|
||||
dropdownEl.classList.toggle("hidden");
|
||||
dropdownEl.classList.toggle("flex");
|
||||
|
|
|
|||
|
|
@ -130,15 +130,15 @@ class Dropdown {
|
|||
}
|
||||
|
||||
toggleSelectBtn(e) {
|
||||
const attribut = e.target
|
||||
const attribute = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`data-${this.prefix}-setting-select`);
|
||||
//toggle dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribut}"]`,
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
|
||||
);
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${attribut}"]`,
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`,
|
||||
);
|
||||
dropdownEl.classList.toggle("hidden");
|
||||
dropdownEl.classList.toggle("flex");
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class Dropdown {
|
|||
const btn = e.target.closest("button");
|
||||
const btnValue = btn.getAttribute("value");
|
||||
const btnSetting = btn.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`
|
||||
`data-${this.prefix}-setting-select-dropdown-btn`,
|
||||
);
|
||||
//stop if same value to avoid new fetching
|
||||
const isSameVal = this.isSameValue(btnSetting, btnValue);
|
||||
|
|
@ -57,7 +57,7 @@ class Dropdown {
|
|||
|
||||
closeAllDrop() {
|
||||
const drops = document.querySelectorAll(
|
||||
`[data-${this.prefix}-setting-select-dropdown]`
|
||||
`[data-${this.prefix}-setting-select-dropdown]`,
|
||||
);
|
||||
drops.forEach((drop) => {
|
||||
drop.classList.add("hidden");
|
||||
|
|
@ -65,8 +65,8 @@ class Dropdown {
|
|||
document
|
||||
.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${drop.getAttribute(
|
||||
`data-${this.prefix}-setting-select-dropdown`
|
||||
)}"]`
|
||||
`data-${this.prefix}-setting-select-dropdown`,
|
||||
)}"]`,
|
||||
)
|
||||
.classList.remove("rotate-180");
|
||||
});
|
||||
|
|
@ -74,7 +74,7 @@ class Dropdown {
|
|||
|
||||
isSameValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`
|
||||
`[data-${this.prefix}-setting-select-text="${btnSetting}"]`,
|
||||
);
|
||||
const currVal = selectCustom.textContent;
|
||||
return currVal === value ? true : false;
|
||||
|
|
@ -82,30 +82,30 @@ class Dropdown {
|
|||
|
||||
setSelectNewValue(btnSetting, value) {
|
||||
const selectCustom = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select="${btnSetting}"]`
|
||||
`[data-${this.prefix}-setting-select="${btnSetting}"]`,
|
||||
);
|
||||
selectCustom.querySelector(
|
||||
`[data-${this.prefix}-setting-select-text]`
|
||||
`[data-${this.prefix}-setting-select-text]`,
|
||||
).textContent = value;
|
||||
}
|
||||
|
||||
hideDropdown(btnSetting) {
|
||||
//hide dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
|
||||
);
|
||||
dropdownEl.classList.add("hidden");
|
||||
dropdownEl.classList.remove("flex");
|
||||
//svg effect
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`
|
||||
`svg[data-${this.prefix}-setting-select="${btnSetting}"]`,
|
||||
);
|
||||
dropdownChevron.classList.remove("rotate-180");
|
||||
}
|
||||
|
||||
changeDropBtnStyle(btnSetting, selectedBtn) {
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`
|
||||
`[data-${this.prefix}-setting-select-dropdown="${btnSetting}"]`,
|
||||
);
|
||||
//reset dropdown btns
|
||||
const btnEls = dropdownEl.querySelectorAll("button");
|
||||
|
|
@ -116,7 +116,7 @@ class Dropdown {
|
|||
"bg-primary",
|
||||
"bg-primary",
|
||||
"text-gray-300",
|
||||
"text-gray-300"
|
||||
"text-gray-300",
|
||||
);
|
||||
btn.classList.add("bg-white", "dark:bg-slate-700", "text-gray-700");
|
||||
});
|
||||
|
|
@ -124,21 +124,21 @@ class Dropdown {
|
|||
selectedBtn.classList.remove(
|
||||
"bg-white",
|
||||
"dark:bg-slate-700",
|
||||
"text-gray-700"
|
||||
"text-gray-700",
|
||||
);
|
||||
selectedBtn.classList.add("dark:bg-primary", "bg-primary", "text-gray-300");
|
||||
}
|
||||
|
||||
toggleSelectBtn(e) {
|
||||
const attribut = e.target
|
||||
const attribute = e.target
|
||||
.closest("button")
|
||||
.getAttribute(`data-${this.prefix}-setting-select`);
|
||||
//toggle dropdown
|
||||
const dropdownEl = document.querySelector(
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribut}"]`
|
||||
`[data-${this.prefix}-setting-select-dropdown="${attribute}"]`,
|
||||
);
|
||||
const dropdownChevron = document.querySelector(
|
||||
`svg[data-${this.prefix}-setting-select="${attribut}"]`
|
||||
`svg[data-${this.prefix}-setting-select="${attribute}"]`,
|
||||
);
|
||||
dropdownEl.classList.toggle("hidden");
|
||||
dropdownEl.classList.toggle("flex");
|
||||
|
|
@ -300,7 +300,7 @@ class Upload {
|
|||
this.dropZoneElement.classList.remove(
|
||||
"border-solid",
|
||||
"bg-gray-100",
|
||||
"dark:bg-slate-700/50"
|
||||
"dark:bg-slate-700/50",
|
||||
);
|
||||
this.dropZoneElement.classList.add("border-dashed");
|
||||
}
|
||||
|
|
@ -309,7 +309,7 @@ class Upload {
|
|||
this.dropZoneElement.classList.add(
|
||||
"border-solid",
|
||||
"bg-gray-100",
|
||||
"dark:bg-slate-700/50"
|
||||
"dark:bg-slate-700/50",
|
||||
);
|
||||
this.dropZoneElement.classList.remove("border-dashed");
|
||||
}
|
||||
|
|
@ -346,13 +346,13 @@ class Upload {
|
|||
if (xhr.status == 201) {
|
||||
this.uploadedArea.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
this.fileSuccess(name, fileSize)
|
||||
this.fileSuccess(name, fileSize),
|
||||
);
|
||||
this.allowReload();
|
||||
} else {
|
||||
this.uploadedArea.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
this.fileFail(name, fileSize)
|
||||
this.fileFail(name, fileSize),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -451,10 +451,10 @@ class Modal {
|
|||
this.modalExtInp = this.modal.querySelector("input#external");
|
||||
|
||||
this.modalTitle = this.modal.querySelector(
|
||||
`[data-${this.prefix}-modal-title]`
|
||||
`[data-${this.prefix}-modal-title]`,
|
||||
);
|
||||
this.modalTxt = this.modal.querySelector(
|
||||
`[data-${this.prefix}-modal-text]`
|
||||
`[data-${this.prefix}-modal-text]`,
|
||||
);
|
||||
this.init();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ class Multiple {
|
|||
);
|
||||
//clone schema to create a group with new num
|
||||
const schemaClone = schema.cloneNode(true);
|
||||
//add special attribut for disabled logic
|
||||
//add special attribute for disabled logic
|
||||
this.changeCloneSuffix(schemaClone, setNum);
|
||||
//set disabled / enabled state
|
||||
this.setDisabledMultNew(schemaClone);
|
||||
|
|
@ -730,7 +730,7 @@ class Multiple {
|
|||
const select = settingContainer.querySelector("select");
|
||||
select.setAttribute("data-method", method);
|
||||
|
||||
//click the custom select dropdown btn vavlue to update select value
|
||||
//click the custom select dropdown btn value to update select value
|
||||
select.parentElement
|
||||
.querySelector(
|
||||
`button[data-setting-select-dropdown-btn][value='${defaultVal}']`,
|
||||
|
|
|
|||
|
|
@ -52,18 +52,18 @@ class Select {
|
|||
try {
|
||||
if (!e.target.closest("button")) {
|
||||
const selectEls = document.querySelectorAll(
|
||||
"div[data-setting-select-dropdown]"
|
||||
"div[data-setting-select-dropdown]",
|
||||
);
|
||||
selectEls.forEach((select) => {
|
||||
select.classList.add("hidden");
|
||||
select.classList.remove("flex");
|
||||
});
|
||||
const btnEls = document.querySelectorAll(
|
||||
"button[data-setting-select]"
|
||||
"button[data-setting-select]",
|
||||
);
|
||||
btnEls.forEach((btn) => {
|
||||
const dropdownChevron = btn.querySelector(
|
||||
`svg[data-setting-select]`
|
||||
`svg[data-setting-select]`,
|
||||
);
|
||||
dropdownChevron.classList.remove("rotate-180");
|
||||
});
|
||||
|
|
@ -87,7 +87,7 @@ class Select {
|
|||
.hasAttribute(`data-setting-select-dropdown-btn`)
|
||||
) {
|
||||
const btn = e.target.closest(
|
||||
`button[data-setting-select-dropdown-btn]`
|
||||
`button[data-setting-select-dropdown-btn]`,
|
||||
);
|
||||
const btnValue = btn.getAttribute("value");
|
||||
|
||||
|
|
@ -116,7 +116,7 @@ class Select {
|
|||
|
||||
//close dropdown
|
||||
const dropdownChevron = selectCustom.querySelector(
|
||||
`svg[data-setting-select]`
|
||||
`svg[data-setting-select]`,
|
||||
);
|
||||
dropdownChevron.classList.remove("rotate-180");
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ class Select {
|
|||
});
|
||||
//select new one
|
||||
const newOption = selectEl.querySelector(
|
||||
`option[value="${selectedValue}"]`
|
||||
`option[value="${selectedValue}"]`,
|
||||
);
|
||||
newOption.selected = true;
|
||||
newOption.setAttribute("selected", "");
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ services:
|
|||
volumes:
|
||||
bw-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
name: bw-universe
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ do
|
|||
export CLIENT_CACHE_ETAG="no"
|
||||
fi
|
||||
elif [ "$test" = "cache_control" ] ; then
|
||||
echo "📝 Running tests whith clientcache control set to public, max-age=3600 ..."
|
||||
echo "📝 Running tests with clientcache control set to public, max-age=3600 ..."
|
||||
if [ "$integration" == "docker" ] ; then
|
||||
find . -type f -name 'docker-compose.*' -exec sed -i 's@CLIENT_CACHE_ETAG: "no"@CLIENT_CACHE_ETAG: "yes"@' {} \;
|
||||
find . -type f -name 'docker-compose.*' -exec sed -i 's@CLIENT_CACHE_CONTROL: "public, max-age=15552000"@CLIENT_CACHE_CONTROL: "public, max-age=3600"@' {} \;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,6 @@ services:
|
|||
volumes:
|
||||
bw-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
name: bw-universe
|
||||
|
|
|
|||
|
|
@ -74,11 +74,11 @@ try:
|
|||
response.raise_for_status()
|
||||
|
||||
if custom_headers:
|
||||
splitted = custom_headers.split(":")
|
||||
split = custom_headers.split(":")
|
||||
|
||||
if response.headers.get(splitted[0].strip()) != splitted[1].strip():
|
||||
if response.headers.get(split[0].strip()) != split[1].strip():
|
||||
print(
|
||||
f"❌ Header {splitted[0].strip()} is not set to {splitted[1].strip()}, exiting ...\nheaders: {response.headers}",
|
||||
f"❌ Header {split[0].strip()} is not set to {split[1].strip()}, exiting ...\nheaders: {response.headers}",
|
||||
flush=True,
|
||||
)
|
||||
exit(1)
|
||||
|
|
|
|||
|
|
@ -214,7 +214,7 @@ do
|
|||
unset X_XSS_PROTECTION
|
||||
fi
|
||||
elif [ "$test" = "multiple_no_httponly_flag" ] ; then
|
||||
echo "🎛️ Running tests with HttpOnly flag overriden for cookie \"bw_cookie\" and default cookies flags ..."
|
||||
echo "🎛️ Running tests with HttpOnly flag overridden for cookie \"bw_cookie\" and default cookies flags ..."
|
||||
if [ "$integration" == "docker" ] ; then
|
||||
find . -type f -name 'docker-compose.*' -exec sed -i 's@COOKIE_FLAGS: ".*"$@COOKIE_FLAGS: "* HttpOnly SameSite=Lax"@' {} \;
|
||||
sed -i '27i \ COOKIE_FLAGS_1: "bw_cookie SameSite=Lax"' docker-compose.yml
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ do
|
|||
export REDIS_DATABASE="1"
|
||||
export REDIS_SSL="yes"
|
||||
|
||||
echo "🧰 Stoping redis ..."
|
||||
echo "🧰 Stopping redis ..."
|
||||
sudo killall redis-server
|
||||
# shellcheck disable=SC2181
|
||||
if [ $? -ne 0 ] ; then
|
||||
|
|
|
|||
|
|
@ -71,7 +71,6 @@ services:
|
|||
volumes:
|
||||
bw-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
name: bw-universe
|
||||
|
|
|
|||
|
|
@ -93,7 +93,6 @@ services:
|
|||
volumes:
|
||||
bw-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
name: bw-universe
|
||||
|
|
|
|||
|
|
@ -80,7 +80,6 @@ services:
|
|||
volumes:
|
||||
bw-data:
|
||||
|
||||
|
||||
networks:
|
||||
bw-universe:
|
||||
name: bw-universe
|
||||
|
|
|
|||
Loading…
Reference in a new issue