From ad277d8c1a96e9935f2b086d388f734c130526bc Mon Sep 17 00:00:00 2001
From: a2-imeri <Alfret2.imeri@live.uwe.ac.uk>
Date: Wed, 15 May 2024 20:12:10 +0100
Subject: [PATCH] Add Admin Interface

---
 .../__pycache__/settings.cpython-310.pyc      | Bin 2518 -> 2549 bytes
 .../__pycache__/settings.cpython-39.pyc       | Bin 2426 -> 2601 bytes
 .../__pycache__/urls.cpython-310.pyc          | Bin 374 -> 416 bytes
 MisplaceAI/MisplaceAI/settings.py             |   2 +-
 MisplaceAI/MisplaceAI/urls.py                 |   5 +-
 MisplaceAI/admin_app/__init__.py              |   0
 MisplaceAI/admin_app/admin.py                 |   3 +
 MisplaceAI/admin_app/apps.py                  |   5 ++
 MisplaceAI/admin_app/migrations/__init__.py   |   0
 MisplaceAI/admin_app/models.py                |   3 +
 .../templates/admin_app/admin_dashboard.html  |  18 +++++
 .../templates/admin_app/admin_login.html      |  39 +++++++++++
 .../templates/admin_app/admin_users.html      |  62 +++++++++++++++++
 MisplaceAI/admin_app/tests.py                 |   3 +
 MisplaceAI/admin_app/urls.py                  |  11 +++
 MisplaceAI/admin_app/views.py                 |  63 ++++++++++++++++++
 MisplaceAI/core/templates/core/navbar.html    |   5 ++
 .../rules/__pycache__/apps.cpython-39.pyc     | Bin 454 -> 454 bytes
 .../rules/__pycache__/models.cpython-310.pyc  | Bin 549 -> 549 bytes
 .../rules/__pycache__/urls.cpython-310.pyc    | Bin 499 -> 499 bytes
 .../rules/__pycache__/views.cpython-310.pyc   | Bin 1714 -> 1714 bytes
 21 files changed, 216 insertions(+), 3 deletions(-)
 create mode 100644 MisplaceAI/admin_app/__init__.py
 create mode 100644 MisplaceAI/admin_app/admin.py
 create mode 100644 MisplaceAI/admin_app/apps.py
 create mode 100644 MisplaceAI/admin_app/migrations/__init__.py
 create mode 100644 MisplaceAI/admin_app/models.py
 create mode 100644 MisplaceAI/admin_app/templates/admin_app/admin_dashboard.html
 create mode 100644 MisplaceAI/admin_app/templates/admin_app/admin_login.html
 create mode 100644 MisplaceAI/admin_app/templates/admin_app/admin_users.html
 create mode 100644 MisplaceAI/admin_app/tests.py
 create mode 100644 MisplaceAI/admin_app/urls.py
 create mode 100644 MisplaceAI/admin_app/views.py

diff --git a/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-310.pyc b/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-310.pyc
index b2fb8276f5548c1496a1d219646b6814fa3f04da..7769e77d63722a1403bc1903da555cc4c5e5fa81 100644
GIT binary patch
delta 59
zcmca6{8gAYpO=@5fq{X+^_NT9-;KOkOpIKUE12F%R>>x&<Ywl@Cl(awB^DGE>p6nB
Mjs*pq6PU}`05irDtpET3

delta 33
pcmew=d`*})pO=@5fq{WR{jE#d&5gWSOpKh9E12GGZe=cD0|28&3JCxJ

diff --git a/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-39.pyc b/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-39.pyc
index bd1fcc2fe9624981c3f5eb4b052d9f815ce76c9d..908ecfc16a21024070a9a52169a3b060fd2485a1 100644
GIT binary patch
delta 405
zcmew*v{HmGk(ZZ?fq{WR{jE#dO}>eIGK>c%YS(y*r%0qoW-_Ko&0$IrO_9!IOc70y
z$z)7ti4sVWjS@_eixNs<i4sm>i4sYXj}lE~OHq(!NM%b=lx9e0iV{mviV{yz4rb6)
z*?6m+k&$z964N@XDviX_l8n^6lFa19lFa-(y~KioVm(I`G3Wfew9ND>k>vcMREWHD
zeo^XXF6K3ij8T)fv)o{enmmDZH6!<A8@68gD6ZVhy!f2dy!4WcmmCZX44O<u+zbp1
zMXU@A3|01%9oaM{e`ZV2i((E9ajxRfFD^+e$xPOdVuLWML{S|Cm7ko*uE;2{xtX1r
zQBNQ^#4*Iv+0E0(H8|eIGbs3$kc+FEW2jF^yklsHf4rNgtB=b{h9Y&4t?H8(any@5
zF)%O`M=>xku<-CO3$U{=voNu6aPUsH;M7uLVq*Ev^pAy|<v$Y(%YUZNEMhE7V93hC
L#Ky?>kA({Wp2BZ1

delta 244
zcmZ1}@=J&>k(ZZ?fq{V`;H*p98QzI}GK{MxYS$Qxrif=Urii9UfJw<r#&nh_ffT7I
z!4&Bzp%j)V;S`oAkrbII(G=Mzu@t#r22J^mAKDoi*(X;pt=pW&yo{0Y)?{AR8;rLm
zKVx0Z#>>FKP~|cCA)ChJ{cH(LRrX+J8hZlYE#}Y==PLH%lEjkCWc|rs*cBPYH;ZvF
zGs+0LxVkxp`h>(ghKBgZyLr0$xU6I-(qLd<DAJhh&RH+c$iTo*9KgW9z{11BEWpmf
f%)-RN%E3MPE~l0R%YP;oDE`JG%)$hQY%Ht*#K%2_

diff --git a/MisplaceAI/MisplaceAI/__pycache__/urls.cpython-310.pyc b/MisplaceAI/MisplaceAI/__pycache__/urls.cpython-310.pyc
index 824207fc5694350a0be5912936807940285d2970..1d9b76ccc5bfb133824986fa4ca1a22a3ea17785 100644
GIT binary patch
delta 142
zcmeyyw18PVpO=@5fq{YH$X}N<7e)q##~=<e=3ro8aA06yC{CED?Jt(foWhmLlEU50
z*vyp98pWQ%6U?B=JF!Kb_ZCAHXL5c~s$OYPPVvOm2I5s*i7C06dAf-O1^QKdV0L_B
aLBYhwjUoaJ3=BLB0*pM&Jd6;?@f!eX;UGf*

delta 100
zcmZ3${EbOFpO=@5fq{Xc;g(C9BO?RDV-N=!vokO-I503U6o*XI_UB4xiDFOT3TDvc
so;X2$;t>OmTMSj4$@xX8lerlih4>g47<d>27<rg^n0Od@7&(3e0E7k+*#H0l

diff --git a/MisplaceAI/MisplaceAI/settings.py b/MisplaceAI/MisplaceAI/settings.py
index a445cda..5d11dec 100644
--- a/MisplaceAI/MisplaceAI/settings.py
+++ b/MisplaceAI/MisplaceAI/settings.py
@@ -44,7 +44,7 @@ INSTALLED_APPS = [
     'rules.apps.RulesConfig',
     'authentication.apps.AuthenticationConfig',
     'core.apps.CoreConfig',
-
+    'admin_app.apps.AdminAppConfig',
 ]
 
 MIDDLEWARE = [
diff --git a/MisplaceAI/MisplaceAI/urls.py b/MisplaceAI/MisplaceAI/urls.py
index 7603c75..445aa5c 100644
--- a/MisplaceAI/MisplaceAI/urls.py
+++ b/MisplaceAI/MisplaceAI/urls.py
@@ -3,8 +3,9 @@ from django.urls import path, include
 
 urlpatterns = [
     path('admin/', admin.site.urls),
-    # path('detection/', include('detection.urls')),
+    path('', include('core.urls')),
     path('rules/', include('rules.urls')),
     path('auth/', include('authentication.urls')), 
-    path('', include('core.urls')),
+    path('admin-app/', include('admin_app.urls')),
+   
 ]
diff --git a/MisplaceAI/admin_app/__init__.py b/MisplaceAI/admin_app/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/MisplaceAI/admin_app/admin.py b/MisplaceAI/admin_app/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/MisplaceAI/admin_app/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/MisplaceAI/admin_app/apps.py b/MisplaceAI/admin_app/apps.py
new file mode 100644
index 0000000..661acc8
--- /dev/null
+++ b/MisplaceAI/admin_app/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+class AdminAppConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'admin_app'
diff --git a/MisplaceAI/admin_app/migrations/__init__.py b/MisplaceAI/admin_app/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/MisplaceAI/admin_app/models.py b/MisplaceAI/admin_app/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/MisplaceAI/admin_app/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/MisplaceAI/admin_app/templates/admin_app/admin_dashboard.html b/MisplaceAI/admin_app/templates/admin_app/admin_dashboard.html
new file mode 100644
index 0000000..93e3301
--- /dev/null
+++ b/MisplaceAI/admin_app/templates/admin_app/admin_dashboard.html
@@ -0,0 +1,18 @@
+{% extends 'core/base.html' %}
+{% load static %}
+
+{% block title %}Admin Dashboard{% endblock %}
+
+{% block content %}
+<div class="container mt-5">
+    <div class="row">
+        <div class="col">
+            <h1>Admin Dashboard</h1>
+            <div class="list-group">
+                <a href="{% url 'admin_users' %}" class="list-group-item list-group-item-action">Users Activity</a>
+                <!-- Add other admin links here -->
+            </div>
+        </div>
+    </div>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/MisplaceAI/admin_app/templates/admin_app/admin_login.html b/MisplaceAI/admin_app/templates/admin_app/admin_login.html
new file mode 100644
index 0000000..e35c5b2
--- /dev/null
+++ b/MisplaceAI/admin_app/templates/admin_app/admin_login.html
@@ -0,0 +1,39 @@
+{% extends 'core/base.html' %}
+{% load static %}
+
+{% block title %}Admin Login{% endblock %}
+
+{% block content %}
+<div class="container mt-5">
+    <div class="row justify-content-center">
+        <div class="col-md-6">
+            <div class="card">
+                <div class="card-header">
+                    <h3 class="text-center">Admin Login</h3>
+                </div>
+                <div class="card-body">
+                    <form method="post">
+                        {% csrf_token %}
+                        {% if messages %}
+                        <div class="alert alert-danger">
+                            {% for message in messages %}
+                            <p>{{ message }}</p>
+                            {% endfor %}
+                        </div>
+                        {% endif %}
+                        <div class="form-group">
+                            <label for="username">Username</label>
+                            <input type="text" class="form-control" id="username" name="username" required>
+                        </div>
+                        <div class="form-group">
+                            <label for="password">Password</label>
+                            <input type="password" class="form-control" id="password" name="password" required>
+                        </div>
+                        <button type="submit" class="btn btn-primary btn-block">Login</button>
+                    </form>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/MisplaceAI/admin_app/templates/admin_app/admin_users.html b/MisplaceAI/admin_app/templates/admin_app/admin_users.html
new file mode 100644
index 0000000..d800cf4
--- /dev/null
+++ b/MisplaceAI/admin_app/templates/admin_app/admin_users.html
@@ -0,0 +1,62 @@
+{% extends 'core/base.html' %}
+{% load static %}
+
+{% block title %}Users Activity{% endblock %}
+
+{% block content %}
+<div class="container mt-5">
+    <div class="row">
+        <div class="col">
+            <h1>Users Activity</h1>
+            <table class="table table-striped">
+                <thead>
+                    <tr>
+                        <th>Username</th>
+                        <th>Email</th>
+                        <th>First Name</th>
+                        <th>Last Name</th>
+                        <th>Date Joined</th>
+                        <th>Last Login</th>
+                        <th>Is Active</th>
+                        <th>Is Staff</th>
+                        <th>Is Superuser</th>
+                        <th>Groups</th>
+                        <th>Actions</th>
+                    </tr>
+                </thead>
+                <tbody>
+                    {% for user in users %}
+                    <tr>
+                        <td>{{ user.username }}</td>
+                        <td>{{ user.email }}</td>
+                        <td>{{ user.first_name }}</td>
+                        <td>{{ user.last_name }}</td>
+                        <td>{{ user.date_joined }}</td>
+                        <td>{{ user.last_login }}</td>
+                        <td>{{ user.is_active }}</td>
+                        <td>{{ user.is_staff }}</td>
+                        <td>{{ user.is_superuser }}</td>
+                        <td>
+                            {% for group in user.groups.all %}
+                            {{ group.name }}{% if not forloop.last %}, {% endif %}
+                            {% endfor %}
+                        </td>
+                        <td>
+                            {% if user.is_active %}
+                            <a href="{% url 'admin_deactivate_user' user.id %}"
+                                class="btn btn-warning btn-sm">Deactivate</a>
+                            {% else %}
+                            <a href="{% url 'admin_activate_user' user.id %}"
+                                class="btn btn-success btn-sm">Activate</a>
+                            {% endif %}
+                            <a href="{% url 'admin_delete_user' user.id %}" class="btn btn-danger btn-sm"
+                                onclick="return confirm('Are you sure you want to delete this user?');">Delete</a>
+                        </td>
+                    </tr>
+                    {% endfor %}
+                </tbody>
+            </table>
+        </div>
+    </div>
+</div>
+{% endblock %}
\ No newline at end of file
diff --git a/MisplaceAI/admin_app/tests.py b/MisplaceAI/admin_app/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/MisplaceAI/admin_app/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/MisplaceAI/admin_app/urls.py b/MisplaceAI/admin_app/urls.py
new file mode 100644
index 0000000..92a3673
--- /dev/null
+++ b/MisplaceAI/admin_app/urls.py
@@ -0,0 +1,11 @@
+from django.urls import path
+from . import views
+
+urlpatterns = [
+    path('login/', views.admin_login_view, name='admin_login'),
+    path('dashboard/', views.admin_dashboard_view, name='admin_dashboard'),
+    path('users/', views.admin_users_view, name='admin_users'),
+    path('users/deactivate/<int:user_id>/', views.admin_deactivate_user_view, name='admin_deactivate_user'),
+    path('users/activate/<int:user_id>/', views.admin_activate_user_view, name='admin_activate_user'),
+    path('users/delete/<int:user_id>/', views.admin_delete_user_view, name='admin_delete_user'),
+]
diff --git a/MisplaceAI/admin_app/views.py b/MisplaceAI/admin_app/views.py
new file mode 100644
index 0000000..a7f28b4
--- /dev/null
+++ b/MisplaceAI/admin_app/views.py
@@ -0,0 +1,63 @@
+from django.shortcuts import render, redirect, get_object_or_404
+from django.contrib.auth import authenticate, login
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.models import User
+from django.contrib import messages
+
+def admin_login_view(request):
+    if request.method == 'POST':
+        username = request.POST.get('username')
+        password = request.POST.get('password')
+        user = authenticate(request, username=username, password=password)
+        if user is not None:
+            if user.is_superuser:
+                login(request, user)
+                return redirect('admin_dashboard')
+            else:
+                messages.error(request, 'You do not have the necessary permissions to access this page.')
+        else:
+            messages.error(request, 'Invalid username or password.')
+
+    return render(request, 'admin_app/admin_login.html')
+
+@login_required
+def admin_dashboard_view(request):
+    if not request.user.is_superuser:
+        return redirect('admin_login')
+    return render(request, 'admin_app/admin_dashboard.html')
+
+def admin_users_view(request):
+    if not request.user.is_staff:
+        return redirect('admin_login')
+    
+    users = User.objects.all()
+    return render(request, 'admin_app/admin_users.html', {'users': users})
+
+def admin_deactivate_user_view(request, user_id):
+    if not request.user.is_staff:
+        return redirect('admin_login')
+
+    user = get_object_or_404(User, id=user_id)
+    user.is_active = False
+    user.save()
+    messages.success(request, f'User {user.username} has been deactivated.')
+    return redirect('admin_users')
+
+def admin_activate_user_view(request, user_id):
+    if not request.user.is_staff:
+        return redirect('admin_login')
+
+    user = get_object_or_404(User, id=user_id)
+    user.is_active = True
+    user.save()
+    messages.success(request, f'User {user.username} has been activated.')
+    return redirect('admin_users')
+
+def admin_delete_user_view(request, user_id):
+    if not request.user.is_staff:
+        return redirect('admin_login')
+
+    user = get_object_or_404(User, id=user_id)
+    user.delete()
+    messages.success(request, f'User {user.username} has been deleted.')
+    return redirect('admin_users')
diff --git a/MisplaceAI/core/templates/core/navbar.html b/MisplaceAI/core/templates/core/navbar.html
index 4f58696..5a0c5f3 100644
--- a/MisplaceAI/core/templates/core/navbar.html
+++ b/MisplaceAI/core/templates/core/navbar.html
@@ -10,6 +10,11 @@
                 <a class="nav-link" href="{% url 'home' %}">Home</a>
             </li>
             {% if user.is_authenticated %}
+            {% if user.is_staff %} {# Check if the user is a staff member (admin) #}
+            <li class="nav-item">
+                <a class="nav-link" href="{% url 'admin_dashboard' %}">Admin Dashboard</a>
+            </li>
+            {% endif %}
             <li class="nav-item">
                 <form method="post" action="{% url 'logout' %}" class="form-inline">
                     {% csrf_token %}
diff --git a/MisplaceAI/rules/__pycache__/apps.cpython-39.pyc b/MisplaceAI/rules/__pycache__/apps.cpython-39.pyc
index 6520755d5f9651200136cc640dbc0a6f74f0d904..31706469dbe44504ed6dba139fb1d69414c59785 100644
GIT binary patch
delta 23
ecmX@ce2kedk(ZZ?fq{WR?1oF)Muv@iI~V~%p9SXt

delta 23
ecmX@ce2kedk(ZZ?fq{X+{;W$H1LH=%9gF}!wFOlG

diff --git a/MisplaceAI/rules/__pycache__/models.cpython-310.pyc b/MisplaceAI/rules/__pycache__/models.cpython-310.pyc
index ead1e8c47db6a427658e77d0ddc21653b3388760..2824feb030c55b134bd72336e3f50b46a45a196a 100644
GIT binary patch
delta 20
bcmZ3=vXq58pO=@5fq{YH35V-OZYd@JEeZqr

delta 20
bcmZ3=vXq58pO=@5fq{V`V86>oZYd@JEkgtx

diff --git a/MisplaceAI/rules/__pycache__/urls.cpython-310.pyc b/MisplaceAI/rules/__pycache__/urls.cpython-310.pyc
index 7704261dde59232899a80cb1f727c50b2b5ad46f..0afb21aa3fd21a6317c48e6bf1b3afcfbcfb2731 100644
GIT binary patch
delta 20
bcmey&{F#|MpO=@5fq{YH8Heje?iY*zIwJ*R

delta 20
bcmey&{F#|MpO=@5fq{WR`-;m(?iY*zImrcc

diff --git a/MisplaceAI/rules/__pycache__/views.cpython-310.pyc b/MisplaceAI/rules/__pycache__/views.cpython-310.pyc
index cd89d7edaaf8a661c4e0e1a21b9d143d4661a98e..5175198a3ed3629c01840fa93443e5fea63fd89f 100644
GIT binary patch
delta 26
icmdnQyNQ=OpO=@5fq{YH1&8ZKZgw`tTa$&^<^upwPzFH&

delta 26
hcmdnQyNQ=OpO=@5fq{WR=ZeclZgw`tsL8@?^8roC1<(Kh

-- 
GitLab