Skip to content

Commit dd41d9b

Browse files
feat: Add "Add New User" button to view_users page
1 parent f810cda commit dd41d9b

18 files changed

Lines changed: 368 additions & 48 deletions

app.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
from src.config import app, db
1+
import datetime
2+
from src.config import app
23
from src import routes
4+
from src.utils import render_template_from_file, get_flask_memory_usage, cpu_usage_percent, get_memory_percent
5+
from src.models import User
6+
from src.scripts.email_me import send_email
37

48
def register_routes():
59
app.register_blueprint(routes.homepage_bp)
@@ -12,9 +16,31 @@ def register_routes():
1216
app.register_blueprint(routes.speedtest_bp)
1317
app.register_blueprint(routes.process_bp)
1418

19+
app.config['is_server_up_email_sent'] = False
20+
21+
def server_up_email():
22+
with app.app_context():
23+
admin_emails = [user.email for user in User.query.filter_by(user_level="admin", receive_email_alerts=True).all()]
24+
if admin_emails:
25+
subject = "SystemGuard Server Started"
26+
context = {
27+
"current_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
28+
"cpu_usage": cpu_usage_percent(),
29+
"memory_usage": get_memory_percent(),
30+
"app_memory_usage": get_flask_memory_usage(),
31+
32+
}
33+
html_body = render_template_from_file("src/templates/email_templates/server_up.html", **context)
34+
# send_email(admin_emails, subject, html_body, is_html=True)
35+
print("Server up email sent to", admin_emails)
36+
1537

1638
if __name__ == "__main__":
1739
register_routes()
40+
# TODO: fix this email alert sent twice
41+
# if not app.config['is_server_up_email_sent']:
42+
# app.config['is_server_up_email_sent'] = True
43+
# server_up_email()
1844

1945
# # Start the memory-consuming program in a separate thread
2046
# memory_thread = threading.Thread(target=memory_consuming_program, daemon=True)

src/config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@
1010

1111
# Initialize the database
1212
db = SQLAlchemy(app)
13+
14+
@app.cli.command("run")
15+
def server_start():
16+
print("Server started")

src/routes/auth.py

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,5 +292,30 @@ def terminal():
292292
return jsonify(output=output)
293293
return render_template('terminal.html')
294294

295-
if __name__ == '__main__':
296-
app.run(debug=True)
295+
@app.route('/add_user', methods=['GET', 'POST'])
296+
def add_user():
297+
if request.method == 'POST':
298+
username = request.form['username']
299+
email = request.form['email']
300+
password = request.form['password']
301+
user_level = request.form.get('user_level', 'user')
302+
receive_email_alerts = request.form.get('receive_email_alerts', 'on') == 'on'
303+
304+
# Check if user already exists
305+
if User.query.filter_by(username=username).first() or User.query.filter_by(email=email).first():
306+
flash('Username or email already exists.', 'danger')
307+
return redirect(url_for('add_user'))
308+
309+
new_user = User(
310+
username=username,
311+
email=email,
312+
password=generate_password_hash(password),
313+
user_level=user_level,
314+
receive_email_alerts=receive_email_alerts
315+
)
316+
db.session.add(new_user)
317+
db.session.commit()
318+
flash('User created successfully!', 'success')
319+
return redirect(url_for('view_users'))
320+
321+
return render_template('add_user.html')

src/routes/settings.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import datetime
12
from flask import render_template, request, flash, blueprints, redirect, url_for
23
from src.config import app, db
3-
from src.models import DashboardSettings
4+
from src.models import DashboardSettings, User
45
from flask_login import login_required, current_user
6+
from src.utils import render_template_from_file
7+
from src.scripts.email_me import send_email
58

69
settings_bp = blueprints.Blueprint("settings", __name__)
710

@@ -27,6 +30,17 @@ def general_settings():
2730
settings.timezone = request.form.get('timezone')
2831
settings.enable_cache = 'enable_cache' in request.form
2932
settings.enable_alerts = 'enable_alerts' in request.form
33+
admin_emails = [user.email for user in User.query.filter_by(user_level="admin", receive_email_alerts=True).all()]
34+
if admin_emails:
35+
subject = "SystemGuard Server Started"
36+
context = {
37+
"current_time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
38+
"notifications_enabled": settings.enable_alerts,
39+
"current_user": current_user.username
40+
}
41+
html_body = render_template_from_file("src/templates/email_templates/notification_alert.html", **context)
42+
print("Notification enabled:", settings.enable_alerts)
43+
send_email(admin_emails, subject, html_body, is_html=True, bypass_alerts=True)
3044
db.session.commit()
3145
flash('General settings updated successfully!', 'success')
3246
return redirect(url_for('general_settings'))

src/scripts/email_me.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,23 @@
88
from src.config import app
99
from src.models import SmptEamilPasswordConfig, DashboardSettings
1010

11-
def send_email(receiver_email, subject, body, attachment_path=None, is_html=False):
11+
system_name = os.uname().sysname
12+
13+
def send_email(receiver_email, subject, body, attachment_path=None, is_html=False, bypass_alerts=False):
1214

1315
if isinstance(receiver_email, str):
1416
receiver_email = [receiver_email] # Convert single address to list
1517

1618
with app.app_context():
17-
dashboard_settings = DashboardSettings.query.first()
18-
if dashboard_settings:
19-
enable_alerts = dashboard_settings.enable_alerts
20-
if not enable_alerts:
21-
print("Email alerts are disabled. Please enable them in the settings.")
22-
flash("Email alerts are disabled. Please enable them in the settings.", "danger")
23-
return redirect(url_for('general_settings'))
24-
19+
if not bypass_alerts:
20+
dashboard_settings = DashboardSettings.query.first()
21+
if dashboard_settings:
22+
enable_alerts = dashboard_settings.enable_alerts
23+
if not enable_alerts:
24+
print("Email alerts are disabled. Please enable them in the settings.")
25+
flash("Email alerts are disabled. Please enable them in the settings.", "danger")
26+
return redirect(url_for('general_settings'))
27+
2528
email_password = SmptEamilPasswordConfig.query.first()
2629
if not email_password:
2730
print("SMTP email credentials not found. Please set EMAIL_ADDRESS and EMAIL_PASSWORD environment variables.")
@@ -35,11 +38,12 @@ def send_email(receiver_email, subject, body, attachment_path=None, is_html=Fals
3538

3639
for email in receiver_email:
3740
try:
41+
server_name = os.uname().nodename
3842
# Create a multipart message
3943
msg = MIMEMultipart()
4044
msg['From'] = EMAIL_ADDRESS
4145
msg['To'] = email
42-
msg['Subject'] = "SystemGuard Alert:" + subject
46+
msg['Subject'] = "SystemGuard Alert from " + system_name + " (" + server_name + "): " + subject
4347
# Append message to the body
4448
append_message = "This is an automated email from the SystemGuard application. Please do not reply to this email."
4549

src/static/css/add_user.css

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/* add_user.css */
2+
3+
.add-user-container {
4+
padding: 30px;
5+
max-width: 600px;
6+
margin: 0 auto;
7+
background-color: #ffffff;
8+
border: 1px solid #ddd;
9+
border-radius: 8px;
10+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
11+
}
12+
13+
.page-title {
14+
margin-bottom: 20px;
15+
font-size: 28px;
16+
font-weight: bold;
17+
color: #333;
18+
text-align: center;
19+
}
20+
21+
form {
22+
display: flex;
23+
flex-direction: column;
24+
gap: 15px;
25+
}
26+
27+
label {
28+
font-size: 16px;
29+
color: #333;
30+
}
31+
32+
input[type="text"],
33+
input[type="email"],
34+
input[type="password"],
35+
select {
36+
font-size: 16px;
37+
padding: 10px;
38+
border: 1px solid #ddd;
39+
border-radius: 4px;
40+
width: 100%;
41+
box-sizing: border-box;
42+
}
43+
44+
input[type="checkbox"] {
45+
margin-right: 10px;
46+
}
47+
48+
button {
49+
background-color: #007bff;
50+
color: white;
51+
padding: 12px;
52+
border: none;
53+
border-radius: 4px;
54+
cursor: pointer;
55+
font-size: 16px;
56+
transition: background-color 0.3s ease;
57+
width: 100%;
58+
}
59+
60+
button:hover {
61+
background-color: #0056b3;
62+
}

src/static/css/view_users.css

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,39 @@
1+
/* view_users.css */
2+
13
.view-users-container {
24
padding: 20px;
5+
max-width: 1200px;
6+
margin: 0 auto;
7+
background-color: #ffffff;
8+
border: 1px solid #ddd;
9+
border-radius: 8px;
10+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
311
}
412

513
.page-title {
614
margin-bottom: 20px;
715
font-size: 24px;
816
font-weight: bold;
17+
color: #333;
18+
display: flex;
19+
justify-content: space-between;
20+
align-items: center;
21+
}
22+
23+
.btn-add-user {
24+
background-color: #28a745;
25+
color: white;
26+
padding: 10px 20px;
27+
text-decoration: none;
28+
border-radius: 4px;
29+
font-size: 16px;
30+
display: inline-block;
31+
margin-top: 10px;
32+
margin-bottom: 10px;
33+
}
34+
35+
.btn-add-user:hover {
36+
background-color: #218838;
937
}
1038

1139
.user-table {
@@ -15,18 +43,23 @@
1543

1644
.user-table th, .user-table td {
1745
border: 1px solid #ddd;
18-
padding: 8px;
46+
padding: 12px;
47+
text-align: left;
1948
}
2049

2150
.user-table th {
2251
background-color: #f4f4f4;
23-
text-align: left;
52+
font-weight: bold;
2453
}
2554

2655
.user-table tr:nth-child(even) {
2756
background-color: #f9f9f9;
2857
}
2958

59+
.user-table tr:hover {
60+
background-color: #f1f1f1;
61+
}
62+
3063
.btn-edit {
3164
background-color: #007bff;
3265
color: white;
@@ -46,6 +79,7 @@
4679
border: none;
4780
border-radius: 4px;
4881
cursor: pointer;
82+
font-size: 14px;
4983
}
5084

5185
.btn-delete:hover {

src/templates/add_user.html

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{% extends 'base.html' %}
2+
{% block title %}Add New User{% endblock %}
3+
{% block extra_head %}
4+
<link rel="stylesheet" href="{{ url_for('static', filename='css/add_user.css') }}">
5+
{% endblock %}
6+
{% block content %}
7+
<div class="add-user-container">
8+
<h2 class="page-title">Add New User</h2>
9+
<form action="{{ url_for('add_user') }}" method="post">
10+
<label for="username">Username:</label>
11+
<input type="text" id="username" name="username" required>
12+
13+
<label for="email">Email:</label>
14+
<input type="email" id="email" name="email" required>
15+
16+
<label for="password">Password:</label>
17+
<input type="password" id="password" name="password" required>
18+
19+
<label for="user_level">User Level:</label>
20+
<select id="user_level" name="user_level">
21+
<option value="user">User</option>
22+
<option value="admin">Admin</option>
23+
</select>
24+
25+
<label for="receive_email_alerts">Receive Email Alerts:</label>
26+
<input type="checkbox" id="receive_email_alerts" name="receive_email_alerts" checked>
27+
28+
<button type="submit">Add User</button>
29+
</form>
30+
</div>
31+
{% endblock %}

src/templates/email_templates/admin_login_alert.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ <h2>User Login Detected</h2>
8181
</div>
8282
<div class="footer">
8383
<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>
84+
<p>If you have any questions, feel free to <a href="mailto:codeperfectplus@gmail.com">contact us</a>.</p>
8585
</div>
8686
</div>
8787
</body>

src/templates/email_templates/login.html

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,6 @@
5151
Hello {{ username }},<br><br>
5252
We noticed a login to your account on {{ login_time }}, This is a Notification that your account was accessed.
5353
</div>
54-
<div class="alert-footer">
55-
<a href="{{ url_for('reset_password') }}">Reset Password</a>
56-
</div>
5754
</div>
5855
</body>
5956

0 commit comments

Comments
 (0)