convert to an abstract class. improve logging and qc
This commit is contained in:
parent
4714f46d03
commit
bab30abe34
@ -26,7 +26,7 @@ include this repo in your project's requiremets.txt, or install it from the comm
|
|||||||
ADDL_INSTALLED_APPS:
|
ADDL_INSTALLED_APPS:
|
||||||
- "wp_oauth_backend"
|
- "wp_oauth_backend"
|
||||||
THIRD_PARTY_AUTH_BACKENDS:
|
THIRD_PARTY_AUTH_BACKENDS:
|
||||||
- "wp_oauth_backend.wp_oauth.WPOAuth2"
|
- "wp_oauth_backend.wp_oauth.StepwiseMathOAuth2"
|
||||||
ENABLE_REQUIRE_THIRD_PARTY_AUTH: true
|
ENABLE_REQUIRE_THIRD_PARTY_AUTH: true
|
||||||
|
|
||||||
add these settings to django.conf:
|
add these settings to django.conf:
|
||||||
|
4
setup.py
4
setup.py
@ -61,8 +61,8 @@ VERSION = ABOUT["__version__"]
|
|||||||
setup(
|
setup(
|
||||||
name='wp-oauth-backend',
|
name='wp-oauth-backend',
|
||||||
version=VERSION,
|
version=VERSION,
|
||||||
description=('An OAuth backend for the WP OAuth Plugin, '
|
description=('An OAuth backend for the WP OAuth Wordpress Plugin, '
|
||||||
'mostly used for Open edX but can be used elsewhere.'),
|
'that is customized for use in Open edX installations.'),
|
||||||
long_description=README,
|
long_description=README,
|
||||||
author='Lawrence McDaniel, lpm0073@gmail.com',
|
author='Lawrence McDaniel, lpm0073@gmail.com',
|
||||||
author_email='lpm0073@gmail.com',
|
author_email='lpm0073@gmail.com',
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
|
"""
|
||||||
|
written by: Lawrence McDaniel
|
||||||
|
https://lawrencemcdaniel.com
|
||||||
|
|
||||||
|
date: oct-2022
|
||||||
|
|
||||||
|
usage: Abstract class implementation of BaseOAuth2 to handle the field
|
||||||
|
mapping and data converstions between the dict that WP Oauth
|
||||||
|
returns versus the dict that Open edX actually needs.
|
||||||
|
"""
|
||||||
|
from abc import abstractmethod
|
||||||
import json
|
import json
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
@ -6,17 +17,27 @@ from social_core.backends.oauth import BaseOAuth2
|
|||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
logger = getLogger(__name__)
|
logger = getLogger(__name__)
|
||||||
|
|
||||||
|
VERBOSE_LOGGING = True
|
||||||
class WPOAuth2(BaseOAuth2):
|
class WPOpenedxOAuth2AbstractClass(BaseOAuth2):
|
||||||
"""WP OAuth authentication backend"""
|
"""
|
||||||
|
WP OAuth authentication backend customized for Open edX
|
||||||
name = 'wp-oauth'
|
"""
|
||||||
|
|
||||||
# https://python-social-auth.readthedocs.io/en/latest/configuration/settings.html
|
# https://python-social-auth.readthedocs.io/en/latest/configuration/settings.html
|
||||||
SOCIAL_AUTH_SANITIZE_REDIRECTS = True # for redirect domain to exactly match the initiating domain.
|
SOCIAL_AUTH_SANITIZE_REDIRECTS = True # requires redirect domain to match the original initiating domain.
|
||||||
ACCESS_TOKEN_METHOD = 'POST'
|
ACCESS_TOKEN_METHOD = 'POST'
|
||||||
SCOPE_SEPARATOR = ','
|
|
||||||
BASE_URL = "https://stepwisemath.ai"
|
@abstractmethod
|
||||||
|
def name(self):
|
||||||
|
raise NotImplementedError("Subclasses should implement this property.")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def BASE_URL(self):
|
||||||
|
raise NotImplementedError("Subclasses should implement this property.")
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def SCOPE_SEPARATOR(self):
|
||||||
|
raise NotImplementedError("Subclasses should implement this property.")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def base_url(self) -> str:
|
def base_url(self) -> str:
|
||||||
@ -51,6 +72,20 @@ class WPOAuth2(BaseOAuth2):
|
|||||||
def get_user_details(self, response) -> dict:
|
def get_user_details(self, response) -> dict:
|
||||||
"""Return user details from the WP account"""
|
"""Return user details from the WP account"""
|
||||||
|
|
||||||
|
if type(response)==dict:
|
||||||
|
if ('ID' not in response.keys()) or ('user_email' not in response.keys()):
|
||||||
|
logger.info('get_user_details() - response object lacks required keys. exiting.')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
if VERBOSE_LOGGING:
|
||||||
|
if not response:
|
||||||
|
logger.info('get_user_details() - response is missing. exiting.')
|
||||||
|
return {}
|
||||||
|
|
||||||
|
logger.info('get_user_details() - start. response: {response}'.format(
|
||||||
|
response=json.dumps(response, sort_keys=True, indent=4)
|
||||||
|
))
|
||||||
|
|
||||||
# try to parse out the first and last names
|
# try to parse out the first and last names
|
||||||
split_name = response.get('display_name', '').split()
|
split_name = response.get('display_name', '').split()
|
||||||
first_name = split_name[0] if len(split_name) > 0 else ''
|
first_name = split_name[0] if len(split_name) > 0 else ''
|
||||||
@ -59,9 +94,10 @@ class WPOAuth2(BaseOAuth2):
|
|||||||
# check for superuser / staff status
|
# check for superuser / staff status
|
||||||
user_roles = response.get('user_roles', [])
|
user_roles = response.get('user_roles', [])
|
||||||
super_user = 'administrator' in user_roles
|
super_user = 'administrator' in user_roles
|
||||||
|
is_staff = 'administrator' in user_roles
|
||||||
|
|
||||||
user_details = {
|
user_details = {
|
||||||
'id': int(response.get('ID')),
|
'id': int(response.get('ID'), 0),
|
||||||
'username': response.get('user_email', ''),
|
'username': response.get('user_email', ''),
|
||||||
'wp_username': response.get('user_login', ''),
|
'wp_username': response.get('user_login', ''),
|
||||||
'email': response.get('user_email', ''),
|
'email': response.get('user_email', ''),
|
||||||
@ -69,16 +105,17 @@ class WPOAuth2(BaseOAuth2):
|
|||||||
'last_name': last_name,
|
'last_name': last_name,
|
||||||
'fullname': response.get('display_name', ''),
|
'fullname': response.get('display_name', ''),
|
||||||
'is_superuser': super_user,
|
'is_superuser': super_user,
|
||||||
'is_staff': super_user,
|
'is_staff': is_staff,
|
||||||
'refresh_token': response.get('refresh_token', ''),
|
'refresh_token': response.get('refresh_token', ''),
|
||||||
'scope': response.get('scope'),
|
'scope': response.get('scope', ''),
|
||||||
'token_type': response.get('token_type', ''),
|
'token_type': response.get('token_type', ''),
|
||||||
'date_joined': response.get('user_registered', ''),
|
'date_joined': response.get('user_registered', ''),
|
||||||
'user_status': response.get('user_status', ''),
|
'user_status': response.get('user_status', ''),
|
||||||
}
|
}
|
||||||
logger.info('get_user_details() - user_details: {user_details}'.format(
|
if VERBOSE_LOGGING:
|
||||||
user_details=json.dumps(user_details, sort_keys=True, indent=4)
|
logger.info('get_user_details() - complete. user_details: {user_details}'.format(
|
||||||
))
|
user_details=json.dumps(user_details, sort_keys=True, indent=4)
|
||||||
|
))
|
||||||
return user_details
|
return user_details
|
||||||
|
|
||||||
def user_data(self, access_token, *args, **kwargs) -> dict:
|
def user_data(self, access_token, *args, **kwargs) -> dict:
|
||||||
@ -88,24 +125,39 @@ class WPOAuth2(BaseOAuth2):
|
|||||||
'access_token': access_token
|
'access_token': access_token
|
||||||
})
|
})
|
||||||
|
|
||||||
logger.info("user_data() url: {url}".format(url=url))
|
if VERBOSE_LOGGING:
|
||||||
|
logger.info("user_data() url: {url}".format(url=url))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = json.loads(self.urlopen(url))
|
response = json.loads(self.urlopen(url))
|
||||||
logger.info('user_data() - response: {response}'.format(
|
|
||||||
response=json.dumps(response, sort_keys=True, indent=4)
|
|
||||||
))
|
|
||||||
user_details = self.get_user_details(response)
|
user_details = self.get_user_details(response)
|
||||||
return user_details
|
return user_details
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.error('user_data() did not work: {err}'.format(err=e))
|
logger.error('user_data() did not work: {err}'.format(err=e))
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
# utility function. not part of psa.
|
||||||
def urlopen(self, url):
|
def urlopen(self, url):
|
||||||
return urlopen(url).read().decode("utf-8")
|
return urlopen(url).read().decode("utf-8")
|
||||||
|
|
||||||
# def get_user_id(self, details, response):
|
class StepwiseMathOAuth2 (WPOpenedxOAuth2AbstractClass):
|
||||||
# return details['id']
|
|
||||||
|
|
||||||
# def get_username(self, strategy, details, backend, user=None, *args, **kwargs):
|
# This is the string value that will appear in the LMS Django Admin
|
||||||
# return details['username']
|
# Third Party Authentication / Provider Configuration (OAuth)
|
||||||
|
# setup page drop-down box titled, "Backend name:", just above
|
||||||
|
# the "Client ID:" and "Client Secret:" fields.
|
||||||
|
def name(self):
|
||||||
|
return 'wp-oauth'
|
||||||
|
|
||||||
|
# note: no slash at the end of the base url. Python Social Auth
|
||||||
|
# might clean this up for you, but i'm not 100% certain of that.
|
||||||
|
def BASE_URL(self):
|
||||||
|
return "https://stepwisemath.ai"
|
||||||
|
|
||||||
|
# the value of the scope separator is user-defined. Check the
|
||||||
|
# scopes field value for your oauth client in your wordpress host.
|
||||||
|
# the wp-oauth default value for scopes is 'basic' but can be
|
||||||
|
# changed to a list. example 'basic, email, profile'. This
|
||||||
|
# list can be delimited with commas, spaces, whatever.
|
||||||
|
def SCOPE_SEPARATOR(self):
|
||||||
|
return ","
|
||||||
|
Loading…
Reference in New Issue
Block a user