minor changes due problems deleting users and generating new passwords

This commit is contained in:
nocci 2025-05-04 17:30:25 +02:00
parent 602ddc7143
commit e8ea813896
1 changed files with 85 additions and 33 deletions

106
setup.sh
View File

@ -116,6 +116,8 @@ gunicorn
apprise
debugpy
pytz
Flask-Session
redis
EOL
# 3. .env Datei in Parent-Folder
@ -155,6 +157,9 @@ APPRISE_URLS=""
#gotify://gotify.example.com/TOKEN
#matrixs://TOKEN@matrix.org/!ROOM_ID"
# Redis URL
REDIS_URL=redis://redis:6379/0
# Enable Debug (e.g. for VS Code)
DEBUGPY=0
EOL
@ -186,12 +191,14 @@ from flask import (
abort
)
from flask_sqlalchemy import SQLAlchemy
from flask_session import Session
from flask_login import LoginManager, UserMixin, login_user, logout_user, login_required, current_user
from werkzeug.security import generate_password_hash, check_password_hash
from flask_wtf import CSRFProtect
from flask import abort
from flask import request, redirect
from flask_wtf import FlaskForm
from flask_wtf.csrf import CSRFProtect
from wtforms import StringField, SelectField, TextAreaField, validators
import io
import warnings
@ -232,6 +239,8 @@ from sqlalchemy.engine import Engine
import sqlite3
from sqlalchemy.orm import joinedload
from functools import wraps
from flask_session import Session
from redis import Redis
@event.listens_for(Engine, "connect")
def enable_foreign_keys(dbapi_connection, connection_record):
@ -287,7 +296,9 @@ if app.debug:
def admin_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if not current_user.is_authenticated or not getattr(current_user, 'is_admin', False):
if not current_user.is_authenticated:
abort(403)
if not current_user.is_admin:
abort(403)
return f(*args, **kwargs)
return decorated_function
@ -311,20 +322,38 @@ load_dotenv(override=True)
# App-Configuration
app.config.update(
# WICHTIGSTE EINSTELLUNGEN
SECRET_KEY=os.getenv('SECRET_KEY'),
SQLALCHEMY_DATABASE_URI = 'sqlite:////app/data/games.db',
SQLALCHEMY_TRACK_MODIFICATIONS = False,
# SESSION-HANDLING (Produktion: Redis verwenden!)
SESSION_TYPE='redis',
SESSION_PERMANENT = False,
SESSION_USE_SIGNER = True,
SESSION_REDIS=Redis.from_url(os.getenv("REDIS_URL", "redis://redis:6379/0")),
SESSION_FILE_DIR = '/app/data/flask-sessions',
SESSION_COOKIE_NAME = 'gamekeys_session',
SESSION_COOKIE_SECURE=os.getenv('SESSION_COOKIE_SECURE', 'False') == 'True',
SESSION_COOKIE_SECURE = os.getenv('SESSION_COOKIE_SECURE', 'False').lower() == 'true',
SESSION_COOKIE_HTTPONLY = True,
SESSION_COOKIE_SAMESITE = 'Lax',
PERMANENT_SESSION_LIFETIME = timedelta(days=30),
SESSION_REFRESH_EACH_REQUEST=False,
WTF_CSRF_ENABLED=os.getenv('CSRF_ENABLED', 'True') == 'True',
# CSRF-PROTECTION
WTF_CSRF_ENABLED = True,
WTF_CSRF_SECRET_KEY = os.getenv('CSRF_SECRET_KEY', os.urandom(32).hex()),
WTF_CSRF_TIME_LIMIT = 3600,
# SECURITYsa & PERFORMANCE
REGISTRATION_ENABLED = os.getenv('REGISTRATION_ENABLED', 'True').lower() == 'true',
SEND_FILE_MAX_AGE_DEFAULT = int(os.getenv('SEND_FILE_MAX_AGE_DEFAULT', 0)),
TEMPLATES_AUTO_RELOAD=os.getenv('TEMPLATES_AUTO_RELOAD', 'True') == 'True'
TEMPLATES_AUTO_RELOAD = os.getenv('TEMPLATES_AUTO_RELOAD', 'True').lower() == 'true',
PREFERRED_URL_SCHEME = 'https' if os.getenv('FORCE_HTTPS') else 'http'
)
Session(app)
interval_hours = int(os.getenv('CHECK_EXPIRING_KEYS_INTERVAL_HOURS', 12))
# Initialisation
@ -993,8 +1022,13 @@ def admin_reset_password(user_id):
new_password = secrets.token_urlsafe(8)
user.password = generate_password_hash(new_password)
db.session.commit()
flash(translate('New password for %(username)s: %(password)s',
username=user.username, password=new_password), 'info')
flash(
translate('New password for {username}: {password}',
username=user.username,
password=new_password),
'info'
)
return redirect(url_for('admin_users'))
@ -1922,9 +1956,9 @@ cat <<HTML_END > templates/admin_users.html
<button type="submit" class="btn btn-danger btn-sm">{{ _('Delete') }}</button>
</form>
<form method="POST" action="{{ url_for('admin_reset_password', user_id=user.id) }}" class="d-inline">
<form method="POST" action="{{ url_for('admin_reset_password', user_id=user.id) }}">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<button type="submit" class="btn btn-warning btn-sm">{{ _('Reset Password') }}</button>
<button type="submit" class="btn btn-warning">{{ _('Reset Password') }}</button>
</form>
{% endif %}
</td>
@ -2103,6 +2137,7 @@ chmod +x entrypoint.sh
# create translate.sh and run it
cat <<'SCRIPT_END' > ../translate.sh
#!/bin/bash
set -e
APP_DIR="steam-gift-manager"
@ -2114,35 +2149,32 @@ if ! command -v jq &>/dev/null; then
echo "❌ jq is required. Install with: sudo apt-get install jq"
exit 1
fi
echo -e "\n\033[1;32m✅ we are extracting translations from the templates.\033[0m"
# 1. Lege JSON-Dateien an, falls sie fehlen
echo -e "\n\033[1;32m✅ Extracting translations...\033[0m"
# 1. create json files
mkdir -p "$TRANSLATION_DIR"
for lang in "${LANGS[@]}"; do
file="$TRANSLATION_DIR/$lang.json"
if [ ! -f "$file" ]; then
echo "{}" > "$file"
echo "Created $file"
fi
[ -f "$file" ] || echo "{}" > "$file"
done
# 2. Extrahiere alle zu übersetzenden Strings
STRINGS=$(grep -rhoP "_\(\s*['\"](.+?)['\"]\s*\)" \
# 2. extract all strings
STRINGS=$(grep -rhoP "_\(\s*['\"]((?:[^']|'[^'])*?)['\"]\s*[,)]" \
"$APP_DIR/templates" "$APP_DIR/app.py" | \
sed -E "s/_\(\s*['\"](.+?)['\"]\s*\)/\1/" | sort | uniq)
sed -E "s/_\(\s*['\"](.+?)['\"]\s*[,)]/\1/" | sort | uniq)
# 3. Ergänze neue Keys in die JSON-Dateien
# 3. put da keys in da json
for lang in "${LANGS[@]}"; do
file="$TRANSLATION_DIR/$lang.json"
tmp="$file.tmp"
cp "$file" "$tmp"
while IFS= read -r key; do
if ! jq -e --arg k "$key" 'has($k)' "$tmp" >/dev/null; then
jq --arg k "$key" '. + {($k): ""}' "$tmp" > "$tmp.new" && mv "$tmp.new" "$tmp"
fi
done <<< "$STRINGS"
jq --argjson keys "$(echo "$STRINGS" | jq -R . | jq -s .)" \
'reduce $keys[] as $k (.; .[$k] = (.[$k] // ""))' "$file" > "$tmp"
mv "$tmp" "$file"
echo "Updated $file"
done
echo -e "\n\033[1;32m✅ JSON translation files updated. Please enter your translations!\033[0m"
echo -e "\n\033[1;32m✅ Done! Translation keys added.\033[0m"
SCRIPT_END
chmod +x ../translate.sh
@ -2201,6 +2233,15 @@ DOCKER_END
# 6. docker-compose.yml
cat <<COMPOSE_END > docker-compose.yml
services:
redis:
image: redis:alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
networks:
- app-network
steam-manager:
build:
context: .
@ -2214,6 +2255,7 @@ services:
- FLASK_DEBUG=0
- REGISTRATION_ENABLED=${REGISTRATION_ENABLED:-True}
- TZ=${TZ}
- REDIS_URL=redis://redis:6379/0
volumes:
- ../data:/app/data
- ./translations:/app/translations:rw
@ -2221,6 +2263,16 @@ services:
user: "${UID:-1000}:${GID:-1000}"
restart: unless-stopped
command: ["/app/entrypoint.sh"]
networks:
- app-network
depends_on:
- redis
volumes:
redis_data:
networks:
app-network:
driver: bridge
COMPOSE_END