class TestSocialSignup(TestCase): 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 test_custom_create_user_pipeline(self): Team.objects.create(signup_token='faketoken') details = { 'username': '******', 'email': '*****@*****.**', 'fullname': 'bob bob', 'first_name': 'bob', 'last_name': 'bob' } # try to create user without a signup token result = social_create_user(self.strategy, details, self.backend) count = User.objects.count() self.assertEqual(count, 0) # try to create user without a wrong/unassociated token self.strategy.session_set('signup_token', 'wrongtoken') result = social_create_user(self.strategy, details, self.backend) count = User.objects.count() self.assertEqual(count, 0) # create user self.strategy.session_set('signup_token', 'faketoken') result = social_create_user(self.strategy, details, self.backend) user = User.objects.get() self.assertEqual(result['is_new'], True) self.assertEqual(user.email, "*****@*****.**")
class TestSocialSignup(TestCase): 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 test_custom_create_user_pipeline(self): Team.objects.create(signup_token="faketoken") details = { "username": "******", "email": "*****@*****.**", "fullname": "bob bob", "first_name": "bob", "last_name": "bob", } # try to create user without a signup token result = social_create_user(self.strategy, details, self.backend) count = User.objects.count() self.assertEqual(count, 0) # try to create user without a wrong/unassociated token self.strategy.session_set("signup_token", "wrongtoken") result = social_create_user(self.strategy, details, self.backend) count = User.objects.count() self.assertEqual(count, 0) # create user self.strategy.session_set("signup_token", "faketoken") result = social_create_user(self.strategy, details, self.backend) user = User.objects.get() self.assertEqual(result["is_new"], True) self.assertEqual(user.email, "*****@*****.**")
def process_social_invite_signup( strategy: DjangoStrategy, invite_id: str, email: str, full_name: str ) -> Union[HttpResponse, User]: try: invite: Union[OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: return redirect(f"/signup/{invite_id}?error_code=invalid_invite&source=social_create_user") try: invite.validate(user=None, email=email) except exceptions.ValidationError as e: return redirect( f"/signup/{invite_id}?error_code={e.get_codes()[0]}&error_detail={e.args[0]}&source=social_create_user" ) try: user = strategy.create_user(email=email, first_name=full_name, password=None) except Exception as e: capture_exception(e) message = "Account unable to be created. This account may already exist. Please try again" " or use different credentials." return redirect(f"/signup/{invite_id}?error_code=unknown&error_detail={message}&source=social_create_user") invite.use(user, prevalidated=True) return user
def social_create_user(strategy: DjangoStrategy, details, backend, user=None, *args, **kwargs): if user: return {"is_new": False} user_email = details["email"][0] if isinstance(details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: company_name = strategy.session_get("company_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not company_name or email_opt_in is None: return redirect(finish_social_signup) _, _, user = User.objects.bootstrap( company_name=company_name, first_name=user_name, email=user_email, email_opt_in=email_opt_in, password=None ) else: from_invite = True try: invite: Union[OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization" ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: processed = render_to_string("auth_error.html", {"message": "Invalid invite link!"},) return HttpResponse(processed, status=401) try: invite.validate(user=None, email=user_email) except ValueError as e: processed = render_to_string("auth_error.html", {"message": str(e)},) return HttpResponse(processed, status=401) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) processed = render_to_string( "auth_error.html", { "message": "Account unable to be created. This account may already exist. Please try again or use different credentials!" }, ) return HttpResponse(processed, status=401) invite.use(user, prevalidated=True) posthoganalytics.capture( user.distinct_id, "user signed up", properties={ "is_first_user": User.objects.count() == 1, "is_first_team_user": not from_invite, "login_provider": backend.name, }, ) return {"is_new": True, "user": user}
def auth(request, provider): redirect_uri = reverse("social:complete", args=(provider, )) request.social_strategy = DjangoStrategy(DjangoStorage, request) try: backend_cls = get_backend(BACKENDS, provider) backend_obj = backend_cls(request.social_strategy, redirect_uri) except MissingBackend: raise Http404('Backend not found') return do_auth(backend_obj, redirect_name=REDIRECT_FIELD_NAME)
def disconnect(request, provider, association_id=None): request.social_strategy = DjangoStrategy(DjangoStorage, request) try: backend_cls = get_backend(BACKENDS, provider) backend_obj = backend_cls(request.social_strategy, "") except MissingBackend: raise Http404('Backend not found') return do_disconnect(backend_obj, request.user, association_id, redirect_name=REDIRECT_FIELD_NAME)
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 social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} user_email = details["email"][0] if isinstance( details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: organization_name = strategy.session_get("organization_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not organization_name or email_opt_in is None: return redirect(finish_social_signup) serializer = OrganizationSignupSerializer( data={ "organization_name": organization_name, "email_opt_in": email_opt_in, "first_name": user_name, "email": user_email, "password": None, }, context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() else: from_invite = True try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: return redirect( f"/signup/{invite_id}?error_code=invalid_invite&source=social_create_user" ) try: invite.validate(user=None, email=user_email) except exceptions.ValidationError as e: return redirect( f"/signup/{invite_id}?error_code={e.get_codes()[0]}&error_detail={e.args[0]}&source=social_create_user" ) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) message = "Account unable to be created. This account may already exist. Please try again" " or use different credentials." return redirect( f"/signup/{invite_id}?error_code=unknown&error_detail={message}&source=social_create_user" ) invite.use(user, prevalidated=True) report_user_signed_up( distinct_id=user.distinct_id, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor="social_create_user", social_provider=backend.name, ) return {"is_new": True, "user": user}
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} backend_processor = "social_create_user" user_email = details["email"][0] if isinstance(details["email"], (list, tuple)) else details["email"] user_name = ( details["fullname"] or f"{details['first_name'] or ''} {details['last_name'] or ''}".strip() or details["username"] ) strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not user_email or not user_name: missing_attr = "email" if not user_email else "name" raise ValidationError( {missing_attr: "This field is required and was not provided by the IdP."}, code="required" ) if invite_id: from_invite = True user = process_social_invite_signup(strategy, invite_id, user_email, user_name) else: # Domain whitelist? user = process_social_domain_whitelist_signup(user_email, user_name) if user: backend_processor = "domain_whitelist" # SAML if not user: user = process_social_saml_signup(backend, user_email, user_name) if user: backend_processor = "saml" if not user: organization_name = strategy.session_get("organization_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not organization_name or email_opt_in is None: return redirect(finish_social_signup) serializer = SignupSerializer( data={ "organization_name": organization_name, "email_opt_in": email_opt_in, "first_name": user_name, "email": user_email, "password": None, }, context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() report_user_signed_up( user, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor=backend_processor, social_provider=backend.name, user_analytics_metadata=user.get_analytics_metadata(), org_analytics_metadata=user.organization.get_analytics_metadata() if user.organization else None, ) return {"is_new": True, "user": user}
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} user_email = details["email"][0] if isinstance( details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: company_name = strategy.session_get("company_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not company_name or email_opt_in is None: return redirect(finish_social_signup) serializer = OrganizationSignupSerializer( data=dict( company_name=company_name, email_opt_in=email_opt_in, first_name=user_name, email=user_email, password=None, ), context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() else: from_invite = True try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: processed = render_to_string( "auth_error.html", {"message": "Invalid invite link!"}, ) return HttpResponse(processed, status=401) try: invite.validate(user=None, email=user_email) except ValueError as e: processed = render_to_string( "auth_error.html", {"message": str(e)}, ) return HttpResponse(processed, status=401) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) processed = render_to_string( "auth_error.html", { "message": "Account unable to be created. This account may already exist. Please try again or use different credentials!" }, ) return HttpResponse(processed, status=401) invite.use(user, prevalidated=True) report_user_signed_up( distinct_id=user.distinct_id, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor="social_create_user", social_provider=backend.name, ) return {"is_new": True, "user": user}
def social_create_user(strategy: DjangoStrategy, details, backend, request, user=None, *args, **kwargs): if user: return {"is_new": False} backend_processor = "social_create_user" user_email = details["email"][0] if isinstance( details["email"], (list, tuple)) else details["email"] user_name = details["fullname"] or details["username"] strategy.session_set("user_name", user_name) strategy.session_set("backend", backend.name) from_invite = False invite_id = strategy.session_get("invite_id") if not invite_id: domain_organization: Optional[Organization] = None # TODO: This feature is currently available only in self-hosted if not settings.MULTI_TENANCY: # Check if the user is on a whitelisted domain domain = user_email.split("@")[-1] # TODO: Handle multiple organizations with the same whitelisted domain domain_organization = Organization.objects.filter( domain_whitelist__contains=[domain]).first() if domain_organization: backend_processor = "domain_whitelist" user = User.objects.create_and_join( organization=domain_organization, email=user_email, password=None, first_name=user_name) else: organization_name = strategy.session_get("organization_name", None) email_opt_in = strategy.session_get("email_opt_in", None) if not organization_name or email_opt_in is None: return redirect(finish_social_signup) serializer = SignupSerializer( data={ "organization_name": organization_name, "email_opt_in": email_opt_in, "first_name": user_name, "email": user_email, "password": None, }, context={"request": request}, ) serializer.is_valid(raise_exception=True) user = serializer.save() else: from_invite = True try: invite: Union[ OrganizationInvite, TeamInviteSurrogate] = OrganizationInvite.objects.select_related( "organization", ).get(id=invite_id) except (OrganizationInvite.DoesNotExist, ValidationError): try: invite = TeamInviteSurrogate(invite_id) except Team.DoesNotExist: return redirect( f"/signup/{invite_id}?error_code=invalid_invite&source=social_create_user" ) try: invite.validate(user=None, email=user_email) except exceptions.ValidationError as e: return redirect( f"/signup/{invite_id}?error_code={e.get_codes()[0]}&error_detail={e.args[0]}&source=social_create_user" ) try: user = strategy.create_user(email=user_email, first_name=user_name, password=None) except Exception as e: capture_exception(e) message = "Account unable to be created. This account may already exist. Please try again" " or use different credentials." return redirect( f"/signup/{invite_id}?error_code=unknown&error_detail={message}&source=social_create_user" ) invite.use(user, prevalidated=True) report_user_signed_up( distinct_id=user.distinct_id, is_instance_first_user=User.objects.count() == 1, is_organization_first_user=not from_invite, new_onboarding_enabled=False, backend_processor=backend_processor, social_provider=backend.name, ) return {"is_new": True, "user": user}
def process_join_answer(message): invite_token = message.text try: company = Company.objects.get(invite_token=invite_token) except Company.DoesNotExist: bot.reply_to( message, _("Sorry, couldn't find lunch group with the given token. :(")) state_registry.del_state(message.from_user.id) return # Authenticate user, create if need to from_user = message.from_user try: social_auth = UserSocialAuth.objects.get(provider='telegram', uid=from_user.id) except UserSocialAuth.DoesNotExist: storage = DjangoStorage() strategy = DjangoStrategy(storage) backend = TelegramAuth(strategy) username = get_username(strategy, from_user.__dict__, backend)['username'] with transaction.atomic(): user = create_user(strategy, from_user.__dict__, backend, username=username)['user'] user.first_name = from_user.first_name or '' user.last_name = from_user.last_name or '' user.has_telegram = True user.telegram_chat_id = message.chat.id user.save() UserSocialAuth.objects.get_or_create(provider='telegram', uid=from_user.id, defaults={ 'extra_data': from_user.__dict__, 'user': user, }) else: user = social_auth.user if not user.is_active: bot.send_message(message.chat.id, _('Sorry, your account has been deactivated.')) return # Create employee and add him to the group employee, created = Employee.objects.get_or_create(company=company, user=user) if created: msg = _( "You've successfully joined lunch group «{}». " "You may manage your participation with /offline and /online commands." ).format(company.name) else: msg = _( "You've joined lunch group «{}» already. " "You may manage your participation with /offline and /online commands." ).format(company.name) bot.send_message(message.chat.id, msg)