minor update

This commit is contained in:
2025-08-26 13:59:33 +05:30
parent 657d57df22
commit d1b8889812
11 changed files with 163 additions and 15 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,23 @@
# Generated by Django 5.2.5 on 2025-08-26 08:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='user',
name='banned_until',
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name='user',
name='is_banned',
field=models.BooleanField(default=False),
),
]
+20
View File
@@ -1,7 +1,9 @@
from datetime import timedelta
from django.contrib.auth.models import AbstractUser
from django.core.validators import FileExtensionValidator
from django.conf import settings
from django.db import models
from django.utils import timezone
class User(AbstractUser):
is_citizen = models.BooleanField(default=False)
@@ -25,6 +27,24 @@ class User(AbstractUser):
related_name='core_user_permissions',
related_query_name='core_user',
)
is_banned = models.BooleanField(default=False)
banned_until = models.DateTimeField(null=True, blank=True)
def ban(self, days=1):
"""Ban user for given days (default 7 days)."""
self.is_banned = True
self.banned_until = timezone.now() + timedelta(days=days)
self.save()
def unban(self):
self.is_banned = False
self.banned_until = None
self.save()
def is_currently_banned(self):
if self.is_banned and self.banned_until:
return timezone.now() < self.banned_until
return False
class Department(models.Model):
name = models.CharField(max_length=100, unique=True)
@@ -0,0 +1,60 @@
{% extends "core/base.html" %}
{% block content %}
<div class="container my-5">
<div class="card shadow-lg">
<div class="card-header bg-primary text-white">
<h3><i class="fas fa-users me-2"></i> Manage Citizens</h3>
</div>
<div class="card-body">
{% if citizens %}
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th>No.</th>
<th>Username</th>
<th>Email</th>
<th>Phone No.</th>
<th>Date Joined</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for citizen in citizens %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ citizen.username }}</td>
<td>{{ citizen.email }}</td>
<td>{{ citizen.phone }}</td>
<td>{{ citizen.date_joined|date:"M d, Y" }}</td>
<td>
{% if citizen.is_currently_banned %}
<span class="badge bg-danger">Banned until {{ citizen.banned_until|date:"M d, Y" }}</span>
{% else %}
<span class="badge bg-success">Active</span>
{% endif %}
</td>
<td>
{% if citizen.is_currently_banned %}
<a href="{% url 'unban_user' citizen.id %}" class="btn btn-sm btn-success">
<i class="fas fa-unlock"></i> Unban
</a>
{% else %}
<a href="{% url 'ban_user' citizen.id %}" class="btn btn-sm btn-danger">
<i class="fas fa-ban"></i> Ban
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="text-muted">No citizen users found.</p>
{% endif %}
</div>
</div>
</div>
{% endblock %}
@@ -12,7 +12,7 @@
<ul class="list-group">
<li class="list-group-item">
<i class="fas fa-users me-2 text-primary"></i>
<a href="#">Manage Users</a>
<a href="{% url 'manage_users' %}">Manage Users</a>
</li>
<li class="list-group-item">
<i class="fas fa-building me-2 text-success"></i>
@@ -16,7 +16,7 @@
<th>Reported By</th>
<th>Status</th>
<th>Created At</th>
<th>Assign Department</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
@@ -41,22 +41,29 @@
<td>{{ issue.created_at|date:"M d, Y H:i" }}</td>
<td>
{% if issue.department %}
<span class="fw-bold text-primary">{{ issue.department.name }}</span>
<span class="fw-bold text-primary">{{ issue.department.name }}</span>
{% else %}
<form method="post" action="">
{% csrf_token %}
<input type="hidden" name="issue_id" value="{{ issue.id }}">
<select name="department" class="form-select form-select-sm">
<option value="">— Select Department —</option>
{% for dept in departments %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-sm btn-primary mt-1">Assign</button>
</form>
<!-- Assign Department Form -->
<form method="post" action="" class="d-inline">
{% csrf_token %}
<input type="hidden" name="issue_id" value="{{ issue.id }}">
<select name="department" class="form-select form-select-sm d-inline w-auto">
<option value="">— Select Department —</option>
{% for dept in departments %}
<option value="{{ dept.id }}">{{ dept.name }}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-sm btn-primary">Assign</button>
</form>
<!-- Report Fake Button -->
<a href="{% url 'delete_fake_issue' issue.id %}"
class="btn btn-sm btn-danger ms-1"
onclick="return confirm('Are you sure you want to delete this issue as FAKE?');">
<i class="fas fa-ban"></i> Report Fake
</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
+4
View File
@@ -21,4 +21,8 @@ urlpatterns = [
path('vote/<int:issue_id>/', views.vote_issue, name='vote_issue'),
path("department/", views.department_dashboard, name="department_dashboard"),
path("update-issue-status/<int:issue_id>/", views.update_issue_status, name="update_issue_status"),
path('manage-users/', views.manage_users, name='manage_users'),
path('ban-user/<int:user_id>/', views.ban_user, name='ban_user'),
path('unban-user/<int:user_id>/', views.unban_user, name='unban_user'),
path('issues/<int:issue_id>/delete_fake/', views.delete_fake_issue, name='delete_fake_issue'),
]
+34
View File
@@ -291,6 +291,40 @@ def assign_department(request, issue_id):
return redirect("manage_issues")
@login_required
@user_passes_test(superadmin_check)
def manage_users(request):
citizens = User.objects.filter(is_citizen=True).order_by('-date_joined')
return render(request, 'core/manage_users.html', {'citizens': citizens})
@login_required
@user_passes_test(superadmin_check)
def ban_user(request, user_id):
citizen = get_object_or_404(User, id=user_id, is_citizen=True)
citizen.ban(days=7) # default ban 7 days
messages.warning(request, f"{citizen.username} has been banned for 7 days.")
return redirect('manage_users')
@login_required
@user_passes_test(superadmin_check)
def unban_user(request, user_id):
citizen = get_object_or_404(User, id=user_id, is_citizen=True)
citizen.unban()
messages.success(request, f"{citizen.username} has been unbanned.")
return redirect('manage_users')
# core/views.py
@login_required
@user_passes_test(superadmin_check)
def delete_fake_issue(request, issue_id):
issue = get_object_or_404(Issue, id=issue_id)
reporter = issue.reporter
issue.delete()
messages.error(request, f"Issue by {reporter.username} was reported fake and deleted.")
return redirect('manage_issues')
def resolver_check(user):
return user.is_resolver