| from typing import List, Optional, Dict, Any |
| from uuid import UUID |
| from ..protocols import ProfileRepository, ExternalUserIdGeneratorService, MCPQualifiedNameService, ProfileConfigurationService, ConnectionStatusService, Logger |
| from ..domain.entities import Profile |
| from ..domain.value_objects import ExternalUserId, AppSlug, ProfileName, EncryptedConfig, ConfigHash |
| from ..domain.exceptions import ProfileNotFoundError, ProfileAlreadyExistsError |
| import json |
|
|
|
|
| class ProfileService: |
| def __init__( |
| self, |
| profile_repo: ProfileRepository, |
| external_user_id_service: ExternalUserIdGeneratorService, |
| mcp_qualified_name_service: MCPQualifiedNameService, |
| profile_config_service: ProfileConfigurationService, |
| connection_status_service: ConnectionStatusService, |
| logger: Logger |
| ): |
| self._profile_repo = profile_repo |
| self._external_user_id_service = external_user_id_service |
| self._mcp_qualified_name_service = mcp_qualified_name_service |
| self._profile_config_service = profile_config_service |
| self._connection_status_service = connection_status_service |
| self._logger = logger |
|
|
| async def create_profile( |
| self, |
| account_id: UUID, |
| profile_name: str, |
| app_slug: str, |
| app_name: str, |
| description: Optional[str] = None, |
| is_default: bool = False, |
| oauth_app_id: Optional[str] = None, |
| enabled_tools: Optional[List[str]] = None, |
| external_user_id: Optional[str] = None |
| ) -> Profile: |
| app_slug_vo = AppSlug(app_slug) |
| profile_name_vo = ProfileName(profile_name) |
| |
| if external_user_id: |
| external_user_id_vo = ExternalUserId(external_user_id) |
| else: |
| external_user_id_vo = self._external_user_id_service.generate( |
| str(account_id), app_slug_vo, profile_name_vo |
| ) |
|
|
| mcp_qualified_name = self._mcp_qualified_name_service.generate(app_slug_vo) |
|
|
| config = { |
| "app_slug": app_slug, |
| "app_name": app_name, |
| "external_user_id": external_user_id_vo.value, |
| "oauth_app_id": oauth_app_id, |
| "enabled_tools": enabled_tools or [], |
| "description": description |
| } |
|
|
| if not self._profile_config_service.validate_config(config): |
| raise ValueError("Invalid profile configuration") |
|
|
| config_json = json.dumps(config) |
| |
| profile = Profile( |
| profile_id=UUID(int=0), |
| account_id=account_id, |
| mcp_qualified_name=mcp_qualified_name, |
| profile_name=profile_name_vo, |
| display_name=profile_name, |
| encrypted_config=EncryptedConfig("placeholder"), |
| config_hash=ConfigHash.from_config(config_json), |
| app_slug=app_slug_vo, |
| app_name=app_name, |
| external_user_id=external_user_id_vo, |
| enabled_tools=enabled_tools or [], |
| is_default=is_default |
| ) |
|
|
| if is_default: |
| await self._profile_repo.set_default(account_id, profile.profile_id, mcp_qualified_name) |
|
|
| created_profile = await self._profile_repo.create(profile) |
| self._logger.info(f"Created profile {created_profile.profile_id} for app {app_slug}") |
| |
| return created_profile |
|
|
| async def get_profile(self, account_id: UUID, profile_id: UUID) -> Optional[Profile]: |
| profile = await self._profile_repo.get_by_id(account_id, profile_id) |
| if profile: |
| return await self._connection_status_service.update_connection_status(profile) |
| return None |
|
|
| async def get_profiles( |
| self, |
| account_id: UUID, |
| app_slug: Optional[str] = None, |
| is_active: Optional[bool] = None |
| ) -> List[Profile]: |
| app_slug_vo = AppSlug(app_slug) if app_slug else None |
| profiles = await self._profile_repo.find_by_account(account_id, app_slug_vo, is_active) |
| |
| updated_profiles = [] |
| for profile in profiles: |
| updated_profile = await self._connection_status_service.update_connection_status(profile) |
| updated_profiles.append(updated_profile) |
| |
| return updated_profiles |
|
|
| async def update_profile( |
| self, |
| account_id: UUID, |
| profile_id: UUID, |
| profile_name: Optional[str] = None, |
| display_name: Optional[str] = None, |
| is_active: Optional[bool] = None, |
| is_default: Optional[bool] = None, |
| enabled_tools: Optional[List[str]] = None |
| ) -> Profile: |
| profile = await self._profile_repo.get_by_id(account_id, profile_id) |
| if not profile: |
| raise ProfileNotFoundError(str(profile_id)) |
|
|
| if profile_name: |
| profile.profile_name = ProfileName(profile_name) |
| if display_name: |
| profile.display_name = display_name |
| if is_active is not None: |
| if is_active: |
| profile.activate() |
| else: |
| profile.deactivate() |
| if is_default is not None: |
| if is_default: |
| await self._profile_repo.set_default(account_id, profile_id, profile.mcp_qualified_name) |
| profile.set_as_default() |
| else: |
| profile.unset_as_default() |
| if enabled_tools is not None: |
| profile.enabled_tools = enabled_tools |
|
|
| updated_profile = await self._profile_repo.update(profile) |
| self._logger.info(f"Updated profile {profile_id}") |
| |
| return updated_profile |
|
|
| async def delete_profile(self, account_id: UUID, profile_id: UUID) -> bool: |
| success = await self._profile_repo.delete(account_id, profile_id) |
| if success: |
| self._logger.info(f"Deleted profile {profile_id}") |
| return success |
|
|
| async def get_profile_by_app( |
| self, |
| account_id: UUID, |
| app_slug: str, |
| profile_name: Optional[str] = None |
| ) -> Optional[Profile]: |
| app_slug_vo = AppSlug(app_slug) |
| profile_name_vo = ProfileName(profile_name) if profile_name else None |
| |
| profile = await self._profile_repo.get_by_app_slug(account_id, app_slug_vo, profile_name_vo) |
| if profile: |
| return await self._connection_status_service.update_connection_status(profile) |
| return None |