trovesuite 1.0.0__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.
- trovesuite/__init__.py +16 -0
- trovesuite/auth/__init__.py +16 -0
- trovesuite/auth/auth_base.py +4 -0
- trovesuite/auth/auth_controller.py +10 -0
- trovesuite/auth/auth_read_dto.py +18 -0
- trovesuite/auth/auth_service.py +334 -0
- trovesuite/auth/auth_write_dto.py +10 -0
- trovesuite/configs/__init__.py +16 -0
- trovesuite/configs/database.py +221 -0
- trovesuite/configs/logging.py +261 -0
- trovesuite/configs/settings.py +153 -0
- trovesuite/entities/__init__.py +11 -0
- trovesuite/entities/health.py +84 -0
- trovesuite/entities/sh_response.py +61 -0
- trovesuite/utils/__init__.py +11 -0
- trovesuite/utils/helper.py +36 -0
- trovesuite-1.0.0.dist-info/METADATA +572 -0
- trovesuite-1.0.0.dist-info/RECORD +21 -0
- trovesuite-1.0.0.dist-info/WHEEL +5 -0
- trovesuite-1.0.0.dist-info/licenses/LICENSE +21 -0
- trovesuite-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: trovesuite
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A comprehensive authentication and authorization service for ERP systems
|
|
5
|
+
Home-page: https://dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
6
|
+
Author: Bright Debrah Owusu
|
|
7
|
+
Author-email: Bright Debrah Owusu <owusu.debrah@deladetech.com>
|
|
8
|
+
Maintainer-email: Bright Debrah Owusu <owusu.debrah@deladetech.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
Project-URL: Homepage, https://dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
11
|
+
Project-URL: Repository, https://dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
12
|
+
Project-URL: Documentation, https://dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
13
|
+
Project-URL: Bug Tracker, https://dev.azure.com/brightgclt/trovesuite/_workitems/create
|
|
14
|
+
Keywords: authentication,authorization,jwt,erp,fastapi,security
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
|
25
|
+
Classifier: Topic :: Security
|
|
26
|
+
Requires-Python: >=3.12
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Requires-Dist: fastapi>=0.116.1
|
|
30
|
+
Requires-Dist: pydantic>=2.11.9
|
|
31
|
+
Requires-Dist: psycopg2-binary>=2.9.9
|
|
32
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
33
|
+
Requires-Dist: python-multipart>=0.0.6
|
|
34
|
+
Requires-Dist: python-jose[cryptography]>=3.3.0
|
|
35
|
+
Requires-Dist: passlib[bcrypt]>=1.7.4
|
|
36
|
+
Requires-Dist: passlib[argon2]<2.0.0,>=1.7.4
|
|
37
|
+
Provides-Extra: dev
|
|
38
|
+
Requires-Dist: pytest>=8.4.2; extra == "dev"
|
|
39
|
+
Requires-Dist: pytest-asyncio>=0.21.1; extra == "dev"
|
|
40
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
41
|
+
Requires-Dist: pytest-mock>=3.12.0; extra == "dev"
|
|
42
|
+
Requires-Dist: factory-boy>=3.3.0; extra == "dev"
|
|
43
|
+
Requires-Dist: faker>=20.1.0; extra == "dev"
|
|
44
|
+
Requires-Dist: black>=23.11.0; extra == "dev"
|
|
45
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: flake8>=6.0.0; extra == "dev"
|
|
47
|
+
Dynamic: author
|
|
48
|
+
Dynamic: home-page
|
|
49
|
+
Dynamic: license-file
|
|
50
|
+
Dynamic: requires-python
|
|
51
|
+
|
|
52
|
+
# TroveSuite Auth Service
|
|
53
|
+
|
|
54
|
+
A comprehensive authentication and authorization service for ERP systems. This package provides JWT token validation, user authorization, and permission checking capabilities.
|
|
55
|
+
|
|
56
|
+
## Features
|
|
57
|
+
|
|
58
|
+
- **JWT Token Validation**: Secure token decoding and validation
|
|
59
|
+
- **User Authorization**: Multi-level authorization with tenant verification
|
|
60
|
+
- **Permission Checking**: Hierarchical permission system (organization > business > app > location > resource)
|
|
61
|
+
- **Database Integration**: PostgreSQL support with connection pooling
|
|
62
|
+
- **Logging**: Comprehensive logging with multiple output formats
|
|
63
|
+
- **Azure Integration**: Support for Azure Storage Queues and Managed Identity
|
|
64
|
+
- **FastAPI Ready**: Built for FastAPI applications
|
|
65
|
+
|
|
66
|
+
## Installation
|
|
67
|
+
|
|
68
|
+
### From Azure DevOps Artifacts
|
|
69
|
+
|
|
70
|
+
#### Using pip
|
|
71
|
+
```bash
|
|
72
|
+
pip install trovesuite --index-url https://pypi.org/simple/ --extra-index-url https://pkgs.dev.azure.com/brightgclt/trovesuite/_packaging/packages/pypi/simple/
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
#### Using Poetry
|
|
76
|
+
```bash
|
|
77
|
+
# Add Azure DevOps Artifacts as a source
|
|
78
|
+
poetry source add --priority=supplemental azure https://pkgs.dev.azure.com/brightgclt/trovesuite/_packaging/packages/pypi/simple/
|
|
79
|
+
|
|
80
|
+
# Install the package
|
|
81
|
+
poetry add trovesuite
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### From Source
|
|
85
|
+
|
|
86
|
+
#### Using pip
|
|
87
|
+
```bash
|
|
88
|
+
git clone https://brightgclt@dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
89
|
+
cd packages
|
|
90
|
+
pip install -e .
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Using Poetry
|
|
94
|
+
```bash
|
|
95
|
+
git clone https://brightgclt@dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
96
|
+
cd packages
|
|
97
|
+
poetry install
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Development Installation
|
|
101
|
+
|
|
102
|
+
#### Using pip
|
|
103
|
+
```bash
|
|
104
|
+
git clone https://brightgclt@dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
105
|
+
cd packages
|
|
106
|
+
pip install -e ".[dev]"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
#### Using Poetry
|
|
110
|
+
```bash
|
|
111
|
+
git clone https://brightgclt@dev.azure.com/brightgclt/trovesuite/_git/packages
|
|
112
|
+
cd packages
|
|
113
|
+
poetry install --with dev
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Quick Start
|
|
117
|
+
|
|
118
|
+
### Basic Usage
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from trovesuite import AuthService
|
|
122
|
+
from trovesuite.configs.settings import db_settings
|
|
123
|
+
|
|
124
|
+
# Configure your database settings
|
|
125
|
+
db_settings.DB_HOST = "localhost"
|
|
126
|
+
db_settings.DB_PORT = 5432
|
|
127
|
+
db_settings.DB_NAME = "your_database"
|
|
128
|
+
db_settings.DB_USER = "your_user"
|
|
129
|
+
db_settings.DB_PASSWORD = "your_password"
|
|
130
|
+
db_settings.SECRET_KEY = "your-secret-key"
|
|
131
|
+
|
|
132
|
+
# Initialize the auth service
|
|
133
|
+
auth_service = AuthService()
|
|
134
|
+
|
|
135
|
+
# Authorize a user
|
|
136
|
+
from trovesuite.auth.auth_write_dto import AuthServiceWriteDto
|
|
137
|
+
auth_data = AuthServiceWriteDto(user_id="user123", tenant="tenant456")
|
|
138
|
+
result = AuthService.authorize(auth_data)
|
|
139
|
+
|
|
140
|
+
if result.success:
|
|
141
|
+
print("User authorized successfully")
|
|
142
|
+
for role in result.data:
|
|
143
|
+
print(f"Role: {role.role_id}, Permissions: {role.permissions}")
|
|
144
|
+
else:
|
|
145
|
+
print(f"Authorization failed: {result.detail}")
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### JWT Token Decoding
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
from trovesuite import AuthService
|
|
152
|
+
from fastapi import Depends
|
|
153
|
+
from fastapi.security import OAuth2PasswordBearer
|
|
154
|
+
|
|
155
|
+
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
|
|
156
|
+
|
|
157
|
+
@app.get("/protected")
|
|
158
|
+
async def protected_route(token: str = Depends(oauth2_scheme)):
|
|
159
|
+
# Decode and validate token
|
|
160
|
+
user_data = AuthService.decode_token(token)
|
|
161
|
+
user_id = user_data["user_id"]
|
|
162
|
+
tenant_id = user_data["tenant_id"]
|
|
163
|
+
|
|
164
|
+
# Authorize user
|
|
165
|
+
from trovesuite.auth.auth_write_dto import AuthServiceWriteDto
|
|
166
|
+
auth_data = AuthServiceWriteDto(user_id=user_id, tenant=tenant_id)
|
|
167
|
+
auth_result = AuthService.authorize(auth_data)
|
|
168
|
+
return auth_result
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Convenience Methods
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from trovesuite import AuthService
|
|
175
|
+
|
|
176
|
+
# Get user info directly from token
|
|
177
|
+
user_info = AuthService.get_user_info_from_token(token)
|
|
178
|
+
print(f"User: {user_info['user_id']}, Tenant: {user_info['tenant_id']}")
|
|
179
|
+
|
|
180
|
+
# Authorize user directly from token (combines decode + authorize)
|
|
181
|
+
auth_result = AuthService.authorize_user_from_token(token)
|
|
182
|
+
|
|
183
|
+
if auth_result.success:
|
|
184
|
+
# Get all user permissions
|
|
185
|
+
all_permissions = AuthService.get_user_permissions(auth_result.data)
|
|
186
|
+
print(f"User has permissions: {all_permissions}")
|
|
187
|
+
|
|
188
|
+
# Check if user has any of the required permissions
|
|
189
|
+
has_any = AuthService.has_any_permission(
|
|
190
|
+
auth_result.data,
|
|
191
|
+
["read", "write", "admin"]
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
# Check if user has all required permissions
|
|
195
|
+
has_all = AuthService.has_all_permissions(
|
|
196
|
+
auth_result.data,
|
|
197
|
+
["read", "write"]
|
|
198
|
+
)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Permission Checking
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from trovesuite import AuthService
|
|
205
|
+
|
|
206
|
+
# After getting user roles from authorization
|
|
207
|
+
user_roles = auth_result.data
|
|
208
|
+
|
|
209
|
+
# Check specific permission
|
|
210
|
+
has_permission = AuthService.check_permission(
|
|
211
|
+
user_roles=user_roles,
|
|
212
|
+
action="read",
|
|
213
|
+
org_id="org123",
|
|
214
|
+
bus_id="bus456",
|
|
215
|
+
app_id="app789"
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
if has_permission:
|
|
219
|
+
print("User has permission to read from this resource")
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
## Configuration
|
|
224
|
+
|
|
225
|
+
### Quick Configuration Check
|
|
226
|
+
|
|
227
|
+
```python
|
|
228
|
+
from trovesuite.configs.settings import db_settings
|
|
229
|
+
|
|
230
|
+
# Check your configuration
|
|
231
|
+
config_summary = db_settings.get_configuration_summary()
|
|
232
|
+
print("Current configuration:")
|
|
233
|
+
for key, value in config_summary.items():
|
|
234
|
+
print(f" {key}: {value}")
|
|
235
|
+
|
|
236
|
+
# The service will automatically validate configuration on import
|
|
237
|
+
# and show warnings for potential issues
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### Environment Variables
|
|
241
|
+
|
|
242
|
+
The service uses environment variables for configuration. Set these in your environment or `.env` file:
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Database Configuration
|
|
246
|
+
DB_HOST=localhost
|
|
247
|
+
DB_PORT=5432
|
|
248
|
+
DB_NAME=your_database
|
|
249
|
+
DB_USER=your_user
|
|
250
|
+
DB_PASSWORD=your_password
|
|
251
|
+
DATABASE_URL=postgresql://user:password@localhost:5432/database
|
|
252
|
+
|
|
253
|
+
# Security
|
|
254
|
+
SECRET_KEY=your-secret-key-here
|
|
255
|
+
ALGORITHM=HS256
|
|
256
|
+
ACCESS_TOKEN_EXPIRE_MINUTES=60
|
|
257
|
+
|
|
258
|
+
# Application
|
|
259
|
+
APP_NAME=Auth Service
|
|
260
|
+
ENVIRONMENT=production
|
|
261
|
+
DEBUG=false
|
|
262
|
+
|
|
263
|
+
# Logging
|
|
264
|
+
LOG_LEVEL=INFO
|
|
265
|
+
LOG_FORMAT=detailed
|
|
266
|
+
LOG_TO_FILE=true
|
|
267
|
+
|
|
268
|
+
# Table Names (customize as needed)
|
|
269
|
+
MAIN_TENANTS_TABLE=tenants
|
|
270
|
+
TENANT_LOGIN_SETTINGS_TABLE=login_settings
|
|
271
|
+
USER_GROUPS_TABLE=user_groups
|
|
272
|
+
ASSIGN_ROLES_TABLE=assign_roles
|
|
273
|
+
ROLE_PERMISSIONS_TABLE=role_permissions
|
|
274
|
+
|
|
275
|
+
# Azure (optional - for queue functionality)
|
|
276
|
+
STORAGE_ACCOUNT_NAME=your-storage-account
|
|
277
|
+
USER_ASSIGNED_MANAGED_IDENTITY=your-managed-identity
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Database Schema
|
|
281
|
+
|
|
282
|
+
The service expects the following database tables:
|
|
283
|
+
|
|
284
|
+
#### Main Schema Tables
|
|
285
|
+
- `tenants` - Tenant information and verification status
|
|
286
|
+
- `role_permissions` - Role-permission mappings
|
|
287
|
+
|
|
288
|
+
#### Tenant Schema Tables (per tenant)
|
|
289
|
+
- `login_settings` - User login configurations (working days, suspension status, etc.)
|
|
290
|
+
- `user_groups` - User-group memberships
|
|
291
|
+
- `assign_roles` - Role assignments to users/groups with resource hierarchy
|
|
292
|
+
|
|
293
|
+
## API Reference
|
|
294
|
+
|
|
295
|
+
### AuthService
|
|
296
|
+
|
|
297
|
+
#### `authorize(user_id: str, tenant_id: str) -> Respons[AuthServiceReadDto]`
|
|
298
|
+
|
|
299
|
+
Authorizes a user and returns their roles and permissions.
|
|
300
|
+
|
|
301
|
+
**Parameters:**
|
|
302
|
+
- `user_id`: The user identifier (must be a non-empty string)
|
|
303
|
+
- `tenant_id`: The tenant identifier (must be a non-empty string)
|
|
304
|
+
|
|
305
|
+
**Returns:**
|
|
306
|
+
- `Respons[AuthServiceReadDto]`: Authorization result with user roles and permissions
|
|
307
|
+
|
|
308
|
+
**Error Codes:**
|
|
309
|
+
- `INVALID_USER_ID`: Invalid or empty user_id
|
|
310
|
+
- `INVALID_TENANT_ID`: Invalid or empty tenant_id
|
|
311
|
+
- `TENANT_NOT_FOUND`: Tenant doesn't exist or is deleted
|
|
312
|
+
- `TENANT_NOT_VERIFIED`: Tenant exists but is not verified
|
|
313
|
+
- `USER_NOT_FOUND`: User doesn't exist in tenant or is inactive
|
|
314
|
+
- `USER_SUSPENDED`: User account is suspended
|
|
315
|
+
- `LOGIN_TIME_RESTRICTED`: Login not allowed at current time
|
|
316
|
+
|
|
317
|
+
#### `decode_token(token: str) -> dict`
|
|
318
|
+
|
|
319
|
+
Decodes and validates a JWT token.
|
|
320
|
+
|
|
321
|
+
**Parameters:**
|
|
322
|
+
- `token`: The JWT token to decode
|
|
323
|
+
|
|
324
|
+
**Returns:**
|
|
325
|
+
- `dict`: Token payload with user_id and tenant_id
|
|
326
|
+
|
|
327
|
+
**Raises:**
|
|
328
|
+
- `HTTPException`: If token is invalid
|
|
329
|
+
|
|
330
|
+
#### `check_permission(user_roles: list, action: str, **kwargs) -> bool`
|
|
331
|
+
|
|
332
|
+
Checks if a user has a specific permission for a resource.
|
|
333
|
+
|
|
334
|
+
**Parameters:**
|
|
335
|
+
- `user_roles`: List of user roles from authorization
|
|
336
|
+
- `action`: The permission action to check
|
|
337
|
+
- `org_id`, `bus_id`, `app_id`, `resource_id`, `shared_resource_id`: Resource identifiers
|
|
338
|
+
|
|
339
|
+
**Returns:**
|
|
340
|
+
- `bool`: True if user has permission, False otherwise
|
|
341
|
+
|
|
342
|
+
#### `get_user_info_from_token(token: str) -> dict`
|
|
343
|
+
|
|
344
|
+
Convenience method to get user information from a JWT token.
|
|
345
|
+
|
|
346
|
+
**Parameters:**
|
|
347
|
+
- `token`: JWT token string
|
|
348
|
+
|
|
349
|
+
**Returns:**
|
|
350
|
+
- `dict`: User information including user_id and tenant_id
|
|
351
|
+
|
|
352
|
+
#### `authorize_user_from_token(token: str) -> Respons[AuthServiceReadDto]`
|
|
353
|
+
|
|
354
|
+
Convenience method to authorize a user directly from a JWT token.
|
|
355
|
+
|
|
356
|
+
**Parameters:**
|
|
357
|
+
- `token`: JWT token string
|
|
358
|
+
|
|
359
|
+
**Returns:**
|
|
360
|
+
- `Respons[AuthServiceReadDto]`: Authorization result with user roles and permissions
|
|
361
|
+
|
|
362
|
+
#### `get_user_permissions(user_roles: list) -> list`
|
|
363
|
+
|
|
364
|
+
Get all unique permissions for a user across all their roles.
|
|
365
|
+
|
|
366
|
+
**Parameters:**
|
|
367
|
+
- `user_roles`: List of user roles from authorization
|
|
368
|
+
|
|
369
|
+
**Returns:**
|
|
370
|
+
- `list`: Unique list of permissions
|
|
371
|
+
|
|
372
|
+
#### `has_any_permission(user_roles: list, required_permissions: list) -> bool`
|
|
373
|
+
|
|
374
|
+
Check if user has any of the required permissions.
|
|
375
|
+
|
|
376
|
+
**Parameters:**
|
|
377
|
+
- `user_roles`: List of user roles from authorization
|
|
378
|
+
- `required_permissions`: List of permissions to check for
|
|
379
|
+
|
|
380
|
+
**Returns:**
|
|
381
|
+
- `bool`: True if user has any of the required permissions
|
|
382
|
+
|
|
383
|
+
#### `has_all_permissions(user_roles: list, required_permissions: list) -> bool`
|
|
384
|
+
|
|
385
|
+
Check if user has all of the required permissions.
|
|
386
|
+
|
|
387
|
+
**Parameters:**
|
|
388
|
+
- `user_roles`: List of user roles from authorization
|
|
389
|
+
- `required_permissions`: List of permissions to check for
|
|
390
|
+
|
|
391
|
+
**Returns:**
|
|
392
|
+
- `bool`: True if user has all of the required permissions
|
|
393
|
+
|
|
394
|
+
### Data Models
|
|
395
|
+
|
|
396
|
+
#### `AuthServiceReadDto`
|
|
397
|
+
|
|
398
|
+
```python
|
|
399
|
+
class AuthServiceReadDto(BaseModel):
|
|
400
|
+
org_id: Optional[str] = None
|
|
401
|
+
bus_id: Optional[str] = None
|
|
402
|
+
app_id: Optional[str] = None
|
|
403
|
+
shared_resource_id: Optional[str] = None
|
|
404
|
+
user_id: Optional[str] = None
|
|
405
|
+
group_id: Optional[str] = None
|
|
406
|
+
role_id: Optional[str] = None
|
|
407
|
+
tenant_id: Optional[str] = None
|
|
408
|
+
permissions: Optional[List[str]] = None
|
|
409
|
+
resource_id: Optional[str] = None
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
#### `Respons[T]`
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
class Respons[T](BaseModel):
|
|
416
|
+
detail: Optional[str] = None
|
|
417
|
+
error: Optional[str] = None
|
|
418
|
+
data: Optional[List[T]] = None
|
|
419
|
+
status_code: int = 200
|
|
420
|
+
success: bool = True
|
|
421
|
+
pagination: Optional[PaginationMeta] = None
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
## Error Handling
|
|
425
|
+
|
|
426
|
+
The service provides comprehensive error handling with specific error codes and user-friendly messages:
|
|
427
|
+
|
|
428
|
+
### Common Error Scenarios
|
|
429
|
+
|
|
430
|
+
```python
|
|
431
|
+
from trovesuite import AuthService
|
|
432
|
+
|
|
433
|
+
# Example: Handle authorization errors
|
|
434
|
+
result = AuthService.authorize("user123", "tenant456")
|
|
435
|
+
|
|
436
|
+
if not result.success:
|
|
437
|
+
if result.error == "TENANT_NOT_FOUND":
|
|
438
|
+
print("Tenant doesn't exist")
|
|
439
|
+
elif result.error == "USER_SUSPENDED":
|
|
440
|
+
print("User account is suspended")
|
|
441
|
+
elif result.error == "LOGIN_TIME_RESTRICTED":
|
|
442
|
+
print("Login not allowed at this time")
|
|
443
|
+
else:
|
|
444
|
+
print(f"Authorization failed: {result.detail}")
|
|
445
|
+
else:
|
|
446
|
+
print("Authorization successful!")
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Best Practices
|
|
450
|
+
|
|
451
|
+
1. **Always check the `success` field** before accessing `data`
|
|
452
|
+
2. **Use specific error codes** for programmatic error handling
|
|
453
|
+
3. **Display user-friendly messages** from the `detail` field
|
|
454
|
+
4. **Log errors** for debugging purposes
|
|
455
|
+
5. **Validate input parameters** before calling service methods
|
|
456
|
+
|
|
457
|
+
### Configuration Validation
|
|
458
|
+
|
|
459
|
+
The service automatically validates configuration on import and shows warnings for potential issues:
|
|
460
|
+
|
|
461
|
+
```python
|
|
462
|
+
# Configuration validation happens automatically
|
|
463
|
+
from trovesuite_auth_service.configs.settings import db_settings
|
|
464
|
+
|
|
465
|
+
# Check configuration summary
|
|
466
|
+
config = db_settings.get_configuration_summary()
|
|
467
|
+
print("Configuration loaded successfully")
|
|
468
|
+
|
|
469
|
+
# Common warnings you might see:
|
|
470
|
+
# - Default SECRET_KEY in production
|
|
471
|
+
# - Missing database configuration
|
|
472
|
+
# - Inconsistent environment settings
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
## Development
|
|
476
|
+
|
|
477
|
+
### Running Tests
|
|
478
|
+
|
|
479
|
+
#### Using pip
|
|
480
|
+
```bash
|
|
481
|
+
pytest
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
#### Using Poetry
|
|
485
|
+
```bash
|
|
486
|
+
poetry run pytest
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
### Code Formatting
|
|
490
|
+
|
|
491
|
+
#### Using pip
|
|
492
|
+
```bash
|
|
493
|
+
black trovesuite/
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
#### Using Poetry
|
|
497
|
+
```bash
|
|
498
|
+
poetry run black trovesuite/
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### Type Checking
|
|
502
|
+
|
|
503
|
+
#### Using pip
|
|
504
|
+
```bash
|
|
505
|
+
mypy trovesuite/
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
#### Using Poetry
|
|
509
|
+
```bash
|
|
510
|
+
poetry run mypy trovesuite/
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Linting
|
|
514
|
+
|
|
515
|
+
#### Using pip
|
|
516
|
+
```bash
|
|
517
|
+
flake8 trovesuite/
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
#### Using Poetry
|
|
521
|
+
```bash
|
|
522
|
+
poetry run flake8 trovesuite/
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
### Poetry Configuration
|
|
526
|
+
|
|
527
|
+
If you're using Poetry in your project, you can add this package to your `pyproject.toml`:
|
|
528
|
+
|
|
529
|
+
```toml
|
|
530
|
+
[tool.poetry.dependencies]
|
|
531
|
+
trovesuite = "^1.0.0"
|
|
532
|
+
|
|
533
|
+
[[tool.poetry.source]]
|
|
534
|
+
name = "azure"
|
|
535
|
+
url = "https://pkgs.dev.azure.com/brightgclt/trovesuite/_packaging/packages/pypi/simple/"
|
|
536
|
+
priority = "supplemental"
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
Then run:
|
|
540
|
+
```bash
|
|
541
|
+
poetry install
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
## Contributing
|
|
545
|
+
|
|
546
|
+
1. Fork the repository
|
|
547
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
548
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
549
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
550
|
+
5. Open a Pull Request
|
|
551
|
+
|
|
552
|
+
## License
|
|
553
|
+
|
|
554
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
555
|
+
|
|
556
|
+
## Support
|
|
557
|
+
|
|
558
|
+
For support, email brightgclt@gmail.com or create a work item in the [Azure DevOps repository](https://dev.azure.com/brightgclt/trovesuite/_workitems/create).
|
|
559
|
+
|
|
560
|
+
## Changelog
|
|
561
|
+
|
|
562
|
+
### 1.0.8
|
|
563
|
+
- Restructured package for direct service imports
|
|
564
|
+
- Added notification services
|
|
565
|
+
- Excluded controllers from package build
|
|
566
|
+
- Updated import paths for better usability
|
|
567
|
+
- JWT token validation
|
|
568
|
+
- User authorization with tenant verification
|
|
569
|
+
- Hierarchical permission checking
|
|
570
|
+
- PostgreSQL database integration
|
|
571
|
+
- Comprehensive logging
|
|
572
|
+
- Azure integration support
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
trovesuite/__init__.py,sha256=a9jSrjmrhOey6yE2I83TO_rVJDogIwGDyL3HJBGiGqM,347
|
|
2
|
+
trovesuite/auth/__init__.py,sha256=qhgPqBHiLOjMcnecLvZQPV3UKV0ADKWp91kXfkpeAi4,336
|
|
3
|
+
trovesuite/auth/auth_base.py,sha256=I3-JU97KZJT89fGdL96HmQLFHXfN3CNokSChsqzeRPo,74
|
|
4
|
+
trovesuite/auth/auth_controller.py,sha256=47LsxPvE2wCqpadLPf_m68M8eR7Zu9HxfSSxZQZKQyM,412
|
|
5
|
+
trovesuite/auth/auth_read_dto.py,sha256=JxTwBlgUZ1S_KMaDuF0AueEhMBFrCiWgsHQDqoI2mMc,577
|
|
6
|
+
trovesuite/auth/auth_service.py,sha256=ZsR6LXE6c0ej4U8rb5SdccL6cyk2t_LicIESe98sUE8,14260
|
|
7
|
+
trovesuite/auth/auth_write_dto.py,sha256=OO4h_EYIxhCzhVZkoicYn31J_vw9tUNDegTeG6u65kE,230
|
|
8
|
+
trovesuite/configs/__init__.py,sha256=h1mSZOaZ3kUy1ZMO_m9O9KklsxywM0RfMVZLh9h9WvQ,328
|
|
9
|
+
trovesuite/configs/database.py,sha256=tXj-AYIUs-gjYrgioTnQafbDhsaIsgimWWLXR3ru-1A,7580
|
|
10
|
+
trovesuite/configs/logging.py,sha256=mGjR2d4urVNry9l5_aXycMMtcY2RAFIpEL35hw33KZg,9308
|
|
11
|
+
trovesuite/configs/settings.py,sha256=7Z9b-yWLSCL_NA28JfOGisQIrOvGb5PhcriQJvnZURk,7189
|
|
12
|
+
trovesuite/entities/__init__.py,sha256=Dbl_03Bueyh2vOP2hykd40MmNMrl5nNHSRGP-kqwwNo,160
|
|
13
|
+
trovesuite/entities/health.py,sha256=H8-XUywzvMfZy2dZwDyJGAUbmuULuZYvYIUWhiaVGdY,2729
|
|
14
|
+
trovesuite/entities/sh_response.py,sha256=1_sw3PpVaDxWsNiBU0W9YLHZgTFxEj4JJBLBfSY63Ho,1579
|
|
15
|
+
trovesuite/utils/__init__.py,sha256=3UPKTz9cluTgAM-ldNsJxsnoPTZiqacXlAmzUEHy6q8,143
|
|
16
|
+
trovesuite/utils/helper.py,sha256=lvZ1mvaqY84dkIPB5Ov0uwYDOWBziAS8twobEJZh2Ik,1002
|
|
17
|
+
trovesuite-1.0.0.dist-info/licenses/LICENSE,sha256=EJT35ct-Q794JYPdAQy3XNczQGKkU1HzToLeK1YVw2s,1070
|
|
18
|
+
trovesuite-1.0.0.dist-info/METADATA,sha256=-ZnZokzKAFp5CuFr3rBFLrDpscH5tcKpbgejfec7-LM,15697
|
|
19
|
+
trovesuite-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
20
|
+
trovesuite-1.0.0.dist-info/top_level.txt,sha256=GzKhG_-MTaxeHrIgkGkBH_nof2vroGFBrjeHKWUIwNc,11
|
|
21
|
+
trovesuite-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Bright Debrah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
trovesuite
|