diff --git a/ingestion/src/metadata/ingestion/source/dashboard/metabase/client.py b/ingestion/src/metadata/ingestion/source/dashboard/metabase/client.py index 72226f24595..17c3215942a 100644 --- a/ingestion/src/metadata/ingestion/source/dashboard/metabase/client.py +++ b/ingestion/src/metadata/ingestion/source/dashboard/metabase/client.py @@ -30,6 +30,7 @@ from metadata.ingestion.source.dashboard.metabase.models import ( MetabaseDashboardList, MetabaseDatabase, MetabaseTable, + MetabaseUser, ) from metadata.utils.constants import AUTHORIZATION_HEADER, NO_ACCESS_TOKEN from metadata.utils.logger import ingestion_logger @@ -194,3 +195,18 @@ class MetabaseClient: logger.debug(traceback.format_exc()) logger.warning(f"Failed to fetch the table with id: {table_id}") return None + + def get_user_details(self, user_id: str) -> Optional[MetabaseUser]: + """ + Get User using user ID + """ + if not user_id: + return None # don't call api if table_id is None + try: + resp_table = self.client.get(f"/user/{user_id}") + if resp_table: + return MetabaseUser(**resp_table) + except Exception: + logger.debug(traceback.format_exc()) + logger.warning(f"Failed to fetch the user with id: {user_id}") + return None diff --git a/ingestion/src/metadata/ingestion/source/dashboard/metabase/metadata.py b/ingestion/src/metadata/ingestion/source/dashboard/metabase/metadata.py index 3d5394a386d..f02095b06ce 100644 --- a/ingestion/src/metadata/ingestion/source/dashboard/metabase/metadata.py +++ b/ingestion/src/metadata/ingestion/source/dashboard/metabase/metadata.py @@ -39,6 +39,7 @@ from metadata.generated.schema.type.basic import ( Markdown, SourceUrl, ) +from metadata.generated.schema.type.entityReferenceList import EntityReferenceList from metadata.ingestion.api.models import Either from metadata.ingestion.api.steps import InvalidSourceException from metadata.ingestion.lineage.models import ConnectionTypeDialectMapper @@ -108,7 +109,9 @@ class MetabaseSource(DashboardServiceSource): """ return dashboard.name - def get_dashboard_details(self, dashboard: MetabaseDashboard) -> dict: + def get_dashboard_details( + self, dashboard: MetabaseDashboard + ) -> Optional[MetabaseDashboardDetails]: """ Get Dashboard Details """ @@ -136,6 +139,24 @@ class MetabaseSource(DashboardServiceSource): ) return None + def get_owner_ref( + self, dashboard_details: MetabaseDashboardDetails + ) -> Optional[EntityReferenceList]: + """ + Get dashboard owner from email + """ + try: + if dashboard_details.creator_id: + owner_details = self.client.get_user_details( + dashboard_details.creator_id + ) + if owner_details and owner_details.email: + return self.metadata.get_reference_by_email(owner_details.email) + except Exception as err: + logger.debug(traceback.format_exc()) + logger.warning(f"Could not fetch owner data due to {err}") + return None + def yield_dashboard( self, dashboard_details: MetabaseDashboardDetails ) -> Iterable[Either[CreateDashboardRequest]]: diff --git a/ingestion/src/metadata/ingestion/source/dashboard/metabase/models.py b/ingestion/src/metadata/ingestion/source/dashboard/metabase/models.py index cd3484c6f8d..28915b84ab0 100644 --- a/ingestion/src/metadata/ingestion/source/dashboard/metabase/models.py +++ b/ingestion/src/metadata/ingestion/source/dashboard/metabase/models.py @@ -19,6 +19,20 @@ from typing_extensions import Annotated MetabaseStrId = Annotated[str, BeforeValidator(lambda x: str(x))] +class MetabaseUser(BaseModel): + """ + Metabase user model + """ + + id: MetabaseStrId + first_name: Optional[str] = None + last_name: Optional[str] = None + common_name: Optional[str] = None + email: Optional[str] = None + is_superuser: Optional[bool] = False + last_edit_timestamp: Optional[str] = Field(None, alias="timestamp") + + class MetabaseDashboard(BaseModel): """ Metabase dashboard model @@ -83,6 +97,7 @@ class MetabaseDashboardDetails(BaseModel): dashcards: List[DashCard] name: Optional[str] = None id: MetabaseStrId + creator_id: Optional[MetabaseStrId] = None collection_id: Optional[MetabaseStrId] = None