Skip to content

Commit f810cda

Browse files
feat: Improve email templates and add email notifications for login/logout events
1 parent 62f065f commit f810cda

12 files changed

Lines changed: 352 additions & 42 deletions

File tree

src/routes/auth.py

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import datetime
12
from flask import Flask, render_template, redirect, url_for, request, blueprints, flash
23
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
34
from flask_sqlalchemy import SQLAlchemy
@@ -11,7 +12,7 @@
1112

1213
from src.config import app, db
1314
from src.models import User, SmptEamilPasswordConfig, DashboardSettings
14-
from src.utils import read_html_file
15+
from src.utils import render_template_from_file
1516

1617
auth_bp = blueprints.Blueprint('auth', __name__)
1718

@@ -67,16 +68,35 @@ def login():
6768
user = User.query.filter_by(username=username).first()
6869
if user and check_password_hash(user.password, password):
6970
login_user(user)
70-
# Get Admin Emails with Alerts Enabled:
71+
receiver_email = current_user.email
7172
admin_email_address = get_email_addresses(user_level='admin', receive_email_alerts=True)
73+
# if receiver_email in admin_email_address don't send email to the admin
74+
# log in alert to admin
75+
7276
if admin_email_address:
73-
login_body = read_html_file("src/templates/email_templates/login.html")
74-
send_email(admin_email_address, 'Login Alert', login_body, is_html=True)
75-
77+
context = {"username": current_user.username, "login_time": datetime.datetime.now()}
78+
login_body = render_template_from_file("src/templates/email_templates/admin_login_alert.html", **context)
79+
# send_email(admin_email_address, 'Login Alert', login_body, is_html=True)
80+
81+
# log in alert to user
82+
if receiver_email:
83+
context = {"username": current_user.username, "login_time": datetime.datetime.now()}
84+
login_body = render_template_from_file("src/templates/email_templates/login.html", **context)
85+
# send_email(receiver_email, 'Login Alert', login_body, is_html=True)
7686
return redirect(url_for('dashboard'))
7787
flash('Invalid username or password', 'danger')
7888
return render_template('login.html')
7989

90+
@app.route('/logout')
91+
def logout():
92+
receiver_email = current_user.email
93+
if receiver_email:
94+
context = {"username": current_user.username}
95+
logout_body = render_template_from_file("src/templates/email_templates/logout.html", **context)
96+
# send_email(receiver_email, 'Logout Alert', logout_body, is_html=True)
97+
logout_user()
98+
return redirect(url_for('login'))
99+
80100
@app.route('/signup', methods=['GET', 'POST'])
81101
def signup():
82102
if request.method == 'POST':
@@ -119,15 +139,6 @@ def protected():
119139
return f'Hello, Admin {current_user.username}! This is a protected page.'
120140
return f'Hello, {current_user.username}! This is a protected page.'
121141

122-
@app.route('/logout')
123-
def logout():
124-
receiver_email = get_email_addresses(user_level='admin', receive_email_alerts=True)
125-
if receiver_email:
126-
logout_body = read_html_file("src/templates/email_templates/logout.html")
127-
send_email(receiver_email, 'Logout Alert', logout_body, is_html=True)
128-
logout_user()
129-
return redirect(url_for('login'))
130-
131142
@app.route('/users')
132143
@login_required
133144
def view_users():

src/routes/process.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from flask import request, render_template, redirect, url_for, flash, session, blueprints
33
from flask_login import login_required, current_user
44
from src.config import app
5-
from src.utils import get_top_processes
5+
from src.utils import get_top_processes, render_template_from_file
66
from src.models import DashboardSettings
77
from src.scripts.email_me import send_email
88

@@ -34,8 +34,9 @@ def process():
3434
flash(f"Process '{process_name}' (PID {pid_to_kill}) killed successfully.", "success")
3535
receiver_email = current_user.email
3636
subject = f"Process '{process_name}' (PID {pid_to_kill}) killed successfully."
37-
body = f"Process '{process_name}' (PID {pid_to_kill}) was killed successfully by {current_user.username}."
38-
send_email(receiver_email, subject, body)
37+
context = {"process_name": process_name, "pid_to_kill": pid_to_kill, "username": current_user.username}
38+
html_body = render_template_from_file("src/templates/email_templates/process_killed.html", **context)
39+
send_email(receiver_email, subject, html_body, is_html=True)
3940
except Exception as e:
4041
flash(f"Failed to kill process '{process_name}' (PID {pid_to_kill}). Error: {e}", "danger")
4142
return redirect(url_for("process")) # Refresh the page after killing process

src/routes/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def card_toggles():
6363
settings.is_disk_usage_card_enabled = 'is_disk_usage_card_enabled' in request.form
6464
settings.is_system_uptime_card_enabled = 'is_system_uptime_card_enabled' in request.form
6565
settings.is_network_statistic_card_enabled = 'is_network_statistic_card_enabled' in request.form
66-
settings.is_network_usage_card_enabled = 'is_network_usage_card_enabled' in request.form
66+
settings.is_speedtest_enabled = 'is_speedtest_enabled' in request.form
6767
db.session.commit()
6868
flash('Card toggles updated successfully!', 'success')
6969
return redirect(url_for('card_toggles'))

src/routes/speedtest.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from flask_login import login_required, current_user
44
from src.config import app, db
55
from src.models import DashboardSettings, SpeedTestResult
6-
from src.utils import run_speedtest
6+
from src.utils import run_speedtest, render_template_from_file
77
from src.scripts.email_me import send_email
88

99
speedtest_bp = blueprints.Blueprint("speedtest", __name__)
@@ -38,8 +38,9 @@ def speedtest():
3838
db.session.commit()
3939
receiver_email = current_user.email
4040
subject = "Speedtest Result"
41-
body = f"Download Speed: {speedtest_result['download_speed']} \nUpload Speed: {speedtest_result['upload_speed']} \nPing: {speedtest_result['ping']} "
42-
send_email(receiver_email, subject, body)
41+
context = {"speedtest_result": speedtest_result}
42+
body = render_template_from_file("src/templates/email_templates/speedtest_result.html", **context)
43+
send_email(receiver_email, subject, body, is_html=True)
4344
return render_template(
4445
"speedtest_result.html",
4546
speedtest_result=speedtest_result,

src/templates/card_toggles.html

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -12,73 +12,73 @@ <h1 class="settings-title">Card Toggles</h1>
1212

1313
<div class="form-row">
1414
<div class="form-group">
15-
<label for="is_user_card_enabled">Enable User Card:</label>
15+
<label for="is_user_card_enabled">User Card:</label>
1616
<input type="checkbox" id="is_user_card_enabled" name="is_user_card_enabled" {% if settings.is_user_card_enabled %}checked{% endif %}>
1717
</div>
1818

1919
<div class="form-group">
20-
<label for="is_server_card_enabled">Enable Server Card:</label>
20+
<label for="is_server_card_enabled">Server Card:</label>
2121
<input type="checkbox" id="is_server_card_enabled" name="is_server_card_enabled" {% if settings.is_server_card_enabled %}checked{% endif %}>
2222
</div>
2323
</div>
2424

2525
<div class="form-row">
2626
<div class="form-group">
27-
<label for="is_battery_card_enabled">Enable Battery Card:</label>
27+
<label for="is_battery_card_enabled">Battery Card:</label>
2828
<input type="checkbox" id="is_battery_card_enabled" name="is_battery_card_enabled" {% if settings.is_battery_card_enabled %}checked{% endif %}>
2929
</div>
3030

3131
<div class="form-group">
32-
<label for="is_cpu_core_card_enabled">Enable CPU Core Card:</label>
32+
<label for="is_cpu_core_card_enabled">CPU Core Card:</label>
3333
<input type="checkbox" id="is_cpu_core_card_enabled" name="is_cpu_core_card_enabled" {% if settings.is_cpu_core_card_enabled %}checked{% endif %}>
3434
</div>
3535
</div>
3636

3737
<div class="form-row">
3838
<div class="form-group">
39-
<label for="is_cpu_usage_card_enabled">Enable CPU Usage Card:</label>
39+
<label for="is_cpu_usage_card_enabled">CPU Usage Card:</label>
4040
<input type="checkbox" id="is_cpu_usage_card_enabled" name="is_cpu_usage_card_enabled" {% if settings.is_cpu_usage_card_enabled %}checked{% endif %}>
4141
</div>
4242

4343
<div class="form-group">
44-
<label for="is_cpu_temp_card_enabled">Enable CPU Temp Card:</label>
44+
<label for="is_cpu_temp_card_enabled">CPU Temp Card:</label>
4545
<input type="checkbox" id="is_cpu_temp_card_enabled" name="is_cpu_temp_card_enabled" {% if settings.is_cpu_temp_card_enabled %}checked{% endif %}>
4646
</div>
4747
</div>
4848

4949
<div class="form-row">
5050
<div class="form-group">
51-
<label for="is_dashboard_memory_card_enabled">Enable Dashboard Memory Card:</label>
51+
<label for="is_dashboard_memory_card_enabled">Dashboard Memory Card:</label>
5252
<input type="checkbox" id="is_dashboard_memory_card_enabled" name="is_dashboard_memory_card_enabled" {% if settings.is_dashboard_memory_card_enabled %}checked{% endif %}>
5353
</div>
5454

5555
<div class="form-group">
56-
<label for="is_memory_usage_card_enabled">Enable Memory Usage Card:</label>
56+
<label for="is_memory_usage_card_enabled">Memory Usage Card:</label>
5757
<input type="checkbox" id="is_memory_usage_card_enabled" name="is_memory_usage_card_enabled" {% if settings.is_memory_usage_card_enabled %}checked{% endif %}>
5858
</div>
5959
</div>
6060

6161
<div class="form-row">
6262
<div class="form-group">
63-
<label for="is_disk_usage_card_enabled">Enable Disk Usage Card:</label>
63+
<label for="is_disk_usage_card_enabled">Disk Usage Card:</label>
6464
<input type="checkbox" id="is_disk_usage_card_enabled" name="is_disk_usage_card_enabled" {% if settings.is_disk_usage_card_enabled %}checked{% endif %}>
6565
</div>
6666

6767
<div class="form-group">
68-
<label for="is_system_uptime_card_enabled">Enable System Uptime Card:</label>
68+
<label for="is_system_uptime_card_enabled">System Uptime Card:</label>
6969
<input type="checkbox" id="is_system_uptime_card_enabled" name="is_system_uptime_card_enabled" {% if settings.is_system_uptime_card_enabled %}checked{% endif %}>
7070
</div>
7171
</div>
7272

7373
<div class="form-row">
7474
<div class="form-group">
75-
<label for="is_network_statistic_card_enabled">Enable Network Statistic Card:</label>
75+
<label for="is_network_statistic_card_enabled">Network Statistic Card:</label>
7676
<input type="checkbox" id="is_network_statistic_card_enabled" name="is_network_statistic_card_enabled" {% if settings.is_network_statistic_card_enabled %}checked{% endif %}>
7777
</div>
7878

7979
<div class="form-group">
80-
<label for="is_network_usage_card_enabled">Enable Network Usage Card:</label>
81-
<input type="checkbox" id="is_network_usage_card_enabled" name="is_network_usage_card_enabled" {% if settings.is_network_usage_card_enabled %}checked{% endif %}>
80+
<label for="is_speedtest_enabled">Speedtest Card:</label>
81+
<input type="checkbox" id="is_speedtest_enabled" name="is_speedtest_enabled" {% if settings.is_speedtest_enabled %}checked{% endif %}>
8282
</div>
8383
</div>
8484

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>User Login Alert</title>
8+
<style>
9+
body {
10+
font-family: 'Arial', sans-serif;
11+
background-color: #f4f4f4;
12+
margin: 0;
13+
padding: 20px;
14+
}
15+
16+
.email-container {
17+
max-width: 600px;
18+
margin: 50px auto;
19+
background-color: #ffffff;
20+
padding: 20px;
21+
border-radius: 8px;
22+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
23+
}
24+
25+
.header {
26+
background-color: #ff9800;
27+
color: white;
28+
padding: 10px;
29+
border-radius: 8px 8px 0 0;
30+
text-align: center;
31+
}
32+
33+
.header h1 {
34+
margin: 0;
35+
font-size: 24px;
36+
}
37+
38+
.content {
39+
padding: 20px;
40+
text-align: left;
41+
}
42+
43+
.content h2 {
44+
font-size: 20px;
45+
color: #333333;
46+
}
47+
48+
.content p {
49+
font-size: 16px;
50+
color: #666666;
51+
line-height: 1.5;
52+
margin: 10px 0;
53+
}
54+
55+
.footer {
56+
text-align: center;
57+
margin-top: 20px;
58+
font-size: 14px;
59+
color: #999999;
60+
}
61+
62+
.footer a {
63+
color: #ff9800;
64+
text-decoration: none;
65+
}
66+
</style>
67+
</head>
68+
69+
<body>
70+
<div class="email-container">
71+
<div class="header">
72+
<h1>SystemGuard Admin Alert</h1>
73+
</div>
74+
<div class="content">
75+
<h2>User Login Detected</h2>
76+
<p>Hello Admin,</p>
77+
<p>This is to notify you that the following user has logged into the SystemGuard application:</p>
78+
<p><strong>Username:</strong> {{ username }}</p>
79+
<p><strong>Login Time:</strong> {{ login_time }}</p>
80+
<p>If this activity is suspicious, please take the necessary action immediately.</p>
81+
</div>
82+
<div class="footer">
83+
<p>Thank you for using SystemGuard!</p>
84+
<p>If you have any questions, feel free to <a href="mailto:support@systemguard.com">contact us</a>.</p>
85+
</div>
86+
</div>
87+
</body>
88+
89+
</html>

src/templates/email_templates/login.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@
4949
</div>
5050
<div class="alert-body">
5151
Hello {{ username }},<br><br>
52-
We noticed a login to your account on {{ login_time }} from the IP address {{ ip_address }}.<br><br>
53-
If this was not you, please reset your password immediately.
52+
We noticed a login to your account on {{ login_time }}, This is a Notification that your account was accessed.
5453
</div>
5554
<div class="alert-footer">
5655
<a href="{{ url_for('reset_password') }}">Reset Password</a>

src/templates/email_templates/logout.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ <h1>SystemGuard Notification</h1>
8787
</div>
8888
<div class="content">
8989
<h2>You have been logged out</h2>
90-
<p>Hello,</p>
90+
<p>Hello, {{username}}!</p>
9191
<p>This is to inform you that your session has ended, and you have been logged out of the SystemGuard
9292
application. If this was not you, please contact the system administrator immediately.</p>
9393
<a href="{{login}}" class="button">Log in Again</a>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Process Killed Notification</title>
8+
<style>
9+
body {
10+
font-family: Arial, sans-serif;
11+
background-color: #f4f4f4;
12+
margin: 0;
13+
padding: 0;
14+
}
15+
16+
.email-container {
17+
max-width: 600px;
18+
margin: 50px auto;
19+
background-color: #ffffff;
20+
padding: 20px;
21+
border-radius: 8px;
22+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
23+
}
24+
25+
.header {
26+
background-color: #d9534f;
27+
color: white;
28+
padding: 10px;
29+
border-radius: 8px 8px 0 0;
30+
text-align: center;
31+
}
32+
33+
.header h1 {
34+
margin: 0;
35+
font-size: 24px;
36+
}
37+
38+
.content {
39+
padding: 20px;
40+
text-align: left;
41+
color: #333;
42+
}
43+
44+
.content p {
45+
font-size: 16px;
46+
margin: 0 0 15px;
47+
}
48+
49+
.footer {
50+
text-align: center;
51+
margin-top: 20px;
52+
font-size: 14px;
53+
color: #999;
54+
}
55+
56+
.footer a {
57+
color: #d9534f;
58+
text-decoration: none;
59+
}
60+
</style>
61+
</head>
62+
63+
<body>
64+
<div class="email-container">
65+
<div class="header">
66+
<h1>Process Killed Notification</h1>
67+
</div>
68+
<div class="content">
69+
<p>Hello,</p>
70+
<p>The process <strong>{{ process_name }}</strong> (PID <strong>{{ pid_to_kill }}</strong>) was killed successfully by <strong>{{ current_user.username }}</strong>.</p>
71+
<p>If you did not initiate this action, please contact the system administrator immediately.</p>
72+
</div>
73+
<div class="footer">
74+
<p>Thank you for using SystemGuard!</p>
75+
<p><a href="mailto:support@systemguard.com">Contact Support</a></p>
76+
</div>
77+
</div>
78+
</body>
79+
80+
</html>

0 commit comments

Comments
 (0)