poprawki i funkcje
This commit is contained in:
parent
8e7a0b3538
commit
f58e2c5da0
124
app.py
124
app.py
@ -12,8 +12,10 @@ import threading
|
|||||||
import time
|
import time
|
||||||
import requests
|
import requests
|
||||||
import smtplib
|
import smtplib
|
||||||
import atexit
|
|
||||||
from email.mime.text import MIMEText
|
from email.mime.text import MIMEText
|
||||||
|
from flask import current_app as app
|
||||||
|
from flask import render_template
|
||||||
|
import atexit
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
# Konfiguracja aplikacji
|
# Konfiguracja aplikacji
|
||||||
@ -108,10 +110,13 @@ def send_pushover_notification(user, message):
|
|||||||
print("Błąd przy wysyłaniu powiadomienia Pushover:", e)
|
print("Błąd przy wysyłaniu powiadomienia Pushover:", e)
|
||||||
|
|
||||||
def send_email_notification(user, subject, message):
|
def send_email_notification(user, subject, message):
|
||||||
|
# Sprawdzamy, czy ustawienia e-mail są poprawnie skonfigurowane
|
||||||
if not user.settings or not user.settings.email_notifications_enabled or not user.settings.smtp_server:
|
if not user.settings or not user.settings.email_notifications_enabled or not user.settings.smtp_server:
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
msg = MIMEText(message)
|
# Uzyskujemy sformatowaną treść e-maila
|
||||||
|
html_body = get_email_template(subject, message)
|
||||||
|
msg = MIMEText(html_body, 'html')
|
||||||
msg["Subject"] = subject
|
msg["Subject"] = subject
|
||||||
msg["From"] = user.settings.smtp_username
|
msg["From"] = user.settings.smtp_username
|
||||||
msg["To"] = user.email
|
msg["To"] = user.email
|
||||||
@ -121,8 +126,9 @@ def send_email_notification(user, subject, message):
|
|||||||
s.login(user.settings.smtp_username, user.settings.smtp_password)
|
s.login(user.settings.smtp_username, user.settings.smtp_password)
|
||||||
s.sendmail(user.settings.smtp_username, [user.email], msg.as_string())
|
s.sendmail(user.settings.smtp_username, [user.email], msg.as_string())
|
||||||
s.quit()
|
s.quit()
|
||||||
|
app.logger.debug("E-mail wysłany pomyślnie")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Błąd przy wysyłaniu powiadomienia e-mail:", e)
|
app.logger.error(f"Błąd przy wysyłaniu powiadomienia e-mail: {e}", exc_info=True)
|
||||||
|
|
||||||
# FUNKCJA SPRAWDZAJĄCA AKTUALIZACJE URZĄDZENIA
|
# FUNKCJA SPRAWDZAJĄCA AKTUALIZACJE URZĄDZENIA
|
||||||
def check_device_update(device):
|
def check_device_update(device):
|
||||||
@ -197,7 +203,61 @@ def check_device_update(device):
|
|||||||
app.logger.error(f"Error connecting to device {device.ip}: {e}", exc_info=True)
|
app.logger.error(f"Error connecting to device {device.ip}: {e}", exc_info=True)
|
||||||
return f"Error: {str(e)}", False, None, None
|
return f"Error: {str(e)}", False, None, None
|
||||||
|
|
||||||
|
def get_email_template(subject, message):
|
||||||
|
return f"""
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
body {{
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}}
|
||||||
|
.container {{
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 20px auto;
|
||||||
|
background-color: #ffffff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,0.1);
|
||||||
|
}}
|
||||||
|
.header {{
|
||||||
|
background-color: #007bff;
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 5px 5px 0 0;
|
||||||
|
}}
|
||||||
|
.content {{
|
||||||
|
margin: 20px 0;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}}
|
||||||
|
.footer {{
|
||||||
|
text-align: center;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #777777;
|
||||||
|
border-top: 1px solid #dddddd;
|
||||||
|
padding-top: 10px;
|
||||||
|
}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h2>{subject}</h2>
|
||||||
|
</div>
|
||||||
|
<div class="content">
|
||||||
|
<p>{message}</p>
|
||||||
|
</div>
|
||||||
|
<div class="footer">
|
||||||
|
<p>Wiadomość wygenerowana automatycznie przez system RouterOS Backup.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
"""
|
||||||
|
|
||||||
def check_all_devices():
|
def check_all_devices():
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
@ -272,8 +332,23 @@ scheduler.start()
|
|||||||
|
|
||||||
@app.route('/')
|
@app.route('/')
|
||||||
def index():
|
def index():
|
||||||
|
if current_user.is_authenticated:
|
||||||
|
return redirect(url_for('dashboard'))
|
||||||
return render_template('index.html')
|
return render_template('index.html')
|
||||||
|
|
||||||
|
@app.route('/dashboard')
|
||||||
|
@login_required
|
||||||
|
def dashboard():
|
||||||
|
devices_count = Device.query.count()
|
||||||
|
pending_updates_count = Device.query.filter_by(update_required=True).count()
|
||||||
|
logs_count = Log.query.count()
|
||||||
|
users_count = User.query.count()
|
||||||
|
return render_template('dashboard.html',
|
||||||
|
devices_count=devices_count,
|
||||||
|
pending_updates_count=pending_updates_count,
|
||||||
|
logs_count=logs_count,
|
||||||
|
users_count=users_count)
|
||||||
|
|
||||||
# Rejestracja
|
# Rejestracja
|
||||||
@app.route('/register', methods=['GET', 'POST'])
|
@app.route('/register', methods=['GET', 'POST'])
|
||||||
def register():
|
def register():
|
||||||
@ -307,7 +382,7 @@ def login():
|
|||||||
if user and user.check_password(password):
|
if user and user.check_password(password):
|
||||||
login_user(user)
|
login_user(user)
|
||||||
flash("Zalogowano pomyślnie.")
|
flash("Zalogowano pomyślnie.")
|
||||||
return redirect(url_for('devices'))
|
return redirect(url_for('dashboard'))
|
||||||
else:
|
else:
|
||||||
flash("Nieprawidłowa nazwa użytkownika lub hasło.")
|
flash("Nieprawidłowa nazwa użytkownika lub hasło.")
|
||||||
return render_template('login.html')
|
return render_template('login.html')
|
||||||
@ -421,7 +496,7 @@ def settings():
|
|||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
# Aktualizacja interwału zadania scheduler'a
|
# Aktualizacja interwału zadania scheduler'a, jeśli masz takie zadanie
|
||||||
try:
|
try:
|
||||||
scheduler.reschedule_job("check_all_devices", trigger="interval", seconds=user_settings.check_interval)
|
scheduler.reschedule_job("check_all_devices", trigger="interval", seconds=user_settings.check_interval)
|
||||||
app.logger.debug(f"Scheduler rescheduled with new interval: {user_settings.check_interval} seconds")
|
app.logger.debug(f"Scheduler rescheduled with new interval: {user_settings.check_interval} seconds")
|
||||||
@ -433,7 +508,6 @@ def settings():
|
|||||||
return render_template('settings.html', settings=user_settings)
|
return render_template('settings.html', settings=user_settings)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.route('/device/<int:device_id>/edit', methods=['GET', 'POST'])
|
@app.route('/device/<int:device_id>/edit', methods=['GET', 'POST'])
|
||||||
@login_required
|
@login_required
|
||||||
def edit_device(device_id):
|
def edit_device(device_id):
|
||||||
@ -531,7 +605,41 @@ def update_firmware(device_id):
|
|||||||
flash(f"Błąd podczas aktualizacji firmware: {e}")
|
flash(f"Błąd podczas aktualizacji firmware: {e}")
|
||||||
return redirect(url_for('device_detail', device_id=device.id))
|
return redirect(url_for('device_detail', device_id=device.id))
|
||||||
|
|
||||||
|
@app.route('/test_pushover', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def test_pushover():
|
||||||
|
message = "To jest testowe powiadomienie Pushover z RouterOS Update."
|
||||||
|
send_pushover_notification(current_user, message)
|
||||||
|
flash("Test powiadomienia Pushover wysłany.")
|
||||||
|
return redirect(url_for('settings'))
|
||||||
|
|
||||||
|
@app.route('/test_email', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def test_email():
|
||||||
|
subject = "Testowy E-mail z RouterOS Update"
|
||||||
|
message = "To jest testowa wiadomość e-mail wysłana z RouterOS Update."
|
||||||
|
send_email_notification(current_user, subject, message)
|
||||||
|
flash("Testowy e-mail wysłany.")
|
||||||
|
return redirect(url_for('settings'))
|
||||||
|
|
||||||
|
@app.route('/reset_password', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def reset_password():
|
||||||
|
if request.method == 'POST':
|
||||||
|
old_password = request.form.get('old_password')
|
||||||
|
new_password = request.form.get('new_password')
|
||||||
|
confirm_password = request.form.get('confirm_password')
|
||||||
|
if not current_user.check_password(old_password):
|
||||||
|
flash("Stare hasło jest nieprawidłowe.")
|
||||||
|
return redirect(url_for('reset_password'))
|
||||||
|
if new_password != confirm_password:
|
||||||
|
flash("Nowe hasło i potwierdzenie nie są zgodne.")
|
||||||
|
return redirect(url_for('reset_password'))
|
||||||
|
current_user.set_password(new_password)
|
||||||
|
db.session.commit()
|
||||||
|
flash("Hasło zostało zresetowane.")
|
||||||
|
return redirect(url_for('reset_password'))
|
||||||
|
return render_template('reset_password.html')
|
||||||
|
|
||||||
# Zamknięcie harmonogramu przy zatrzymaniu aplikacji
|
# Zamknięcie harmonogramu przy zatrzymaniu aplikacji
|
||||||
|
|
||||||
@ -539,4 +647,4 @@ atexit.register(lambda: scheduler.shutdown())
|
|||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
scheduler.add_job(func=clean_old_logs, trigger="interval", days=1)
|
scheduler.add_job(func=clean_old_logs, trigger="interval", days=1)
|
||||||
app.run(host='0.0.0.0', port=5581, use_reloader=False, debug=True)
|
app.run(host='0.0.0.0', port=5582, use_reloader=False, debug=True)
|
@ -10,27 +10,31 @@
|
|||||||
<body class="d-flex flex-column min-vh-100">
|
<body class="d-flex flex-column min-vh-100">
|
||||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<span class="navbar-brand">RouterOS Update</span>
|
|
||||||
|
<a href="{{ url_for('index') }}" class="navbar-brand">RouterOS Update</a>
|
||||||
|
<div>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarButtons" aria-controls="navbarButtons" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarButtons" aria-controls="navbarButtons" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="collapse navbar-collapse" id="navbarButtons">
|
<div class="collapse navbar-collapse" id="navbarButtons">
|
||||||
<div class="ms-auto">
|
<div class="ms-auto">
|
||||||
{% if current_user.is_authenticated %}
|
{% if current_user.is_authenticated %}
|
||||||
<div class="btn-group me-2" role="group">
|
<div class="btn-group me-2" role="group">
|
||||||
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('devices') }}'">Urządzenia</button>
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('dashboard') }}'">Dashboard</button>
|
||||||
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('logs') }}'">Logi</button>
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('devices') }}'">Urządzenia</button>
|
||||||
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('settings') }}'">Ustawienia</button>
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('logs') }}'">Logi</button>
|
||||||
</div>
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('settings') }}'">Ustawienia</button>
|
||||||
<div class="btn-group" role="group">
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('reset_password') }}'">Reset hasła</button>
|
||||||
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('logout') }}'">Wyloguj</button>
|
</div>
|
||||||
</div>
|
<div class="btn-group" role="group">
|
||||||
{% else %}
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('logout') }}'">Wyloguj</button>
|
||||||
<div class="btn-group me-2" role="group">
|
</div>
|
||||||
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('login') }}'">Logowanie</button>
|
{% else %}
|
||||||
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('register') }}'">Rejestracja</button>
|
<div class="btn-group me-2" role="group">
|
||||||
</div>
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('login') }}'">Logowanie</button>
|
||||||
{% endif %}
|
<button type="button" class="btn btn-outline-light" onclick="window.location.href='{{ url_for('register') }}'">Rejestracja</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
42
templates/dashboard.html
Normal file
42
templates/dashboard.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Dashboard - RouterOS Update{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="mb-4">Dashboard</h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card text-white bg-primary mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Urządzenia</h5>
|
||||||
|
<p class="card-text display-6">{{ devices_count }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card text-white bg-danger mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Wymagają aktualizacji</h5>
|
||||||
|
<p class="card-text display-6">{{ pending_updates_count }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card text-white bg-success mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Logi</h5>
|
||||||
|
<p class="card-text display-6">{{ logs_count }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="card text-white bg-secondary mb-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Użytkownicy</h5>
|
||||||
|
<p class="card-text display-6">{{ users_count }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Możesz dodać dodatkowe statystyki lub wykresy poniżej -->
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -1,16 +1,15 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% block title %}Strona główna - RouterOS Update{% endblock %}
|
{% block title %}Strona główna - RouterOS Update{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="p-5 mb-4 bg-light rounded-3">
|
<div class="d-flex flex-column align-items-center justify-content-center" style="min-height: 80vh;">
|
||||||
<div class="container-fluid py-5">
|
<div class="text-center">
|
||||||
<h1 class="display-5 fw-bold">Witamy w RouterOS Update</h1>
|
<img src="https://mikrotik.com/logo/assets/logo-colors-dark-ToiqSI6u.svg" alt="Mikrotik Logo" class="img-fluid" style="max-width: 200px;">
|
||||||
<p class="col-md-8 fs-4">Monitoruj swoje urządzenia, sprawdzaj aktualizacje oraz zarządzaj powiadomieniami w jednym miejscu.</p>
|
<h1 class="mt-3">Witamy w RouterOS Update</h1>
|
||||||
{% if not current_user.is_authenticated %}
|
<p class="lead">Zarządzaj aktualizacjami swoich urządzeń RouterOS w prosty sposób.</p>
|
||||||
<button type="button" class="btn btn-primary btn-lg" onclick="window.location.href='{{ url_for('login') }}'">Logowanie</button>
|
<div class="mt-4">
|
||||||
<button type="button" class="btn btn-secondary btn-lg" onclick="window.location.href='{{ url_for('register') }}'">Rejestracja</button>
|
<a href="{{ url_for('login') }}" class="btn btn-primary btn-lg me-3">Login</a>
|
||||||
{% else %}
|
<a href="{{ url_for('register') }}" class="btn btn-success btn-lg">Rejestracja</a>
|
||||||
<button type="button" class="btn btn-primary btn-lg" onclick="window.location.href='{{ url_for('devices') }}'">Moje urządzenia</button>
|
</div>
|
||||||
{% endif %}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
24
templates/reset_password.html
Normal file
24
templates/reset_password.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
{% block title %}Reset hasła - RouterOS Update{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<h2 class="mb-4">Reset hasła</h2>
|
||||||
|
<form method="POST">
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="old_password" class="form-label">Stare hasło</label>
|
||||||
|
<input type="password" class="form-control" name="old_password" id="old_password" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="new_password" class="form-label">Nowe hasło</label>
|
||||||
|
<input type="password" class="form-control" name="new_password" id="new_password" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label for="confirm_password" class="form-label">Potwierdź nowe hasło</label>
|
||||||
|
<input type="password" class="form-control" name="confirm_password" id="confirm_password" required>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Zresetuj hasło</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -3,7 +3,9 @@
|
|||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8">
|
<div class="col-md-8">
|
||||||
<h2>Ustawienia powiadomień</h2>
|
<h2 class="mb-4">Ustawienia powiadomień i systemu</h2>
|
||||||
|
|
||||||
|
<!-- Główny formularz ustawień -->
|
||||||
<form method="POST">
|
<form method="POST">
|
||||||
<fieldset class="border p-3 mb-3">
|
<fieldset class="border p-3 mb-3">
|
||||||
<legend class="w-auto">Pushover</legend>
|
<legend class="w-auto">Pushover</legend>
|
||||||
@ -21,7 +23,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<!-- Pozostała część formularza SMTP oraz interwału -->
|
|
||||||
<fieldset class="border p-3 mb-3">
|
<fieldset class="border p-3 mb-3">
|
||||||
<legend class="w-auto">SMTP (E-mail)</legend>
|
<legend class="w-auto">SMTP (E-mail)</legend>
|
||||||
<div class="form-check mb-2">
|
<div class="form-check mb-2">
|
||||||
@ -69,6 +70,18 @@
|
|||||||
|
|
||||||
<button type="submit" class="btn btn-primary">Zapisz ustawienia</button>
|
<button type="submit" class="btn btn-primary">Zapisz ustawienia</button>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Przyciski testowe w osobnym bloku, ułożone w jednej linii po prawej stronie -->
|
||||||
|
<div class="mt-4">
|
||||||
|
<div class="d-flex justify-content-end">
|
||||||
|
<form method="POST" action="{{ url_for('test_pushover') }}" class="d-inline me-2">
|
||||||
|
<button type="submit" class="btn btn-secondary">Test Pushover</button>
|
||||||
|
</form>
|
||||||
|
<form method="POST" action="{{ url_for('test_email') }}" class="d-inline">
|
||||||
|
<button type="submit" class="btn btn-secondary">Test E-mail</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user