diff --git a/Database/admindatahandler.py b/Database/admindatahandler.py index d3b67b2..b4d6344 100644 --- a/Database/admindatahandler.py +++ b/Database/admindatahandler.py @@ -1,6 +1,8 @@ from datetime import datetime import re +from flask import session + from Database import DatabaseConfig beehive_admin_collection = DatabaseConfig.get_beehive_admin_collection() @@ -22,4 +24,14 @@ def check_admin_available(google_id: str): } count = beehive_admin_collection.count_documents(query) - return count == 0 \ No newline at end of file + return count == 0 + +def is_admin(): + if 'google_id' in session: + query = { + "google_id": session['google_id'] + } + admin = beehive_admin_collection.find_one(query) + if admin and admin.get("role") == "admin": + return True + return False diff --git a/Database/userdatahandler.py b/Database/userdatahandler.py index 3137761..31f8c85 100644 --- a/Database/userdatahandler.py +++ b/Database/userdatahandler.py @@ -1,6 +1,8 @@ from datetime import datetime, timedelta import re +from flask import session + from Database import DatabaseConfig @@ -92,6 +94,18 @@ def getallusers(): users = beehive_user_collection.find() return users +def get_currentuser_from_session(): + user_data = session.get('user') + if user_data is None: + return None + + user_id = user_data.get('user_id') + if not user_id: + return None + + user = beehive_user_collection.find_one({'_id': user_id}) + return user + # Get all images from MongoDB def get_images_by_user(username): images = beehive_image_collection.find({'username': username}) diff --git a/app.py b/app.py index 11c848c..8c21d0d 100644 --- a/app.py +++ b/app.py @@ -1,4 +1,5 @@ import base64 +from functools import wraps import json import os import datetime @@ -19,10 +20,11 @@ from PIL import Image -from Database.admindatahandler import check_admin_available, create_admin +from Database.admindatahandler import check_admin_available, create_admin, is_admin from Database.userdatahandler import ( create_user, - delete_image, + delete_image, + get_currentuser_from_session, get_image_by_id, get_images_by_user, get_password_by_username, @@ -68,6 +70,32 @@ def wrapper(*args, **kwargs): return wrapper +def role_required(required_role): + def decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + + if "google_id" in session: + if required_role == 'admin' and not is_admin(): + return render_template('403.html') + + elif "username" in session: + user = get_currentuser_from_session() + + if user is None: + print("User not found in session!") + return render_template('403.html') + + if user.get('role') != required_role: + return render_template('403.html') + + else: + return render_template('403.html') + + return func(*args, **kwargs) + + return wrapper + return decorator # Home page @app.route('/') @@ -179,11 +207,11 @@ def upload_image(): if filename.lower().endswith('.pdf'): thumbnail_path = generate_pdf_thumbnail(filepath, filename) - return redirect(url_for('profile')) - + else: flash('Invalid file type. Allowed types are: jpg, jpeg, png, gif, webp, heif, pdf', 'danger') - return redirect(url_for('profile')) + + return redirect(url_for('profile')) def generate_pdf_thumbnail(pdf_path, filename): """Generate an image from the first page of a PDF using PyMuPDF.""" @@ -324,31 +352,38 @@ def authorize(): json.dump(session, json_file, indent=4) return redirect("/admin") else: - return render_template("404.html") + return render_template("403.html") @app.route("/admin") -# @login_is_required +@role_required("admin") +@login_is_required def protected_area(): admin_name = session.get("name") total_img = total_images() todays_image = todays_images() return render_template("admin.html", admin_name=admin_name, total_img=total_img, todays_image = todays_image) - +@login_is_required +@role_required("admin") @app.route("/admin/logout") def adminlogout(): session.clear() return redirect("/") + @app.route('/admin/users') +@role_required("admin") def getallusers(): users = userdatahandler.getallusers() return render_template('users.html', users=users) + + @app.route('/admin/users/') +@role_required("admin") def user_images_show(username): user = get_user_by_username(username) if not user: diff --git a/requirements.txt b/requirements.txt index 3d10d8f..fe69768 100644 Binary files a/requirements.txt and b/requirements.txt differ diff --git a/static/css/profile.css b/static/css/profile.css index 9ce5696..3f8ae67 100644 --- a/static/css/profile.css +++ b/static/css/profile.css @@ -497,8 +497,6 @@ h2{ stroke: black; stroke-width: 2px; fill: transparent; - rx: 1em; - ry: 1em; stroke-dasharray: 25; transition: fill 0.25s, stroke 0.3s ease; animation: 4s linear infinite stroke-animation; @@ -584,8 +582,6 @@ h2{ stroke: #0055d4; stroke-width: 2px; fill: none; - rx: 1em; - ry: 1em; stroke-dasharray: 0 100; } diff --git a/static/css/style.css b/static/css/style.css index a046fb0..5cb2355 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -82,4 +82,28 @@ button:disabled { color: #ff0400; } +@media (max-width: 480px) { + .container { + margin-top: 90px; + max-width: 80%; + padding: 15px; + } + h2 { + font-size: 30px; + } + + input { + font-size: 14px; + padding: 8px; + } + + button { + font-size: 14px; + padding: 10px; + } + + p { + font-size: 15px; + } +} \ No newline at end of file diff --git a/static/js/dragdrop.js b/static/js/dragdrop.js new file mode 100644 index 0000000..7ee33cc --- /dev/null +++ b/static/js/dragdrop.js @@ -0,0 +1,67 @@ +document.addEventListener('DOMContentLoaded', function() { + const fileInput = document.querySelector('input[type="file"]'); + const uploadButton = document.getElementById('uploadButton'); + const fileError = document.getElementById('fileError'); + const allowedTypes = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'heif', 'pdf']; + + //Validating dropped file + function validateFile(file) { + const fileExtension = file.name.split('.').pop().toLowerCase(); + if (!allowedTypes.includes(fileExtension)) { + uploadButton.disabled = true; + fileError.style.display = 'block'; + fileInput.value = ''; // Clear the file input + return false; + } + uploadButton.disabled = false; + fileError.style.display = 'none'; + return true; + } + + // Prevent default drag behaviors + ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => { + document.addEventListener(eventName, preventDefaults, false); + }); + + function preventDefaults(e) { + e.preventDefault(); + e.stopPropagation(); + } + + // Changing the Opacity for better visual + ['dragenter', 'dragover'].forEach(eventName => { + document.addEventListener(eventName, highlight, false); + }); + + ['dragleave', 'drop'].forEach(eventName => { + document.addEventListener(eventName, unhighlight, false); + }); + + function highlight(e) { + document.body.style.opacity = '0.7'; + document.body.style.transition = 'opacity 0.2s ease'; + } + + function unhighlight(e) { + document.body.style.opacity = '1'; + } + + document.addEventListener('drop', function(e) { + const dt = e.dataTransfer; + const files = dt.files; + + if (files.length > 0) { + const file = files[0]; + if (validateFile(file)) { + // Update the file input with the dropped file + fileInput.files = files; + + // Show upload form if hidden + const uploadForm = document.getElementById('uploadForm'); + if (uploadForm.style.display === 'none' || uploadForm.style.display === '') { + uploadForm.style.display = 'block'; + } + } + } + }); +}); \ No newline at end of file diff --git a/templates/403.html b/templates/403.html new file mode 100644 index 0000000..a1c1e99 --- /dev/null +++ b/templates/403.html @@ -0,0 +1,18 @@ + + + + + + Beehive + + + + + + admin_panel_settings + + +

You don't have permission to access this page. Only admins are allowed due to privacy restrictions.

+ + + \ No newline at end of file diff --git a/templates/404.html b/templates/404.html deleted file mode 100644 index fe8f336..0000000 --- a/templates/404.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - Beehive - - - -

You're not an admin, Go back!

- - - - \ No newline at end of file diff --git a/templates/admin.html b/templates/admin.html index 9edaaff..31ad41d 100644 --- a/templates/admin.html +++ b/templates/admin.html @@ -16,7 +16,6 @@

{{ admin_name }}Admin

-

Total Images

diff --git a/templates/profile.html b/templates/profile.html index ca0022b..526233f 100644 --- a/templates/profile.html +++ b/templates/profile.html @@ -192,6 +192,7 @@ } +