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
|
validate that the object passed is a dict containing at least the keys
|
||||||
in qc_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']
|
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
|
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
|
return False
|
||||||
|
|
||||||
def is_wp_oauth_response(self, response) -> bool:
|
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
|
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.
|
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']
|
qc_keys = ['ID' 'display_name', 'user_email', 'user_login', 'user_roles']
|
||||||
if all(key in response for key in qc_keys): return True
|
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
|
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.
|
# override Python Social Auth default end points.
|
||||||
# see https://wp-oauth.com/docs/general/endpoints/
|
# see https://wp-oauth.com/docs/general/endpoints/
|
||||||
#
|
#
|
||||||
@ -159,6 +182,10 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
|||||||
@user_details.setter
|
@user_details.setter
|
||||||
def user_details(self, value: dict):
|
def user_details(self, value: dict):
|
||||||
if self.is_valid_user_details(value):
|
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
|
self._user_details = value
|
||||||
else:
|
else:
|
||||||
logger.error('user_details.setter: tried to pass an invalid object {value}'.format(
|
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
|
# see https://python-social-auth.readthedocs.io/en/latest/backends/implementation.html
|
||||||
# Return user details from the Wordpress user account
|
# Return user details from the Wordpress user account
|
||||||
def get_user_details(self, response) -> dict:
|
def get_user_details(self, response) -> dict:
|
||||||
tainted = False
|
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(
|
||||||
if not response:
|
response=json.dumps(response, sort_keys=True, indent=4)
|
||||||
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)
|
|
||||||
))
|
))
|
||||||
tainted = True
|
# if we have cached results then we might be able to recover.
|
||||||
else:
|
return self.user_details
|
||||||
# -------------------------------------------------------------
|
|
||||||
# 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 tainted and self.user_details:
|
if VERBOSE_LOGGING: logger.info('get_user_details() begin with response: {response}'.format(
|
||||||
logger.warning('get_user_details() - returning cached results. user_details: {user_details}'.format(
|
response=json.dumps(response, sort_keys=True, indent=4)
|
||||||
user_details=json.dumps(self.user_details, 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
|
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.')
|
# expected use case #1: response object is a dict with all required keys.
|
||||||
return None
|
# -------------------------------------------------------------
|
||||||
|
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
|
# build and internally cache the get_user_details() dict
|
||||||
@ -281,6 +295,9 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if not self.is_valid_user_details(response):
|
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
|
return self.user_details
|
||||||
|
|
||||||
# refresh our internal user_details property after having validated
|
# refresh our internal user_details property after having validated
|
||||||
|
Loading…
Reference in New Issue
Block a user