mirror of
https://github.com/okxlin/appstore.git
synced 2026-09-22 16:00:58 +00:00
Merge pull request #7032 from okxlin/maint-pr-7025-whodb-publish
maint: publish rebuilt WhoDB 0.129.0
This commit is contained in:
@@ -1,88 +0,0 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 8080
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: HTTP-порт
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: ./data
|
||||
edit: true
|
||||
envKey: APP_DATA_DIR
|
||||
labelEn: Data Directory
|
||||
labelZh: 数据目录
|
||||
label:
|
||||
en: Data Directory
|
||||
zh: 数据目录
|
||||
zh-Hant: 資料目錄
|
||||
ja: データディレクトリ
|
||||
ko: 데이터 디렉터리
|
||||
ru: Каталог данных
|
||||
ms: Direktori data
|
||||
pt-br: Diretorio de dados
|
||||
required: true
|
||||
type: text
|
||||
- default: ./db-data
|
||||
edit: true
|
||||
envKey: DB_DATA_DIR
|
||||
labelEn: Local Database Directory
|
||||
labelZh: 本地数据库目录
|
||||
label:
|
||||
en: Local Database Directory
|
||||
zh: 本地数据库目录
|
||||
zh-Hant: 本機資料庫目錄
|
||||
ja: ローカルデータベースディレクトリ
|
||||
ko: 로컬 데이터베이스 디렉터리
|
||||
ru: Каталог локальных баз данных
|
||||
ms: Direktori pangkalan data setempat
|
||||
pt-br: Diretorio de bancos de dados locais
|
||||
required: true
|
||||
type: text
|
||||
- default: generate
|
||||
edit: true
|
||||
envKey: WHODB_ENCRYPTION_KEY
|
||||
labelEn: Session Encryption Key
|
||||
labelZh: 会话加密密钥
|
||||
label:
|
||||
en: Session Encryption Key
|
||||
zh: 会话加密密钥
|
||||
zh-Hant: 工作階段加密金鑰
|
||||
ja: セッション暗号化キー
|
||||
ko: 세션 암호화 키
|
||||
ru: Ключ шифрования сеансов
|
||||
ms: Kunci penyulitan sesi
|
||||
pt-br: Chave de criptografia da sessao
|
||||
required: true
|
||||
type: password
|
||||
- default: "false"
|
||||
edit: true
|
||||
envKey: WHODB_SECURE
|
||||
labelEn: HTTPS Secure Cookie
|
||||
labelZh: HTTPS 安全 Cookie
|
||||
label:
|
||||
en: HTTPS Secure Cookie
|
||||
zh: HTTPS 安全 Cookie
|
||||
zh-Hant: HTTPS 安全 Cookie
|
||||
ja: HTTPS セキュア Cookie
|
||||
ko: HTTPS 보안 쿠키
|
||||
ru: Защищенные Cookie для HTTPS
|
||||
ms: Cookie selamat HTTPS
|
||||
pt-br: Cookie seguro HTTPS
|
||||
required: true
|
||||
type: select
|
||||
values:
|
||||
- label: "false"
|
||||
value: "false"
|
||||
- label: "true"
|
||||
value: "true"
|
||||
@@ -1,22 +0,0 @@
|
||||
services:
|
||||
whodb:
|
||||
image: clidey/whodb:0.127.0
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
- 1panel-network
|
||||
ports:
|
||||
- "${PANEL_APP_PORT_HTTP}:8080"
|
||||
environment:
|
||||
- WHODB_ENCRYPTION_KEY=${WHODB_ENCRYPTION_KEY}
|
||||
- WHODB_SECURE=${WHODB_SECURE}
|
||||
- WHODB_DATA_DIR=/data
|
||||
volumes:
|
||||
- "${APP_DATA_DIR}:/data"
|
||||
- "${DB_DATA_DIR}:/db"
|
||||
labels:
|
||||
createdBy: "Apps"
|
||||
|
||||
networks:
|
||||
1panel-network:
|
||||
external: true
|
||||
@@ -1,6 +1,6 @@
|
||||
CONTAINER_NAME=whodb-compose-check
|
||||
PANEL_APP_PORT_HTTP=8080
|
||||
APP_DATA_DIR=./data
|
||||
DB_DATA_DIR=./db-data
|
||||
WHODB_ENCRYPTION_KEY=generate
|
||||
WHODB_SECURE=false
|
||||
CONTAINER_NAME=whodb
|
||||
@@ -0,0 +1,128 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 8080
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-hant: HTTP 埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: HTTP-порт
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
tr: HTTP Bağlantı Noktası
|
||||
es-es: Puerto HTTP
|
||||
fa: درگاه HTTP
|
||||
lo: ພອດ HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: ./data
|
||||
edit: true
|
||||
envKey: APP_DATA_DIR
|
||||
labelEn: Data Directory
|
||||
labelZh: 数据目录
|
||||
label:
|
||||
en: Data Directory
|
||||
zh: 数据目录
|
||||
zh-hant: 資料目錄
|
||||
ja: データディレクトリ
|
||||
ko: 데이터 디렉터리
|
||||
ru: Каталог данных
|
||||
ms: Direktori data
|
||||
pt-br: Diretorio de dados
|
||||
tr: Veri Dizini
|
||||
es-es: Directorio de datos
|
||||
fa: فهرست دادهها
|
||||
lo: ໂຟນເດີຂໍ້ມູນ
|
||||
required: true
|
||||
type: text
|
||||
- default: ./db-data
|
||||
edit: true
|
||||
envKey: DB_DATA_DIR
|
||||
labelEn: Local Database Directory
|
||||
labelZh: 本地数据库目录
|
||||
label:
|
||||
en: Local Database Directory
|
||||
zh: 本地数据库目录
|
||||
zh-hant: 本機資料庫目錄
|
||||
ja: ローカルデータベースディレクトリ
|
||||
ko: 로컬 데이터베이스 디렉터리
|
||||
ru: Каталог локальных баз данных
|
||||
ms: Direktori pangkalan data setempat
|
||||
pt-br: Diretorio de bancos de dados locais
|
||||
tr: Yerel Veritabanı Dizini
|
||||
es-es: Directorio de base de datos local
|
||||
fa: فهرست پایگاه داده محلی
|
||||
lo: ໂຟນເດີຖານຂໍ້ມູນທ້ອງຖິ່ນ
|
||||
required: true
|
||||
type: text
|
||||
- default: generate
|
||||
edit: true
|
||||
envKey: WHODB_ENCRYPTION_KEY
|
||||
labelEn: Session Encryption Key
|
||||
labelZh: 会话加密密钥
|
||||
label:
|
||||
en: Session Encryption Key
|
||||
zh: 会话加密密钥
|
||||
zh-hant: 工作階段加密金鑰
|
||||
ja: セッション暗号化キー
|
||||
ko: 세션 암호화 키
|
||||
ru: Ключ шифрования сеансов
|
||||
ms: Kunci penyulitan sesi
|
||||
pt-br: Chave de criptografia da sessao
|
||||
tr: Oturum Şifreleme Anahtarı
|
||||
es-es: Clave de cifrado de sesión
|
||||
fa: کلید رمزنگاری نشست
|
||||
lo: ຄີເຂົ້າລະຫັດເຊດຊັນ
|
||||
required: true
|
||||
type: password
|
||||
- default: 'false'
|
||||
edit: true
|
||||
envKey: WHODB_SECURE
|
||||
labelEn: HTTPS Secure Cookie
|
||||
labelZh: HTTPS 安全 Cookie
|
||||
label:
|
||||
en: HTTPS Secure Cookie
|
||||
zh: HTTPS 安全 Cookie
|
||||
zh-hant: HTTPS 安全 Cookie
|
||||
ja: HTTPS セキュア Cookie
|
||||
ko: HTTPS 보안 쿠키
|
||||
ru: Защищенные Cookie для HTTPS
|
||||
ms: Cookie selamat HTTPS
|
||||
pt-br: Cookie seguro HTTPS
|
||||
tr: HTTPS Güvenli Çerezi
|
||||
es-es: Cookie segura HTTPS
|
||||
fa: کوکی امن HTTPS
|
||||
lo: ຄຸກກີປອດໄພ HTTPS
|
||||
required: true
|
||||
type: select
|
||||
values:
|
||||
- label: 'false'
|
||||
value: 'false'
|
||||
- label: 'true'
|
||||
value: 'true'
|
||||
- default: Asia/Shanghai
|
||||
edit: true
|
||||
envKey: TZ
|
||||
labelEn: Timezone
|
||||
labelZh: 时区
|
||||
label:
|
||||
en: Timezone
|
||||
zh: 时区
|
||||
zh-hant: 時區
|
||||
ja: タイムゾーン
|
||||
ko: 시간대
|
||||
ru: Часовой пояс
|
||||
ms: Zon waktu
|
||||
pt-br: Fuso horário
|
||||
tr: Saat Dilimi
|
||||
es-es: Zona horaria
|
||||
fa: منطقه زمانی
|
||||
lo: ເຂດເວລາ
|
||||
required: true
|
||||
type: text
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
whodb:
|
||||
image: clidey/whodb:latest
|
||||
image: "clidey/whodb:0.129.0"
|
||||
container_name: ${CONTAINER_NAME}
|
||||
restart: always
|
||||
networks:
|
||||
@@ -62,6 +62,40 @@ set_env_value() {
|
||||
mv -f -- "$temp_file" "$ENV_FILE"
|
||||
}
|
||||
|
||||
resolve_app_path() {
|
||||
local key="$1"
|
||||
local raw="$2"
|
||||
local clean candidate resolved current part
|
||||
local -a parts=()
|
||||
case "$raw" in
|
||||
""|/*|.|..|../*|*/../*|*/..) echo "unsafe ${key} path" >&2; return 1 ;;
|
||||
esac
|
||||
if [[ "$raw" =~ [[:cntrl:]] ]]; then
|
||||
echo "unsafe ${key} path" >&2
|
||||
return 1
|
||||
fi
|
||||
clean="${raw#./}"
|
||||
[[ -n "$clean" ]] || { echo "unsafe ${key} path" >&2; return 1; }
|
||||
command -v realpath >/dev/null 2>&1 || { echo "realpath is required" >&2; return 1; }
|
||||
candidate="$ROOT_DIR/$clean"
|
||||
resolved="$(realpath -m -- "$candidate")" || { echo "unsafe ${key} path" >&2; return 1; }
|
||||
case "$resolved" in
|
||||
"$ROOT_DIR"/*) ;;
|
||||
*) echo "unsafe ${key} path" >&2; return 1 ;;
|
||||
esac
|
||||
current="$ROOT_DIR"
|
||||
IFS='/' read -r -a parts <<< "$clean"
|
||||
for part in "${parts[@]}"; do
|
||||
[[ -z "$part" || "$part" == "." ]] && continue
|
||||
current="$current/$part"
|
||||
if [[ -L "$current" ]]; then
|
||||
echo "unsafe ${key} path" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
printf '%s\n' "$resolved"
|
||||
}
|
||||
|
||||
generate_key() {
|
||||
local value=""
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
@@ -89,20 +123,7 @@ write_key_cache() {
|
||||
|
||||
data_dir_raw="$(read_effective_value APP_DATA_DIR)"
|
||||
[[ -n "$data_dir_raw" ]] || data_dir_raw="./data"
|
||||
case "$data_dir_raw" in
|
||||
*$'\n'* | *$'\r'* | *\\* | *'$'* | *'#'* | *'"'* | *"'") fail "APP_DATA_DIR contains unsupported dotenv characters" ;;
|
||||
esac
|
||||
|
||||
case "$data_dir_raw" in
|
||||
/*) data_dir_abs="$(realpath -m -- "$data_dir_raw")" ;;
|
||||
*)
|
||||
data_dir_abs="$(realpath -m -- "${ROOT_DIR}/${data_dir_raw#./}")"
|
||||
case "$data_dir_abs" in
|
||||
"${ROOT_DIR}" | "${ROOT_DIR}"/*) ;;
|
||||
*) fail "Relative APP_DATA_DIR must stay inside the application directory" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
data_dir_abs="$(resolve_app_path "APP_DATA_DIR" "$data_dir_raw")"
|
||||
|
||||
[[ "$data_dir_abs" != "/" ]] || fail "APP_DATA_DIR must not be the filesystem root"
|
||||
if [[ -e "$data_dir_abs" && ! -d "$data_dir_abs" ]]; then
|
||||
@@ -112,20 +133,7 @@ mkdir -p -- "$data_dir_abs"
|
||||
|
||||
db_data_dir_raw="$(read_effective_value DB_DATA_DIR)"
|
||||
[[ -n "$db_data_dir_raw" ]] || db_data_dir_raw="./db-data"
|
||||
case "$db_data_dir_raw" in
|
||||
*$'\n'* | *$'\r'* | *\\* | *'$'* | *'#'* | *'"'* | *"'") fail "DB_DATA_DIR contains unsupported dotenv characters" ;;
|
||||
esac
|
||||
|
||||
case "$db_data_dir_raw" in
|
||||
/*) db_data_dir_abs="$(realpath -m -- "$db_data_dir_raw")" ;;
|
||||
*)
|
||||
db_data_dir_abs="$(realpath -m -- "${ROOT_DIR}/${db_data_dir_raw#./}")"
|
||||
case "$db_data_dir_abs" in
|
||||
"${ROOT_DIR}" | "${ROOT_DIR}"/*) ;;
|
||||
*) fail "Relative DB_DATA_DIR must stay inside the application directory" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
db_data_dir_abs="$(resolve_app_path "DB_DATA_DIR" "$db_data_dir_raw")"
|
||||
|
||||
[[ "$db_data_dir_abs" != "/" ]] || fail "DB_DATA_DIR must not be the filesystem root"
|
||||
[[ "$db_data_dir_abs" != "$data_dir_abs" ]] || fail "DB_DATA_DIR must differ from APP_DATA_DIR"
|
||||
@@ -159,7 +167,7 @@ secure_cookie="$(read_effective_value WHODB_SECURE)"
|
||||
[[ "$secure_cookie" == "true" || "$secure_cookie" == "false" ]] || fail "WHODB_SECURE must be true or false"
|
||||
|
||||
write_key_cache "$cache_file" "$encryption_key"
|
||||
set_env_value APP_DATA_DIR "$data_dir_raw"
|
||||
set_env_value DB_DATA_DIR "$db_data_dir_raw"
|
||||
set_env_value APP_DATA_DIR "$data_dir_abs"
|
||||
set_env_value DB_DATA_DIR "$db_data_dir_abs"
|
||||
set_env_value WHODB_ENCRYPTION_KEY "$encryption_key"
|
||||
set_env_value WHODB_SECURE "$secure_cookie"
|
||||
@@ -0,0 +1,35 @@
|
||||
# WhoDB
|
||||
|
||||
## Introduction
|
||||
|
||||
WhoDB is a lightweight browser workspace for exploring, querying, and editing multiple database systems.
|
||||
|
||||
## Features
|
||||
|
||||
- Browse schemas and edit data across multiple database engines.
|
||||
- Run queries, inspect relationships, and import or export data.
|
||||
- Optionally connect local or hosted AI providers.
|
||||
- Persist encrypted database login sessions.
|
||||
- Persist and connect local SQLite or DuckDB files through a separate directory.
|
||||
|
||||
## Access and configuration
|
||||
|
||||
After installation, open `http://<server-ip>:8080`; the actual published port is the value of `PANEL_APP_PORT_HTTP` in the installation form.
|
||||
|
||||
- `APP_DATA_DIR` is mounted at `/data` for encrypted sessions and the key cache.
|
||||
- `DB_DATA_DIR` is mounted at `/db` for local SQLite and DuckDB files. Enter a path relative to `/db`, such as `example.db`, in WhoDB.
|
||||
- Leave `WHODB_ENCRYPTION_KEY` as `generate` to create and persist a 64-character hexadecimal key. Do not replace the key while existing sessions are in use.
|
||||
- Set `WHODB_SECURE` to `true` when WhoDB is behind an HTTPS reverse proxy.
|
||||
|
||||
## Security and data handling
|
||||
|
||||
WhoDB stores database credentials in encrypted browser sessions. Protect the application `.env`, `APP_DATA_DIR`, `DB_DATA_DIR`, and backups. The Community image does not provide a separate global access login, so do not expose the port to an untrusted network; use a VPN, IP allowlist, or an authenticated 1Panel reverse proxy. Optional AI providers may receive user requests and database context, so review the selected provider's data and credential policy.
|
||||
|
||||
Back up both persistent directories before upgrades, migrations, or uninstalling.
|
||||
|
||||
## References
|
||||
|
||||
- Website: <https://whodb.com/>
|
||||
- Source: <https://github.com/clidey/whodb>
|
||||
- Documentation: <https://docs.whodb.com/>
|
||||
- Docker persistence: <https://github.com/clidey/whodb/blob/main/README.md#docker-with-persistent-sessions>
|
||||
+5
-1
@@ -13,12 +13,16 @@ additionalProperties:
|
||||
description:
|
||||
en: A lightweight workspace for multiple databases
|
||||
zh: 轻量级多数据库管理工作台
|
||||
zh-Hant: 輕量級多資料庫管理工作台
|
||||
zh-hant: 輕量級多資料庫管理工作台
|
||||
ja: 複数データベース向けの軽量管理ワークスペース
|
||||
ko: 여러 데이터베이스를 위한 가벼운 관리 작업 공간
|
||||
ru: Легковесная рабочая среда для управления разными базами данных
|
||||
ms: Ruang kerja ringan untuk mengurus pelbagai pangkalan data
|
||||
pt-br: Espaco de trabalho leve para gerenciar varios bancos de dados
|
||||
tr: Birden fazla veritabanı için hafif bir çalışma alanı
|
||||
es-es: Espacio de trabajo ligero para múltiples bases de datos
|
||||
fa: محیط کاری سبک برای چندین پایگاه داده
|
||||
lo: ພື້ນທີ່ເຮັດວຽກຂະໜາດເບົາສຳລັບຫຼາຍຖານຂໍ້ມູນ
|
||||
type: tool
|
||||
crossVersionUpdate: true
|
||||
limit: 1
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
PANEL_APP_PORT_HTTP=8080
|
||||
APP_DATA_DIR=./data
|
||||
DB_DATA_DIR=./db-data
|
||||
WHODB_ENCRYPTION_KEY=generate
|
||||
WHODB_SECURE=false
|
||||
CONTAINER_NAME=whodb
|
||||
@@ -1,88 +0,0 @@
|
||||
additionalProperties:
|
||||
formFields:
|
||||
- default: 8080
|
||||
edit: true
|
||||
envKey: PANEL_APP_PORT_HTTP
|
||||
labelEn: HTTP Port
|
||||
labelZh: HTTP 端口
|
||||
label:
|
||||
en: HTTP Port
|
||||
zh: HTTP 端口
|
||||
zh-Hant: HTTP 埠
|
||||
ja: HTTP ポート
|
||||
ko: HTTP 포트
|
||||
ru: HTTP-порт
|
||||
ms: Port HTTP
|
||||
pt-br: Porta HTTP
|
||||
required: true
|
||||
rule: paramPort
|
||||
type: number
|
||||
- default: ./data
|
||||
edit: true
|
||||
envKey: APP_DATA_DIR
|
||||
labelEn: Data Directory
|
||||
labelZh: 数据目录
|
||||
label:
|
||||
en: Data Directory
|
||||
zh: 数据目录
|
||||
zh-Hant: 資料目錄
|
||||
ja: データディレクトリ
|
||||
ko: 데이터 디렉터리
|
||||
ru: Каталог данных
|
||||
ms: Direktori data
|
||||
pt-br: Diretorio de dados
|
||||
required: true
|
||||
type: text
|
||||
- default: ./db-data
|
||||
edit: true
|
||||
envKey: DB_DATA_DIR
|
||||
labelEn: Local Database Directory
|
||||
labelZh: 本地数据库目录
|
||||
label:
|
||||
en: Local Database Directory
|
||||
zh: 本地数据库目录
|
||||
zh-Hant: 本機資料庫目錄
|
||||
ja: ローカルデータベースディレクトリ
|
||||
ko: 로컬 데이터베이스 디렉터리
|
||||
ru: Каталог локальных баз данных
|
||||
ms: Direktori pangkalan data setempat
|
||||
pt-br: Diretorio de bancos de dados locais
|
||||
required: true
|
||||
type: text
|
||||
- default: generate
|
||||
edit: true
|
||||
envKey: WHODB_ENCRYPTION_KEY
|
||||
labelEn: Session Encryption Key
|
||||
labelZh: 会话加密密钥
|
||||
label:
|
||||
en: Session Encryption Key
|
||||
zh: 会话加密密钥
|
||||
zh-Hant: 工作階段加密金鑰
|
||||
ja: セッション暗号化キー
|
||||
ko: 세션 암호화 키
|
||||
ru: Ключ шифрования сеансов
|
||||
ms: Kunci penyulitan sesi
|
||||
pt-br: Chave de criptografia da sessao
|
||||
required: true
|
||||
type: password
|
||||
- default: "false"
|
||||
edit: true
|
||||
envKey: WHODB_SECURE
|
||||
labelEn: HTTPS Secure Cookie
|
||||
labelZh: HTTPS 安全 Cookie
|
||||
label:
|
||||
en: HTTPS Secure Cookie
|
||||
zh: HTTPS 安全 Cookie
|
||||
zh-Hant: HTTPS 安全 Cookie
|
||||
ja: HTTPS セキュア Cookie
|
||||
ko: HTTPS 보안 쿠키
|
||||
ru: Защищенные Cookie для HTTPS
|
||||
ms: Cookie selamat HTTPS
|
||||
pt-br: Cookie seguro HTTPS
|
||||
required: true
|
||||
type: select
|
||||
values:
|
||||
- label: "false"
|
||||
value: "false"
|
||||
- label: "true"
|
||||
value: "true"
|
||||
@@ -1,165 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd -P)"
|
||||
ENV_FILE="${ENV_FILE:-${ROOT_DIR}/.env}"
|
||||
|
||||
fail() {
|
||||
printf '%s\n' "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
strip_matching_quotes() {
|
||||
local value="$1"
|
||||
if [[ ${#value} -ge 2 ]]; then
|
||||
if [[ "${value:0:1}" == '"' && "${value: -1}" == '"' ]]; then
|
||||
value="${value:1:${#value}-2}"
|
||||
elif [[ "${value:0:1}" == "'" && "${value: -1}" == "'" ]]; then
|
||||
value="${value:1:${#value}-2}"
|
||||
fi
|
||||
fi
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
read_env_value() {
|
||||
local key="$1"
|
||||
local value=""
|
||||
if [[ -f "$ENV_FILE" ]]; then
|
||||
value="$(grep -E "^${key}=" "$ENV_FILE" | tail -n 1 | cut -d '=' -f 2- || true)"
|
||||
fi
|
||||
strip_matching_quotes "$value"
|
||||
}
|
||||
|
||||
read_effective_value() {
|
||||
local key="$1"
|
||||
if [[ -v "$key" ]]; then
|
||||
strip_matching_quotes "${!key}"
|
||||
else
|
||||
read_env_value "$key"
|
||||
fi
|
||||
}
|
||||
|
||||
set_env_value() {
|
||||
local key="$1"
|
||||
local value="$2"
|
||||
local temp_file
|
||||
temp_file="$(mktemp "${ROOT_DIR}/.whodb-env.tmp.XXXXXX")"
|
||||
awk -v key="$key" -v value="$value" '
|
||||
BEGIN { written = 0 }
|
||||
$0 ~ "^" key "=" {
|
||||
if (!written) {
|
||||
print key "=" value
|
||||
written = 1
|
||||
}
|
||||
next
|
||||
}
|
||||
{ print }
|
||||
END {
|
||||
if (!written) print key "=" value
|
||||
}
|
||||
' "$ENV_FILE" > "$temp_file"
|
||||
chmod --reference="$ENV_FILE" "$temp_file"
|
||||
mv -f -- "$temp_file" "$ENV_FILE"
|
||||
}
|
||||
|
||||
generate_key() {
|
||||
local value=""
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
value="$(openssl rand -hex 32)"
|
||||
elif [[ -r /dev/urandom ]] && command -v od >/dev/null 2>&1; then
|
||||
value="$(od -An -N32 -tx1 /dev/urandom | tr -d ' \n')"
|
||||
fi
|
||||
[[ "$value" =~ ^[0-9a-f]{64}$ ]] || fail "Unable to generate a secure WhoDB encryption key"
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
write_key_cache() {
|
||||
local cache_file="$1"
|
||||
local value="$2"
|
||||
local temp_file
|
||||
umask 077
|
||||
temp_file="$(mktemp "${cache_file}.tmp.XXXXXX")"
|
||||
printf '%s\n' "$value" > "$temp_file"
|
||||
chmod 600 "$temp_file"
|
||||
mv -f -- "$temp_file" "$cache_file"
|
||||
}
|
||||
|
||||
[[ -f "$ENV_FILE" ]] || fail "$ENV_FILE not found"
|
||||
[[ ! -L "$ENV_FILE" ]] || fail "$ENV_FILE must not be a symbolic link"
|
||||
|
||||
data_dir_raw="$(read_effective_value APP_DATA_DIR)"
|
||||
[[ -n "$data_dir_raw" ]] || data_dir_raw="./data"
|
||||
case "$data_dir_raw" in
|
||||
*$'\n'* | *$'\r'* | *\\* | *'$'* | *'#'* | *'"'* | *"'") fail "APP_DATA_DIR contains unsupported dotenv characters" ;;
|
||||
esac
|
||||
|
||||
case "$data_dir_raw" in
|
||||
/*) data_dir_abs="$(realpath -m -- "$data_dir_raw")" ;;
|
||||
*)
|
||||
data_dir_abs="$(realpath -m -- "${ROOT_DIR}/${data_dir_raw#./}")"
|
||||
case "$data_dir_abs" in
|
||||
"${ROOT_DIR}" | "${ROOT_DIR}"/*) ;;
|
||||
*) fail "Relative APP_DATA_DIR must stay inside the application directory" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ "$data_dir_abs" != "/" ]] || fail "APP_DATA_DIR must not be the filesystem root"
|
||||
if [[ -e "$data_dir_abs" && ! -d "$data_dir_abs" ]]; then
|
||||
fail "APP_DATA_DIR must be a directory"
|
||||
fi
|
||||
mkdir -p -- "$data_dir_abs"
|
||||
|
||||
db_data_dir_raw="$(read_effective_value DB_DATA_DIR)"
|
||||
[[ -n "$db_data_dir_raw" ]] || db_data_dir_raw="./db-data"
|
||||
case "$db_data_dir_raw" in
|
||||
*$'\n'* | *$'\r'* | *\\* | *'$'* | *'#'* | *'"'* | *"'") fail "DB_DATA_DIR contains unsupported dotenv characters" ;;
|
||||
esac
|
||||
|
||||
case "$db_data_dir_raw" in
|
||||
/*) db_data_dir_abs="$(realpath -m -- "$db_data_dir_raw")" ;;
|
||||
*)
|
||||
db_data_dir_abs="$(realpath -m -- "${ROOT_DIR}/${db_data_dir_raw#./}")"
|
||||
case "$db_data_dir_abs" in
|
||||
"${ROOT_DIR}" | "${ROOT_DIR}"/*) ;;
|
||||
*) fail "Relative DB_DATA_DIR must stay inside the application directory" ;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
|
||||
[[ "$db_data_dir_abs" != "/" ]] || fail "DB_DATA_DIR must not be the filesystem root"
|
||||
[[ "$db_data_dir_abs" != "$data_dir_abs" ]] || fail "DB_DATA_DIR must differ from APP_DATA_DIR"
|
||||
if [[ -e "$db_data_dir_abs" && ! -d "$db_data_dir_abs" ]]; then
|
||||
fail "DB_DATA_DIR must be a directory"
|
||||
fi
|
||||
mkdir -p -- "$db_data_dir_abs"
|
||||
|
||||
cache_file="${data_dir_abs}/.whodb_encryption_key"
|
||||
[[ ! -L "$cache_file" ]] || fail "WhoDB encryption key cache must not be a symbolic link"
|
||||
if [[ -e "$cache_file" && ! -f "$cache_file" ]]; then
|
||||
fail "WhoDB encryption key cache must be a regular file"
|
||||
fi
|
||||
|
||||
cached_key=""
|
||||
if [[ -s "$cache_file" ]]; then
|
||||
cached_key="$(sed -n '1p' "$cache_file")"
|
||||
[[ "$cached_key" =~ ^[0-9a-f]{64}$ ]] || fail "Persisted WhoDB encryption key is invalid"
|
||||
fi
|
||||
|
||||
requested_key="$(read_effective_value WHODB_ENCRYPTION_KEY)"
|
||||
if [[ -z "$requested_key" || "$requested_key" == "generate" ]]; then
|
||||
encryption_key="${cached_key:-$(generate_key)}"
|
||||
else
|
||||
[[ "$requested_key" =~ ^[0-9a-fA-F]{64}$ ]] || fail "WHODB_ENCRYPTION_KEY must be generate or exactly 64 hexadecimal characters"
|
||||
encryption_key="${requested_key,,}"
|
||||
fi
|
||||
|
||||
secure_cookie="$(read_effective_value WHODB_SECURE)"
|
||||
[[ -n "$secure_cookie" ]] || secure_cookie=false
|
||||
[[ "$secure_cookie" == "true" || "$secure_cookie" == "false" ]] || fail "WHODB_SECURE must be true or false"
|
||||
|
||||
write_key_cache "$cache_file" "$encryption_key"
|
||||
set_env_value APP_DATA_DIR "$data_dir_raw"
|
||||
set_env_value DB_DATA_DIR "$db_data_dir_raw"
|
||||
set_env_value WHODB_ENCRYPTION_KEY "$encryption_key"
|
||||
set_env_value WHODB_SECURE "$secure_cookie"
|
||||
@@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
docker-compose down --volumes
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
exec "${SCRIPT_DIR}/init.sh"
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
Reference in New Issue
Block a user