Skip to content

Commit 5e70fdf

Browse files
feat: option added to enable/disable notification alert
1 parent 006d616 commit 5e70fdf

12 files changed

Lines changed: 365 additions & 60 deletions

File tree

src/models.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ class User(db.Model, UserMixin):
8686
email = db.Column(db.String(150), unique=True, nullable=False)
8787
password = db.Column(db.String(150), nullable=False)
8888
user_level = db.Column(db.String(50), nullable=False, default='user')
89+
receive_email_alerts = db.Column(db.Boolean, default=True)
8990

9091

9192
class EmailPassword(db.Model):
@@ -108,7 +109,8 @@ class EmailPassword(db.Model):
108109
# Create admin user if not exists
109110
if not User.query.filter_by(username='admin').first():
110111
hashed_password = generate_password_hash('adminpassword')
111-
admin_user = User(username='admin', email="codeperfectplus@gmail.com", password=hashed_password, user_level='admin')
112+
admin_user = User(username='admin', email="codeperfectplus@gmail.com", password=hashed_password, user_level='admin',
113+
receive_email_alerts=True)
112114

113115
db.session.add(admin_user)
114116
db.session.commit()
@@ -117,7 +119,7 @@ class EmailPassword(db.Model):
117119
if not User.query.filter_by(username='user').first():
118120
hashed_password = generate_password_hash('userpassword')
119121
user = User(username='user', email="test@mail.com",
120-
password=hashed_password, user_level='user')
122+
password=hashed_password, user_level='user', receive_email_alerts=False)
121123

122124
db.session.add(user)
123125
db.session.commit()

src/routes/auth.py

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,24 @@
2020
def load_user(user_id):
2121
return User.query.get(int(user_id))
2222

23+
24+
def get_admin_emails_for_email_alerts():
25+
with app.app_context():
26+
admin_emails = User.query.filter_by(user_level='admin', receive_email_alerts=True).all()
27+
print(admin_emails)
28+
if not admin_emails:
29+
return None
30+
return [admin.email for admin in admin_emails]
31+
32+
def get_all_users_emails(receive_email_alerts=True):
33+
with app.app_context():
34+
users = User.query.filter_by(receive_email_alerts=receive_email_alerts).all()
35+
if not users:
36+
return None
37+
return [user.email for user in users]
38+
39+
40+
2341
@app.route('/login', methods=['GET', 'POST'])
2442
def login():
2543
if request.method == 'POST':
@@ -28,6 +46,10 @@ def login():
2846
user = User.query.filter_by(username=username).first()
2947
if user and check_password_hash(user.password, password):
3048
login_user(user)
49+
admin_email_address = get_admin_emails_for_email_alerts()
50+
if admin_email_address:
51+
send_email(admin_email_address, 'Login Alert', f'{user.username} logged in to the system.')
52+
3153
return redirect(url_for('dashboard'))
3254
flash('Invalid username or password', 'danger')
3355
return render_template('login.html')
@@ -50,6 +72,15 @@ def signup():
5072

5173
hashed_password = generate_password_hash(password)
5274
new_user = User(username=username, password=hashed_password)
75+
76+
admin_email_address = get_admin_emails_for_email_alerts()
77+
# extends the signup user to send an email to the admin
78+
if admin_email_address:
79+
send_email(admin_email_address, 'New User Alert', f'{username} has signed up to the system.')
80+
81+
# send email to the new user
82+
send_email([new_user.email], 'Welcome to the system', f'Hello {new_user.username}, welcome to the system.')
83+
5384
db.session.add(new_user)
5485
db.session.commit()
5586
flash('Account created successfully, please log in.')
@@ -90,25 +121,55 @@ def logout():
90121
# return f(*args, **kwargs)
91122
# return decorated_function
92123

124+
@app.route('/users')
125+
@login_required
126+
def view_users():
127+
if current_user.user_level != 'admin':
128+
flash("Your account does not have permission to view this page.", "danger")
129+
return render_template("error/permission_denied.html")
130+
131+
# Fetch all users from the database
132+
users = User.query.all()
133+
134+
return render_template('view_users.html', users=users)
135+
93136
@app.route('/user/<username>', methods=['GET', 'POST'])
94137
@login_required
95138
def change_user_settings(username):
96139
user = User.query.filter_by(username=username).first_or_404()
97140

98141
if request.method == 'POST':
99142
new_username = request.form['username']
143+
new_email = request.form['email']
100144
new_user_level = request.form['user_level']
101-
145+
receive_email_alerts = 'receive_email_alerts' in request.form
146+
102147
# Update user details
103148
user.username = new_username
149+
user.email = new_email
104150
user.user_level = new_user_level
151+
user.receive_email_alerts = receive_email_alerts
152+
105153
db.session.commit()
106-
154+
107155
flash('User settings updated successfully!', 'success')
108156
return redirect(url_for('change_user_settings', username=user.username))
109157

110158
return render_template('change_user.html', user=user)
111159

160+
@app.route('/delete_user/<username>', methods=['POST'])
161+
@login_required
162+
def delete_user(username):
163+
if current_user.user_level != 'admin':
164+
flash("Your account does not have permission to perform this action.", "danger")
165+
return redirect(url_for('view_users')) # Redirect to the users page
166+
167+
user = User.query.filter_by(username=username).first_or_404()
168+
db.session.delete(user)
169+
db.session.commit()
170+
171+
flash(f'User {username} has been deleted successfully!', 'success')
172+
return redirect(url_for('view_users'))
112173

113174
@app.route("/update-email-password", methods=["GET", "POST"])
114175
@login_required
@@ -134,17 +195,30 @@ def update_email_password():
134195
@login_required
135196
def send_email_page():
136197
if request.method == "POST":
137-
receiver_email = request.form.get("receiver_email")
198+
199+
receiver_email = request.form.get("recipient")
138200
subject = request.form.get("subject")
139201
body = request.form.get("body")
140202
attachment = request.files.get("attachment")
141203

204+
if not receiver_email or not subject or not body:
205+
flash("Please provide recipient, subject, and body.", "danger")
206+
return redirect(url_for('send_email_page'))
207+
208+
if receiver_email == "all_users":
209+
receiver_email = get_all_users_emails()
210+
elif receiver_email == "admin_users":
211+
receiver_email = get_admin_emails_for_email_alerts()
212+
213+
if not receiver_email:
214+
flash("No users found to send email to.", "danger")
215+
return redirect(url_for('send_email_page'))
216+
142217
# Save attachment if any
143218
attachment_path = None
144219
if attachment:
145220
attachment_path = f"/tmp/{attachment.filename}"
146221
attachment.save(attachment_path)
147-
148222
try:
149223
send_email(receiver_email, subject, body, attachment_path)
150224
flash("Email sent successfully!", "success")

src/routes/speedtest.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import datetime
22
from flask import render_template, blueprints
3-
3+
from flask_login import login_required, current_user
44
from src.config import app, db
55
from src.models import DashboardSettings, SpeedTestResult
66
from src.utils import run_speedtest
7+
from src.scripts.email_me import send_email
78

89
speedtest_bp = blueprints.Blueprint("speedtest", __name__)
910

1011
@app.route("/speedtest")
12+
@login_required
1113
def speedtest():
1214
settings = DashboardSettings.query.first()
1315
SPEEDTEST_COOLDOWN_IN_HOURS = settings.speedtest_cooldown
@@ -34,6 +36,10 @@ def speedtest():
3436
)
3537
db.session.add(new_result)
3638
db.session.commit()
39+
receiver_email = current_user.email
40+
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)
3743
return render_template(
3844
"speedtest_result.html",
3945
speedtest_result=speedtest_result,

src/scripts/email_me.py

Lines changed: 45 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from email.mime.text import MIMEText
55
from email.mime.base import MIMEBase
66
from email import encoders
7-
87
from dotenv import load_dotenv
98

109
# Load environment variables from .env file
@@ -14,48 +13,49 @@
1413
EMAIL_ADDRESS = os.getenv("EMAIL_ADDRESS")
1514
EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")
1615

17-
1816
def send_email(receiver_email, subject, body, attachment_path=None):
19-
try:
20-
# Create a multipart message
21-
msg = MIMEMultipart()
22-
msg['From'] = EMAIL_ADDRESS
23-
msg['To'] = receiver_email
24-
msg['Subject'] = subject
25-
# append message to the body
26-
append_message = "This is an automated email from the SystemGuru application. Please do not reply to this email."
27-
body = body + "\n\n" + append_message
28-
29-
# Attach the body with the msg instance
30-
msg.attach(MIMEText(body, 'plain'))
31-
32-
# Attach a file if provided
33-
if attachment_path:
34-
with open(attachment_path, "rb") as attachment:
35-
part = MIMEBase("application", "octet-stream")
36-
part.set_payload(attachment.read())
37-
encoders.encode_base64(part)
38-
part.add_header(
39-
"Content-Disposition",
40-
f"attachment; filename= {attachment_path}",
41-
)
42-
msg.attach(part)
43-
44-
# Create an SMTP session
45-
server = smtplib.SMTP('smtp.gmail.com', 587) # Use Gmail's SMTP server
46-
server.starttls() # Enable security
47-
48-
# Login with sender's email and password
49-
server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
50-
51-
# Send the email
52-
text = msg.as_string()
53-
server.sendmail(EMAIL_ADDRESS, receiver_email, text)
54-
55-
# Close the SMTP session
56-
server.quit()
57-
58-
print(f"Email sent successfully to {receiver_email}")
59-
60-
except Exception as e:
61-
print(f"Failed to send email. Error: {str(e)}")
17+
if isinstance(receiver_email, str):
18+
receiver_email = [receiver_email] # Convert single address to list
19+
20+
for email in receiver_email:
21+
try:
22+
# Create a multipart message
23+
msg = MIMEMultipart()
24+
msg['From'] = EMAIL_ADDRESS
25+
msg['To'] = email
26+
msg['Subject'] = subject
27+
# Append message to the body
28+
append_message = "This is an automated email from the SystemGuard application. Please do not reply to this email."
29+
full_body = body + "\n\n" + append_message
30+
31+
# Attach the body with the msg instance
32+
msg.attach(MIMEText(full_body, 'plain'))
33+
34+
# Attach a file if provided
35+
if attachment_path:
36+
with open(attachment_path, "rb") as attachment:
37+
part = MIMEBase("application", "octet-stream")
38+
part.set_payload(attachment.read())
39+
encoders.encode_base64(part)
40+
part.add_header(
41+
"Content-Disposition",
42+
f"attachment; filename= {os.path.basename(attachment_path)}",
43+
)
44+
msg.attach(part)
45+
46+
# Create an SMTP session
47+
with smtplib.SMTP('smtp.gmail.com', 587) as server: # Use Gmail's SMTP server
48+
server.starttls() # Enable security
49+
50+
# Login with sender's email and password
51+
server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
52+
53+
# Send the email
54+
text = msg.as_string()
55+
server.sendmail(EMAIL_ADDRESS, email, text)
56+
57+
print(f"Email sent successfully to {email}")
58+
59+
except Exception as e:
60+
print(f"Failed to send email to {email}. Error: {str(e)}")
61+

0 commit comments

Comments
 (0)