drf-iam 0.0.1.post0__py3-none-any.whl

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.
drf_iam/__init__.py ADDED
File without changes
drf_iam/admin.py ADDED
@@ -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
+
drf_iam/apps.py ADDED
@@ -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
drf_iam/models.py ADDED
@@ -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}"
drf_iam/permissions.py ADDED
@@ -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
drf_iam/tests.py ADDED
@@ -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,12 @@
1
+ drf_iam/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ drf_iam/admin.py,sha256=xH4T6xGKuylRCTwqLPJAx3Eb07Mb0Qb43iYAWX_cSN8,788
3
+ drf_iam/apps.py,sha256=HUJatT0Wf-6ft19lWNkSqI7fnsnAjoLKQrjPUnVAcn8,611
4
+ drf_iam/models.py,sha256=3K0f0SKWiiMFKbiLQ_SKrwV-B5jzzm-HH2gO8nOGs54,1296
5
+ drf_iam/permissions.py,sha256=kUhB7V48sb4v3uZI2lWv40hvI85nE61rL-amh6OY8mg,958
6
+ drf_iam/tests.py,sha256=mrbGGRNg5jwbTJtWWa7zSKdDyeB4vmgZCRc2nk6VY-g,60
7
+ drf_iam/migrations/0001_initial.py,sha256=y_4jXnr7gjU4UXxVrgVrStTSFu3h1ZrmjEZDL4FtZa4,3086
8
+ drf_iam/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
+ drf_iam-0.0.1.post0.dist-info/METADATA,sha256=LXFRG58OZ96UenArozVYTCdrxlBqA34vNLGVCiWEB8k,947
10
+ drf_iam-0.0.1.post0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
11
+ drf_iam-0.0.1.post0.dist-info/top_level.txt,sha256=daz6AaQ9e_cfCjLk2aRoLb_PCOoFofYUX4DU85VwHSM,8
12
+ drf_iam-0.0.1.post0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.8.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ drf_iam