mcli-framework 7.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.
Potentially problematic release.
This version of mcli-framework might be problematic. Click here for more details.
- mcli/app/chat_cmd.py +42 -0
- mcli/app/commands_cmd.py +226 -0
- mcli/app/completion_cmd.py +216 -0
- mcli/app/completion_helpers.py +288 -0
- mcli/app/cron_test_cmd.py +697 -0
- mcli/app/logs_cmd.py +419 -0
- mcli/app/main.py +492 -0
- mcli/app/model/model.py +1060 -0
- mcli/app/model_cmd.py +227 -0
- mcli/app/redis_cmd.py +269 -0
- mcli/app/video/video.py +1114 -0
- mcli/app/visual_cmd.py +303 -0
- mcli/chat/chat.py +2409 -0
- mcli/chat/command_rag.py +514 -0
- mcli/chat/enhanced_chat.py +652 -0
- mcli/chat/system_controller.py +1010 -0
- mcli/chat/system_integration.py +1016 -0
- mcli/cli.py +25 -0
- mcli/config.toml +20 -0
- mcli/lib/api/api.py +586 -0
- mcli/lib/api/daemon_client.py +203 -0
- mcli/lib/api/daemon_client_local.py +44 -0
- mcli/lib/api/daemon_decorator.py +217 -0
- mcli/lib/api/mcli_decorators.py +1032 -0
- mcli/lib/auth/auth.py +85 -0
- mcli/lib/auth/aws_manager.py +85 -0
- mcli/lib/auth/azure_manager.py +91 -0
- mcli/lib/auth/credential_manager.py +192 -0
- mcli/lib/auth/gcp_manager.py +93 -0
- mcli/lib/auth/key_manager.py +117 -0
- mcli/lib/auth/mcli_manager.py +93 -0
- mcli/lib/auth/token_manager.py +75 -0
- mcli/lib/auth/token_util.py +1011 -0
- mcli/lib/config/config.py +47 -0
- mcli/lib/discovery/__init__.py +1 -0
- mcli/lib/discovery/command_discovery.py +274 -0
- mcli/lib/erd/erd.py +1345 -0
- mcli/lib/erd/generate_graph.py +453 -0
- mcli/lib/files/files.py +76 -0
- mcli/lib/fs/fs.py +109 -0
- mcli/lib/lib.py +29 -0
- mcli/lib/logger/logger.py +611 -0
- mcli/lib/performance/optimizer.py +409 -0
- mcli/lib/performance/rust_bridge.py +502 -0
- mcli/lib/performance/uvloop_config.py +154 -0
- mcli/lib/pickles/pickles.py +50 -0
- mcli/lib/search/cached_vectorizer.py +479 -0
- mcli/lib/services/data_pipeline.py +460 -0
- mcli/lib/services/lsh_client.py +441 -0
- mcli/lib/services/redis_service.py +387 -0
- mcli/lib/shell/shell.py +137 -0
- mcli/lib/toml/toml.py +33 -0
- mcli/lib/ui/styling.py +47 -0
- mcli/lib/ui/visual_effects.py +634 -0
- mcli/lib/watcher/watcher.py +185 -0
- mcli/ml/api/app.py +215 -0
- mcli/ml/api/middleware.py +224 -0
- mcli/ml/api/routers/admin_router.py +12 -0
- mcli/ml/api/routers/auth_router.py +244 -0
- mcli/ml/api/routers/backtest_router.py +12 -0
- mcli/ml/api/routers/data_router.py +12 -0
- mcli/ml/api/routers/model_router.py +302 -0
- mcli/ml/api/routers/monitoring_router.py +12 -0
- mcli/ml/api/routers/portfolio_router.py +12 -0
- mcli/ml/api/routers/prediction_router.py +267 -0
- mcli/ml/api/routers/trade_router.py +12 -0
- mcli/ml/api/routers/websocket_router.py +76 -0
- mcli/ml/api/schemas.py +64 -0
- mcli/ml/auth/auth_manager.py +425 -0
- mcli/ml/auth/models.py +154 -0
- mcli/ml/auth/permissions.py +302 -0
- mcli/ml/backtesting/backtest_engine.py +502 -0
- mcli/ml/backtesting/performance_metrics.py +393 -0
- mcli/ml/cache.py +400 -0
- mcli/ml/cli/main.py +398 -0
- mcli/ml/config/settings.py +394 -0
- mcli/ml/configs/dvc_config.py +230 -0
- mcli/ml/configs/mlflow_config.py +131 -0
- mcli/ml/configs/mlops_manager.py +293 -0
- mcli/ml/dashboard/app.py +532 -0
- mcli/ml/dashboard/app_integrated.py +738 -0
- mcli/ml/dashboard/app_supabase.py +560 -0
- mcli/ml/dashboard/app_training.py +615 -0
- mcli/ml/dashboard/cli.py +51 -0
- mcli/ml/data_ingestion/api_connectors.py +501 -0
- mcli/ml/data_ingestion/data_pipeline.py +567 -0
- mcli/ml/data_ingestion/stream_processor.py +512 -0
- mcli/ml/database/migrations/env.py +94 -0
- mcli/ml/database/models.py +667 -0
- mcli/ml/database/session.py +200 -0
- mcli/ml/experimentation/ab_testing.py +845 -0
- mcli/ml/features/ensemble_features.py +607 -0
- mcli/ml/features/political_features.py +676 -0
- mcli/ml/features/recommendation_engine.py +809 -0
- mcli/ml/features/stock_features.py +573 -0
- mcli/ml/features/test_feature_engineering.py +346 -0
- mcli/ml/logging.py +85 -0
- mcli/ml/mlops/data_versioning.py +518 -0
- mcli/ml/mlops/experiment_tracker.py +377 -0
- mcli/ml/mlops/model_serving.py +481 -0
- mcli/ml/mlops/pipeline_orchestrator.py +614 -0
- mcli/ml/models/base_models.py +324 -0
- mcli/ml/models/ensemble_models.py +675 -0
- mcli/ml/models/recommendation_models.py +474 -0
- mcli/ml/models/test_models.py +487 -0
- mcli/ml/monitoring/drift_detection.py +676 -0
- mcli/ml/monitoring/metrics.py +45 -0
- mcli/ml/optimization/portfolio_optimizer.py +834 -0
- mcli/ml/preprocessing/data_cleaners.py +451 -0
- mcli/ml/preprocessing/feature_extractors.py +491 -0
- mcli/ml/preprocessing/ml_pipeline.py +382 -0
- mcli/ml/preprocessing/politician_trading_preprocessor.py +569 -0
- mcli/ml/preprocessing/test_preprocessing.py +294 -0
- mcli/ml/scripts/populate_sample_data.py +200 -0
- mcli/ml/tasks.py +400 -0
- mcli/ml/tests/test_integration.py +429 -0
- mcli/ml/tests/test_training_dashboard.py +387 -0
- mcli/public/oi/oi.py +15 -0
- mcli/public/public.py +4 -0
- mcli/self/self_cmd.py +1246 -0
- mcli/workflow/daemon/api_daemon.py +800 -0
- mcli/workflow/daemon/async_command_database.py +681 -0
- mcli/workflow/daemon/async_process_manager.py +591 -0
- mcli/workflow/daemon/client.py +530 -0
- mcli/workflow/daemon/commands.py +1196 -0
- mcli/workflow/daemon/daemon.py +905 -0
- mcli/workflow/daemon/daemon_api.py +59 -0
- mcli/workflow/daemon/enhanced_daemon.py +571 -0
- mcli/workflow/daemon/process_cli.py +244 -0
- mcli/workflow/daemon/process_manager.py +439 -0
- mcli/workflow/daemon/test_daemon.py +275 -0
- mcli/workflow/dashboard/dashboard_cmd.py +113 -0
- mcli/workflow/docker/docker.py +0 -0
- mcli/workflow/file/file.py +100 -0
- mcli/workflow/gcloud/config.toml +21 -0
- mcli/workflow/gcloud/gcloud.py +58 -0
- mcli/workflow/git_commit/ai_service.py +328 -0
- mcli/workflow/git_commit/commands.py +430 -0
- mcli/workflow/lsh_integration.py +355 -0
- mcli/workflow/model_service/client.py +594 -0
- mcli/workflow/model_service/download_and_run_efficient_models.py +288 -0
- mcli/workflow/model_service/lightweight_embedder.py +397 -0
- mcli/workflow/model_service/lightweight_model_server.py +714 -0
- mcli/workflow/model_service/lightweight_test.py +241 -0
- mcli/workflow/model_service/model_service.py +1955 -0
- mcli/workflow/model_service/ollama_efficient_runner.py +425 -0
- mcli/workflow/model_service/pdf_processor.py +386 -0
- mcli/workflow/model_service/test_efficient_runner.py +234 -0
- mcli/workflow/model_service/test_example.py +315 -0
- mcli/workflow/model_service/test_integration.py +131 -0
- mcli/workflow/model_service/test_new_features.py +149 -0
- mcli/workflow/openai/openai.py +99 -0
- mcli/workflow/politician_trading/commands.py +1790 -0
- mcli/workflow/politician_trading/config.py +134 -0
- mcli/workflow/politician_trading/connectivity.py +490 -0
- mcli/workflow/politician_trading/data_sources.py +395 -0
- mcli/workflow/politician_trading/database.py +410 -0
- mcli/workflow/politician_trading/demo.py +248 -0
- mcli/workflow/politician_trading/models.py +165 -0
- mcli/workflow/politician_trading/monitoring.py +413 -0
- mcli/workflow/politician_trading/scrapers.py +966 -0
- mcli/workflow/politician_trading/scrapers_california.py +412 -0
- mcli/workflow/politician_trading/scrapers_eu.py +377 -0
- mcli/workflow/politician_trading/scrapers_uk.py +350 -0
- mcli/workflow/politician_trading/scrapers_us_states.py +438 -0
- mcli/workflow/politician_trading/supabase_functions.py +354 -0
- mcli/workflow/politician_trading/workflow.py +852 -0
- mcli/workflow/registry/registry.py +180 -0
- mcli/workflow/repo/repo.py +223 -0
- mcli/workflow/scheduler/commands.py +493 -0
- mcli/workflow/scheduler/cron_parser.py +238 -0
- mcli/workflow/scheduler/job.py +182 -0
- mcli/workflow/scheduler/monitor.py +139 -0
- mcli/workflow/scheduler/persistence.py +324 -0
- mcli/workflow/scheduler/scheduler.py +679 -0
- mcli/workflow/sync/sync_cmd.py +437 -0
- mcli/workflow/sync/test_cmd.py +314 -0
- mcli/workflow/videos/videos.py +242 -0
- mcli/workflow/wakatime/wakatime.py +11 -0
- mcli/workflow/workflow.py +37 -0
- mcli_framework-7.0.0.dist-info/METADATA +479 -0
- mcli_framework-7.0.0.dist-info/RECORD +186 -0
- mcli_framework-7.0.0.dist-info/WHEEL +5 -0
- mcli_framework-7.0.0.dist-info/entry_points.txt +7 -0
- mcli_framework-7.0.0.dist-info/licenses/LICENSE +21 -0
- mcli_framework-7.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
"""Permission management system"""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import List, Set, Dict, Any
|
|
6
|
+
from functools import wraps
|
|
7
|
+
|
|
8
|
+
from fastapi import HTTPException, status
|
|
9
|
+
from sqlalchemy.orm import Session
|
|
10
|
+
|
|
11
|
+
from mcli.ml.database.models import User, UserRole
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Permission(Enum):
|
|
15
|
+
"""System permissions"""
|
|
16
|
+
|
|
17
|
+
# Model permissions
|
|
18
|
+
MODEL_VIEW = "model:view"
|
|
19
|
+
MODEL_CREATE = "model:create"
|
|
20
|
+
MODEL_EDIT = "model:edit"
|
|
21
|
+
MODEL_DELETE = "model:delete"
|
|
22
|
+
MODEL_DEPLOY = "model:deploy"
|
|
23
|
+
|
|
24
|
+
# Prediction permissions
|
|
25
|
+
PREDICTION_VIEW = "prediction:view"
|
|
26
|
+
PREDICTION_CREATE = "prediction:create"
|
|
27
|
+
PREDICTION_DELETE = "prediction:delete"
|
|
28
|
+
|
|
29
|
+
# Portfolio permissions
|
|
30
|
+
PORTFOLIO_VIEW = "portfolio:view"
|
|
31
|
+
PORTFOLIO_CREATE = "portfolio:create"
|
|
32
|
+
PORTFOLIO_EDIT = "portfolio:edit"
|
|
33
|
+
PORTFOLIO_DELETE = "portfolio:delete"
|
|
34
|
+
PORTFOLIO_TRADE = "portfolio:trade"
|
|
35
|
+
|
|
36
|
+
# Data permissions
|
|
37
|
+
DATA_VIEW = "data:view"
|
|
38
|
+
DATA_CREATE = "data:create"
|
|
39
|
+
DATA_EDIT = "data:edit"
|
|
40
|
+
DATA_DELETE = "data:delete"
|
|
41
|
+
|
|
42
|
+
# User permissions
|
|
43
|
+
USER_VIEW = "user:view"
|
|
44
|
+
USER_CREATE = "user:create"
|
|
45
|
+
USER_EDIT = "user:edit"
|
|
46
|
+
USER_DELETE = "user:delete"
|
|
47
|
+
|
|
48
|
+
# Admin permissions
|
|
49
|
+
ADMIN_ACCESS = "admin:access"
|
|
50
|
+
ADMIN_SETTINGS = "admin:settings"
|
|
51
|
+
ADMIN_MONITORING = "admin:monitoring"
|
|
52
|
+
ADMIN_AUDIT = "admin:audit"
|
|
53
|
+
|
|
54
|
+
# System permissions
|
|
55
|
+
SYSTEM_STATUS = "system:status"
|
|
56
|
+
SYSTEM_CONFIG = "system:config"
|
|
57
|
+
SYSTEM_RESTART = "system:restart"
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
# Role-based permission mapping
|
|
61
|
+
ROLE_PERMISSIONS: Dict[UserRole, Set[Permission]] = {
|
|
62
|
+
UserRole.ADMIN: set(Permission), # Admin has all permissions
|
|
63
|
+
|
|
64
|
+
UserRole.ANALYST: {
|
|
65
|
+
Permission.MODEL_VIEW,
|
|
66
|
+
Permission.MODEL_CREATE,
|
|
67
|
+
Permission.MODEL_EDIT,
|
|
68
|
+
Permission.MODEL_DEPLOY,
|
|
69
|
+
Permission.PREDICTION_VIEW,
|
|
70
|
+
Permission.PREDICTION_CREATE,
|
|
71
|
+
Permission.PORTFOLIO_VIEW,
|
|
72
|
+
Permission.PORTFOLIO_CREATE,
|
|
73
|
+
Permission.PORTFOLIO_EDIT,
|
|
74
|
+
Permission.DATA_VIEW,
|
|
75
|
+
Permission.DATA_CREATE,
|
|
76
|
+
Permission.DATA_EDIT,
|
|
77
|
+
Permission.SYSTEM_STATUS,
|
|
78
|
+
},
|
|
79
|
+
|
|
80
|
+
UserRole.USER: {
|
|
81
|
+
Permission.MODEL_VIEW,
|
|
82
|
+
Permission.PREDICTION_VIEW,
|
|
83
|
+
Permission.PREDICTION_CREATE,
|
|
84
|
+
Permission.PORTFOLIO_VIEW,
|
|
85
|
+
Permission.PORTFOLIO_CREATE,
|
|
86
|
+
Permission.PORTFOLIO_EDIT,
|
|
87
|
+
Permission.PORTFOLIO_TRADE,
|
|
88
|
+
Permission.DATA_VIEW,
|
|
89
|
+
Permission.SYSTEM_STATUS,
|
|
90
|
+
},
|
|
91
|
+
|
|
92
|
+
UserRole.VIEWER: {
|
|
93
|
+
Permission.MODEL_VIEW,
|
|
94
|
+
Permission.PREDICTION_VIEW,
|
|
95
|
+
Permission.PORTFOLIO_VIEW,
|
|
96
|
+
Permission.DATA_VIEW,
|
|
97
|
+
Permission.SYSTEM_STATUS,
|
|
98
|
+
},
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def has_permission(user: User, permission: Permission) -> bool:
|
|
103
|
+
"""Check if user has specific permission"""
|
|
104
|
+
user_permissions = ROLE_PERMISSIONS.get(user.role, set())
|
|
105
|
+
return permission in user_permissions
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def check_permission(user: User, permission: Permission) -> None:
|
|
109
|
+
"""Check permission and raise exception if not allowed"""
|
|
110
|
+
if not has_permission(user, permission):
|
|
111
|
+
raise HTTPException(
|
|
112
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
113
|
+
detail=f"Permission denied: {permission.value}"
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def require_permission(permission: Permission):
|
|
118
|
+
"""Decorator to require specific permission"""
|
|
119
|
+
|
|
120
|
+
def decorator(func):
|
|
121
|
+
@wraps(func)
|
|
122
|
+
async def wrapper(*args, **kwargs):
|
|
123
|
+
# Extract user from kwargs (assumes it's passed as current_user)
|
|
124
|
+
current_user = kwargs.get('current_user')
|
|
125
|
+
|
|
126
|
+
if not current_user:
|
|
127
|
+
raise HTTPException(
|
|
128
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
129
|
+
detail="Authentication required"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
check_permission(current_user, permission)
|
|
133
|
+
return await func(*args, **kwargs)
|
|
134
|
+
|
|
135
|
+
return wrapper
|
|
136
|
+
|
|
137
|
+
return decorator
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def require_any_permission(*permissions: Permission):
|
|
141
|
+
"""Decorator to require any of the specified permissions"""
|
|
142
|
+
|
|
143
|
+
def decorator(func):
|
|
144
|
+
@wraps(func)
|
|
145
|
+
async def wrapper(*args, **kwargs):
|
|
146
|
+
current_user = kwargs.get('current_user')
|
|
147
|
+
|
|
148
|
+
if not current_user:
|
|
149
|
+
raise HTTPException(
|
|
150
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
151
|
+
detail="Authentication required"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
if not any(has_permission(current_user, p) for p in permissions):
|
|
155
|
+
raise HTTPException(
|
|
156
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
157
|
+
detail=f"Permission denied. Required: {[p.value for p in permissions]}"
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
return await func(*args, **kwargs)
|
|
161
|
+
|
|
162
|
+
return wrapper
|
|
163
|
+
|
|
164
|
+
return decorator
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def require_all_permissions(*permissions: Permission):
|
|
168
|
+
"""Decorator to require all of the specified permissions"""
|
|
169
|
+
|
|
170
|
+
def decorator(func):
|
|
171
|
+
@wraps(func)
|
|
172
|
+
async def wrapper(*args, **kwargs):
|
|
173
|
+
current_user = kwargs.get('current_user')
|
|
174
|
+
|
|
175
|
+
if not current_user:
|
|
176
|
+
raise HTTPException(
|
|
177
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
178
|
+
detail="Authentication required"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
for permission in permissions:
|
|
182
|
+
check_permission(current_user, permission)
|
|
183
|
+
|
|
184
|
+
return await func(*args, **kwargs)
|
|
185
|
+
|
|
186
|
+
return wrapper
|
|
187
|
+
|
|
188
|
+
return decorator
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class PermissionChecker:
|
|
192
|
+
"""FastAPI dependency for permission checking"""
|
|
193
|
+
|
|
194
|
+
def __init__(self, permission: Permission):
|
|
195
|
+
self.permission = permission
|
|
196
|
+
|
|
197
|
+
def __call__(self, current_user: User) -> User:
|
|
198
|
+
check_permission(current_user, self.permission)
|
|
199
|
+
return current_user
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
# Resource-based permissions
|
|
203
|
+
class ResourcePermission:
|
|
204
|
+
"""Check permissions for specific resources"""
|
|
205
|
+
|
|
206
|
+
@staticmethod
|
|
207
|
+
def can_edit_portfolio(user: User, portfolio) -> bool:
|
|
208
|
+
"""Check if user can edit a specific portfolio"""
|
|
209
|
+
# Admin can edit any portfolio
|
|
210
|
+
if user.role == UserRole.ADMIN:
|
|
211
|
+
return True
|
|
212
|
+
|
|
213
|
+
# User can edit their own portfolio
|
|
214
|
+
if portfolio.user_id == user.id:
|
|
215
|
+
return True
|
|
216
|
+
|
|
217
|
+
return False
|
|
218
|
+
|
|
219
|
+
@staticmethod
|
|
220
|
+
def can_view_portfolio(user: User, portfolio) -> bool:
|
|
221
|
+
"""Check if user can view a specific portfolio"""
|
|
222
|
+
# Admin can view any portfolio
|
|
223
|
+
if user.role == UserRole.ADMIN:
|
|
224
|
+
return True
|
|
225
|
+
|
|
226
|
+
# User can view their own portfolio
|
|
227
|
+
if portfolio.user_id == user.id:
|
|
228
|
+
return True
|
|
229
|
+
|
|
230
|
+
# Analyst can view any portfolio
|
|
231
|
+
if user.role == UserRole.ANALYST:
|
|
232
|
+
return True
|
|
233
|
+
|
|
234
|
+
return False
|
|
235
|
+
|
|
236
|
+
@staticmethod
|
|
237
|
+
def can_delete_model(user: User, model) -> bool:
|
|
238
|
+
"""Check if user can delete a specific model"""
|
|
239
|
+
# Only admin can delete models
|
|
240
|
+
return user.role == UserRole.ADMIN
|
|
241
|
+
|
|
242
|
+
@staticmethod
|
|
243
|
+
def can_deploy_model(user: User, model) -> bool:
|
|
244
|
+
"""Check if user can deploy a specific model"""
|
|
245
|
+
# Admin and Analyst can deploy models
|
|
246
|
+
return user.role in [UserRole.ADMIN, UserRole.ANALYST]
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# Audit logging
|
|
250
|
+
class AuditLogger:
|
|
251
|
+
"""Log permission-related actions"""
|
|
252
|
+
|
|
253
|
+
@staticmethod
|
|
254
|
+
async def log_access(
|
|
255
|
+
user: User,
|
|
256
|
+
resource: str,
|
|
257
|
+
action: str,
|
|
258
|
+
success: bool,
|
|
259
|
+
details: Dict[str, Any] = None,
|
|
260
|
+
db: Session = None
|
|
261
|
+
):
|
|
262
|
+
"""Log access attempt"""
|
|
263
|
+
log_entry = {
|
|
264
|
+
"user_id": str(user.id),
|
|
265
|
+
"username": user.username,
|
|
266
|
+
"resource": resource,
|
|
267
|
+
"action": action,
|
|
268
|
+
"success": success,
|
|
269
|
+
"timestamp": datetime.utcnow(),
|
|
270
|
+
"details": details or {}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
# In production, save to database or logging service
|
|
274
|
+
print(f"AUDIT: {log_entry}")
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# Permission groups for easier management
|
|
278
|
+
class PermissionGroup:
|
|
279
|
+
"""Predefined permission groups"""
|
|
280
|
+
|
|
281
|
+
BASIC_USER = {
|
|
282
|
+
Permission.MODEL_VIEW,
|
|
283
|
+
Permission.PREDICTION_VIEW,
|
|
284
|
+
Permission.PORTFOLIO_VIEW,
|
|
285
|
+
Permission.DATA_VIEW,
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
TRADER = BASIC_USER | {
|
|
289
|
+
Permission.PREDICTION_CREATE,
|
|
290
|
+
Permission.PORTFOLIO_CREATE,
|
|
291
|
+
Permission.PORTFOLIO_EDIT,
|
|
292
|
+
Permission.PORTFOLIO_TRADE,
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
DATA_SCIENTIST = TRADER | {
|
|
296
|
+
Permission.MODEL_CREATE,
|
|
297
|
+
Permission.MODEL_EDIT,
|
|
298
|
+
Permission.DATA_CREATE,
|
|
299
|
+
Permission.DATA_EDIT,
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
ADMIN = set(Permission) # All permissions
|