minor changes due problems deleting users and generating new passwords
This commit is contained in:
parent
602ddc7143
commit
e8ea813896
106
setup.sh
106
setup.sh
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue