src.offers.offer_service
Offer service for creating and retrieving credential offers.
1"""Offer service for creating and retrieving credential offers.""" 2 3import uuid 4 5from src.access_control.access_control_port import AccessControlPort 6from src.offers.models import Offer 7from src.offers.offers_client_port import OffersClientPort 8from src.offers.offers_repository_port import OffersRepositoryPort 9 10 11class PermissionDeniedError(Exception): 12 """Raised when access control denies the requested action.""" 13 14class DoesNotExistInRepositoryError(Exception): 15 """Raised when offer cannot be found in Repository""" 16 17class DoesNotExistInClientError(Exception): 18 """Raised when offer cannot be found in API""" 19 20class OfferService: 21 """Service that orchestrates offer creation.""" 22 23 _access_control: AccessControlPort 24 _offers_client: OffersClientPort 25 _offers_repository: OffersRepositoryPort 26 27 def __init__( 28 self, 29 access_control: AccessControlPort, 30 offers_client: OffersClientPort, 31 offers_repository: OffersRepositoryPort, 32 ) -> None: 33 """Initialise the service with its dependencies. 34 35 Args: 36 access_control: Adapter for checking resource permissions. 37 offers_repository: Adapter for persisting offers. 38 offers_client: Adapter for interacting with oid4vci agent. 39 public_url: Publicly accessible base URL of this issuer service, 40 used to build the offer URI. 41 """ 42 self._access_control = access_control 43 self._offers_client = offers_client 44 self._offers_repository = offers_repository 45 46 def create_offer(self, award_id: str, bearer_token: str) -> Offer: 47 """Create, persist, and return a new credential offer. 48 49 Args: 50 award_id: The award/achievement to issue. 51 bearer_token: The caller's bearer token used for permission checking. 52 53 Returns: 54 The newly created Offer. 55 56 Raises: 57 PermissionDeniedError: When the caller is not permitted to import the award. 58 """ 59 if not self._access_control.may_import( 60 bearer_token, award_id, "Award", "import" 61 ): 62 raise PermissionDeniedError(award_id) 63 64 offer_id = str(uuid.uuid4()) 65 # award: Award = Award() # TODO: Get the actual award from where? 66 67 # TODO: wrap in transaction 68 uri = self._offers_client.create(offer_id) 69 offer = Offer( 70 offer_id = offer_id, 71 award_id = award_id, 72 uri = uri 73 ) 74 self._offers_repository.store(offer) 75 76 return offer 77 78 79 def get_offer(self, offer_id: str) -> Offer: 80 """Retrieve an offer by its identifier. 81 82 Args: 83 offer_id: The unique offer identifier. 84 85 Returns: 86 The matching Offer. 87 88 Raises: 89 KeyError: When no offer with the given id exists. 90 """ 91 92 upstream_offer = self._offers_client.get(offer_id) 93 stored_offer = self._offers_repository.get(offer_id) 94 return Offer( 95 offer_id = offer_id, 96 award_id = stored_offer.award_id, 97 uri = upstream_offer.uri, 98 )
12class PermissionDeniedError(Exception): 13 """Raised when access control denies the requested action."""
Raised when access control denies the requested action.
15class DoesNotExistInRepositoryError(Exception): 16 """Raised when offer cannot be found in Repository"""
Raised when offer cannot be found in Repository
Raised when offer cannot be found in API
21class OfferService: 22 """Service that orchestrates offer creation.""" 23 24 _access_control: AccessControlPort 25 _offers_client: OffersClientPort 26 _offers_repository: OffersRepositoryPort 27 28 def __init__( 29 self, 30 access_control: AccessControlPort, 31 offers_client: OffersClientPort, 32 offers_repository: OffersRepositoryPort, 33 ) -> None: 34 """Initialise the service with its dependencies. 35 36 Args: 37 access_control: Adapter for checking resource permissions. 38 offers_repository: Adapter for persisting offers. 39 offers_client: Adapter for interacting with oid4vci agent. 40 public_url: Publicly accessible base URL of this issuer service, 41 used to build the offer URI. 42 """ 43 self._access_control = access_control 44 self._offers_client = offers_client 45 self._offers_repository = offers_repository 46 47 def create_offer(self, award_id: str, bearer_token: str) -> Offer: 48 """Create, persist, and return a new credential offer. 49 50 Args: 51 award_id: The award/achievement to issue. 52 bearer_token: The caller's bearer token used for permission checking. 53 54 Returns: 55 The newly created Offer. 56 57 Raises: 58 PermissionDeniedError: When the caller is not permitted to import the award. 59 """ 60 if not self._access_control.may_import( 61 bearer_token, award_id, "Award", "import" 62 ): 63 raise PermissionDeniedError(award_id) 64 65 offer_id = str(uuid.uuid4()) 66 # award: Award = Award() # TODO: Get the actual award from where? 67 68 # TODO: wrap in transaction 69 uri = self._offers_client.create(offer_id) 70 offer = Offer( 71 offer_id = offer_id, 72 award_id = award_id, 73 uri = uri 74 ) 75 self._offers_repository.store(offer) 76 77 return offer 78 79 80 def get_offer(self, offer_id: str) -> Offer: 81 """Retrieve an offer by its identifier. 82 83 Args: 84 offer_id: The unique offer identifier. 85 86 Returns: 87 The matching Offer. 88 89 Raises: 90 KeyError: When no offer with the given id exists. 91 """ 92 93 upstream_offer = self._offers_client.get(offer_id) 94 stored_offer = self._offers_repository.get(offer_id) 95 return Offer( 96 offer_id = offer_id, 97 award_id = stored_offer.award_id, 98 uri = upstream_offer.uri, 99 )
Service that orchestrates offer creation.
28 def __init__( 29 self, 30 access_control: AccessControlPort, 31 offers_client: OffersClientPort, 32 offers_repository: OffersRepositoryPort, 33 ) -> None: 34 """Initialise the service with its dependencies. 35 36 Args: 37 access_control: Adapter for checking resource permissions. 38 offers_repository: Adapter for persisting offers. 39 offers_client: Adapter for interacting with oid4vci agent. 40 public_url: Publicly accessible base URL of this issuer service, 41 used to build the offer URI. 42 """ 43 self._access_control = access_control 44 self._offers_client = offers_client 45 self._offers_repository = offers_repository
Initialise the service with its dependencies.
Args: access_control: Adapter for checking resource permissions. offers_repository: Adapter for persisting offers. offers_client: Adapter for interacting with oid4vci agent. public_url: Publicly accessible base URL of this issuer service, used to build the offer URI.
47 def create_offer(self, award_id: str, bearer_token: str) -> Offer: 48 """Create, persist, and return a new credential offer. 49 50 Args: 51 award_id: The award/achievement to issue. 52 bearer_token: The caller's bearer token used for permission checking. 53 54 Returns: 55 The newly created Offer. 56 57 Raises: 58 PermissionDeniedError: When the caller is not permitted to import the award. 59 """ 60 if not self._access_control.may_import( 61 bearer_token, award_id, "Award", "import" 62 ): 63 raise PermissionDeniedError(award_id) 64 65 offer_id = str(uuid.uuid4()) 66 # award: Award = Award() # TODO: Get the actual award from where? 67 68 # TODO: wrap in transaction 69 uri = self._offers_client.create(offer_id) 70 offer = Offer( 71 offer_id = offer_id, 72 award_id = award_id, 73 uri = uri 74 ) 75 self._offers_repository.store(offer) 76 77 return offer
Create, persist, and return a new credential offer.
Args: award_id: The award/achievement to issue. bearer_token: The caller's bearer token used for permission checking.
Returns: The newly created Offer.
Raises: PermissionDeniedError: When the caller is not permitted to import the award.
80 def get_offer(self, offer_id: str) -> Offer: 81 """Retrieve an offer by its identifier. 82 83 Args: 84 offer_id: The unique offer identifier. 85 86 Returns: 87 The matching Offer. 88 89 Raises: 90 KeyError: When no offer with the given id exists. 91 """ 92 93 upstream_offer = self._offers_client.get(offer_id) 94 stored_offer = self._offers_repository.get(offer_id) 95 return Offer( 96 offer_id = offer_id, 97 award_id = stored_offer.award_id, 98 uri = upstream_offer.uri, 99 )
Retrieve an offer by its identifier.
Args: offer_id: The unique offer identifier.
Returns: The matching Offer.
Raises: KeyError: When no offer with the given id exists.