def get_username(strategy, details, backend, user=None, *args, **kwargs): """ Copy of social_core.pipeline.user.get_username with additional logging and case insensitive username checks. """ if 'username' not in backend.setting('USER_FIELDS', USER_FIELDS): return storage = strategy.storage if not user: email_as_username = strategy.setting('USERNAME_IS_FULL_EMAIL', False) uuid_length = strategy.setting('UUID_LENGTH', 16) max_length = storage.user.username_max_length() do_slugify = strategy.setting('SLUGIFY_USERNAMES', False) do_clean = strategy.setting('CLEAN_USERNAMES', True) if do_clean: override_clean = strategy.setting('CLEAN_USERNAME_FUNCTION') if override_clean: clean_func = module_member(override_clean) else: clean_func = storage.user.clean_username else: clean_func = lambda val: val if do_slugify: override_slug = strategy.setting('SLUGIFY_FUNCTION') if override_slug: slug_func = module_member(override_slug) else: slug_func = slugify else: slug_func = lambda val: val if email_as_username and details.get('email'): username = details['email'] elif details.get('username'): username = details['username'] else: username = uuid4().hex short_username = (username[:max_length - uuid_length] if max_length is not None else username) final_username = slug_func(clean_func(username[:max_length])) # Generate a unique username for current user using username # as base but adding a unique hash at the end. Original # username is cut to avoid any field max_length. # The final_username may be empty and will skip the loop. # We are using our own version of user_exists to avoid possible case sensitivity issues. while not final_username or user_exists({'username': final_username}): # These log statements are here for debugging purposes and should be removed when ENT-1500 is resolved. logger.info(u'Username %s is either empty or already in use, generating a new username!', final_username) username = short_username + uuid4().hex[:uuid_length] final_username = slug_func(clean_func(username[:max_length])) logger.info(u'Generated username %s.', final_username) else: final_username = storage.user.get_username(user) return {'username': final_username}
def send_email_validation(self, backend, email, force_update=False, partial_token=None): from social_core.utils import module_member email_validation = self.setting('EMAIL_VALIDATION_FUNCTION') send_email = module_member(email_validation) # remove all codes with this email before creating new one CustomCode.objects.filter(email=email).delete() code = self.storage.code.make_code(email) user = self.request.user # store user data in code. We will use it after confirmation email link click. fields_to_store = ('first_name', 'last_name', 'password', 'next') if force_update: # when users change their email they should be redirected to page they come from # now it is /accounts/ url post_data = self.request.POST.copy() post_data['next'] = post_data.get('next', self.request.path) self.request.POST = post_data for field in fields_to_store: f_val = self.request.POST.get(field) # hack: to not override built-in func `next` in model, it is saved under 'next_page' filedname if field == 'next': field = 'next_page' setattr( code, field, f_val ) if user and user.is_authenticated(): code.force_update = force_update code.user_id = user.id code.save() self.request.session['cc_id'] = code.id send_email(self, backend, code, partial_token) return code
def get_login_providers(request, short=False): """ Returns a list of available login providers based on the AUTHENTICATION_BACKENDS setting. Each provider is represented as a dictionary containing the backend name, name of required parameter if required and its verbose name. """ def extract_backend_data(klass): """ Helper function which extracts information useful for use in templates from SocialAuth subclasses and returns it as a dictionary. """ return { 'name': klass.name, 'required_field': klass.REQUIRED_FIELD_NAME, 'required_field_verbose': klass.REQUIRED_FIELD_VERBOSE_NAME, } backends = (module_member(auth_backend) for auth_backend in setting('AUTHENTICATION_BACKENDS')) providers = [extract_backend_data(backend) for backend in backends if issubclass(backend, BaseAuth)] if short: return providers[:setting('AUTHENTICATION_PROVIDERS_BRIEF', DEFAULT_AUTHENTICATION_PROVIDERS_BRIEF)] return providers
def setUp(self): HTTPretty.enable() Backend = module_member(self.backend_path) self.strategy = views.load_strategy() self.backend = Backend(self.strategy, redirect_uri=self.complete_url) self.name = self.backend.name.upper().replace('-', '_') self.complete_url = self.strategy.build_absolute_uri( self.raw_complete_url.format(self.backend.name) ) backends = (self.backend_path, ) load_backends(backends, force_load=True) user_data_body = json.loads(self.user_data_body) self.email = '*****@*****.**' user_data_body['email'] = self.email self.user_data_body = json.dumps(user_data_body) self.do_rest_login()
from sqlalchemy import Column, Integer, String, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.ext.declarative import declarative_base from social_core.utils import setting_name, module_member from social_sqlalchemy.storage import SQLAlchemyUserMixin, \ SQLAlchemyAssociationMixin, \ SQLAlchemyNonceMixin, \ SQLAlchemyPartialMixin, \ BaseSQLAlchemyStorage SocialBase = declarative_base() DB_SESSION_ATTR = cherrypy.config.get(setting_name('DB_SESSION_ATTR'), 'db') UID_LENGTH = cherrypy.config.get(setting_name('UID_LENGTH'), 255) User = module_member(cherrypy.config[setting_name('USER_MODEL')]) class CherryPySocialBase(object): @classmethod def _session(cls): return getattr(cherrypy.request, DB_SESSION_ATTR) class UserSocialAuth(CherryPySocialBase, SQLAlchemyUserMixin, SocialBase): """Social Auth association model""" uid = Column(String(UID_LENGTH)) user_id = Column(Integer, ForeignKey(User.id), nullable=False, index=True) user = relationship(User, backref='social_auth') @classmethod
def wrapper(request, *args, **kwargs): is_logged_in = module_member( request.backend.setting('LOGGEDIN_FUNCTION')) if not is_logged_in(request): raise HTTPForbidden('Not authorized user') return func(request, *args, **kwargs)
from django.conf import settings from django.core.urlresolvers import reverse from django.http import Http404 from social_core.utils import setting_name, module_member, get_strategy from social_core.exceptions import MissingBackend from social_core.backends.utils import get_backend BACKENDS = settings.AUTHENTICATION_BACKENDS STRATEGY = getattr(settings, setting_name('STRATEGY'), 'social_django.strategy.DjangoStrategy') STORAGE = getattr(settings, setting_name('STORAGE'), 'social_django.models.DjangoStorage') Strategy = module_member(STRATEGY) Storage = module_member(STORAGE) def load_strategy(request=None): return get_strategy(STRATEGY, STORAGE, request) def load_backend(strategy, name, redirect_uri): Backend = get_backend(BACKENDS, name) return Backend(strategy, redirect_uri) def psa(redirect_uri=None, load_strategy=load_strategy): def decorator(func): @wraps(func)
def _load_backend_classes(base_class=BaseAuth): """ Load the list of python-social-auth backend classes from Django settings """ for class_path in settings.AUTHENTICATION_BACKENDS: auth_class = module_member(class_path) if issubclass(auth_class, base_class): yield auth_class
def _get_helper(self, name, do_import=False): this_config = self.config.get(setting_name(name), DEFAULTS.get(name, None)) return do_import and module_member(this_config) or this_config
def get_username(strategy, details, backend, user=None, *args, **kwargs): # lint-amnesty, pylint: disable=keyword-arg-before-vararg """ Copy of social_core.pipeline.user.get_username to achieve 1. additional logging 2. case insensitive username checks 3. enforce same maximum and minimum length restrictions we have in `user_api/accounts` """ if 'username' not in backend.setting('USER_FIELDS', USER_FIELDS): return storage = strategy.storage if not user: email_as_username = strategy.setting('USERNAME_IS_FULL_EMAIL', False) uuid_length = strategy.setting('UUID_LENGTH', 16) min_length = strategy.setting('USERNAME_MIN_LENGTH', accounts.USERNAME_MIN_LENGTH) max_length = strategy.setting('USERNAME_MAX_LENGTH', accounts.USERNAME_MAX_LENGTH) do_slugify = strategy.setting('SLUGIFY_USERNAMES', False) do_clean = strategy.setting('CLEAN_USERNAMES', True) if do_clean: override_clean = strategy.setting('CLEAN_USERNAME_FUNCTION') if override_clean: clean_func = module_member(override_clean) else: clean_func = storage.user.clean_username else: clean_func = lambda val: val if do_slugify: override_slug = strategy.setting('SLUGIFY_FUNCTION') if override_slug: slug_func = module_member(override_slug) else: slug_func = slugify else: slug_func = lambda val: val if email_as_username and details.get('email'): username = details['email'] elif details.get('username'): username = details['username'] else: username = uuid4().hex short_username = (username[:max_length - uuid_length] if max_length is not None else username) final_username = slug_func(clean_func(username[:max_length])) # Generate a unique username for current user using username # as base but adding a unique hash at the end. Original # username is cut to avoid any field max_length. # The final_username may be empty and will skip the loop. # We are using our own version of user_exists to avoid possible case sensitivity issues. while not final_username or len(final_username) < min_length or user_exists({'username': final_username}): username = short_username + uuid4().hex[:uuid_length] final_username = slug_func(clean_func(username[:max_length])) logger.info('[THIRD_PARTY_AUTH] New username generated. Username: {username}'.format( username=final_username)) else: final_username = storage.user.get_username(user) return {'username': final_username}
from django.conf import settings from django.core.urlresolvers import reverse from django.http import Http404 from social_core.utils import setting_name, module_member, get_strategy, \ set_current_strategy_getter from social_core.exceptions import MissingBackend from social_core.backends.utils import get_backend BACKENDS = settings.AUTHENTICATION_BACKENDS STRATEGY = getattr(settings, setting_name('STRATEGY'), 'social_django.strategy.DjangoStrategy') STORAGE = getattr(settings, setting_name('STORAGE'), 'social_django.models.DjangoStorage') Strategy = module_member(STRATEGY) Storage = module_member(STORAGE) def load_strategy(request=None): return get_strategy(STRATEGY, STORAGE, request) def load_backend(strategy, name, redirect_uri): Backend = get_backend(BACKENDS, name) return Backend(strategy, redirect_uri) def psa(redirect_uri=None, load_strategy=load_strategy): def decorator(func): @wraps(func)
def _load_backend_classes(base_class=BaseAuth): """ Load the list of python-social-auth backend classes from Django settings """ for class_path in settings.AUTHENTICATION_BACKENDS: auth_class = module_member(class_path) if issubclass(auth_class, base_class): yield auth_class
def get_strategy(strategy, storage, *args, **kwargs): strategy = module_member(strategy) return strategy(request=args[0], *args, **kwargs)
def get_or_create_user(strategy, details, backend, user=None, *args, **kwargs): if 'username' not in backend.setting('USER_FIELDS', USER_FIELDS): return storage = strategy.storage if not user: email_as_username = strategy.setting('USERNAME_IS_FULL_EMAIL', False) uuid_length = strategy.setting('UUID_LENGTH', 16) max_length = storage.user.username_max_length() do_slugify = strategy.setting('SLUGIFY_USERNAMES', False) do_clean = strategy.setting('CLEAN_USERNAMES', True) if do_clean: override_clean = strategy.setting('CLEAN_USERNAME_FUNCTION') if override_clean: clean_func = module_member(override_clean) else: clean_func = storage.user.clean_username else: def f(val): return val clean_func = f if do_slugify: override_slug = strategy.setting('SLUGIFY_FUNCTION') if override_slug: slug_func = module_member(override_slug) else: slug_func = slugify else: def f(val): return val slug_func = f if email_as_username and details.get('email'): username = details['email'] elif details.get('username'): username = details['username'] else: username = uuid4().hex short_username = (username[:max_length - uuid_length] if max_length is not None else username) final_username = slug_func(clean_func(username[:max_length])) if not final_username: username = short_username + uuid4().hex[:uuid_length] final_username = slug_func(clean_func(username[:max_length])) fields = dict((name, kwargs.get(name, details.get(name))) for name in backend.setting('USER_FIELDS', USER_FIELDS)) if not fields: return user, user_created = User.objects.get_or_create( fields, username=final_username) return {'is_new': user_created, 'user': user} return {'is_new': False}
def setUp(self): super().setUp() Backend = module_member('social_core.backends.github.GithubOAuth2') self.strategy = DjangoStrategy(DjangoStorage) self.backend = Backend(self.strategy, redirect_uri='/complete/github') self.login_redirect_url = '/'
def complete(self, backend, *args, **kwargs): login = cherrypy.config.get(setting_name('LOGIN_METHOD')) do_login = module_member(login) if login else self.do_login user = getattr(cherrypy.request, 'user', None) return do_complete(self.backend, do_login, user=user, *args, **kwargs)
def get_helper(name, do_import=False): config = web.config.get(setting_name(name), DEFAULTS.get(name, None)) return do_import and module_member(config) or config
def get_helper(name, do_import=False): config = current_app.config.get(setting_name(name), DEFAULTS.get(name, None)) if do_import: config = module_member(config) return config
def _get_helper(self, name, do_import=False): this_config = self.config.get(setting_name(name), DEFAULTS.get(name, None)) return do_import and module_member(this_config) or this_config
def get_access_token(self, app, config, extra_data): handler = self.context.get('handler') request = self.context.get('request') strategy = load_strategy(handler, request, config) backend_path = config.get('backend_path') Backend = module_member(backend_path) if not issubclass(Backend, BaseAuth): return extra_data.get('access_token') backend = Backend(strategy, None) refresh_token = extra_data.get('refresh_token') or extra_data.get( 'access_token') expires_on = None params_expires_on = extra_data.get('expires_on') params_token_updated = extra_data.get('token_updated') params_expires_in = extra_data.get('expires') or extra_data.get( 'expires_in') try: if params_expires_on: expires_on = int(params_expires_on) elif params_expires_in and params_token_updated: expires_on = int(params_token_updated) + int(params_expires_in) except (ValueError, TypeError): pass try: if refresh_token and (not expires_on or expires_on <= int(time.time())): response = backend.refresh_token(token=refresh_token) if not backend.EXTRA_DATA or len(backend.EXTRA_DATA) == 0: backend.GET_ALL_EXTRA_DATA = True new_extra_data = backend.extra_data(user=None, uid=None, response=response, details={}) access_token = new_extra_data.get('access_token') new_extra_data = { 'expires_on': new_extra_data.get('expires_on'), 'access_token': new_extra_data.get('access_token'), 'expires': new_extra_data.get('expires'), 'auth_time': new_extra_data.get('auth_time'), 'refresh_token': new_extra_data.get('refresh_token'), 'token_updated': int(time.time()) } request = self.context.get('request') extra_data_key = '_'.join(['extra_data', app]) new_extra_data_str = json.dumps(new_extra_data) if settings.COOKIE_COMPRESS: new_extra_data_str = compress_data(new_extra_data_str) configuration.session_set(request, extra_data_key, new_extra_data_str, secure=not settings.COOKIE_COMPRESS) return access_token except Exception: pass return extra_data.get('access_token')