示例#1
0
    def test_post_user_list_with_existing_account(self):
        """POSTing to the user-list with username/email for an existing account
        should fail to create a new user, but should return an http 400 response.

        """
        # Generate an existing user.
        user = {
            "email": "*****@*****.**",
            "first_name": "F",
            "last_name": "L"
        }
        user['username'] = user_utils.username_hash(user['email'])
        user = self.User.objects.create(**user)

        url = reverse('user-list')
        expected_error = "This user account already exists."

        # First try to create with an existing email
        data = {'email': user.email, 'password': '******'}
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertContains(response, expected_error, status_code=400)

        # Then with an existing username
        data = {'username': user.username, 'password': '******'}
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
示例#2
0
 def _generate_username(self, data):
     """NOTE: We allow users to sign up with an email/password pair. This
     method will generate a (hopefully unique) username hash using the
     email address (the first 30 chars from an md5 hex digest).
     """
     if not data.get('username', False) and 'email' in data:
         data['username'] = user_utils.username_hash(data['email'])
     return data
示例#3
0
def create_account(request):
    """Yet another way to create an account."""
    if request.method == "POST":
        form = UserForm(request.POST)
        password_form = SetNewPasswordForm(request.POST, prefix="pw")
        if form.is_valid() and password_form.is_valid():
            User = get_user_model()
            email = form.cleaned_data['email'].strip().lower()

            try:
                # Ensure the email isn't already tied to an account
                user = User.objects.get(email__iexact=email)
                messages.info(
                    request, "It looks like you already have an "
                    "account! Log in to continue.")
                return redirect("officehours:login")
            except User.DoesNotExist:
                # Create & activate the account
                # XXX This is a hack to keep these users from getting the
                # XXX `selected_by_default` content from the `goals` app.
                # XXX We *must* set this before we craete the user, hence the
                # XXX use of the email in the key.
                _key = "omit-default-selections-{}".format(slugify(email))
                cache.set(_key, True, 30)

                user = form.save(commit=False)
                user.is_active = True
                user.username = username_hash(email)
                user.set_password(password_form.cleaned_data['password'])
                user.save()

                # Set their IP address.
                user.userprofile.ip_address = get_client_ip(request)
                user.userprofile.save()

                user = authenticate(
                    email=email,
                    password=password_form.cleaned_data['password'])
                login_user(request, user)
                return redirect("officehours:index")
        else:
            messages.error(
                request, "We could not process your request. "
                "Please see the details, below.")
    else:
        password_form = SetNewPasswordForm(prefix='pw')
        form = UserForm()

    context = {
        'form': form,
        'password_form': password_form,
    }
    return render(request, "officehours/create_account.html", context)
示例#4
0
    def validate_email(self, value):
        """Validate several things, given a user's email:

        * this is a valid email address
        * there are no existing users with this email
        * there are no users with a username hashed from this email

        """
        User = get_user_model()
        criteria = (Q(email=value) | Q(username=user_utils.username_hash(value)))
        if not self.partial and User.objects.filter(criteria).exists():
            raise serializers.ValidationError("This user account already exists.")
        validators.validate_email(value)
        return value
示例#5
0
    def test_post_oauth_create_when_authenticated(self):
        """Authenticated POSTs should return the user's data."""
        # Create a test user.
        User = get_user_model()
        email = '*****@*****.**'
        user = User.objects.create(username=username_hash(email), email=email)
        profile = UserProfile.objects.get(user=user)
        profile.google_token = "A-TOKEN-STRING"
        profile.save()

        url = self.get_url("user-oauth")
        payload = {
            'email': email,
            'first_name': 'Existing',
            'last_name': 'User',
            'image_url': 'http://example.com/avatar.jpg',
            'oauth_token': 'A-TOKEN-STRING',
        }

        with patch('userprofile.api.verify_token') as mock_verify:
            mock_verify.return_value = 'A-TOKEN-STRING'
            response = self.client.post(url, payload)

        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(response.data['email'], '*****@*****.**')
        # No data was updated, we're only returning existing info.
        self.assertEqual(response.data['first_name'], 'Existing')
        self.assertEqual(response.data['last_name'], 'User')
        self.assertEqual(response.data['google_image'],
                         'http://example.com/avatar.jpg')
        self.assertEqual(response.data['google_token'], 'A-TOKEN-STRING')
        self.assertEqual(response.data['token'], user.auth_token.key)

        # Clean up
        profile.delete()
        user.delete()
示例#6
0
    def test_post_user_list_with_existing_account_email_as_username(self):
        """POSTing to the user-list with the email address for an existing account
        (even if provided as the username) should fail to create a new user,
        but should return an http 400 response.

        """
        # Generate an existing user.
        user = {
            "email": "*****@*****.**",
            "first_name": "F",
            "last_name": "L"
        }
        user['username'] = user_utils.username_hash(user['email'])
        user = self.User.objects.create(**user)

        url = self.get_url('user-list')
        expected_error = "This user account already exists."

        # First try to create this account, but include the email in the
        # username field.
        data = {'username': user.email, 'password': '******'}
        response = self.client.post(url, data)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertContains(response, expected_error, status_code=400)
示例#7
0
    def oauth_create(self, request, pk=None):
        """GET: List the current user's profile / google details.

        POST: Create the user if they don't already exist and return their
        profile details. The POST payload should include the following:

            {
                'email': '...',
                'first_name': '...',
                'last_name': '...',
                'image_url': '...',
                'oauth_token': '...',
            }

        Of the above values, the `email` and `oauth_token` fields are required.

        """
        content = {}
        authed = request.user.is_authenticated()
        user = request.user if authed else None
        result_status = status.HTTP_200_OK

        # Not authenticated, return empty list.
        if not authed and request.method == 'GET':
            return Response(content, status=result_status)

        # Not authenticated & this is a POST: get or create the user.
        elif not authed and request.method == "POST":
            User = get_user_model()
            try:
                data = request.data

                # Verify the given token info: https://goo.gl/MIKN9X
                token = verify_token(data.get('oauth_token'))
                if token is None:
                    return Response(
                        data={'error': 'Invalid auth token'},
                        status=status.HTTP_400_BAD_REQUEST
                    )

                # Note: email + (a verified) token serves as username + password.
                email = data.get('email').strip().lower()

                # XXX This is a hack to keep these users from getting the
                # XXX `selected_by_default` content from the `goals` app.
                # XXX We *must* set this before we craete the user, hence the
                # XXX use of the email in the key.
                _key = "omit-default-selections-{}".format(slugify(email))
                cache.set(_key, True, 30)

                # XXX The only unique thing about user accounts is email.
                created = False
                try:
                    user = User.objects.get(email__iexact=email)
                except User.DoesNotExist:
                    user = User.objects.create(
                        email=email,
                        username=username_hash(email)
                    )
                    created = True

                # Update the Profile fields.
                profile = user.userprofile
                profile.google_token = token  # This will change periodically
                profile.google_image = data.get('image_url', '')
                profile.app_logins += 1
                if created:
                    # Save the IP address on the user's profile
                    try:
                        profile.ip_address = get_client_ip(request)
                    except:  # XXX: Don't let any exception prevent signup.
                        pass
                profile.save()

                # Update user fields.
                if not user.username:
                    user.username = username_hash(email)
                user.first_name = data.get('first_name', '')
                user.last_name = data.get('last_name', '')
                user.is_active = True  # Auto-activate accounts from Google
                user.save()

                if created:
                    result_status = status.HTTP_201_CREATED
                else:
                    result_status = status.HTTP_200_OK
            except Exception as err:
                # Log the traceback.
                exc_type, exc_value, exc_traceback = sys.exc_info()
                tb = traceback.format_exception(exc_type, exc_value, exc_traceback)
                tb_string = "{}\n".format("\n".join(tb))
                logger.error(tb_string)

                return Response(
                    data={'error': '{}'.format(err)},
                    status=status.HTTP_400_BAD_REQUEST
                )

        if user:
            content = {
                'id': user.id,
                'profile_id': user.userprofile.id,
                'email': user.email,
                'first_name': user.first_name,
                'last_name': user.last_name,
                'google_image': user.userprofile.google_image,
                'google_token': user.userprofile.google_token,
                'phone': user.userprofile.phone,
                'token': user.auth_token.key,
                'needs_onboarding': user.userprofile.needs_onboarding,
            }
        return Response(content, status=result_status)