drf-iam 0.0.1.post0__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.
@@ -0,0 +1,2 @@
1
+ include README.md
2
+ recursive-include drf_iam/migrations *
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.2
2
+ Name: drf-iam
3
+ Version: 0.0.1.post0
4
+ Summary: IAM-style roles and permissions for Django Rest Framework
5
+ Home-page: https://github.com/tushar1328/drf-iam.git
6
+ Author: Tushar Patel
7
+ Author-email: tushar.patel@gmail.com
8
+ Classifier: Framework :: Django
9
+ Classifier: Framework :: Django :: 3.2
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.6
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: Django>=3.2
16
+ Requires-Dist: djangorestframework>=3.12
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: home-page
23
+ Dynamic: requires-dist
24
+ Dynamic: requires-python
25
+ Dynamic: summary
26
+
27
+ ## Rest Framework IAM
28
+
29
+ A simple Django application for Role Based Access Control (RBAC) using Django Rest Framework
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install drf-iam
35
+ ```
@@ -0,0 +1,9 @@
1
+ ## Rest Framework IAM
2
+
3
+ A simple Django application for Role Based Access Control (RBAC) using Django Rest Framework
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install drf-iam
9
+ ```
File without changes
@@ -0,0 +1,29 @@
1
+ from django.contrib import admin
2
+
3
+ from drf_iam.models import Policy, Role, RolePolicy
4
+
5
+
6
+ @admin.register(Policy)
7
+ class PolicyAdmin(admin.ModelAdmin):
8
+ list_display = ('action', 'resource_type', 'description')
9
+ search_fields = ('action', 'resource_type')
10
+ list_filter = ('action', 'resource_type')
11
+
12
+ class PoliciesInline(admin.TabularInline):
13
+ model = Role.policies.through
14
+
15
+ @admin.register(Role)
16
+ class RoleAdmin(admin.ModelAdmin):
17
+ list_display = ('name', 'description')
18
+ search_fields = ('name', 'description')
19
+ list_filter = ('name', 'description')
20
+ inlines = [PoliciesInline]
21
+
22
+
23
+ @admin.register(RolePolicy)
24
+ class RolePolicyAdmin(admin.ModelAdmin):
25
+ list_display = ('role', 'policy')
26
+ search_fields = ('role', 'policy')
27
+ list_filter = ('role', 'policy')
28
+
29
+
@@ -0,0 +1,19 @@
1
+ import logging
2
+
3
+ from django.apps import AppConfig
4
+ from django.db.models.signals import post_migrate
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ class DrfIamConfig(AppConfig):
9
+ default_auto_field = "django.db.models.BigAutoField"
10
+ name = "drf_iam"
11
+
12
+ def ready(self):
13
+ if not hasattr(self, 'already_loaded'):
14
+ from drf_iam.utils.load_viewset_permissions import load_permissions_from_urls
15
+ post_migrate.connect(
16
+ load_permissions_from_urls,
17
+ dispatch_uid="drf_iam.utils.load_permissions_from_urls",
18
+ )
19
+ self.already_loaded = True
@@ -0,0 +1,97 @@
1
+ # Generated by Django 5.2 on 2025-04-19 11:30
2
+
3
+ import django.db.models.deletion
4
+ from django.db import migrations, models
5
+
6
+
7
+ class Migration(migrations.Migration):
8
+
9
+ initial = True
10
+
11
+ dependencies = []
12
+
13
+ operations = [
14
+ migrations.CreateModel(
15
+ name="Role",
16
+ fields=[
17
+ (
18
+ "id",
19
+ models.BigAutoField(
20
+ auto_created=True,
21
+ primary_key=True,
22
+ serialize=False,
23
+ verbose_name="ID",
24
+ ),
25
+ ),
26
+ ("name", models.CharField(max_length=100, unique=True)),
27
+ ("description", models.TextField(blank=True)),
28
+ ],
29
+ ),
30
+ migrations.CreateModel(
31
+ name="Policy",
32
+ fields=[
33
+ (
34
+ "id",
35
+ models.BigAutoField(
36
+ auto_created=True,
37
+ primary_key=True,
38
+ serialize=False,
39
+ verbose_name="ID",
40
+ ),
41
+ ),
42
+ ("action", models.CharField(max_length=100)),
43
+ ("resource_type", models.CharField(max_length=100)),
44
+ ("description", models.TextField(blank=True)),
45
+ ],
46
+ options={
47
+ "verbose_name": "policy",
48
+ "verbose_name_plural": "policies",
49
+ "ordering": ["action", "resource_type"],
50
+ "unique_together": {("action", "resource_type")},
51
+ },
52
+ ),
53
+ migrations.CreateModel(
54
+ name="RolePolicy",
55
+ fields=[
56
+ (
57
+ "id",
58
+ models.BigAutoField(
59
+ auto_created=True,
60
+ primary_key=True,
61
+ serialize=False,
62
+ verbose_name="ID",
63
+ ),
64
+ ),
65
+ (
66
+ "policy",
67
+ models.ForeignKey(
68
+ on_delete=django.db.models.deletion.CASCADE, to="drf_iam.policy"
69
+ ),
70
+ ),
71
+ (
72
+ "role",
73
+ models.ForeignKey(
74
+ on_delete=django.db.models.deletion.CASCADE, to="drf_iam.role"
75
+ ),
76
+ ),
77
+ ],
78
+ options={
79
+ "verbose_name": "role policy",
80
+ "verbose_name_plural": "role policies",
81
+ "ordering": ["role", "policy"],
82
+ "unique_together": {("role", "policy")},
83
+ },
84
+ ),
85
+ migrations.AddField(
86
+ model_name="role",
87
+ name="policies",
88
+ field=models.ManyToManyField(
89
+ blank=True,
90
+ db_index=True,
91
+ related_name="policies",
92
+ related_query_name="policies",
93
+ through="drf_iam.RolePolicy",
94
+ to="drf_iam.policy",
95
+ ),
96
+ ),
97
+ ]
File without changes
@@ -0,0 +1,40 @@
1
+ from django.db import models
2
+
3
+
4
+ class Role(models.Model):
5
+ name = models.CharField(max_length=100, unique=True)
6
+ description = models.TextField(blank=True)
7
+ policies = models.ManyToManyField('Policy', through='RolePolicy', blank=True, related_name='policies',
8
+ related_query_name='policies', db_index=True)
9
+
10
+ def __str__(self):
11
+ return self.name
12
+
13
+
14
+ class Policy(models.Model):
15
+ action = models.CharField(max_length=100)
16
+ resource_type = models.CharField(max_length=100)
17
+ description = models.TextField(blank=True)
18
+
19
+ def __str__(self):
20
+ return f"{self.action} on {self.resource_type}"
21
+
22
+ class Meta:
23
+ unique_together = ('action', 'resource_type')
24
+ ordering = ['action', 'resource_type']
25
+ verbose_name_plural = 'policies'
26
+ verbose_name = 'policy'
27
+
28
+
29
+ class RolePolicy(models.Model):
30
+ role = models.ForeignKey(Role, on_delete=models.CASCADE, db_index=True)
31
+ policy = models.ForeignKey(Policy, on_delete=models.CASCADE, db_index=True)
32
+
33
+ class Meta:
34
+ unique_together = ('role', 'policy')
35
+ ordering = ['role', 'policy']
36
+ verbose_name_plural = 'role policies'
37
+ verbose_name = 'role policy'
38
+
39
+ def __str__(self):
40
+ return f"{self.role.name} - {self.policy}"
@@ -0,0 +1,24 @@
1
+ from rest_framework import permissions
2
+
3
+ class DRFIamPermission(permissions.IsAuthenticated):
4
+ def has_permission(self, request, view):
5
+ user = request.user
6
+ role = getattr(user, 'role', None)
7
+ if not role:
8
+ return False
9
+ if not hasattr(user, '_cached_policy_actions'):
10
+ user._cached_policy_actions = set(
11
+ role.policies.values_list('action', flat=True)
12
+ )
13
+ policy_actions = user._cached_policy_actions
14
+ # Resolve view name
15
+ view_name = getattr(view, 'iam_policy_name', None)
16
+ if not view_name:
17
+ view_class_name = view.__class__.__name__.lower()
18
+ view_name = view_class_name.replace('viewset', '')
19
+
20
+ # Resolve action (DRF view.action or fallback to HTTP method)
21
+ action = getattr(view, 'action', request.method.lower())
22
+ policy_action = f"{view_name}:{action}"
23
+
24
+ return policy_action in policy_actions
@@ -0,0 +1,3 @@
1
+ from django.test import TestCase
2
+
3
+ # Create your tests here.
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.2
2
+ Name: drf-iam
3
+ Version: 0.0.1.post0
4
+ Summary: IAM-style roles and permissions for Django Rest Framework
5
+ Home-page: https://github.com/tushar1328/drf-iam.git
6
+ Author: Tushar Patel
7
+ Author-email: tushar.patel@gmail.com
8
+ Classifier: Framework :: Django
9
+ Classifier: Framework :: Django :: 3.2
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Python: >=3.6
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: Django>=3.2
16
+ Requires-Dist: djangorestframework>=3.12
17
+ Dynamic: author
18
+ Dynamic: author-email
19
+ Dynamic: classifier
20
+ Dynamic: description
21
+ Dynamic: description-content-type
22
+ Dynamic: home-page
23
+ Dynamic: requires-dist
24
+ Dynamic: requires-python
25
+ Dynamic: summary
26
+
27
+ ## Rest Framework IAM
28
+
29
+ A simple Django application for Role Based Access Control (RBAC) using Django Rest Framework
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ pip install drf-iam
35
+ ```
@@ -0,0 +1,16 @@
1
+ MANIFEST.in
2
+ README.md
3
+ setup.py
4
+ drf_iam/__init__.py
5
+ drf_iam/admin.py
6
+ drf_iam/apps.py
7
+ drf_iam/models.py
8
+ drf_iam/permissions.py
9
+ drf_iam/tests.py
10
+ drf_iam.egg-info/PKG-INFO
11
+ drf_iam.egg-info/SOURCES.txt
12
+ drf_iam.egg-info/dependency_links.txt
13
+ drf_iam.egg-info/requires.txt
14
+ drf_iam.egg-info/top_level.txt
15
+ drf_iam/migrations/0001_initial.py
16
+ drf_iam/migrations/__init__.py
@@ -0,0 +1,2 @@
1
+ Django>=3.2
2
+ djangorestframework>=3.12
@@ -0,0 +1 @@
1
+ drf_iam
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,26 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name='drf-iam',
5
+ version='0.0.1r',
6
+ packages=find_packages(), # Automatically finds all sub-packages
7
+ include_package_data=True, # Include non-Python files from MANIFEST.in
8
+ install_requires=[
9
+ 'Django>=3.2',
10
+ 'djangorestframework>=3.12'
11
+ ],
12
+ author='Tushar Patel',
13
+ author_email='tushar.patel@gmail.com',
14
+ description='IAM-style roles and permissions for Django Rest Framework',
15
+ long_description=open('README.md').read(),
16
+ long_description_content_type='text/markdown', # Important if using Markdown
17
+ url='https://github.com/tushar1328/drf-iam.git', # Optional but helpful
18
+ classifiers=[
19
+ 'Framework :: Django',
20
+ 'Framework :: Django :: 3.2',
21
+ 'Programming Language :: Python :: 3',
22
+ 'License :: OSI Approved :: MIT License', # Or your license
23
+ 'Operating System :: OS Independent',
24
+ ],
25
+ python_requires='>=3.6', # Or your minimum supported Python version
26
+ )