Skip to content

Commit f1a4389

Browse files
feat: Add different email alerts and dashboards for different users
- Implement different email alerts for different actions - Create separate dashboards for different user roles (Developer, Admin, IT Manager, Manager) - Update relevant templates to reflect the changes
1 parent c00f0be commit f1a4389

17 files changed

Lines changed: 260 additions & 112 deletions

File tree

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ chmod +x install_miniconda.sh && sudo ./install_miniconda.sh
5757
- Update itself to the latest version.
5858
- Easy download and installation using a bash script.
5959
- Logged user and admin user will get the notification if the user kill some process manully on dashbaord.
60+
- Different email alerts for different actions.
61+
- Different Dashboards for different users.(Deveoper, Admin, IT Manager, Manager)
6062

6163
## Email Feature 📧
6264

src/assets/predefine_user.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"username": "admin",
4+
"email": "codeperfectplus@gmail.com",
5+
"password": "admin",
6+
"user_level": "admin",
7+
"profession": "developer",
8+
"receive_email_alerts": true
9+
},
10+
{
11+
"username": "manager",
12+
"email": "dr47806@gmail.com",
13+
"password": "manager",
14+
"user_level": "user",
15+
"profession": "manager",
16+
"receive_email_alerts": true
17+
}
18+
]

src/models.py

Lines changed: 62 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import json
12
import datetime
2-
from flask_login import UserMixin
3+
from flask_login import UserMixin, current_user
34
from werkzeug.security import generate_password_hash, check_password_hash
45

5-
from src.config import db, app
66

7+
from src.config import db, app
78

89
class SpeedTestResult(db.Model):
910
__tablename__ = "SpeedTestResult"
@@ -18,28 +19,37 @@ def __repr__(self):
1819
f"<SpeedTestResult {self.download_speed}, {self.upload_speed}, {self.ping}>"
1920
)
2021

21-
class DashboardSettings(db.Model):
22-
__tablename__ = "DashboardSettings"
22+
class User(db.Model, UserMixin):
23+
__tablename__ = 'users'
24+
2325
id = db.Column(db.Integer, primary_key=True)
26+
username = db.Column(db.String(50), unique=True, nullable=False)
27+
email = db.Column(db.String(100), unique=True, nullable=False)
28+
password = db.Column(db.String(100), nullable=False)
29+
user_level = db.Column(db.String(10), nullable=False, default='user')
30+
receive_email_alerts = db.Column(db.Boolean, default=False)
31+
profession = db.Column(db.String(50), nullable=True)
2432

25-
# speedtest setting
26-
speedtest_cooldown = db.Column(db.Integer, default=1)
27-
number_of_speedtests = db.Column(db.Integer, default=1)
33+
# Backref renamed to avoid conflict
34+
dashboard_settings = db.relationship('DashboardSettings', backref='user', uselist=False)
2835

29-
# general settings
30-
timezone = db.Column(db.String(50), default="Asia/Kolkata")
31-
enable_cache = db.Column(db.Boolean, default=True)
32-
enable_alerts = db.Column(db.Boolean, default=False)
36+
class DashboardSettings(db.Model):
37+
__tablename__ = 'dashboard_settings'
3338

34-
# page enable/disable
39+
id = db.Column(db.Integer, primary_key=True)
40+
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
41+
42+
speedtest_cooldown = db.Column(db.Integer, default=3600)
43+
number_of_speedtests = db.Column(db.Integer, default=3)
44+
45+
# Feature Toggles
3546
is_cpu_info_enabled = db.Column(db.Boolean, default=True)
3647
is_memory_info_enabled = db.Column(db.Boolean, default=True)
3748
is_disk_info_enabled = db.Column(db.Boolean, default=True)
3849
is_network_info_enabled = db.Column(db.Boolean, default=True)
39-
is_process_info_enabled = db.Column(db.Boolean, default=False)
50+
is_process_info_enabled = db.Column(db.Boolean, default=True)
4051

41-
42-
# card enable/disable
52+
# Card Toggles
4353
is_user_card_enabled = db.Column(db.Boolean, default=True)
4454
is_server_card_enabled = db.Column(db.Boolean, default=True)
4555
is_battery_card_enabled = db.Column(db.Boolean, default=True)
@@ -51,10 +61,15 @@ class DashboardSettings(db.Model):
5161
is_disk_usage_card_enabled = db.Column(db.Boolean, default=True)
5262
is_system_uptime_card_enabled = db.Column(db.Boolean, default=True)
5363
is_network_statistic_card_enabled = db.Column(db.Boolean, default=True)
54-
is_speedtest_enabled = db.Column(db.Boolean, default=False)
55-
56-
def __repr__(self):
57-
return f"<DashboardSettings {self.speedtest_cooldown}, {self.timezone}, {self.number_of_speedtests}>"
64+
is_speedtest_enabled = db.Column(db.Boolean, default=True)
65+
66+
class GeneralSettings(db.Model):
67+
__tablename__ = 'general_settings'
68+
69+
id = db.Column(db.Integer, primary_key=True)
70+
enable_alerts = db.Column(db.Boolean, default=False)
71+
timezone = db.Column(db.String(50), default='UTC')
72+
enable_cache = db.Column(db.Boolean, default=False)
5873

5974

6075
class SystemInfo(db.Model):
@@ -81,13 +96,6 @@ class SystemInfo(db.Model):
8196
def __repr__(self):
8297
return f"<SystemInfo {self.username}, {self.cpu_percent}, {self.memory_percent}, {self.disk_usage}, {self.battery_percent}, {self.cpu_core}, {self.boot_time}, {self.network_sent}, {self.network_received}, {self.process_count}, {self.swap_memory}, {self.uptime}, {self.ipv4_connections}, {self.ipv6_connections}, {self.dashboard_memory_usage}>"
8398

84-
class User(db.Model, UserMixin):
85-
id = db.Column(db.Integer, primary_key=True)
86-
username = db.Column(db.String(150), unique=True, nullable=False)
87-
email = db.Column(db.String(150), unique=True, nullable=False)
88-
password = db.Column(db.String(150), nullable=False)
89-
user_level = db.Column(db.String(50), nullable=False, default='user')
90-
receive_email_alerts = db.Column(db.Boolean, default=True)
9199

92100

93101
class SmptEamilPasswordConfig(db.Model):
@@ -102,32 +110,37 @@ class SmptEamilPasswordConfig(db.Model):
102110
db.create_all()
103111

104112
# Initialize default settings
105-
settings = DashboardSettings.query.first()
106-
if not settings:
107-
db.session.add(DashboardSettings())
108-
db.session.commit()
109-
110-
# Create admin user if not exists
111-
if not User.query.filter_by(username='admin').first():
112-
hashed_password = generate_password_hash('adminpassword')
113-
admin_user = User(username='admin', email="codeperfectplus@gmail.com", password=hashed_password, user_level='admin',
114-
receive_email_alerts=True)
115-
116-
db.session.add(admin_user)
113+
general_settings = GeneralSettings.query.first()
114+
if not general_settings:
115+
db.session.add(GeneralSettings())
117116
db.session.commit()
118117

119-
# create a user if not exists
120-
if not User.query.filter_by(username='user').first():
121-
hashed_password = generate_password_hash('userpassword')
122-
user = User(username='user', email="test@mail.com",
123-
password=hashed_password, user_level='user', receive_email_alerts=False)
124-
125-
db.session.add(user)
126-
db.session.commit()
118+
# initialize default dashboard settings for users
119+
users = User.query.all()
120+
for user in users:
121+
if not user.dashboard_settings:
122+
db.session.add(DashboardSettings(user_id=user.id))
123+
db.session.commit()
124+
125+
126+
pre_defined_users_json = "src/assets/predefine_user.json"
127+
with open(pre_defined_users_json, "r") as file:
128+
pre_defined_users = json.load(file)
129+
for user in pre_defined_users:
130+
if not User.query.filter_by(user_level=user['user_level']).first():
131+
hashed_password = generate_password_hash(user['password'])
132+
user = User(username=user['username'], email=user['email'], password=hashed_password, user_level=user['user_level'],
133+
receive_email_alerts=user['receive_email_alerts'], profession=user['profession'])
134+
135+
db.session.add(user)
136+
db.session.commit()
127137

128138
# ibject for all templates
129139
@app.context_processor
130140
def inject_settings():
131-
settings = DashboardSettings.query.first()
132-
return dict(settings=settings)
133-
141+
if current_user.is_anonymous:
142+
return dict(settings=None)
143+
settings = DashboardSettings.query.filter_by(user_id=current_user.id).first() # Retrieve user-specific settings from DB
144+
general_settings = GeneralSettings.query.first()
145+
all_settings = dict(settings=settings, general_settings=general_settings)
146+
return all_settings

src/routes/auth.py

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -47,19 +47,6 @@ def get_email_addresses(user_level=None, receive_email_alerts=True, fetch_all_us
4747
# Return list of email addresses
4848
return [user.email for user in users]
4949

50-
# Get Admin Emails with Alerts Enabled:
51-
# admin_emails = get_email_addresses(user_level='admin', receive_email_alerts=True)
52-
# Get All Admin Emails Regardless of Alert Preference:
53-
# all_admin_emails = get_email_addresses(user_level='admin', fetch_all_users=True)
54-
55-
# Get All Users with Alerts Enabled:
56-
# all_user_emails = get_email_addresses(receive_email_alerts=True)
57-
# Get All Users Regardless of Alert Preference:
58-
# all_users_emails = get_email_addresses(fetch_all_users=True)
59-
60-
61-
62-
6350
@app.route('/login', methods=['GET', 'POST'])
6451
def login():
6552
if request.method == 'POST':
@@ -109,6 +96,7 @@ def signup():
10996
confirm_password = request.form['confirm_password']
11097
user_level = request.form.get('user_level', 'user') # Default to 'user' if not provided
11198
receive_email_alerts = 'receive_email_alerts' in request.form # Checkbox is either checked or not
99+
profession = request.form.get('profession', None)
112100

113101
if password != confirm_password:
114102
flash('Passwords do not match')
@@ -120,7 +108,12 @@ def signup():
120108
return redirect(url_for('signup'))
121109

122110
hashed_password = generate_password_hash(password)
123-
new_user = User(username=username, email=email, password=hashed_password, user_level=user_level, receive_email_alerts=receive_email_alerts)
111+
new_user = User(username=username,
112+
email=email,
113+
password=hashed_password,
114+
user_level=user_level,
115+
receive_email_alerts=receive_email_alerts,
116+
profession=profession)
124117

125118
# Get Admin Emails with Alerts Enabled:
126119
admin_email_address = get_email_addresses(user_level='admin', receive_email_alerts=True)
@@ -202,8 +195,23 @@ def delete_user(username):
202195
return redirect(url_for('view_users')) # Redirect to the users page
203196

204197
user = User.query.filter_by(username=username).first_or_404()
198+
199+
# Get Admin Emails with Alerts Enabled:
200+
admin_email_address = get_email_addresses(user_level='admin', receive_email_alerts=True)
201+
if admin_email_address:
202+
subject = "User Deletion Alert"
203+
context = {
204+
"username": user.username,
205+
"deletion_time": datetime.datetime.now(),
206+
"current_user": current_user.username,
207+
}
208+
html_body = render_template_from_file("src/templates/email_templates/deletion_email.html", **context)
209+
send_smpt_email(admin_email_address, subject, html_body, is_html=True)
210+
205211
db.session.delete(user)
206212
db.session.commit()
213+
214+
207215

208216
flash(f'User {username} has been deleted successfully!', 'success')
209217
return redirect(url_for('view_users'))

src/routes/homepage.py

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import datetime
22
from flask import render_template, blueprints
3-
from flask_login import login_required
3+
from flask_login import login_required, current_user
44

55
from src.config import app
66
from src.models import SpeedTestResult, DashboardSettings, SystemInfo
@@ -46,13 +46,47 @@ def dashboard():
4646
source = None
4747
show_prompt = True
4848
remaining_time_for_next_test = None
49-
49+
5050
return render_template(
51-
"dashboard.html",
52-
system_info=system_info,
53-
speedtest_result=speedtest_result,
54-
source=source,
55-
last_timestamp=last_timestamp,
56-
next_test_time=remaining_time_for_next_test,
57-
show_prompt=show_prompt,
58-
)
51+
"dashboard/developer.html",
52+
system_info=system_info,
53+
speedtest_result=speedtest_result,
54+
source=source,
55+
last_timestamp=last_timestamp,
56+
next_test_time=remaining_time_for_next_test,
57+
show_prompt=show_prompt,
58+
current_user=current_user,
59+
)
60+
# if current_user.profession == "developer":
61+
# return render_template(
62+
# "dashboard/developer.html",
63+
# system_info=system_info,
64+
# speedtest_result=speedtest_result,
65+
# source=source,
66+
# last_timestamp=last_timestamp,
67+
# next_test_time=remaining_time_for_next_test,
68+
# show_prompt=show_prompt,
69+
# current_user=current_user,
70+
# )
71+
# elif current_user.profession == "manager":
72+
# return render_template(
73+
# "dashboard/manager.html",
74+
# system_info=system_info,
75+
# speedtest_result=speedtest_result,
76+
# source=source,
77+
# last_timestamp=last_timestamp,
78+
# next_test_time=remaining_time_for_next_test,
79+
# show_prompt=show_prompt,
80+
# current_user=current_user,
81+
# )
82+
# else:
83+
# return render_template(
84+
# "dashboard/developer.html",
85+
# system_info=system_info,
86+
# speedtest_result=speedtest_result,
87+
# source=source,
88+
# last_timestamp=last_timestamp,
89+
# next_test_time=remaining_time_for_next_test,
90+
# show_prompt=show_prompt,
91+
# current_user=current_user,
92+
# )

0 commit comments

Comments
 (0)