abs-auth-rbac-core 0.1.13__py3-none-any.whl → 0.1.15__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.
Potentially problematic release.
This version of abs-auth-rbac-core might be problematic. Click here for more details.
- abs_auth_rbac_core/rbac/service.py +114 -6
- {abs_auth_rbac_core-0.1.13.dist-info → abs_auth_rbac_core-0.1.15.dist-info}/METADATA +2 -1
- {abs_auth_rbac_core-0.1.13.dist-info → abs_auth_rbac_core-0.1.15.dist-info}/RECORD +4 -4
- {abs_auth_rbac_core-0.1.13.dist-info → abs_auth_rbac_core-0.1.15.dist-info}/WHEEL +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from typing import List, Optional, Callable,Any,Tuple
|
|
2
2
|
import os
|
|
3
|
+
from pydantic import BaseModel
|
|
3
4
|
import casbin
|
|
4
5
|
from casbin_sqlalchemy_adapter import Adapter
|
|
6
|
+
from casbin_redis_watcher import RedisWatcher, WatcherOptions,new_watcher
|
|
5
7
|
from sqlalchemy import and_, select
|
|
6
8
|
from sqlalchemy.orm import Session, joinedload
|
|
7
9
|
from ..schema import CreatePermissionSchema
|
|
@@ -21,9 +23,17 @@ from abs_exception_core.exceptions import (
|
|
|
21
23
|
)
|
|
22
24
|
|
|
23
25
|
from ..models.gov_casbin_rule import GovCasbinRule
|
|
26
|
+
from redis import Redis
|
|
27
|
+
|
|
28
|
+
class RedisWatcherSchema(BaseModel):
|
|
29
|
+
host: str
|
|
30
|
+
port: int
|
|
31
|
+
channel: str
|
|
32
|
+
ssl: Optional[bool] = False
|
|
33
|
+
password: Optional[str] = None
|
|
24
34
|
|
|
25
35
|
class RBACService:
|
|
26
|
-
def __init__(self, session: Callable[...,Session]):
|
|
36
|
+
def __init__(self, session: Callable[...,Session],redis_config:Optional[RedisWatcherSchema]=None):
|
|
27
37
|
"""
|
|
28
38
|
Service For Managing the RBAC
|
|
29
39
|
Args:
|
|
@@ -31,9 +41,10 @@ class RBACService:
|
|
|
31
41
|
"""
|
|
32
42
|
self.db = session
|
|
33
43
|
self.enforcer = None
|
|
34
|
-
self._initialize_casbin()
|
|
44
|
+
self._initialize_casbin(redis_config)
|
|
45
|
+
self.watcher = None
|
|
35
46
|
|
|
36
|
-
def _initialize_casbin(self):
|
|
47
|
+
def _initialize_casbin(self,redis_config:Optional[RedisWatcherSchema]=None):
|
|
37
48
|
"""
|
|
38
49
|
Initiates the casbin policy using the default rules
|
|
39
50
|
"""
|
|
@@ -54,6 +65,47 @@ class RBACService:
|
|
|
54
65
|
# Load policies
|
|
55
66
|
self.enforcer.load_policy()
|
|
56
67
|
|
|
68
|
+
if redis_config:
|
|
69
|
+
try:
|
|
70
|
+
# Create Redis client with proper configuration
|
|
71
|
+
redis_client = Redis(
|
|
72
|
+
host=redis_config.host,
|
|
73
|
+
port=redis_config.port,
|
|
74
|
+
password=redis_config.password if hasattr(redis_config, 'password') else None,
|
|
75
|
+
ssl=redis_config.ssl,
|
|
76
|
+
decode_responses=True,
|
|
77
|
+
socket_connect_timeout=5,
|
|
78
|
+
socket_timeout=5,
|
|
79
|
+
retry_on_timeout=True,
|
|
80
|
+
health_check_interval=30
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Test Redis connection
|
|
84
|
+
redis_client.ping()
|
|
85
|
+
print(f"✅ Redis connection established to {redis_config.host}:{redis_config.port}")
|
|
86
|
+
|
|
87
|
+
# Create Watcher and Options
|
|
88
|
+
test_option = WatcherOptions()
|
|
89
|
+
test_option.pub_client = redis_client
|
|
90
|
+
test_option.sub_client = redis_client
|
|
91
|
+
test_option.channel = redis_config.channel
|
|
92
|
+
test_option.optional_update_callback = lambda _: self.enforcer.load_policy()
|
|
93
|
+
|
|
94
|
+
# Create watcher
|
|
95
|
+
watcher = new_watcher(test_option)
|
|
96
|
+
|
|
97
|
+
self.enforcer.set_watcher(watcher)
|
|
98
|
+
self.watcher = watcher
|
|
99
|
+
self.enforcer.save_policy()
|
|
100
|
+
print(f"✅ Casbin Redis watcher initialized on channel: {redis_config.channel}")
|
|
101
|
+
|
|
102
|
+
except Exception as e:
|
|
103
|
+
print(f"⚠️ Failed to initialize Redis watcher: {e}")
|
|
104
|
+
print("⚠️ Casbin will work without Redis watcher (no real-time policy updates)")
|
|
105
|
+
self.watcher = None
|
|
106
|
+
else:
|
|
107
|
+
print("ℹ️ Redis watcher not configured - Casbin will work without real-time policy updates")
|
|
108
|
+
|
|
57
109
|
def add_policy(self,role:str,resource:str,action:str,module:str):
|
|
58
110
|
"""
|
|
59
111
|
Add a policy to the casbin enforcer
|
|
@@ -104,10 +156,14 @@ class RBACService:
|
|
|
104
156
|
"""
|
|
105
157
|
with self.db() as session:
|
|
106
158
|
try:
|
|
107
|
-
|
|
108
|
-
|
|
159
|
+
if hasattr(permissions,'model_dump'):
|
|
160
|
+
add_permissions = [Permission(**permission.model_dump()) for permission in permissions]
|
|
161
|
+
else:
|
|
162
|
+
add_permissions = [Permission(**permission) for permission in permissions]
|
|
163
|
+
|
|
164
|
+
session.bulk_save_objects(add_permissions)
|
|
109
165
|
session.commit()
|
|
110
|
-
return
|
|
166
|
+
return add_permissions
|
|
111
167
|
except Exception as e:
|
|
112
168
|
raise e
|
|
113
169
|
|
|
@@ -849,3 +905,55 @@ class RBACService:
|
|
|
849
905
|
else:
|
|
850
906
|
with self.db() as session:
|
|
851
907
|
return query_role(session)
|
|
908
|
+
|
|
909
|
+
def is_watcher_active(self) -> bool:
|
|
910
|
+
"""Check if Redis watcher is active and connected"""
|
|
911
|
+
return self.watcher is not None and hasattr(self.watcher, 'pub_client') and self.watcher.pub_client is not None
|
|
912
|
+
|
|
913
|
+
def get_watcher_status(self) -> dict:
|
|
914
|
+
"""Get detailed watcher status information"""
|
|
915
|
+
if not self.is_watcher_active():
|
|
916
|
+
return {
|
|
917
|
+
"active": False,
|
|
918
|
+
"message": "Watcher not initialized or not active"
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
try:
|
|
922
|
+
# Test Redis connection
|
|
923
|
+
self.watcher.pub_client.ping()
|
|
924
|
+
return {
|
|
925
|
+
"active": True,
|
|
926
|
+
"host": self.watcher.pub_client.connection_pool.connection_kwargs.get('host'),
|
|
927
|
+
"port": self.watcher.pub_client.connection_pool.connection_kwargs.get('port'),
|
|
928
|
+
"channel": getattr(self.watcher, 'channel', 'unknown'),
|
|
929
|
+
"connected": True
|
|
930
|
+
}
|
|
931
|
+
except Exception as e:
|
|
932
|
+
return {
|
|
933
|
+
"active": False,
|
|
934
|
+
"error": str(e),
|
|
935
|
+
"message": "Watcher exists but Redis connection failed"
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
def reload_policies(self) -> bool:
|
|
939
|
+
"""Manually reload policies from database"""
|
|
940
|
+
try:
|
|
941
|
+
self.enforcer.load_policy()
|
|
942
|
+
return True
|
|
943
|
+
except Exception as e:
|
|
944
|
+
print(f"Failed to reload policies: {e}")
|
|
945
|
+
return False
|
|
946
|
+
|
|
947
|
+
def get_policy_count(self) -> int:
|
|
948
|
+
"""Get the total number of policies in the enforcer"""
|
|
949
|
+
return len(self.enforcer.get_policy())
|
|
950
|
+
|
|
951
|
+
def clear_all_policies(self) -> bool:
|
|
952
|
+
"""Clear all policies from the enforcer (use with caution)"""
|
|
953
|
+
try:
|
|
954
|
+
self.enforcer.clear_policy()
|
|
955
|
+
self.enforcer.save_policy()
|
|
956
|
+
return True
|
|
957
|
+
except Exception as e:
|
|
958
|
+
print(f"Failed to clear policies: {e}")
|
|
959
|
+
return False
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: abs-auth-rbac-core
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.15
|
|
4
4
|
Summary: RBAC and Auth core utilities including JWT token management.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: AutoBridgeSystems
|
|
@@ -11,6 +11,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
12
|
Requires-Dist: abs-exception-core (>=0.1.0,<0.2.0)
|
|
13
13
|
Requires-Dist: casbin (>=1.41.0,<2.0.0)
|
|
14
|
+
Requires-Dist: casbin-redis-watcher (>=1.3.0,<2.0.0)
|
|
14
15
|
Requires-Dist: casbin-sqlalchemy-adapter (>=1.4.0,<2.0.0)
|
|
15
16
|
Requires-Dist: fastapi[standard] (>=0.115.12,<0.116.0)
|
|
16
17
|
Requires-Dist: passlib (>=1.7.4,<2.0.0)
|
|
@@ -17,11 +17,11 @@ abs_auth_rbac_core/models/user_role.py,sha256=20pqmtJPzlUrI9ulHGouk8XlFgrGG7I6ik
|
|
|
17
17
|
abs_auth_rbac_core/rbac/__init__.py,sha256=oYjtpmfrkEbwWCBAWuRoU1fM4fCpBxkF_lwQrelK1As,79
|
|
18
18
|
abs_auth_rbac_core/rbac/decorator.py,sha256=pEFAW0Nn2iE4KBctPhNOmO_VLeJFDX2V9v2LsCu6kHY,1824
|
|
19
19
|
abs_auth_rbac_core/rbac/policy.conf,sha256=wghhhKxgZH0rPhh1QFrIpq9nevJT3s7OxxvXiU3zzuI,305
|
|
20
|
-
abs_auth_rbac_core/rbac/service.py,sha256=
|
|
20
|
+
abs_auth_rbac_core/rbac/service.py,sha256=hvMlkamWXZnDvorrjBb5t0Km8gUMw2vOPKbAHa8cX1M,37236
|
|
21
21
|
abs_auth_rbac_core/schema/__init__.py,sha256=v9xibJ8Wr9k0u6PEYNK0LCGUJD71SB5vxu9BZG0S7tM,46
|
|
22
22
|
abs_auth_rbac_core/schema/permission.py,sha256=XvxPU68FY0PFgkF4GR2bSrzNvFB8c8OgY_d0JOJvMc8,203
|
|
23
23
|
abs_auth_rbac_core/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
24
|
abs_auth_rbac_core/util/permission_constants.py,sha256=ICnn7mDoNt4_adUcbMjWtBeY2MgJu4F9qS5jRgR3nNU,92039
|
|
25
|
-
abs_auth_rbac_core-0.1.
|
|
26
|
-
abs_auth_rbac_core-0.1.
|
|
27
|
-
abs_auth_rbac_core-0.1.
|
|
25
|
+
abs_auth_rbac_core-0.1.15.dist-info/METADATA,sha256=xFzOT4_Y3FtdPnRLnZr8W0_gZp1lwAsOCJkUCWpsE_A,6689
|
|
26
|
+
abs_auth_rbac_core-0.1.15.dist-info/WHEEL,sha256=fGIA9gx4Qxk2KDKeNJCbOEwSrmLtjWCwzBz351GyrPQ,88
|
|
27
|
+
abs_auth_rbac_core-0.1.15.dist-info/RECORD,,
|
|
File without changes
|