micro-users 1.0.3__tar.gz → 1.1.0__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 (33) hide show
  1. {micro_users-1.0.3 → micro_users-1.1.0}/PKG-INFO +6 -5
  2. {micro_users-1.0.3 → micro_users-1.1.0}/README.md +3 -4
  3. {micro_users-1.0.3 → micro_users-1.1.0}/micro_users.egg-info/PKG-INFO +6 -5
  4. {micro_users-1.0.3 → micro_users-1.1.0}/micro_users.egg-info/SOURCES.txt +2 -1
  5. {micro_users-1.0.3 → micro_users-1.1.0}/pyproject.toml +4 -2
  6. {micro_users-1.0.3 → micro_users-1.1.0}/setup.py +3 -1
  7. {micro_users-1.0.3 → micro_users-1.1.0}/users/forms.py +19 -44
  8. micro_users-1.1.0/users/migrations/0001_initial.py +63 -0
  9. micro_users-1.1.0/users/tests.py +3 -0
  10. micro_users-1.0.3/users/static/css/login.css +0 -134
  11. {micro_users-1.0.3 → micro_users-1.1.0}/LICENSE +0 -0
  12. {micro_users-1.0.3 → micro_users-1.1.0}/MANIFEST.in +0 -0
  13. {micro_users-1.0.3 → micro_users-1.1.0}/micro_users.egg-info/dependency_links.txt +0 -0
  14. {micro_users-1.0.3 → micro_users-1.1.0}/micro_users.egg-info/requires.txt +0 -0
  15. {micro_users-1.0.3 → micro_users-1.1.0}/micro_users.egg-info/top_level.txt +0 -0
  16. {micro_users-1.0.3 → micro_users-1.1.0}/setup.cfg +0 -0
  17. {micro_users-1.0.3 → micro_users-1.1.0}/users/__init__.py +0 -0
  18. {micro_users-1.0.3 → micro_users-1.1.0}/users/admin.py +0 -0
  19. {micro_users-1.0.3 → micro_users-1.1.0}/users/apps.py +0 -0
  20. {micro_users-1.0.3 → micro_users-1.1.0}/users/filters.py +0 -0
  21. {micro_users-1.0.3 → micro_users-1.1.0}/users/migrations/__init__.py +0 -0
  22. {micro_users-1.0.3 → micro_users-1.1.0}/users/models.py +0 -0
  23. {micro_users-1.0.3 → micro_users-1.1.0}/users/signals.py +0 -0
  24. {micro_users-1.0.3 → micro_users-1.1.0}/users/tables.py +0 -0
  25. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/registration/login.html +0 -0
  26. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/user_activity_log.html +0 -0
  27. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/users/manage_users.html +0 -0
  28. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/users/profile.html +0 -0
  29. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/users/profile_edit.html +0 -0
  30. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/users/user_actions.html +0 -0
  31. {micro_users-1.0.3 → micro_users-1.1.0}/users/templates/users/user_form.html +0 -0
  32. {micro_users-1.0.3 → micro_users-1.1.0}/users/urls.py +0 -0
  33. {micro_users-1.0.3 → micro_users-1.1.0}/users/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: micro_users
3
- Version: 1.0.3
3
+ Version: 1.1.0
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
@@ -15,6 +15,8 @@ Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
18
20
  Classifier: License :: OSI Approved :: MIT License
19
21
  Classifier: Operating System :: OS Independent
20
22
  Requires-Python: >=3.9
@@ -36,7 +38,7 @@ Requires-Dist: babel>=2.1
36
38
 
37
39
  ## Requirements
38
40
  - **Must be installed on a fresh database.**
39
- - Python 3.9+
41
+ - Python 3.11+
40
42
  - Django 5.1+
41
43
  - django-crispy-forms 2.4+
42
44
  - django-tables2 2.7+
@@ -48,7 +50,7 @@ Requires-Dist: babel>=2.1
48
50
  ## Features
49
51
  - Custom AbstractUser model
50
52
  - User permissions system
51
- - Activity logging (login/logout tracking)
53
+ - Activity logging (login/logout, CRUD tracking)
52
54
  - Localization support
53
55
  - Admin interface integration
54
56
  - CRUD views and templates
@@ -87,9 +89,8 @@ urlpatterns = [
87
89
  ]
88
90
  ```
89
91
 
90
- 4. make migrations and migrate:
92
+ 4. Run migrations:
91
93
  ```bash
92
- python manage.py makemigrations users
93
94
  python manage.py migrate users
94
95
  ```
95
96
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## Requirements
9
9
  - **Must be installed on a fresh database.**
10
- - Python 3.9+
10
+ - Python 3.11+
11
11
  - Django 5.1+
12
12
  - django-crispy-forms 2.4+
13
13
  - django-tables2 2.7+
@@ -19,7 +19,7 @@
19
19
  ## Features
20
20
  - Custom AbstractUser model
21
21
  - User permissions system
22
- - Activity logging (login/logout tracking)
22
+ - Activity logging (login/logout, CRUD tracking)
23
23
  - Localization support
24
24
  - Admin interface integration
25
25
  - CRUD views and templates
@@ -58,9 +58,8 @@ urlpatterns = [
58
58
  ]
59
59
  ```
60
60
 
61
- 4. make migrations and migrate:
61
+ 4. Run migrations:
62
62
  ```bash
63
- python manage.py makemigrations users
64
63
  python manage.py migrate users
65
64
  ```
66
65
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: micro-users
3
- Version: 1.0.3
3
+ Version: 1.1.0
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
@@ -15,6 +15,8 @@ Classifier: Programming Language :: Python :: 3.9
15
15
  Classifier: Programming Language :: Python :: 3.10
16
16
  Classifier: Programming Language :: Python :: 3.11
17
17
  Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
18
20
  Classifier: License :: OSI Approved :: MIT License
19
21
  Classifier: Operating System :: OS Independent
20
22
  Requires-Python: >=3.9
@@ -36,7 +38,7 @@ Requires-Dist: babel>=2.1
36
38
 
37
39
  ## Requirements
38
40
  - **Must be installed on a fresh database.**
39
- - Python 3.9+
41
+ - Python 3.11+
40
42
  - Django 5.1+
41
43
  - django-crispy-forms 2.4+
42
44
  - django-tables2 2.7+
@@ -48,7 +50,7 @@ Requires-Dist: babel>=2.1
48
50
  ## Features
49
51
  - Custom AbstractUser model
50
52
  - User permissions system
51
- - Activity logging (login/logout tracking)
53
+ - Activity logging (login/logout, CRUD tracking)
52
54
  - Localization support
53
55
  - Admin interface integration
54
56
  - CRUD views and templates
@@ -87,9 +89,8 @@ urlpatterns = [
87
89
  ]
88
90
  ```
89
91
 
90
- 4. make migrations and migrate:
92
+ 4. Run migrations:
91
93
  ```bash
92
- python manage.py makemigrations users
93
94
  python manage.py migrate users
94
95
  ```
95
96
 
@@ -16,10 +16,11 @@ users/forms.py
16
16
  users/models.py
17
17
  users/signals.py
18
18
  users/tables.py
19
+ users/tests.py
19
20
  users/urls.py
20
21
  users/views.py
22
+ users/migrations/0001_initial.py
21
23
  users/migrations/__init__.py
22
- users/static/css/login.css
23
24
  users/templates/user_activity_log.html
24
25
  users/templates/registration/login.html
25
26
  users/templates/users/manage_users.html
@@ -8,10 +8,10 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "micro_users"
11
- version = "1.0.3"
11
+ version = "1.1.0"
12
12
  description = "Arabic Django user management app with abstract user, permissions, and activity logging"
13
13
  readme = "README.md"
14
- requires-python = ">=3.9"
14
+ requires-python = ">=3.11"
15
15
  license = { text = "MIT" }
16
16
  authors = [
17
17
  { name = "DeBeski", email = "debeski1@gmail.com" }
@@ -38,6 +38,8 @@ classifiers = [
38
38
  "Programming Language :: Python :: 3.10",
39
39
  "Programming Language :: Python :: 3.11",
40
40
  "Programming Language :: Python :: 3.12",
41
+ "Programming Language :: Python :: 3.13",
42
+ "Programming Language :: Python :: 3.14",
41
43
  "License :: OSI Approved :: MIT License",
42
44
  "Operating System :: OS Independent",
43
45
  ]
@@ -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.0.3",
8
+ version="1.1.0",
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",
@@ -23,6 +23,8 @@ setup(
23
23
  "Programming Language :: Python :: 3.10",
24
24
  "Programming Language :: Python :: 3.11",
25
25
  "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
26
28
  "License :: OSI Approved :: MIT License",
27
29
  "Operating System :: OS Independent",
28
30
  ],
@@ -10,6 +10,7 @@ from crispy_forms.bootstrap import FormActions
10
10
  from PIL import Image
11
11
  from django.core.exceptions import ValidationError
12
12
  from django.utils.translation import gettext_lazy as _
13
+ from django.db.models import Q
13
14
 
14
15
  User = get_user_model()
15
16
 
@@ -48,28 +49,15 @@ class CustomUserCreationForm(UserCreationForm):
48
49
 
49
50
  # Split permissions queryset into two parts for 2 columns
50
51
  permissions_list = list(Permissions.objects.exclude(
51
- codename__in=[
52
- 'add_logentry', 'change_logentry', 'delete_logentry', 'view_logentry',
53
- 'add_theme', 'change_theme', 'delete_theme', 'view_theme',
54
- 'add_group', 'change_group', 'delete_group', 'view_group',
55
- 'add_permission', 'change_permission', 'delete_permission', 'view_permission',
56
- 'add_permissions', 'change_permissions', 'delete_permissions', 'view_permissions',
57
- 'add_contenttype', 'change_contenttype', 'delete_contenttype', 'view_contenttype',
58
- 'add_session', 'change_session', 'delete_session', 'view_session',
59
- 'add_government', 'delete_government', 'view_government',
60
- 'add_minister', 'delete_minister', 'view_minister',
61
- 'add_decreecategory', 'delete_decreecategory', 'view_decreecategory',
62
- 'add_periodictask', 'change_periodictask', 'delete_periodictask', 'view_periodictask',
63
- 'add_periodictasks', 'change_periodictasks', 'delete_periodictasks', 'view_periodictasks',
64
- 'add_clockedschedule', 'change_clockedschedule', 'delete_clockedschedule', 'view_clockedschedule',
65
- 'add_crontabschedule', 'change_crontabschedule', 'delete_crontabschedule', 'view_crontabschedule',
66
- 'add_intervalschedule', 'change_intervalschedule', 'delete_intervalschedule', 'view_intervalschedule',
67
- 'add_solarschedule', 'change_solarschedule', 'delete_solarschedule', 'view_solarschedule',
68
- 'add_customuser', 'change_customuser', 'delete_customuser', 'view_customuser',
69
- 'add_useractivitylog', 'change_useractivitylog', 'delete_useractivitylog', 'view_useractivitylog',
70
- 'download_doc', 'gen_pub_pdf', 'download_doc', 'delete_decree', 'delete_publication', 'delete_objection',
71
- 'delete_formplus', 'view_decree', 'view_formplus', 'gen_pub_pdf', 'view_publication',
72
- ]
52
+ Q(codename__regex=r'^(delete_)') |
53
+ Q(content_type__app_label__in=[
54
+ 'admin',
55
+ 'auth',
56
+ 'contenttypes',
57
+ 'sessions',
58
+ 'django_celery_beat',
59
+ 'users'
60
+ ])
73
61
  ))
74
62
  mid_point = len(permissions_list) // 2
75
63
  permissions_right = permissions_list[:mid_point]
@@ -176,28 +164,15 @@ class CustomUserChangeForm(UserChangeForm):
176
164
 
177
165
  # Split permissions queryset into two parts for 2 columns
178
166
  permissions_list = list(Permissions.objects.exclude(
179
- codename__in=[
180
- 'add_logentry', 'change_logentry', 'delete_logentry', 'view_logentry',
181
- 'add_theme', 'change_theme', 'delete_theme', 'view_theme',
182
- 'add_group', 'change_group', 'delete_group', 'view_group',
183
- 'add_permission', 'change_permission', 'delete_permission', 'view_permission',
184
- 'add_permissions', 'change_permissions', 'delete_permissions', 'view_permissions',
185
- 'add_contenttype', 'change_contenttype', 'delete_contenttype', 'view_contenttype',
186
- 'add_session', 'change_session', 'delete_session', 'view_session',
187
- 'add_government', 'delete_government', 'view_government',
188
- 'add_minister', 'delete_minister', 'view_minister',
189
- 'add_decreecategory', 'delete_decreecategory', 'view_decreecategory',
190
- 'add_periodictask', 'change_periodictask', 'delete_periodictask', 'view_periodictask',
191
- 'add_periodictasks', 'change_periodictasks', 'delete_periodictasks', 'view_periodictasks',
192
- 'add_clockedschedule', 'change_clockedschedule', 'delete_clockedschedule', 'view_clockedschedule',
193
- 'add_crontabschedule', 'change_crontabschedule', 'delete_crontabschedule', 'view_crontabschedule',
194
- 'add_intervalschedule', 'change_intervalschedule', 'delete_intervalschedule', 'view_intervalschedule',
195
- 'add_solarschedule', 'change_solarschedule', 'delete_solarschedule', 'view_solarschedule',
196
- 'add_customuser', 'change_customuser', 'delete_customuser', 'view_customuser',
197
- 'add_useractivitylog', 'change_useractivitylog', 'delete_useractivitylog', 'view_useractivitylog',
198
- 'download_doc', 'gen_pub_pdf', 'download_doc', 'delete_decree', 'delete_publication', 'delete_objection',
199
- 'delete_formplus', 'view_decree', 'view_formplus', 'gen_pub_pdf', 'view_publication',
200
- ]
167
+ Q(codename__regex=r'^(delete_)') |
168
+ Q(content_type__app_label__in=[
169
+ 'admin',
170
+ 'auth',
171
+ 'contenttypes',
172
+ 'sessions',
173
+ 'django_celery_beat',
174
+ 'users'
175
+ ])
201
176
  ))
202
177
  mid_point = len(permissions_list) // 2
203
178
  self.permissions_right = permissions_list[:mid_point]
@@ -0,0 +1,63 @@
1
+ # Generated by Django 5.2.8 on 2025-12-03 15:01
2
+
3
+ import django.contrib.auth.models
4
+ import django.contrib.auth.validators
5
+ import django.db.models.deletion
6
+ import django.utils.timezone
7
+ from django.conf import settings
8
+ from django.db import migrations, models
9
+
10
+
11
+ class Migration(migrations.Migration):
12
+
13
+ initial = True
14
+
15
+ dependencies = [
16
+ ('auth', '0012_alter_user_first_name_max_length'),
17
+ ]
18
+
19
+ operations = [
20
+ migrations.CreateModel(
21
+ name='CustomUser',
22
+ fields=[
23
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
24
+ ('password', models.CharField(max_length=128, verbose_name='password')),
25
+ ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
26
+ ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
27
+ ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
28
+ ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
29
+ ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
30
+ ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
31
+ ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
32
+ ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
33
+ ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
34
+ ('phone', models.CharField(blank=True, max_length=15, null=True, verbose_name='رقم الهاتف')),
35
+ ('occupation', models.CharField(blank=True, max_length=100, null=True, verbose_name='جهة العمل')),
36
+ ('profile_picture', models.ImageField(blank=True, null=True, upload_to='profile_pictures/')),
37
+ ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
38
+ ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
39
+ ],
40
+ options={
41
+ 'verbose_name': 'user',
42
+ 'verbose_name_plural': 'users',
43
+ 'abstract': False,
44
+ },
45
+ managers=[
46
+ ('objects', django.contrib.auth.models.UserManager()),
47
+ ],
48
+ ),
49
+ migrations.CreateModel(
50
+ name='UserActivityLog',
51
+ fields=[
52
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
53
+ ('action', models.CharField(choices=[('LOGIN', 'تسجيل دخـول'), ('LOGOUT', 'تسجيل خـروج'), ('CREATE', 'انشـاء'), ('UPDATE', 'تعديـل'), ('DELETE', 'حــذف'), ('VIEW', 'عـرض'), ('DOWNLOAD', 'تحميل'), ('CONFIRM', 'تأكيـد'), ('REJECT', 'رفــض')], max_length=10, verbose_name='العملية')),
54
+ ('model_name', models.CharField(blank=True, max_length=100, null=True, verbose_name='القسم')),
55
+ ('object_id', models.IntegerField(blank=True, null=True, verbose_name='ID')),
56
+ ('number', models.CharField(blank=True, max_length=50, null=True, verbose_name='المستند')),
57
+ ('ip_address', models.GenericIPAddressField(blank=True, null=True, verbose_name='عنوان IP')),
58
+ ('user_agent', models.TextField(blank=True, null=True, verbose_name='agent')),
59
+ ('timestamp', models.DateTimeField(auto_now_add=True, verbose_name='الوقت')),
60
+ ('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='اسم المستخدم')),
61
+ ],
62
+ ),
63
+ ]
@@ -0,0 +1,3 @@
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
@@ -1,134 +0,0 @@
1
- ::selection {
2
- background: #d4c591;
3
- }
4
- ::-webkit-selection {
5
- background: #d4c591;
6
- }
7
- ::-moz-selection {
8
- background: #c9aa5e;
9
- }
10
-
11
- .page {
12
- display: flex;
13
- flex-direction: column;
14
- height: calc(100% - 15vh);
15
- position: absolute;
16
- place-content: center;
17
- width: calc(100% - 40px);
18
- }
19
- @media (max-width: 767px) {
20
- .page {
21
- height: auto;
22
- margin-bottom: 20px;
23
- padding-bottom: 20px;
24
- }
25
- }
26
- .container {
27
- height: 320px;
28
- margin: 0 auto;
29
- width: 640px;
30
- }
31
- @media (max-width: 767px) {
32
- .container {
33
- flex-direction: column;
34
- height: 630px;
35
- width: 320px;
36
- }
37
- }
38
- .left {
39
- background: white;
40
- height: calc(100% - 40px);
41
- top: 20px;
42
- position: relative;
43
- width: 60%;
44
- box-shadow: 0px 0px 10px 4px rgba(0,0,0,0.03);
45
-
46
- }
47
- @media (max-width: 767px) {
48
- .left {
49
- height: 100%;
50
- left: 5%;
51
- width: 110%;
52
- max-height: 270px;
53
- }
54
- }
55
- /* .login {
56
- font-size: 38px;
57
- font-weight: 600;
58
- }
59
- .eula {
60
- color: #adadad;
61
- font-size: 14px;
62
- line-height: 1.5;
63
- margin: 40px;
64
- } */
65
- .right {
66
- background: #cb9447;
67
- box-shadow: 0px 0px 20px 8px rgba(0,0,0,0.07);
68
- color: #F1F1F2;
69
- position: relative;
70
- width: 58%;
71
- }
72
- @media (max-width: 767px) {
73
- .right {
74
- flex-shrink: 0;
75
- height: 100%;
76
- width: 100%;
77
- max-height: 350px;
78
- }
79
- }
80
- svg {
81
- position: absolute;
82
- width: 320px;
83
- }
84
- path {
85
- fill: none;
86
- stroke: url(#linearGradient);;
87
- stroke-width: 3;
88
- stroke-dasharray: 240 1386;
89
- }
90
- .form {
91
- margin: 35px 35px 35px 20px;
92
- position: absolute;
93
- }
94
- label {
95
- color: #c2c2c5;
96
- display: block;
97
- font-size: 14px;
98
- height: 16px;
99
- margin-top: 20px;
100
- margin-bottom: 5px;
101
- }
102
- input {
103
- background: transparent;
104
- border: 0;
105
- color: #2d0202;
106
- font-size: 20px;
107
- height: 30px;
108
- line-height: 30px;
109
- outline: none !important;
110
- width: 100%;
111
- margin-top: 30px;
112
- margin-bottom: 10px;
113
- }
114
- input::-moz-focus-inner {
115
- border: 0;
116
- }
117
- #submit {
118
- color: #707075;
119
- margin-top: 40px;
120
- transition: color 300ms;
121
- }
122
- #submit:focus {
123
- color: #575757;
124
- }
125
- #submit:active {
126
- color: #4d4d4d;
127
- }
128
-
129
- .titlebar {
130
- background-color: var(--title);
131
- flex-direction: row;
132
- height: 7vh;
133
- justify-content: center !important
134
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes