acl do /login

This commit is contained in:
Mateusz Gruszczyński 2025-03-26 00:11:10 +01:00
parent 26a9d803a1
commit 60754ec23b
4 changed files with 53 additions and 2 deletions

1
alters.txt Normal file
View File

@ -0,0 +1 @@
ALTER TABLE global_settings ADD COLUMN allowed_login_hosts TEXT;

47
app.py
View File

@ -5,7 +5,10 @@ from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
from markupsafe import Markup
import markdown as md
from flask import abort
from flask import request, flash, abort
import os
import re
import socket
app = Flask(__name__)
# Ładujemy konfigurację z pliku config.py
@ -52,11 +55,32 @@ class GlobalSettings(db.Model):
id = db.Column(db.Integer, primary_key=True)
numer_konta = db.Column(db.String(50), nullable=False)
numer_telefonu_blik = db.Column(db.String(50), nullable=False)
allowed_login_hosts = db.Column(db.Text, nullable=True)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
def is_allowed_ip(remote_ip, allowed_hosts_str):
# Jeśli istnieje plik awaryjny, zawsze zezwalamy na dostęp
if os.path.exists("emergency_access.txt"):
return True
# Rozdzielamy wpisy mogą być oddzielone przecinkami lub znakami nowej linii
allowed_hosts = re.split(r'[\n,]+', allowed_hosts_str.strip())
allowed_ips = set()
for host in allowed_hosts:
host = host.strip()
if not host:
continue
try:
# Rozwiązywanie nazwy domeny do adresu IP.
resolved_ip = socket.gethostbyname(host)
allowed_ips.add(resolved_ip)
except Exception:
# Jeśli rozwiązywanie nazwy nie powiedzie się, pomijamy ten wpis.
continue
return remote_ip in allowed_ips
# Dodaj filtr Markdown pozwala na zagnieżdżanie linków i obrazków w opisie
@app.template_filter('markdown')
@ -86,6 +110,17 @@ def zbiorka(zbiorka_id):
@app.route('/login', methods=['GET', 'POST'])
def login():
# Pobierz ustawienia globalne, w tym dozwolone hosty
settings = GlobalSettings.query.first()
allowed_hosts_str = ""
if settings and settings.allowed_login_hosts:
allowed_hosts_str = settings.allowed_login_hosts
# Sprawdzenie, czy adres IP klienta jest dozwolony
if not is_allowed_ip(request.remote_addr, allowed_hosts_str):
flash('Dostęp do endpointu /login jest zablokowany dla Twojego adresu IP', 'danger')
return redirect(url_for('index'))
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
@ -99,6 +134,7 @@ def login():
flash('Nieprawidłowe dane logowania', 'danger')
return render_template('login.html')
@app.route('/logout')
@login_required
def logout():
@ -290,13 +326,19 @@ def admin_settings():
if request.method == 'POST':
numer_konta = request.form.get('numer_konta')
numer_telefonu_blik = request.form.get('numer_telefonu_blik')
allowed_login_hosts = request.form.get('allowed_login_hosts')
if settings is None:
settings = GlobalSettings(numer_konta=numer_konta, numer_telefonu_blik=numer_telefonu_blik)
settings = GlobalSettings(
numer_konta=numer_konta,
numer_telefonu_blik=numer_telefonu_blik,
allowed_login_hosts=allowed_login_hosts
)
db.session.add(settings)
else:
settings.numer_konta = numer_konta
settings.numer_telefonu_blik = numer_telefonu_blik
settings.allowed_login_hosts = allowed_login_hosts
db.session.commit()
flash('Ustawienia globalne zostały zaktualizowane', 'success')
@ -304,6 +346,7 @@ def admin_settings():
return render_template('admin/settings.html', settings=settings)
@app.route('/robots.txt')
def robots():
if app.config.get("BLOCK_BOTS", False):

3
emergency_access Normal file
View File

@ -0,0 +1,3 @@
Jeśli ten plik istwnieje w katalogu apliakcji, to wylacza zebzpieczenie logowania do panelu admina z ograniczeniem IP.
Musi miec rozszerzenie .txt

View File

@ -16,6 +16,10 @@
<label for="numer_telefonu_blik" class="form-label">Globalny numer telefonu BLIK</label>
<input type="text" class="form-control" id="numer_telefonu_blik" name="numer_telefonu_blik" value="{{ settings.numer_telefonu_blik if settings else '' }}" required>
</div>
<div class="mb-3">
<label for="allowed_login_hosts" class="form-label">Dozwolone hosty logowania</label>
<textarea class="form-control" id="allowed_login_hosts" name="allowed_login_hosts" rows="4" placeholder="Podaj adresy IP lub nazwy domen oddzielone przecinkami lub nowymi liniami">{{ settings.allowed_login_hosts if settings and settings.allowed_login_hosts else '' }}</textarea>
</div>
<button type="submit" class="btn btn-primary">Zapisz ustawienia</button>
<a href="{{ url_for('admin_dashboard') }}" class="btn btn-secondary">Powrót</a>
</form>