documentation
This commit is contained in:
		@@ -4,11 +4,11 @@ written by:     Lawrence McDaniel
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
date:           oct-2022
 | 
					date:           oct-2022
 | 
				
			||||||
 | 
					
 | 
				
			||||||
usage:          Abstract class implementation of BaseOAuth2 to handle the field 
 | 
					usage:          subclass of BaseOAuth2 Third Party Authtencation client to 
 | 
				
			||||||
                mapping and data converstions between the dict that WP Oauth 
 | 
					                handle the field mapping and data conversions between 
 | 
				
			||||||
                returns versus the dict that Open edX actually needs.
 | 
					                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
 | 
				
			||||||
@@ -20,85 +20,90 @@ logger = getLogger(__name__)
 | 
				
			|||||||
VERBOSE_LOGGING = True
 | 
					VERBOSE_LOGGING = True
 | 
				
			||||||
class StepwiseMathWPOAuth2(BaseOAuth2):
 | 
					class StepwiseMathWPOAuth2(BaseOAuth2):
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    WP OAuth authentication backend customized for Open edX
 | 
					    WP OAuth authentication backend customized for Open edX.
 | 
				
			||||||
 | 
					    see https://python-social-auth.readthedocs.io/en/latest/backends/implementation.html
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    # private utility function. not part of psa.
 | 
					 | 
				
			||||||
    def _urlopen(self, url):
 | 
					 | 
				
			||||||
        return urlopen(url).read().decode("utf-8")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # https://python-social-auth.readthedocs.io/en/latest/configuration/settings.html
 | 
					    def __init__(self, strategy, redirect_uri=None):
 | 
				
			||||||
 | 
					        super().__init__(strategy, redirect_uri)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					        if VERBOSE_LOGGING:
 | 
				
			||||||
    def ACCESS_TOKEN_METHOD(self):
 | 
					            logger.info('StepwiseMathWPOAuth2() -  ready.')
 | 
				
			||||||
        return 'POST'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # require redirect domain to match the original initiating domain.
 | 
					 | 
				
			||||||
    @property
 | 
					 | 
				
			||||||
    def SOCIAL_AUTH_SANITIZE_REDIRECTS(self):
 | 
					 | 
				
			||||||
        return True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # This defines the backend name and identifies it during the auth process. 
 | 
				
			||||||
 | 
					    # The name is used in the URLs /login/<backend name> and /complete/<backend name>.
 | 
				
			||||||
 | 
					    #
 | 
				
			||||||
    # This is the string value that will appear in the LMS Django Admin
 | 
					    # This is the string value that will appear in the LMS Django Admin
 | 
				
			||||||
    # Third Party Authentication / Provider Configuration (OAuth)
 | 
					    # Third Party Authentication / Provider Configuration (OAuth)
 | 
				
			||||||
    # setup page drop-down box titled, "Backend name:", just above
 | 
					    # setup page drop-down box titled, "Backend name:", just above
 | 
				
			||||||
    # the "Client ID:" and "Client Secret:" fields.
 | 
					    # the "Client ID:" and "Client Secret:" fields.
 | 
				
			||||||
    @property
 | 
					    name = 'stepwisemath-oauth'
 | 
				
			||||||
    def name(self):
 | 
					 | 
				
			||||||
        return 'stepwisemath-oauth'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # note: no slash at the end of the base url. Python Social Auth
 | 
					    # 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.
 | 
					    # might clean this up for you, but i'm not 100% certain of that.
 | 
				
			||||||
    @property
 | 
					    BASE_URL = "https://stepwisemath.ai"
 | 
				
			||||||
    def BASE_URL(self):
 | 
					
 | 
				
			||||||
        return "https://stepwisemath.ai"
 | 
					    # The default key name where the user identification field is defined, it’s 
 | 
				
			||||||
 | 
					    # used in the auth process when some basic user data is returned. This Id 
 | 
				
			||||||
 | 
					    # is stored in the UserSocialAuth.uid field and this, together with the 
 | 
				
			||||||
 | 
					    # UserSocialAuth.provider field, is used to uniquely identify a user association.
 | 
				
			||||||
 | 
					    ID_KEY = 'id'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Flags the backend to enforce email validation during the pipeline 
 | 
				
			||||||
 | 
					    # (if the corresponding pipeline social_core.pipeline.mail.mail_validation was enabled).
 | 
				
			||||||
 | 
					    REQUIRES_EMAIL_VALIDATION = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Some providers give nothing about the user but some basic data like the 
 | 
				
			||||||
 | 
					    # user Id or an email address. The default scope attribute is used to 
 | 
				
			||||||
 | 
					    # specify a default value for the scope argument to request those extra bits.
 | 
				
			||||||
 | 
					    DEFAULT_SCOPE = 'basic'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # Specifying the method type required to retrieve your access token if it’s 
 | 
				
			||||||
 | 
					    # not the default GET request.
 | 
				
			||||||
 | 
					    ACCESS_TOKEN_METHOD = 'POST'    
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # require redirect domain to match the original initiating domain.
 | 
				
			||||||
 | 
					    SOCIAL_AUTH_SANITIZE_REDIRECTS = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # During the auth process some basic user data is returned by the provider 
 | 
				
			||||||
 | 
					    # or retrieved by the user_data() method which usually is used to call 
 | 
				
			||||||
 | 
					    # some API on the provider to retrieve it. This data will be stored in the 
 | 
				
			||||||
 | 
					    # UserSocialAuth.extra_data attribute, but to make it accessible under some 
 | 
				
			||||||
 | 
					    # common names on different providers, this attribute defines a list of 
 | 
				
			||||||
 | 
					    # tuples in the form (name, alias) where name is the key in the user data 
 | 
				
			||||||
 | 
					    # (which should be a dict instance) and alias is the name to store it on extra_data.
 | 
				
			||||||
 | 
					    EXTRA_DATA = [
 | 
				
			||||||
 | 
					            ('id', 'id'),
 | 
				
			||||||
 | 
					            ('is_superuser', 'is_superuser'),
 | 
				
			||||||
 | 
					            ('is_staff', 'is_staff'),
 | 
				
			||||||
 | 
					            ('date_joined', 'date_joined'),
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # the value of the scope separator is user-defined. Check the 
 | 
					    # the value of the scope separator is user-defined. Check the 
 | 
				
			||||||
    # scopes field value for your oauth client in your wordpress host.
 | 
					    # scopes field value for your oauth client in your wordpress host.
 | 
				
			||||||
    # the wp-oauth default value for scopes is 'basic' but can be
 | 
					    # the wp-oauth default value for scopes is 'basic' but can be
 | 
				
			||||||
    # changed to a list. example 'basic, email, profile'. This 
 | 
					    # changed to a list. example 'basic, email, profile'. This 
 | 
				
			||||||
    # list can be delimited with commas, spaces, whatever.
 | 
					    # list can be delimited with commas, spaces, whatever.
 | 
				
			||||||
    @property
 | 
					    SCOPE_SEPARATOR = " "
 | 
				
			||||||
    def SCOPE_SEPARATOR(self):
 | 
					 | 
				
			||||||
        return ","
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    # private utility function. not part of psa.
 | 
				
			||||||
    def base_url(self) -> str:
 | 
					    def _urlopen(self, url):
 | 
				
			||||||
        return self.BASE_URL
 | 
					        return urlopen(url).read().decode("utf-8")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # override AUTHORIZATION_URL in parent class
 | 
					    # override Python Social Auth default end points
 | 
				
			||||||
    # see https://wp-oauth.com/docs/general/endpoints/
 | 
					    # see https://wp-oauth.com/docs/general/endpoints/
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def AUTHORIZATION_URL(self) -> str:
 | 
					    def AUTHORIZATION_URL(self) -> str:
 | 
				
			||||||
        return f"{self.base_url}/oauth/authorize"
 | 
					        return f"{self.BASE_URL}/oauth/authorize"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # overrides ACCESS_TOKEN_URL from parent class
 | 
					 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    # see https://wp-oauth.com/docs/general/endpoints/
 | 
					 | 
				
			||||||
    def ACCESS_TOKEN_URL(self) -> str:
 | 
					    def ACCESS_TOKEN_URL(self) -> str:
 | 
				
			||||||
        return f"{self.base_url}/oauth/token"
 | 
					        return f"{self.BASE_URL}/oauth/token"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # overrides USER_QUERY from parent class
 | 
					 | 
				
			||||||
    # see https://wp-oauth.com/docs/general/endpoints/
 | 
					 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def USER_QUERY(self) -> str:
 | 
					    def USER_QUERY(self) -> str:
 | 
				
			||||||
        return f"{self.base_url}/oauth/me"
 | 
					        return f"{self.BASE_URL}/oauth/me"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # overrides EXTRA_DATA from parent class
 | 
					 | 
				
			||||||
    # see https://python-social-auth.readthedocs.io/en/latest/backends/implementation.html
 | 
					 | 
				
			||||||
    @property
 | 
					 | 
				
			||||||
    def EXTRA_DATA(self) -> list:
 | 
					 | 
				
			||||||
        return [
 | 
					 | 
				
			||||||
            ('id', 'id'),
 | 
					 | 
				
			||||||
            ('username', 'username'),
 | 
					 | 
				
			||||||
            ('email', 'email'),
 | 
					 | 
				
			||||||
            ('first_name', 'first_name'),
 | 
					 | 
				
			||||||
            ('last_name', 'last_name'),
 | 
					 | 
				
			||||||
            ('fullname', 'fullname'),
 | 
					 | 
				
			||||||
            ('is_superuser', 'is_superuser'),
 | 
					 | 
				
			||||||
            ('is_staff', 'is_staff'),
 | 
					 | 
				
			||||||
            ('date_joined', 'date_joined'),
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # implementation of get_user_details()
 | 
					 | 
				
			||||||
    # see https://python-social-auth.readthedocs.io/en/latest/backends/implementation.html
 | 
					    # see https://python-social-auth.readthedocs.io/en/latest/backends/implementation.html
 | 
				
			||||||
    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"""
 | 
				
			||||||
@@ -169,6 +174,5 @@ class StepwiseMathWPOAuth2(BaseOAuth2):
 | 
				
			|||||||
            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() {err}'.format(err=e))
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user