import json
from tornado import escape
from q2_sdk.core.configuration import settings
from q2_sdk.core.http_handlers.base_handler import Q2BaseRequestHandler
from q2_sdk.hq.db.vendor_config import VendorConfig
from q2_sdk.hq.models.hq_credentials import HqCredentials
from q2_marketplace.models.marketplace import SubscriptionEvent, SubscriptionSuccess
[docs]
class ProductRequestHandler(Q2BaseRequestHandler):
"""
RequestHandler meant to be used in conjunction with the Q2Marketplace
"""
def _get_hq_creds_from_event(self, event: SubscriptionEvent) -> HqCredentials:
try:
vault_key = event.sso_user_id.split(":")[1]
except (AttributeError, IndexError):
self.logger.warning(
"Received improperly formatted user ID. Falling back on configured HQ credentials."
)
return self.hq_credentials
if not settings.TEST_MODE and settings.DEBUG:
return self.hq_credentials
return self.vault.get_hq_creds(vault_key)
async def post(self, route=None):
payload = escape.json_decode(self.request.body)
self.logger.debug("SubscriptionEvent payload: %s", payload)
subscription_event = payload.get("subscription_event")
event = SubscriptionEvent.from_json(subscription_event)
self.hq_credentials = self._get_hq_creds_from_event(event)
if route == "subscribe":
subscription_result = await self.subscribe(event)
elif route == "cancel":
subscription_result = await self.cancel(event)
elif route == "update":
subscription_result = await self.update(event)
else:
self.set_status(400, "Only subscribe, cancel, and update routes defined")
return
if subscription_result:
json_result = json.dumps(subscription_result.to_json())
self.write(json_result)
self.set_status(200)
[docs]
async def subscribe(self, subscription_event: SubscriptionEvent):
"""Invoked with a POST to /marketplace/{{Name}}/subscribe for a SUBSCRIPTION_ORDER event
:param subscription_event: Subscription Event
"""
return SubscriptionSuccess()
[docs]
async def cancel(self, subscription_event: SubscriptionEvent):
"""Invoked with a POST to /marketplace/{{Name}}/cancel for SUBSCRIPTION_CANCEL event
Note: The users subscription will always successfully cancel regardless of what value or status_code returned,
except for error code ErrorCode.DO_NOT_CANCEL.
:param subscription_event: Subscription Event
"""
return SubscriptionSuccess()
[docs]
async def update(self, subscription_event: SubscriptionEvent):
"""Invoked with a POST to /marketplace/{{Name}}/update for a SUBSCRIPTION_CHANGE event
:param subscription_event: Subscription Event
"""
return SubscriptionSuccess()
[docs]
async def get_vendor_config(self, vendor_name: str) -> dict:
"""Gets the vendor config values as a dict. Normally used by a SSO extension."""
vendor_config_obj = VendorConfig(self.logger, self.hq_credentials)
vendor_config_response = await vendor_config_obj.get(vendor_name)
config = {}
if vendor_config_response is not None:
for vendor_config in vendor_config_response:
config.update({
vendor_config.ConfigName.pyval: vendor_config.ConfigValue.pyval
})
return config