From da6d76b5f2b8ac4658cd5ba926d075fce3efa2d0 Mon Sep 17 00:00:00 2001
From: Ethan Clay <Ethan2.Clay@live.uwe.ac.uk>
Date: Tue, 11 Feb 2025 10:17:10 +0000
Subject: [PATCH] Begin to work on manage users

---
 .env-example                             |   2 +-
 app/admin/routes.py                      |  33 ++++-
 app/models/user.py                       |  16 +++
 app/profile/routes.py                    |  14 +--
 app/templates/admin/manage_bookings.html |   1 -
 app/templates/admin/manage_users.html    | 148 +++++++++++++++++++++++
 6 files changed, 202 insertions(+), 12 deletions(-)
 create mode 100644 app/templates/admin/manage_users.html

diff --git a/.env-example b/.env-example
index 40a2857..20e7d46 100644
--- a/.env-example
+++ b/.env-example
@@ -3,5 +3,5 @@ DATABASE_HOST=database
 #If using pydebug you will need to use 127.0.0.1
 DATABASE_USER=user
 DATABASE_PASSWORD=password1
-DATABASE_NAME=database
+DATABASE_NAME=mydatabase
 SECRET_KEY=fsodfhiosdfhdsiofh34903urwej09jf
diff --git a/app/admin/routes.py b/app/admin/routes.py
index 3ef6e8d..5ad8bf8 100644
--- a/app/admin/routes.py
+++ b/app/admin/routes.py
@@ -1,7 +1,7 @@
 from flask import render_template, redirect, url_for, request, jsonify, flash
 from app import db
 from app import admin_permission, permission_required, super_admin_permission
-from app.models import Listings, ListingImages
+from app.models import Listings, ListingImages, User
 from app.admin import bp
 from app.main.utils import generate_time_options
 
@@ -46,7 +46,7 @@ def edit_booking(id):
 @bp.route('/manage_users')
 @permission_required(super_admin_permission)
 def manage_users():
-    return render_template('admin/index.html')
+    return render_template('admin/manage_users.html')
 
 @bp.route('/manage_user_bookings')
 @permission_required(admin_permission)
@@ -155,6 +155,23 @@ def get_bookings():
     
     return jsonify(result)
 
+
+@bp.route('get_users', methods=['GET'])
+@permission_required(super_admin_permission)
+def get_users():
+    all_users = User.get_all_users()
+
+    result = [
+        {
+            'id': user.id,
+            'username': user.username,
+            'email': user.email,
+            'role': user.role.name,
+        } for user in all_users
+    ]
+    
+    return jsonify(result)
+
 @bp.route('create_listing', methods=['GET'])
 @permission_required(admin_permission)
 def create_listing():
@@ -230,6 +247,18 @@ def delete_booking():
 
     return jsonify(success), http_code
 
+@bp.route('delete_user', methods=['DELETE'])
+@permission_required(admin_permission)
+def delete_user():
+    http_code = 400
+    user_id = request.form.get('id')
+    success = User.delete_user(user_id)
+
+    if success:
+        http_code = 200
+
+    return jsonify(success), http_code
+
 @bp.route('/delete_image/<int:image_id>', methods=['POST'])
 @permission_required(admin_permission)
 def delete_image(image_id):
diff --git a/app/models/user.py b/app/models/user.py
index c0b838a..ae88eb7 100644
--- a/app/models/user.py
+++ b/app/models/user.py
@@ -56,3 +56,19 @@ class User(UserMixin, db.Model):
         if user and user.role:
             return user.role.name
         return None
+    
+    @classmethod
+    def get_all_users(cls):
+        return cls.query.all()
+    
+    @classmethod
+    def delete_user(cls, user_id = None):
+
+        user =  cls.search_user_id(user_id)
+
+        if user:
+            db.session.delete(user)
+            db.session.commit()
+            return True
+        
+        return False
diff --git a/app/profile/routes.py b/app/profile/routes.py
index 3479ff0..70ac51d 100644
--- a/app/profile/routes.py
+++ b/app/profile/routes.py
@@ -40,9 +40,9 @@ def signup():
 
             login_user(new_user)
 
-            if session['callback']:
-                flash("Account successfully created. Please review your booking before continuing", 'success')
+            if 'callback' in session.keys():
                 callback = session.pop('callback')
+                flash("Account successfully created. Please review your booking before continuing", 'success')
                 return redirect(callback)
             
             flash('Successfully created your account. You have been logged in automatically', 'success')
@@ -74,8 +74,6 @@ def is_valid_username(username):
     return all(c.isalnum() or c in allowed_special_chars for c in username)
 
 
-from flask_principal import Identity, identity_changed
-
 @bp.route('/login', methods=['POST'])
 def login_post():
     username_field = request.form.get('username')
@@ -95,10 +93,10 @@ def login_post():
 
     identity_changed.send(current_app._get_current_object(), identity=Identity(user.id))
 
-    if session['callback']:
-                callback = session.pop('callback')
-                flash("You have been successfully logged in. Please review your booking before continuing", 'success')
-                return redirect(callback)
+    if 'callback' in session.keys():
+        callback = session.pop('callback')
+        flash("You have been successfully logged in. Please review your booking before continuing", 'success')
+        return redirect(callback)
     
     return redirect(url_for('profile.index'))
 
diff --git a/app/templates/admin/manage_bookings.html b/app/templates/admin/manage_bookings.html
index e3c686a..2573160 100644
--- a/app/templates/admin/manage_bookings.html
+++ b/app/templates/admin/manage_bookings.html
@@ -85,7 +85,6 @@
             </tbody>
         </table>
     </div>
-    <!-- Include this modal in your HTML code -->
 <div class="modal fade" id="confirm_booking_deletion" tabindex="-1">
     <div class="modal-dialog">
         <div class="modal-content">
diff --git a/app/templates/admin/manage_users.html b/app/templates/admin/manage_users.html
new file mode 100644
index 0000000..ef9b208
--- /dev/null
+++ b/app/templates/admin/manage_users.html
@@ -0,0 +1,148 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="container my-4">
+    <div class="d-flex justify-content-between mb-3">
+        <h2>Manage Bookings</h2>
+    </div>
+    <!-- Manage bookings table starts -->
+    <div class="table-container">
+        <table id="manage_bookings" class="table table-striped table-bordered display hover" style="width:100%">
+            <thead>
+                <tr>
+                    <th>Id</th>
+                    <th>User Name</th>
+                    <th>Email</th>
+                    <th>Role</th>
+                    <th>Actions</th>
+                </tr>
+            </thead>
+            <tbody>
+            </tbody>
+        </table>
+    </div>
+</div>
+<div class="modal fade" id="confirm_user_deletion" tabindex="-1">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title" id="confirm_user_deletion">Confirm Deletion</h5>
+                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+            </div>
+            <div class="modal-body">
+                <p>Type 'CONFIRM' to delete this entry:</p>
+                <input type="text" id="conifrmation_input" class="form-control">
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
+                <button type="button" class="btn btn-primary" id="confirm_deletion_button">Delete</button>
+            </div>
+        </div>
+    </div>
+</div>
+<style>
+    .table-container {
+        width: 100%;
+        overflow-x: auto;
+        overflow-y: hidden;
+    }
+    
+    @media (max-width: 800px) {
+        .table-container {
+            padding: 0 10px;
+        }
+    }
+    
+    .dataTables_wrapper {
+        width: 100%;
+    }
+    
+    table.dataTable.no-footer {
+        margin-bottom: 30px;
+    }
+    
+</style>
+<script>
+    $(document).ready(function() {
+        // Load table
+        const table = $('#manage_bookings').DataTable({
+            pageLength: 10,
+            ordering: false,
+            ajax: {
+                url: "{{ url_for('admin.get_users') }}",
+                dataSrc: '',
+                data: function(d) {
+                    d.username = $('#username').val();
+                    d.email = $('#email').val();
+                    d.role_id = $('#role').val();
+                }
+            },
+            columns: [
+                { data: 'id', visible: false }, // Hidden id column
+                { data: 'username' },
+                { data: 'email' },
+                { data: 'role' },
+                {
+                    data: null,
+                    className: "dt-center",
+                    defaultContent: `
+                        <div class="dropdown">
+                            <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-expanded="false">
+                                Actions
+                            </button>
+                            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                                <a class="dropdown-item edit-btn" href="#">Edit</a>
+                                <a class="dropdown-item delete-btn" href="#">Delete</a>
+                            </div>
+                        </div>`
+                }
+            ],
+            language: {
+                emptyTable: "No users could be found"
+            },
+            createdRow: function(row, data, dataIndex) { //Attach ID to edit button and delete button.
+                $(row).find('.edit-btn').attr('data-id', data.id);
+                $(row).find('.delete-btn').attr('data-id', data.id);
+            }
+        });
+
+        $('#manage_bookings tbody').on('click', '.edit-btn', function() {
+            const id = $(this).data('id');
+            window.location.href = `manage_user/edit/${id}`;
+        });
+
+        let delete_user;
+        $('#manage_bookings tbody').on('click', '.delete-btn', function() {
+            delete_user = table.row($(this).parents('tr'));
+            $('#confirm_user_deletion').modal('show');
+        });
+
+        $('#confirm_deletion_button').on('click', function() {
+            const confirmation_input = $('#conifrmation_input').val().trim();
+            if (confirmation_input === 'CONFIRM') {
+                $.ajax({
+                    url: "{{ url_for('admin.delete_user') }}",
+                    method: "DELETE",
+                    data: { id: delete_user.data().id },
+                    success: function() {
+                        delete_user.remove().draw();
+                        $('#confirm_user_deletion').modal('hide');
+                    },
+                    error: function() {
+                        alert('Failed to delete the booking. Please try again.');
+                    }
+                });
+            } else {
+                alert('Please type "CONFIRM" to delete the booking.');
+            }
+        });
+
+        $('#confirm_user_deletion').on('hidden.bs.modal', function () {
+            $('#conifrmation_input').val('');
+        });
+    });
+</script>
+
+
+
+
+{% endblock %}
-- 
GitLab