Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0edb87c347 | |||
| 678cc61cef | |||
| f26ab5c5fb |
+2
-2
@@ -7116,8 +7116,8 @@ def register():
|
||||
name = (request.form.get('name') or '').strip()
|
||||
last_name = (request.form.get('last-name') or '').strip()
|
||||
|
||||
# Always generate username from abbreviation logic and auto-extend on collisions.
|
||||
username = us.build_unique_username_from_name(name, last_name)
|
||||
# Generate a truly anonymized username for new users.
|
||||
username = us.build_anonymous_username()
|
||||
|
||||
permission_preset = (request.form.get('permission_preset') or 'standard_user').strip()
|
||||
use_custom_permissions = request.form.get('use_custom_permissions') == 'on'
|
||||
|
||||
+57
-5
@@ -13,6 +13,8 @@ Provides methods for creating, validating, and retrieving user information.
|
||||
import hashlib
|
||||
import copy
|
||||
import re
|
||||
import secrets
|
||||
import string
|
||||
from bson.objectid import ObjectId
|
||||
import settings as cfg
|
||||
from settings import MongoClient
|
||||
@@ -57,6 +59,12 @@ def build_name_synonym(first_name, last_name=''):
|
||||
return combined[:6].title()
|
||||
|
||||
|
||||
def _generate_anonymous_username(prefix='user', length=8):
|
||||
"""Generate a random anonymized username using lowercase letters and digits."""
|
||||
alphabet = string.ascii_lowercase + string.digits
|
||||
return prefix + ''.join(secrets.choice(alphabet) for _ in range(length))
|
||||
|
||||
|
||||
def build_username_from_name(first_name, last_name=''):
|
||||
"""
|
||||
Build a deterministic username abbreviation from first and last name.
|
||||
@@ -73,6 +81,22 @@ def build_username_from_name(first_name, last_name=''):
|
||||
return alias.lower()
|
||||
|
||||
|
||||
def build_anonymous_username():
|
||||
"""
|
||||
Build a truly anonymized username that is not derived from the user's
|
||||
first name or last name.
|
||||
"""
|
||||
for _ in range(10):
|
||||
candidate = _generate_anonymous_username()
|
||||
if not get_user(candidate):
|
||||
return candidate
|
||||
|
||||
suffix = 2
|
||||
while get_user(f"user{suffix}"):
|
||||
suffix += 1
|
||||
return f"user{suffix}"
|
||||
|
||||
|
||||
def build_unique_username_from_name(first_name, last_name=''):
|
||||
"""
|
||||
Build a unique username based on the abbreviation logic.
|
||||
@@ -592,11 +616,39 @@ def get_user(username):
|
||||
dict: User document or None if not found
|
||||
"""
|
||||
client = MongoClient(cfg.MONGODB_HOST, cfg.MONGODB_PORT)
|
||||
db = client[cfg.MONGODB_DB]
|
||||
users = db['users']
|
||||
users_return = users.find_one({'Username': username})
|
||||
client.close()
|
||||
return users_return
|
||||
try:
|
||||
def find_in_db(database_name):
|
||||
db = client[database_name]
|
||||
users = db['users']
|
||||
return users.find_one({'Username': username}) or users.find_one({'username': username})
|
||||
|
||||
# Try current tenant first when available
|
||||
try:
|
||||
from tenant import get_tenant_context
|
||||
ctx = get_tenant_context()
|
||||
if ctx and ctx.db_name:
|
||||
user = find_in_db(ctx.db_name)
|
||||
if user:
|
||||
return user
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Fallback to default configured database
|
||||
user = find_in_db(cfg.MONGODB_DB)
|
||||
if user:
|
||||
return user
|
||||
|
||||
# Last fallback: search all tenant databases if the user belongs to a tenant-specific DB
|
||||
for database_name in client.list_database_names():
|
||||
if database_name == cfg.MONGODB_DB or not database_name.startswith('inventar_'):
|
||||
continue
|
||||
user = find_in_db(database_name)
|
||||
if user:
|
||||
return user
|
||||
|
||||
return None
|
||||
finally:
|
||||
client.close()
|
||||
|
||||
|
||||
def check_admin(username):
|
||||
|
||||
@@ -106,11 +106,16 @@ services:
|
||||
INVENTAR_DELETED_ARCHIVE_FOLDER: /data/deleted-archives
|
||||
|
||||
# Performance Tuning
|
||||
INVENTAR_WORKER_CLASS: gevent
|
||||
INVENTAR_WORKERS: "4"
|
||||
INVENTAR_THREADS: "2"
|
||||
INVENTAR_WORKER_TIMEOUT: "30"
|
||||
INVENTAR_WORKER_CONNECTIONS: "100"
|
||||
INVENTAR_WORKER_CLASS: ${INVENTAR_WORKER_CLASS:-gevent}
|
||||
INVENTAR_WORKERS: "${INVENTAR_WORKERS:-4}"
|
||||
INVENTAR_THREADS: "${INVENTAR_THREADS:-2}"
|
||||
INVENTAR_WORKER_TIMEOUT: "${INVENTAR_WORKER_TIMEOUT:-30}"
|
||||
INVENTAR_WORKER_CONNECTIONS: "${INVENTAR_WORKER_CONNECTIONS:-100}"
|
||||
|
||||
# Auto-scaled runtime settings
|
||||
INVENTAR_APP_CPUS: ${INVENTAR_APP_CPUS:-1.0}
|
||||
INVENTAR_APP_MEM_LIMIT: ${INVENTAR_APP_MEM_LIMIT:-256m}
|
||||
INVENTAR_APP_MEM_SWAP_LIMIT: ${INVENTAR_APP_MEM_SWAP_LIMIT:-512m}
|
||||
|
||||
# Multi-Tenant
|
||||
INVENTAR_MULTITENANT_ENABLED: "true"
|
||||
@@ -131,9 +136,9 @@ services:
|
||||
# Resource Limits (per instance)
|
||||
# With 10 instances: each gets ~150MB, totaling ~1.5GB
|
||||
# Adjust based on server resources
|
||||
mem_limit: 256m
|
||||
memswap_limit: 512m
|
||||
cpus: "1.0"
|
||||
mem_limit: "${INVENTAR_APP_MEM_LIMIT:-256m}"
|
||||
memswap_limit: "${INVENTAR_APP_MEM_SWAP_LIMIT:-512m}"
|
||||
cpus: "${INVENTAR_APP_CPUS:-1.0}"
|
||||
|
||||
# Health check for load balancer
|
||||
healthcheck:
|
||||
|
||||
@@ -504,12 +504,71 @@ ensure_min_docker_disk_space() {
|
||||
fi
|
||||
}
|
||||
|
||||
detect_server_capacity() {
|
||||
local cpus mem_kb mem_gb app_workers app_cpus app_mem app_mem_swap
|
||||
|
||||
cpus="$(nproc 2>/dev/null || echo 1)"
|
||||
mem_kb="$(awk '/MemAvailable:/ {print $2; exit}' /proc/meminfo 2>/dev/null || awk '/MemTotal:/ {print $2; exit}' /proc/meminfo || echo 0)"
|
||||
mem_gb=$(( (mem_kb + 1024*1024 - 1) / (1024*1024) ))
|
||||
|
||||
if [ "$cpus" -ge 8 ] && [ "$mem_gb" -ge 16 ]; then
|
||||
app_workers=8
|
||||
app_cpus="2.0"
|
||||
app_mem="512m"
|
||||
app_mem_swap="1024m"
|
||||
elif [ "$cpus" -ge 4 ] && [ "$mem_gb" -ge 8 ]; then
|
||||
app_workers=4
|
||||
app_cpus="1.0"
|
||||
app_mem="384m"
|
||||
app_mem_swap="768m"
|
||||
elif [ "$cpus" -ge 2 ] && [ "$mem_gb" -ge 4 ]; then
|
||||
app_workers=2
|
||||
app_cpus="0.75"
|
||||
app_mem="320m"
|
||||
app_mem_swap="640m"
|
||||
else
|
||||
app_workers=1
|
||||
app_cpus="0.5"
|
||||
app_mem="256m"
|
||||
app_mem_swap="512m"
|
||||
fi
|
||||
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
local env_app_cpus env_app_mem env_app_mem_swap env_workers
|
||||
env_app_cpus="$(awk -F= '/^INVENTAR_APP_CPUS=/{print $2; exit}' "$ENV_FILE" | tr -d ' ' || true)"
|
||||
env_app_mem="$(awk -F= '/^INVENTAR_APP_MEM_LIMIT=/{print $2; exit}' "$ENV_FILE" | tr -d ' ' || true)"
|
||||
env_app_mem_swap="$(awk -F= '/^INVENTAR_APP_MEM_SWAP_LIMIT=/{print $2; exit}' "$ENV_FILE" | tr -d ' ' || true)"
|
||||
env_workers="$(awk -F= '/^INVENTAR_WORKERS=/{print $2; exit}' "$ENV_FILE" | tr -d ' ' || true)"
|
||||
|
||||
[ -n "$env_app_cpus" ] && app_cpus="$env_app_cpus"
|
||||
[ -n "$env_app_mem" ] && app_mem="$env_app_mem"
|
||||
[ -n "$env_app_mem_swap" ] && app_mem_swap="$env_app_mem_swap"
|
||||
[ -n "$env_workers" ] && app_workers="$env_workers"
|
||||
fi
|
||||
|
||||
INVENTAR_APP_CPUS="${INVENTAR_APP_CPUS:-$app_cpus}"
|
||||
INVENTAR_APP_MEM_LIMIT="${INVENTAR_APP_MEM_LIMIT:-$app_mem}"
|
||||
INVENTAR_APP_MEM_SWAP_LIMIT="${INVENTAR_APP_MEM_SWAP_LIMIT:-$app_mem_swap}"
|
||||
INVENTAR_WORKERS="${INVENTAR_WORKERS:-$app_workers}"
|
||||
INVENTAR_THREADS="${INVENTAR_THREADS:-2}"
|
||||
|
||||
echo "Detected host capacity: CPUs=$cpus, RAM=${mem_gb}GB"
|
||||
echo "Configured app runtime: INVENTAR_WORKERS=$INVENTAR_WORKERS, INVENTAR_APP_CPUS=$INVENTAR_APP_CPUS, INVENTAR_APP_MEM_LIMIT=$INVENTAR_APP_MEM_LIMIT"
|
||||
}
|
||||
|
||||
write_env_file() {
|
||||
cat > "$ENV_FILE" <<EOF
|
||||
NUITKA_BUILD=$NUITKA_BUILD_VALUE
|
||||
INVENTAR_HTTP_PORT=$HTTP_PORT_VALUE
|
||||
INVENTAR_HTTP_PORTS=${HTTP_PORTS_VALUE// /,}
|
||||
INVENTAR_APP_IMAGE=$APP_IMAGE_VALUE
|
||||
INVENTAR_APP_CPUS=$INVENTAR_APP_CPUS
|
||||
INVENTAR_APP_MEM_LIMIT=$INVENTAR_APP_MEM_LIMIT
|
||||
INVENTAR_APP_MEM_SWAP_LIMIT=$INVENTAR_APP_MEM_SWAP_LIMIT
|
||||
INVENTAR_WORKERS=$INVENTAR_WORKERS
|
||||
INVENTAR_THREADS=$INVENTAR_THREADS
|
||||
INVENTAR_WORKER_TIMEOUT=${INVENTAR_WORKER_TIMEOUT:-30}
|
||||
INVENTAR_WORKER_CONNECTIONS=${INVENTAR_WORKER_CONNECTIONS:-100}
|
||||
EOF
|
||||
}
|
||||
|
||||
@@ -518,7 +577,7 @@ write_runtime_compose_override() {
|
||||
services:
|
||||
app:
|
||||
working_dir: /app/Web
|
||||
command: ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", "--workers", "2", "--timeout", "30", "--graceful-timeout", "20", "--max-requests", "200", "--max-requests-jitter", "50", "--log-level", "info", "--access-logfile", "-", "--error-logfile", "-"]
|
||||
command: ["gunicorn", "app:app", "--bind", "0.0.0.0:8000", "--workers", "${INVENTAR_WORKERS:-2}", "--threads", "${INVENTAR_THREADS:-2}", "--timeout", "${INVENTAR_WORKER_TIMEOUT:-30}", "--graceful-timeout", "20", "--worker-connections", "${INVENTAR_WORKER_CONNECTIONS:-100}", "--max-requests", "200", "--max-requests-jitter", "50", "--log-level", "info", "--access-logfile", "-", "--error-logfile", "-"]
|
||||
image: ${APP_IMAGE_VALUE}
|
||||
build: null
|
||||
EOF
|
||||
@@ -595,6 +654,7 @@ configure_nuitka_mode
|
||||
resolve_app_image
|
||||
configure_host_ports
|
||||
ensure_min_docker_disk_space
|
||||
detect_server_capacity
|
||||
ensure_app_image_loaded
|
||||
write_env_file
|
||||
write_runtime_compose_override
|
||||
|
||||
Reference in New Issue
Block a user