micro-users 1.1.1__tar.gz → 1.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of micro-users might be problematic. Click here for more details.

Files changed (32) hide show
  1. {micro_users-1.1.1 → micro_users-1.2.1}/PKG-INFO +15 -1
  2. {micro_users-1.1.1 → micro_users-1.2.1}/README.md +14 -0
  3. {micro_users-1.1.1 → micro_users-1.2.1}/micro_users.egg-info/PKG-INFO +15 -1
  4. {micro_users-1.1.1 → micro_users-1.2.1}/micro_users.egg-info/SOURCES.txt +1 -0
  5. {micro_users-1.1.1 → micro_users-1.2.1}/pyproject.toml +1 -1
  6. {micro_users-1.1.1 → micro_users-1.2.1}/setup.py +1 -1
  7. {micro_users-1.1.1 → micro_users-1.2.1}/users/tables.py +6 -0
  8. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/users/manage_users.html +1 -1
  9. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/users/user_actions.html +7 -2
  10. micro_users-1.2.1/users/templates/users/user_detail.html +49 -0
  11. {micro_users-1.1.1 → micro_users-1.2.1}/users/urls.py +4 -3
  12. {micro_users-1.1.1 → micro_users-1.2.1}/users/views.py +35 -8
  13. {micro_users-1.1.1 → micro_users-1.2.1}/LICENSE +0 -0
  14. {micro_users-1.1.1 → micro_users-1.2.1}/MANIFEST.in +0 -0
  15. {micro_users-1.1.1 → micro_users-1.2.1}/micro_users.egg-info/dependency_links.txt +0 -0
  16. {micro_users-1.1.1 → micro_users-1.2.1}/micro_users.egg-info/requires.txt +0 -0
  17. {micro_users-1.1.1 → micro_users-1.2.1}/micro_users.egg-info/top_level.txt +0 -0
  18. {micro_users-1.1.1 → micro_users-1.2.1}/setup.cfg +0 -0
  19. {micro_users-1.1.1 → micro_users-1.2.1}/users/__init__.py +0 -0
  20. {micro_users-1.1.1 → micro_users-1.2.1}/users/admin.py +0 -0
  21. {micro_users-1.1.1 → micro_users-1.2.1}/users/apps.py +0 -0
  22. {micro_users-1.1.1 → micro_users-1.2.1}/users/filters.py +0 -0
  23. {micro_users-1.1.1 → micro_users-1.2.1}/users/forms.py +0 -0
  24. {micro_users-1.1.1 → micro_users-1.2.1}/users/migrations/0001_initial.py +0 -0
  25. {micro_users-1.1.1 → micro_users-1.2.1}/users/migrations/__init__.py +0 -0
  26. {micro_users-1.1.1 → micro_users-1.2.1}/users/models.py +0 -0
  27. {micro_users-1.1.1 → micro_users-1.2.1}/users/signals.py +0 -0
  28. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/registration/login.html +0 -0
  29. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/user_activity_log.html +0 -0
  30. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/users/profile.html +0 -0
  31. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/users/profile_edit.html +0 -0
  32. {micro_users-1.1.1 → micro_users-1.2.1}/users/templates/users/user_form.html +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: micro_users
3
- Version: 1.1.1
3
+ Version: 1.2.1
4
4
  Summary: Arabic Django user management app with abstract user, permissions, and activity logging
5
5
  Home-page: https://github.com/debeski/micro-users
6
6
  Author: DeBeski
@@ -105,3 +105,17 @@ users/
105
105
  ├── templates/ # HTML templates
106
106
  └── migrations/ # Database migrations
107
107
  ```
108
+
109
+ ## Version History
110
+
111
+ | Version | Changes |
112
+ |----------|---------|
113
+ | v1.0.0 | Initial release as pip package |
114
+ | v1.0.1 | Fixed a couple of new issues as a pip package |
115
+ | v1.0.2 | Fixed the readme and building files |
116
+ | v1.0.3 | Still getting the hang of this pip publish thing |
117
+ | v1.0.4 | Honestly still messing with and trying settings and stuff out |
118
+ | v1.1.0 | OK, finally a working seamless micro-users app |
119
+ | v1.1.1 | Fixed a bug where a staff member can edit the admin details |
120
+ | v1.2.0 | Added User Details view with specific user activity log |
121
+ | v1.2.1 | Fixed a minot import bug |
@@ -74,3 +74,17 @@ users/
74
74
  ├── templates/ # HTML templates
75
75
  └── migrations/ # Database migrations
76
76
  ```
77
+
78
+ ## Version History
79
+
80
+ | Version | Changes |
81
+ |----------|---------|
82
+ | v1.0.0 | Initial release as pip package |
83
+ | v1.0.1 | Fixed a couple of new issues as a pip package |
84
+ | v1.0.2 | Fixed the readme and building files |
85
+ | v1.0.3 | Still getting the hang of this pip publish thing |
86
+ | v1.0.4 | Honestly still messing with and trying settings and stuff out |
87
+ | v1.1.0 | OK, finally a working seamless micro-users app |
88
+ | v1.1.1 | Fixed a bug where a staff member can edit the admin details |
89
+ | v1.2.0 | Added User Details view with specific user activity log |
90
+ | v1.2.1 | Fixed a minot import bug |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: micro-users
3
- Version: 1.1.1
3
+ Version: 1.2.1
4
4
  Summary: Arabic Django user management app with abstract user, permissions, and activity logging
5
5
  Home-page: https://github.com/debeski/micro-users
6
6
  Author: DeBeski
@@ -105,3 +105,17 @@ users/
105
105
  ├── templates/ # HTML templates
106
106
  └── migrations/ # Database migrations
107
107
  ```
108
+
109
+ ## Version History
110
+
111
+ | Version | Changes |
112
+ |----------|---------|
113
+ | v1.0.0 | Initial release as pip package |
114
+ | v1.0.1 | Fixed a couple of new issues as a pip package |
115
+ | v1.0.2 | Fixed the readme and building files |
116
+ | v1.0.3 | Still getting the hang of this pip publish thing |
117
+ | v1.0.4 | Honestly still messing with and trying settings and stuff out |
118
+ | v1.1.0 | OK, finally a working seamless micro-users app |
119
+ | v1.1.1 | Fixed a bug where a staff member can edit the admin details |
120
+ | v1.2.0 | Added User Details view with specific user activity log |
121
+ | v1.2.1 | Fixed a minot import bug |
@@ -26,4 +26,5 @@ users/templates/users/manage_users.html
26
26
  users/templates/users/profile.html
27
27
  users/templates/users/profile_edit.html
28
28
  users/templates/users/user_actions.html
29
+ users/templates/users/user_detail.html
29
30
  users/templates/users/user_form.html
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "micro_users"
11
- version = "1.1.1"
11
+ version = "1.2.1"
12
12
  description = "Arabic Django user management app with abstract user, permissions, and activity logging"
13
13
  readme = "README.md"
14
14
  requires-python = ">=3.11"
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="micro_users",
8
- version="1.1.1",
8
+ version="1.2.1",
9
9
  author="DeBeski",
10
10
  author_email="debeski1@gmail.com",
11
11
  description="Arabic django user management app with abstract user, permissions, and activity logging",
@@ -38,3 +38,9 @@ class UserActivityLogTable(tables.Table):
38
38
  template_name = "django_tables2/bootstrap5.html"
39
39
  fields = ("timestamp", "user", "user.full_name", "action", "model_name", "object_id", "number")
40
40
  attrs = {'class': 'table table-hover align-middle'}
41
+
42
+ class UserActivityLogTableNoUser(UserActivityLogTable):
43
+ class Meta(UserActivityLogTable.Meta):
44
+ # Remove the 'user' and 'user.full_name' columns
45
+ exclude = ("user", "user.full_name")
46
+
@@ -65,7 +65,7 @@
65
65
 
66
66
  // Update the modal content
67
67
  document.getElementById("userName").textContent = userName;
68
- form.action = `/manage/users/delete/${userId}/`; // Update form action with user ID
68
+ form.action = "{% url 'delete_user' 0 %}".replace("/0/", `/${userId}/`);
69
69
  });
70
70
  });
71
71
  </script>
@@ -11,7 +11,12 @@
11
11
  </li> {% endcomment %}
12
12
  {% if not record.is_superuser %}
13
13
  <li>
14
- <a class="dropdown-item" href="{% url 'edit_user' record.id %}" title="تعديل">
14
+ <a class="dropdown-item" href="{% url 'user_detail' record.pk %}" title="عرض">
15
+ <i class="bi bi-person-dash-fill text-dark me-1 h5"> </i> عرض
16
+ </a>
17
+ </li>
18
+ <li>
19
+ <a class="dropdown-item" href="{% url 'edit_user' record.pk %}" title="تعديل">
15
20
  <i class="bi bi-person-dash-fill text-dark me-1 h5"> </i> تعديل
16
21
  </a>
17
22
  </li>
@@ -19,7 +24,7 @@
19
24
  {% if user.is_superuser and not record.is_staff %}
20
25
  <li>
21
26
  <a class="dropdown-item" href="#" data-bs-toggle="modal" data-bs-target="#deleteModal"
22
- data-user-id="{{ record.id }}" data-user-name="{{ record.username }}">
27
+ data-user-id="{{ record.pk }}" data-user-name="{{ record.username }}">
23
28
  <i class="bi bi-x-octagon text-danger me-1 h5"> </i> حذف
24
29
  </a>
25
30
  </li>
@@ -0,0 +1,49 @@
1
+ {% extends "base.html" %}
2
+ {% load crispy_forms_tags %}
3
+ {% load django_tables2 %}
4
+
5
+ {% block content %}
6
+ <div class="container mt-4">
7
+ <!-- USER INFO CARD -->
8
+ <div class="card mb-4 shadow-sm">
9
+ <div class="card-header bg-primary text-white">
10
+ تفاصيل المستخدم
11
+ </div>
12
+ <div class="card-body">
13
+ <h5>{{ detail_user.get_full_name }} ({{ detail_user.username }})</h5>
14
+ <p class="mb-1"><strong>البريد:</strong> {{ detail_user.email }}</p>
15
+ <p class="mb-1"><strong>تاريخ الإنشاء:</strong> {{ detail_user.date_joined|date:"Y-m-d" }}</p>
16
+ <p class="mb-1"><strong>آخر دخول:</strong> {{ detail_user.last_login|date:"Y-m-d H:i" }}</p>
17
+ <p class="mb-1"><strong>الصلاحيات:</strong>
18
+ {% if detail_user.is_superuser %}
19
+ مدير النظام
20
+ {% elif detail_user.is_staff %}
21
+ مستخدم اداري
22
+ {% else %}
23
+ مستخدم عادي
24
+ {% endif %}
25
+ </p>
26
+ </div>
27
+ </div>
28
+
29
+ <!-- ACTIVITY LOG TABLE -->
30
+ <div class="card shadow-sm">
31
+ <div class="card-header bg-secondary text-white">
32
+ سجل نشاط المستخدم
33
+ </div>
34
+ <div class="card-body">
35
+ {% render_table table %}
36
+ </div>
37
+ </div>
38
+
39
+ <!-- BACK BUTTON -->
40
+ <div class="mb-3">
41
+ <a href="{% url 'manage_users' %}" class="btn btn-outline-secondary">
42
+ <i class="bi bi-arrow-right me-2"></i> العودة إلى إدارة المستخدمين
43
+ </a>
44
+ </div>
45
+
46
+ </div>
47
+
48
+
49
+ {% endblock %}
@@ -9,10 +9,11 @@ urlpatterns = [
9
9
  path('logout/', auth_views.LogoutView.as_view(), name='logout'),
10
10
  path("users/", views.UserListView.as_view(), name="manage_users"),
11
11
  path('users/create/', views.create_user, name='create_user'),
12
- path('users/edit/<int:user_id>/', views.edit_user, name='edit_user'),
13
- path('users/delete/<int:user_id>/', views.delete_user, name='delete_user'),
12
+ path('users/edit/<int:pk>/', views.edit_user, name='edit_user'),
13
+ path('users/delete/<int:pk>/', views.delete_user, name='delete_user'),
14
14
  path("profile", views.user_profile, name="user_profile"),
15
15
  path('profile/edit/', views.edit_profile, name='edit_profile'),
16
16
  path("logs/", views.UserActivityLogView.as_view(), name="user_activity_log"),
17
- path('reset_password/<int:user_id>/', views.reset_password, name="reset_password"),
17
+ path('reset_password/<int:pk>/', views.reset_password, name="reset_password"),
18
+ path("users/<int:pk>/", views.UserDetailView.as_view(), name="user_detail"),
18
19
  ]
@@ -9,12 +9,13 @@ from django.http import JsonResponse
9
9
  from django.shortcuts import render, redirect, get_object_or_404
10
10
  from django_tables2 import RequestConfig, SingleTableView
11
11
  from django_filters.views import FilterView
12
+ from django.views.generic.detail import DetailView
12
13
 
13
14
  # Project imports
14
15
  #################
15
16
 
16
17
  from .signals import get_client_ip
17
- from .tables import UserTable, UserActivityLogTable
18
+ from .tables import UserTable, UserActivityLogTable, UserActivityLogTableNoUser
18
19
  from .forms import CustomUserCreationForm, CustomUserChangeForm, ArabicPasswordChangeForm, ResetPasswordForm, UserProfileEditForm
19
20
  from .filters import UserFilter, UserActivityLogFilter
20
21
  from .models import UserActivityLog
@@ -32,6 +33,7 @@ def is_staff(user):
32
33
  def is_superuser(user):
33
34
  return user.is_superuser
34
35
 
36
+
35
37
  # Class Function for managing users
36
38
  class UserListView(LoginRequiredMixin, UserPassesTestMixin, FilterView, SingleTableView):
37
39
  model = User
@@ -80,8 +82,8 @@ def create_user(request):
80
82
 
81
83
  # Function for editing an existing User
82
84
  @user_passes_test(is_staff)
83
- def edit_user(request, user_id):
84
- user = get_object_or_404(User, id=user_id)
85
+ def edit_user(request, pk):
86
+ user = get_object_or_404(User, pk=pk)
85
87
  form_reset = ResetPasswordForm(user, data=request.POST or None)
86
88
 
87
89
  if request.method == "POST":
@@ -101,8 +103,8 @@ def edit_user(request, user_id):
101
103
 
102
104
  # Function for deleting a User
103
105
  @user_passes_test(is_superuser)
104
- def delete_user(request, user_id):
105
- user = get_object_or_404(User, id=user_id)
106
+ def delete_user(request, pk):
107
+ user = get_object_or_404(User, pk=pk)
106
108
  if request.method == "POST":
107
109
  user.delete()
108
110
  UserActivityLog.objects.create(
@@ -139,10 +141,35 @@ class UserActivityLogView(LoginRequiredMixin, UserPassesTestMixin, SingleTableVi
139
141
  return context
140
142
 
141
143
 
144
+ class UserDetailView(LoginRequiredMixin, UserPassesTestMixin, DetailView, SingleTableView):
145
+ model = User
146
+ template_name = "users/user_detail.html"
147
+ context_object_name = "detail_user" # Keep clear naming
148
+ table_class = UserActivityLogTableNoUser
149
+ paginate_by = 10
150
+
151
+ def test_func(self):
152
+ # only staff can view user detail page
153
+ return self.request.user.is_staff
154
+
155
+ def get_queryset(self):
156
+ # This is for the DetailView (only target user)
157
+ return User.objects.all()
158
+
159
+ def get_table_data(self):
160
+ # filter log table to user in URL
161
+ return UserActivityLog.objects.filter(user=self.get_object()).order_by('-timestamp')
162
+
163
+ def get_context_data(self, **kwargs):
164
+ context = super().get_context_data(**kwargs)
165
+ context['table'] = self.get_table() # table instance
166
+ return context
167
+
168
+
142
169
  # Function that resets a user password
143
170
  @user_passes_test(is_staff)
144
- def reset_password(request, user_id):
145
- user = get_object_or_404(User, id=user_id)
171
+ def reset_password(request, pk):
172
+ user = get_object_or_404(User, id=pk)
146
173
 
147
174
  if request.method == "POST":
148
175
  form = ResetPasswordForm(user=user, data=request.POST) # ✅ Correct usage with SetPasswordForm
@@ -151,7 +178,7 @@ def reset_password(request, user_id):
151
178
  return redirect("manage_users") # Redirect after successful reset
152
179
  else:
153
180
  print("Form errors:", form.errors) # Debugging
154
- return redirect("edit_user", user_id=user_id) # Redirect to edit user on failure
181
+ return redirect("edit_user", pk=pk) # Redirect to edit user on failure
155
182
 
156
183
  return redirect("manage_users") # Fallback redirect
157
184
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes