refactor how validations affect workflow. add more logging
This commit is contained in:
parent
a5f5ce6c14
commit
738886e596
@ -111,9 +111,16 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
||||
validate that the object passed is a dict containing at least the keys
|
||||
in qc_keys.
|
||||
"""
|
||||
if not type(response) == dict: return False
|
||||
if not type(response) == dict:
|
||||
logger.warning('is_valid_user_details() was expecting a dict but received an object of type: {type}'.format(
|
||||
type=type(response)
|
||||
))
|
||||
return False
|
||||
qc_keys = ['id', 'date_joined', 'email', 'first_name', 'fullname', 'is_staff', 'is_superuser', 'last_name', 'username']
|
||||
if all(key in response for key in qc_keys): return True
|
||||
logger.warning('is_valid_user_details() received an invalid response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
return False
|
||||
|
||||
def is_wp_oauth_response(self, response) -> bool:
|
||||
@ -121,11 +128,27 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
||||
validate the structure of the response object from wp-oauth. it's
|
||||
supposed to be a dict with at least the keys included in qc_keys.
|
||||
"""
|
||||
if not type(response) == dict: return False
|
||||
if not type(response) == dict:
|
||||
logger.warning('is_valid_user_details() was expecting a dict but received an object of type: {type}'.format(
|
||||
type=type(response)
|
||||
))
|
||||
return False
|
||||
qc_keys = ['ID' 'display_name', 'user_email', 'user_login', 'user_roles']
|
||||
if all(key in response for key in qc_keys): return True
|
||||
logger.warning('is_wp_oauth_response() received an invalid response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
return False
|
||||
|
||||
def is_wp_oauth_extended_response(self, response) -> bool:
|
||||
"""
|
||||
validate the structure of the extended response object from wp-oauth. it's
|
||||
supposed to be a dict with at least the keys included in qc_keys.
|
||||
"""
|
||||
if not self.is_valid_user_details(response): return False
|
||||
qc_keys = ['access_token' 'expires_in', 'refresh_token', 'scope', 'token_type']
|
||||
if all(key in response for key in qc_keys): return True
|
||||
return False
|
||||
# override Python Social Auth default end points.
|
||||
# see https://wp-oauth.com/docs/general/endpoints/
|
||||
#
|
||||
@ -159,6 +182,10 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
||||
@user_details.setter
|
||||
def user_details(self, value: dict):
|
||||
if self.is_valid_user_details(value):
|
||||
if VERBOSE_LOGGING:
|
||||
logger.info('user_details.setter: new value set {value}'.format(
|
||||
value=json.dumps(value, sort_keys=True, indent=4)
|
||||
))
|
||||
self._user_details = value
|
||||
else:
|
||||
logger.error('user_details.setter: tried to pass an invalid object {value}'.format(
|
||||
@ -168,62 +195,49 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
||||
# see https://python-social-auth.readthedocs.io/en/latest/backends/implementation.html
|
||||
# Return user details from the Wordpress user account
|
||||
def get_user_details(self, response) -> dict:
|
||||
tainted = False
|
||||
|
||||
if not response:
|
||||
logger.warning('get_user_details() - response object is missing.')
|
||||
tainted = True
|
||||
|
||||
if type(response)!=dict:
|
||||
logger.warning('get_user_details() - was expecting a response object of type dict but received an object of type {t}'.format(
|
||||
t=type(response)
|
||||
))
|
||||
tainted = True
|
||||
|
||||
if not tainted:
|
||||
# a def in the third_party_auth pipeline list calls get_user_details() after its already
|
||||
# been called once. i don't know why. but, it passes the original get_user_details() dict
|
||||
# enhanced with additional token-related keys. if we receive this modified dict then we
|
||||
# should pass it along to the next defs in the pipeline.
|
||||
#
|
||||
# If most of the original keys (see dict definition below) exist in the response object
|
||||
# then we can assume that this is our case.
|
||||
if self.is_valid_user_details(response):
|
||||
# -------------------------------------------------------------
|
||||
# expected use case #2: a potentially enhanced version of an original user_details dict.
|
||||
# -------------------------------------------------------------
|
||||
if VERBOSE_LOGGING:
|
||||
logger.info('get_user_details() - detected an enhanced get_user_details() dict in the response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
return response
|
||||
|
||||
# otherwise we pobably received the default response from the oauth provider based on
|
||||
# the scopes 'basic' 'email' 'profile'. We'll check a few of the most important keys to see
|
||||
# if they exist.
|
||||
if not self.is_wp_oauth_response(response):
|
||||
logger.warning('get_user_details() - response object is missing one or more required keys: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
if not (self.is_valid_user_details(response) or self.is_wp_oauth_response(response)):
|
||||
logger.error('get_user_details() - received an unrecognized response object. Cannot conitnue: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
tainted = True
|
||||
else:
|
||||
# -------------------------------------------------------------
|
||||
# expected use case #1: response object is a dict with all required keys.
|
||||
# -------------------------------------------------------------
|
||||
if VERBOSE_LOGGING:
|
||||
logger.info('get_user_details() - start. response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
# if we have cached results then we might be able to recover.
|
||||
return self.user_details
|
||||
|
||||
if tainted and self.user_details:
|
||||
logger.warning('get_user_details() - returning cached results. user_details: {user_details}'.format(
|
||||
user_details=json.dumps(self.user_details, sort_keys=True, indent=4)
|
||||
if VERBOSE_LOGGING: logger.info('get_user_details() begin with response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
# a def in the third_party_auth pipeline list calls get_user_details() after its already
|
||||
# been called once. i don't know why. but, it passes the original get_user_details() dict
|
||||
# enhanced with additional token-related keys. if we receive this modified dict then we
|
||||
# should pass it along to the next defs in the pipeline.
|
||||
#
|
||||
# If most of the original keys (see dict definition below) exist in the response object
|
||||
# then we can assume that this is our case.
|
||||
if self.is_wp_oauth_extended_response(response):
|
||||
# -------------------------------------------------------------
|
||||
# expected use case #2: a potentially enhanced version of an original user_details dict.
|
||||
# -------------------------------------------------------------
|
||||
if VERBOSE_LOGGING:
|
||||
logger.info('get_user_details() - detected an enhanced get_user_details() dict in the response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
return response
|
||||
|
||||
# at this point we've ruled out the possibility of the response object
|
||||
# being a derivation of a user_details dict. So, it should therefore
|
||||
# conform to the structure of a wp-oauth dict.
|
||||
if not self.is_wp_oauth_response(response):
|
||||
logger.warning('get_user_details() - response object is not a valid wp-oauth object. Cannot continue. {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
return self.user_details
|
||||
|
||||
if tainted:
|
||||
logger.error('response object is missing or misformed, and no cached results were found. Cannot get user details from oauth provider.')
|
||||
return None
|
||||
# -------------------------------------------------------------
|
||||
# expected use case #1: response object is a dict with all required keys.
|
||||
# -------------------------------------------------------------
|
||||
if VERBOSE_LOGGING:
|
||||
logger.info('get_user_details() - start. response: {response}'.format(
|
||||
response=json.dumps(response, sort_keys=True, indent=4)
|
||||
))
|
||||
|
||||
# ---------------------------------------------------------------------
|
||||
# build and internally cache the get_user_details() dict
|
||||
@ -281,6 +295,9 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
||||
return None
|
||||
|
||||
if not self.is_valid_user_details(response):
|
||||
logger.error('user_data() response object is invalid: {response}'.format(
|
||||
response=json.dumps(self.user_details, sort_keys=True, indent=4)
|
||||
))
|
||||
return self.user_details
|
||||
|
||||
# refresh our internal user_details property after having validated
|
||||
|
Loading…
Reference in New Issue
Block a user