cryogenic22 commited on
Commit
16c033c
·
verified ·
1 Parent(s): d99a7d6

Create core/security/auth.py

Browse files
Files changed (1) hide show
  1. core/security/auth.py +240 -0
core/security/auth.py ADDED
@@ -0,0 +1,240 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from typing import Dict, List, Any, Optional
2
+ from pydantic import BaseModel
3
+ from datetime import datetime, timedelta
4
+ import jwt
5
+ from passlib.hash import bcrypt
6
+ from enum import Enum
7
+ import uuid
8
+
9
+ class UserRole(Enum):
10
+ ADMIN = "admin"
11
+ USER = "user"
12
+ VIEWER = "viewer"
13
+
14
+ class Permission(Enum):
15
+ READ = "read"
16
+ WRITE = "write"
17
+ EXECUTE = "execute"
18
+ MANAGE = "manage"
19
+
20
+ class User(BaseModel):
21
+ """User model"""
22
+ id: str
23
+ username: str
24
+ email: str
25
+ hashed_password: str
26
+ role: UserRole
27
+ tenant_id: str
28
+ permissions: List[Permission]
29
+ metadata: Dict[str, Any]
30
+ created_at: datetime
31
+ last_login: Optional[datetime]
32
+ is_active: bool = True
33
+
34
+ class Tenant(BaseModel):
35
+ """Tenant model for multi-tenancy"""
36
+ id: str
37
+ name: str
38
+ config: Dict[str, Any]
39
+ created_at: datetime
40
+ features: List[str]
41
+ is_active: bool = True
42
+
43
+ class AuthManager:
44
+ """Handles authentication and authorization"""
45
+
46
+ def __init__(self, config: Dict[str, Any]):
47
+ self.config = config
48
+ self.secret_key = config['secret_key']
49
+ self.token_expiry = config.get('token_expiry', 3600) # 1 hour default
50
+
51
+ async def create_user(
52
+ self,
53
+ username: str,
54
+ email: str,
55
+ password: str,
56
+ role: UserRole,
57
+ tenant_id: str,
58
+ permissions: List[Permission]
59
+ ) -> User:
60
+ """Create new user"""
61
+ hashed_password = bcrypt.hash(password)
62
+
63
+ user = User(
64
+ id=str(uuid.uuid4()),
65
+ username=username,
66
+ email=email,
67
+ hashed_password=hashed_password,
68
+ role=role,
69
+ tenant_id=tenant_id,
70
+ permissions=permissions,
71
+ metadata={},
72
+ created_at=datetime.now()
73
+ )
74
+
75
+ # Store user in database
76
+ await self.store_user(user)
77
+
78
+ return user
79
+
80
+ async def authenticate(self, username: str, password: str) -> Optional[str]:
81
+ """Authenticate user and return JWT token"""
82
+ user = await self.get_user_by_username(username)
83
+ if not user or not user.is_active:
84
+ return None
85
+
86
+ if not bcrypt.verify(password, user.hashed_password):
87
+ return None
88
+
89
+ # Update last login
90
+ user.last_login = datetime.now()
91
+ await self.update_user(user)
92
+
93
+ # Generate JWT token
94
+ token_data = {
95
+ 'sub': user.id,
96
+ 'username': user.username,
97
+ 'role': user.role.value,
98
+ 'tenant_id': user.tenant_id,
99
+ 'permissions': [p.value for p in user.permissions],
100
+ 'exp': datetime.utcnow() + timedelta(seconds=self.token_expiry)
101
+ }
102
+
103
+ return jwt.encode(token_data, self.secret_key, algorithm='HS256')
104
+
105
+ async def verify_token(self, token: str) -> Optional[Dict[str, Any]]:
106
+ """Verify JWT token and return payload"""
107
+ try:
108
+ payload = jwt.decode(token, self.secret_key, algorithms=['HS256'])
109
+ return payload
110
+ except jwt.ExpiredSignatureError:
111
+ return None
112
+ except jwt.InvalidTokenError:
113
+ return None
114
+
115
+ async def has_permission(
116
+ self,
117
+ user_id: str,
118
+ permission: Permission,
119
+ resource: str
120
+ ) -> bool:
121
+ """Check if user has specific permission"""
122
+ user = await self.get_user(user_id)
123
+ if not user or not user.is_active:
124
+ return False
125
+
126
+ # Admin role has all permissions
127
+ if user.role == UserRole.ADMIN:
128
+ return True
129
+
130
+ # Check specific permission
131
+ return permission in user.permissions
132
+
133
+ class AuditLogger:
134
+ """Handles audit logging"""
135
+
136
+ def __init__(self, storage_manager: Any):
137
+ self.storage = storage_manager
138
+
139
+ async def log_event(
140
+ self,
141
+ event_type: str,
142
+ user_id: str,
143
+ tenant_id: str,
144
+ resource: str,
145
+ action: str,
146
+ status: str,
147
+ details: Dict[str, Any]
148
+ ):
149
+ """Log audit event"""
150
+ event = {
151
+ 'event_type': event_type,
152
+ 'user_id': user_id,
153
+ 'tenant_id': tenant_id,
154
+ 'resource': resource,
155
+ 'action': action,
156
+ 'status': status,
157
+ 'details': details,
158
+ 'timestamp': datetime.now().isoformat()
159
+ }
160
+
161
+ await self.storage.store(
162
+ type=StorageType.AUDIT,
163
+ data=event,
164
+ tenant_id=tenant_id
165
+ )
166
+
167
+ class SecurityManager:
168
+ """Main security manager"""
169
+
170
+ def __init__(self, config: Dict[str, Any], storage_manager: Any):
171
+ self.config = config
172
+ self.auth_manager = AuthManager(config)
173
+ self.audit_logger = AuditLogger(storage_manager)
174
+
175
+ async def initialize_tenant(
176
+ self,
177
+ name: str,
178
+ features: List[str],
179
+ config: Dict[str, Any]
180
+ ) -> Tenant:
181
+ """Initialize new tenant"""
182
+ tenant = Tenant(
183
+ id=str(uuid.uuid4()),
184
+ name=name,
185
+ config=config,
186
+ features=features,
187
+ created_at=datetime.now()
188
+ )
189
+
190
+ # Store tenant
191
+ await self.store_tenant(tenant)
192
+
193
+ return tenant
194
+
195
+ async def handle_request(
196
+ self,
197
+ token: str,
198
+ resource: str,
199
+ action: Permission
200
+ ) -> Optional[Dict[str, Any]]:
201
+ """Handle authenticated request"""
202
+ # Verify token
203
+ payload = await self.auth_manager.verify_token(token)
204
+ if not payload:
205
+ return None
206
+
207
+ # Check permission
208
+ has_permission = await self.auth_manager.has_permission(
209
+ payload['sub'],
210
+ action,
211
+ resource
212
+ )
213
+
214
+ if not has_permission:
215
+ return None
216
+
217
+ # Log access
218
+ await self.audit_logger.log_event(
219
+ event_type="access",
220
+ user_id=payload['sub'],
221
+ tenant_id=payload['tenant_id'],
222
+ resource=resource,
223
+ action=action.value,
224
+ status="success",
225
+ details={}
226
+ )
227
+
228
+ return payload
229
+
230
+ # Example usage:
231
+ security_config = {
232
+ 'secret_key': 'your-secret-key',
233
+ 'token_expiry': 3600,
234
+ 'password_policy': {
235
+ 'min_length': 8,
236
+ 'require_special': True
237
+ }
238
+ }
239
+
240
+ security_manager = SecurityManager(security_config, storage_manager)