from typing import Any, Type from flask import g from owsclient import OwsClient from owsrequest.ows_client import request_context_getter from pydantic import BaseModel, field_validator from artist import config from artist.schema import LabelProfile ows_client = OwsClient( environment=config.ENVIRONMENT, service_name="ows-permissions", request_context_getter=request_context_getter, ) def get_ows_client() -> OwsClient: return ows_client class Vendor(BaseModel): vendor_id: str vendor_uuid: str @field_validator("vendor_id", mode="before") @classmethod def convert_vendor_id_to_str(cls: Type["Vendor"], value: Any) -> Any: """Original vendor_id may be '*' or number both, so it converts a value to the sane type.""" if isinstance(value, int): return str(value) return value def get_directly_accessible_vendors() -> dict[str, Vendor]: """Returns map (id to Vendor instance) of directly accessible vendor(s) for jwt authorization token and profile headers from the request context. """ response = get_ows_client().get( "ows-permissions", "/v2/profile/vendors/direct-access", headers={ "Content-Type": "application/json", "Orchard-Profile-Type": g.request_context.profile_type, "Orchard-Profile-Id": g.request_context.profile_id, }, ) response.raise_for_status() vendor_id_to_vendor = {} for vendor_data in response.json().get("vendors", []): vendor = Vendor(**vendor_data) vendor_id_to_vendor[vendor.vendor_id] = vendor return vendor_id_to_vendor def get_single_vendor_id_for_label_profile(request_context: LabelProfile) -> int | None: """ Returns vendor_id of single vendor accessible for a given LabelProfile. Raises: ValueError: if the profile type is not 'LabelProfile' ValueError: if more than one vendor is returned """ if not request_context.profile_type or request_context.profile_type != "LabelProfile": raise ValueError("Profile type must be 'LabelProfile'") response = get_ows_client().get( "ows-permissions", "/v2/profile/self/vendors/direct-access", headers={ "Content-Type": "application/json", "Orchard-Profile-Type": request_context.profile_type, "Orchard-Profile-Id": str(request_context.profile_id), }, ) response.raise_for_status() if not response: return None vendors = response.json().get('vendors', []) if not vendors: return None if len(vendors) > 1: raise ValueError(f"Expected a single Vendor for LabelProfile {request_context.profile_id}") return vendors[0].get('vendor_id') def get_subaccount_ids_for_label_profile(request_context: LabelProfile) -> list[int]: """ Returns subaccount ids accessible for a given LabelProfile. Raises: ValueError: if the profile type is not 'LabelProfile' """ if not request_context.profile_type or request_context.profile_type != "LabelProfile": raise ValueError("Profile type must be 'LabelProfile'") response = get_ows_client().get( "ows-permissions", "/v2/profile/self/subaccounts/direct-access", headers={ "Content-Type": "application/json", "Orchard-Profile-Type": request_context.profile_type, "Orchard-Profile-Id": str(request_context.profile_id), }, ) response.raise_for_status() if not response: return [] subaccounts = response.json().get('subaccounts', []) if not subaccounts: return [] return [subaccount['subaccount_id'] for subaccount in subaccounts]