Beispiel #1
0
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, "*****@*****.**")
Beispiel #2
0
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, "*****@*****.**")
Beispiel #3
0
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
Beispiel #4
0
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}
Beispiel #5
0
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)
Beispiel #6
0
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)
Beispiel #7
0
 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 = "/"
Beispiel #8
0
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}
Beispiel #9
0
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}
Beispiel #10
0
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}
Beispiel #11
0
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}
Beispiel #12
0
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)