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