diff --git a/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-310.pyc b/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-310.pyc index b2fb8276f5548c1496a1d219646b6814fa3f04da..7769e77d63722a1403bc1903da555cc4c5e5fa81 100644 Binary files a/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-310.pyc and b/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-310.pyc differ diff --git a/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-39.pyc b/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-39.pyc index bd1fcc2fe9624981c3f5eb4b052d9f815ce76c9d..908ecfc16a21024070a9a52169a3b060fd2485a1 100644 Binary files a/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-39.pyc and b/MisplaceAI/MisplaceAI/__pycache__/settings.cpython-39.pyc differ diff --git a/MisplaceAI/MisplaceAI/__pycache__/urls.cpython-310.pyc b/MisplaceAI/MisplaceAI/__pycache__/urls.cpython-310.pyc index 824207fc5694350a0be5912936807940285d2970..1d9b76ccc5bfb133824986fa4ca1a22a3ea17785 100644 Binary files a/MisplaceAI/MisplaceAI/__pycache__/urls.cpython-310.pyc and b/MisplaceAI/MisplaceAI/__pycache__/urls.cpython-310.pyc differ diff --git a/MisplaceAI/MisplaceAI/settings.py b/MisplaceAI/MisplaceAI/settings.py index a445cdaa398143a9af2c49665f012110390c728e..5d11dec4dfb81b71707ecf3d8867c097ac35d0c2 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 7603c75a46a7e63ea3132bbccf693facce5cd6a3..445aa5cca5bd38e3289f7cc3206dbbd25d39146c 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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MisplaceAI/admin_app/admin.py b/MisplaceAI/admin_app/admin.py new file mode 100644 index 0000000000000000000000000000000000000000..8c38f3f3dad51e4585f3984282c2a4bec5349c1e --- /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 0000000000000000000000000000000000000000..661acc88bda93fe1bce4d1bb35fd6d88f602dcee --- /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 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/MisplaceAI/admin_app/models.py b/MisplaceAI/admin_app/models.py new file mode 100644 index 0000000000000000000000000000000000000000..71a836239075aa6e6e4ecb700e9c42c95c022d91 --- /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 0000000000000000000000000000000000000000..93e33016877f4b90d7ed59c09ea2c0f782bd1892 --- /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 0000000000000000000000000000000000000000..e35c5b2194ee3789992d0d614db843a1de895c96 --- /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 0000000000000000000000000000000000000000..d800cf44921eed3fbe79374e38ada3174d1f9785 --- /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 0000000000000000000000000000000000000000..7ce503c2dd97ba78597f6ff6e4393132753573f6 --- /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 0000000000000000000000000000000000000000..92a3673f7402e74072668a03da0ec7b9b841321d --- /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 0000000000000000000000000000000000000000..a7f28b49c0c1f931e73ee18d7cbcc6634380e8a7 --- /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 4f586968c051c59cb083b1e7567ceffc74bac25b..5a0c5f3fc08939625cd2a2bad2201eefb981c582 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 Binary files a/MisplaceAI/rules/__pycache__/apps.cpython-39.pyc and b/MisplaceAI/rules/__pycache__/apps.cpython-39.pyc differ diff --git a/MisplaceAI/rules/__pycache__/models.cpython-310.pyc b/MisplaceAI/rules/__pycache__/models.cpython-310.pyc index ead1e8c47db6a427658e77d0ddc21653b3388760..2824feb030c55b134bd72336e3f50b46a45a196a 100644 Binary files a/MisplaceAI/rules/__pycache__/models.cpython-310.pyc and b/MisplaceAI/rules/__pycache__/models.cpython-310.pyc differ diff --git a/MisplaceAI/rules/__pycache__/urls.cpython-310.pyc b/MisplaceAI/rules/__pycache__/urls.cpython-310.pyc index 7704261dde59232899a80cb1f727c50b2b5ad46f..0afb21aa3fd21a6317c48e6bf1b3afcfbcfb2731 100644 Binary files a/MisplaceAI/rules/__pycache__/urls.cpython-310.pyc and b/MisplaceAI/rules/__pycache__/urls.cpython-310.pyc differ diff --git a/MisplaceAI/rules/__pycache__/views.cpython-310.pyc b/MisplaceAI/rules/__pycache__/views.cpython-310.pyc index cd89d7edaaf8a661c4e0e1a21b9d143d4661a98e..5175198a3ed3629c01840fa93443e5fea63fd89f 100644 Binary files a/MisplaceAI/rules/__pycache__/views.cpython-310.pyc and b/MisplaceAI/rules/__pycache__/views.cpython-310.pyc differ