"""Module that checks product ownership.""" from typing import Any from owsresponse import response from requests import HTTPError from assets.constants import error from assets.exceptions import ProductNotFound from assets.logic import asset_upload as asset_upload_logic from assets.models import ows_account, ows_artist, ows_product, ows_track from assets.models.cache import ownership def _wrap_ownership_response( ownership_data: dict[str, Any], error_message: str | None = None ) -> response.Response: """Wrap ownership flag to ownership response. Args: ownership_data(dict): Ownership cached info. error_message(str | None): Error message. Returns: response.Response: Response object with ownership status. """ if ownership_data.get("ownership"): return response.Response(message=error.SUCCESS_CODE) return response.create_error_response( status=403, code=error.ERROR_CODE_NOT_OWNED, message=error_message, ) def check_ownership( product_id: int, account_type: str | None = None, account_id: int | None = None ) -> response.Response: """Method to check grass user product ownership. Args: product_id (int): Product id. account_type (str | None): Grass account type. account_id (int | None): Grass account id. Returns: response.Response: Response object with ownership status. """ cached_ownership = ownership.get( ownership.ENTITY_TYPE_PRODUCT, product_id, account_type, account_id ) if cached_ownership: return _wrap_ownership_response(cached_ownership, error.ERROR_PRODUCT_NOT_OWNED) product_ownership = _check_product_ownership(product_id, account_type, account_id) ownership.save( ownership.ENTITY_TYPE_PRODUCT, product_id, account_type, account_id, product_ownership, ) return _wrap_ownership_response( {"ownership": product_ownership}, error.ERROR_PRODUCT_NOT_OWNED ) def check_track_ownership( track_id: int, account_type: str | None = None, account_id: int | None = None ) -> response.Response: """Check grass user track ownership. Args: track_id (int): Unique track id. account_type (str | None): Grass account type. account_id (int | None): Grass account id. """ cached_ownership = ownership.get( ownership.ENTITY_TYPE_TRACK, track_id, account_type, account_id ) if cached_ownership: return _wrap_ownership_response(cached_ownership, error.ERROR_PRODUCT_NOT_OWNED) track = ows_track.get_track_by_id(track_id) product_ownership = _check_product_ownership( track["product_id"], account_type, account_id ) ownership.save( ownership.ENTITY_TYPE_TRACK, track_id, account_type, account_id, product_ownership, ) return _wrap_ownership_response( {"ownership": product_ownership}, error.ERROR_PRODUCT_NOT_OWNED ) def _check_product_ownership( product_id: int, account_type: str | None, account_id: int | None ) -> bool: """Check product ownership.""" try: ows_product.check_ownership(product_id, account_type, account_id) return True except HTTPError as e: if e.response.status_code == 403: return False raise def check_vendor_ownership( vendor_id: int, account_type: str | None = None, account_id: str | None = None ) -> response.Response: """Method to check given vendor exists or not. Args: vendor_id (int): Vendor id. account_type (str | None): Grass Account Type. account_id (str | None): Grass Account ID. Returns: response.Response: Response object with ownership status. """ ows_account.lookup_vendor(vendor_id=vendor_id) int_account_id = int(account_id) if account_id is not None else None return _wrap_ownership_response( {"ownership": (account_type == "vendor" and int_account_id == vendor_id)}, error.ERROR_VENDOR_NOT_OWNED, ) def is_valid_artist( artist_id: int, account_type: str | None = None, account_id: str | None = None ) -> response.Response: """Method to check given artist exists or not. Args: artist_id (int): Artist id. account_type (str | None): Grass Account Type. account_id (str | None): Grass Account ID. Returns: response.Response: Response object with ownership status. """ cached_ownership = ownership.get( ownership.ENTITY_TYPE_ARTIST, artist_id, account_type, account_id ) if cached_ownership: return _wrap_ownership_response(cached_ownership, error.ERROR_ARTIST_NOT_OWNED) artist_ownership = _check_artist_ownership(artist_id, account_type, account_id) ownership.save( ownership.ENTITY_TYPE_ARTIST, artist_id, account_type, account_id, artist_ownership, ) return _wrap_ownership_response( {"ownership": artist_ownership}, error.ERROR_ARTIST_NOT_OWNED ) def _check_artist_ownership( artist_id: int, account_type: str | None, account_id: str | None ) -> bool: try: ows_artist.check_ownership(artist_id, account_type, account_id) return True except HTTPError as ex: if ex.response.status_code == 403: return False raise def check_profile_track_access( profile_type: str, profile_uuid: str, tuid: int ) -> response.Response: """Check profile track access.""" error_message = "Track access denied" cached_ownership = ownership.get( ownership.ENTITY_TYPE_TRACK, tuid, profile_type, profile_uuid ) if cached_ownership: return _wrap_ownership_response(cached_ownership, error_message) track_ownership = _check_track_ownership(tuid, profile_uuid) ownership.save( ownership.ENTITY_TYPE_TRACK, tuid, profile_type, profile_uuid, track_ownership, ) return _wrap_ownership_response({"ownership": track_ownership}, error_message) def _check_track_ownership(tuid: int, profile_uuid: str) -> bool: try: ows_track.check_profile_track_access(profile_uuid, tuid) return True except HTTPError as e: if e.response.status_code == 403: return False raise def get_asset_product_owner(filename: str) -> dict[str, Any]: """Get the owner of an asset by its filename. Looks up the asset's product id and retrieves the owner information from ows-product. Args: filename (str): Asset filename (with or without extension). Returns: dict: Ownership data. """ asset = asset_upload_logic.get_asset_upload_by_filename(filename) product_id = asset.get("product_id") if not product_id: raise ProductNotFound(error.ERROR_RELEASE_NOT_FOUND) product = ows_product.get_product_by_id(product_id) product_vendor_id = product["vendor_id"] product_subaccount_id = product["subaccount_id"] return { "vendor_id": int(product_vendor_id or 0), "subaccount_id": int(product_subaccount_id or 0), }