Skip to content
This repository has been archived by the owner on Oct 28, 2020. It is now read-only.

Commit

Permalink
[fix bug 1046671] Upgrade django browserid to version 0.11.
Browse files Browse the repository at this point in the history
* Remove browserid from submodules.
* Add browserid in requirements/prod.txt.
  • Loading branch information
akatsoulas committed Jan 30, 2015
1 parent 661b127 commit 7f1746d
Show file tree
Hide file tree
Showing 73 changed files with 5,280 additions and 229 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Expand Up @@ -34,9 +34,6 @@
[submodule "vendor-local/src/django-database-email-backend"]
path = vendor-local/src/django-database-email-backend
url = https://github.com/stefanfoulis/django-database-email-backend.git
[submodule "vendor-local/src/django-browserid"]
path = vendor-local/src/django-browserid
url = git://github.com/mozilla/django-browserid.git
[submodule "vendor-local/src/django"]
path = vendor-local/src/django
url = git://github.com/django/django.git
2 changes: 0 additions & 2 deletions .travis.yml
Expand Up @@ -7,9 +7,7 @@ before_install:
- mysql -e 'create database remo character set utf8;'
- git submodule update --init --recursive
install:
- pip install -r requirements/compiled.txt
- pip install -r requirements/dev.txt
- pip install coverage
script:
- python manage.py test --with-coverage --cover-erase --cover-package=remo
after_success:
Expand Down
39 changes: 39 additions & 0 deletions remo/base/backend.py
@@ -0,0 +1,39 @@
from django.conf import settings
from django.contrib.auth.models import Group, User

from django_browserid.auth import BrowserIDBackend, default_username_algo

from remo.base.mozillians import BadStatusCodeError, is_vouched


USERNAME_ALGO = getattr(settings, 'BROWSERID_USERNAME_ALGO',
default_username_algo)


class RemoBrowserIDBackend(BrowserIDBackend):

def create_user(self, email):
try:
data = is_vouched(email)
except BadStatusCodeError:
data = None

# Add vouched mozillians to our db please.
if data and data['is_vouched']:
user = User.objects.create_user(username=USERNAME_ALGO(email),
email=email)
# Due to privacy settings, this might be missing
if 'full_name' not in data:
data['full_name'] = 'Anonymous Mozillian'
else:
user.userprofile.mozillian_username = data['username']
user.userprofile.save()

first_name, last_name = (data['full_name'].split(' ', 1)
if ' ' in data['full_name']
else ('', data['full_name']))
user.first_name = first_name
user.last_name = last_name
user.save()
user.groups.add(Group.objects.get(name='Mozillians'))
return user
2 changes: 1 addition & 1 deletion remo/base/middleware.py
Expand Up @@ -20,7 +20,7 @@ def process_request(self, request):
request.user.userprofile.registration_complete and not
request.user.groups.filter(name='Mozillians').exists()):
allow_urls = [
reverse('browserid_logout'),
reverse('browserid.logout'),
reverse('profiles_edit',
kwargs={'display_name':
request.user.userprofile.display_name})]
Expand Down
3 changes: 1 addition & 2 deletions remo/base/templates/base_fd4.html
Expand Up @@ -58,7 +58,6 @@
{% endcompress %}
{% include "includes/google_analytics.html" %}

{{ browserid_css() }}
</head>

<body data-mapbox-token="{{ settings.MAPBOX_TOKEN }}">
Expand Down Expand Up @@ -90,7 +89,7 @@
{% set next=request.get_full_path() %}
{% endif %}
<span id="login-menu-locator">
{{ browserid_login(text='Sign in', next=request.GET.next|default(next|default(''))) }}
{{ browserid_login(next=request.GET.next|default(next|default(''))) }}
</span>
or
<a href="#" data-reveal-id="join-modal">Join</a>
Expand Down
57 changes: 57 additions & 0 deletions remo/base/tests/__init__.py
Expand Up @@ -19,6 +19,63 @@
'django.contrib.auth.hashers.MD5PasswordHasher',
)

VOUCHED_MOZILLIAN = """
{
"meta": {
"previous": null,
"total_count": 1,
"offset": 0,
"limit": 20,
"next": null
},
"objects":
[
{
"website": "",
"bio": "",
"groups": [
"foo bar"
],
"skills": [],
"email": "vouched@mail.com",
"is_vouched": true
}
]
}
"""

NOT_VOUCHED_MOZILLIAN = """
{
"meta": {
"previous": null,
"total_count": 1,
"offset": 0,
"limit": 20,
"next": null
},
"objects": [
{
"website": "",
"bio": "",
"groups": [
"no login"
],
"skills": [],
"is_vouched": false,
"email": "not_vouched@mail.com"
}
]
}
"""


class MozillianResponse(object):
"""Mozillians Response."""

def __init__(self, content=None, status_code=200):
self.content = content
self.status_code = status_code


@override_settings(AUTHENTICATION_BACKENDS=AUTHENTICATION_BACKENDS,
PASSWORD_HASHERS=PASSWORD_HASHERS)
Expand Down
15 changes: 11 additions & 4 deletions remo/base/tests/browserid_mock.py
Expand Up @@ -12,10 +12,17 @@ class mock_browserid(object):

def __init__(self, email=None):
self.settings_patches = (
patch.object(settings, 'AUTHENTICATION_BACKENDS',
['django_browserid.auth.BrowserIDBackend']),
patch.object(settings, 'SITE_URL', 'http://testserver'))
self.patcher = patch('django_browserid.base._verify_http_request')
patch.object(
settings, 'AUTHENTICATION_BACKENDS',
('django_browserid.auth.BrowserIDBackend',)
),
patch.object(
settings, 'BROWSERID_AUDIENCES',
['http://testserver'],
)
)

self.patcher = patch('django_browserid.base.requests.post')
if email is not None:
self.return_value = {'status': 'okay', 'email': email}
else:
Expand Down
46 changes: 46 additions & 0 deletions remo/base/tests/test_backend.py
@@ -0,0 +1,46 @@
from django.contrib.auth.models import User

import mock
from nose.tools import eq_

from remo.base.backend import RemoBrowserIDBackend
from remo.base.tests import RemoTestCase


class RemoBackendTests(RemoTestCase):

@mock.patch('remo.base.backend.is_vouched')
def test_create_mozillian_user_with_private_data(self, mocked_vouched):
""" Test user creation for user with private data in Mozillians."""

email = 'mozillian@example.com'

eq_(User.objects.filter(email=email).count(), 0)

backend = RemoBrowserIDBackend()
backend.User = mock.Mock()
mocked_vouched.return_value = {'is_vouched': True,
'email': email}
backend.create_user(email)

user = User.objects.get(email=email)
eq_(user.get_full_name(), u'Anonymous Mozillian')

@mock.patch('remo.base.backend.is_vouched')
def test_create_mozillian_user_with_public_name(self, mocked_vouched):
""" Test user creation for user with private data in Mozillians."""

email = 'mozillian@example.com'

eq_(User.objects.filter(email=email).count(), 0)

backend = RemoBrowserIDBackend()
backend.User = mock.Mock()
mocked_vouched.return_value = {'is_vouched': True,
'email': email,
'full_name': 'Awesome Mozillian',
'username': 'remobot'}
backend.create_user(email)

user = User.objects.get(email=email)
eq_(user.get_full_name(), u'Awesome Mozillian')
114 changes: 17 additions & 97 deletions remo/base/tests/test_views.py
Expand Up @@ -14,15 +14,16 @@
from django.test.utils import override_settings

import mock
from funfactory.helpers import urlparams
from jinja2 import Markup
from nose.exc import SkipTest
from nose.tools import eq_, ok_
from test_utils import TestCase

from remo.base import mozillians
from remo.base.helpers import AES_PADDING, enc_string, mailhide, pad_string
from remo.base.tests import RemoTestCase, requires_login, requires_permission
from remo.base.tests import (MozillianResponse, RemoTestCase,
VOUCHED_MOZILLIAN, NOT_VOUCHED_MOZILLIAN,
requires_login, requires_permission)
from remo.base.tests.browserid_mock import mock_browserid
from remo.base.views import robots_txt
from remo.events.models import EventGoal
Expand All @@ -35,68 +36,10 @@
from remo.reports.tests import ActivityFactory, CampaignFactory


VOUCHED_MOZILLIAN = """
{
"meta": {
"previous": null,
"total_count": 1,
"offset": 0,
"limit": 20,
"next": null
},
"objects":
[
{
"website": "",
"bio": "",
"groups": [
"foo bar"
],
"skills": [],
"email": "vouched@mail.com",
"is_vouched": true
}
]
}
"""

NOT_VOUCHED_MOZILLIAN = """
{
"meta": {
"previous": null,
"total_count": 1,
"offset": 0,
"limit": 20,
"next": null
},
"objects": [
{
"website": "",
"bio": "",
"groups": [
"no login"
],
"skills": [],
"is_vouched": false,
"email": "not_vouched@mail.com"
}
]
}
"""


assert json.loads(VOUCHED_MOZILLIAN)
assert json.loads(NOT_VOUCHED_MOZILLIAN)


class MozillianResponse(object):
"""Mozillians Response."""

def __init__(self, content=None, status_code=200):
self.content = content
self.status_code = status_code


class MozilliansTest(TestCase):
"""Test Moziilians."""

Expand All @@ -111,6 +54,7 @@ def mocked_get(url, **options):
return MozillianResponse(NOT_VOUCHED_MOZILLIAN)
if 'trouble' in url:
return MozillianResponse('Failed', status_code=500)

rget.side_effect = mocked_get

ok_(mozillians.is_vouched('vouched@mail.com'))
Expand All @@ -127,31 +71,6 @@ def mocked_get(url, **options):
except mozillians.BadStatusCodeError, msg:
ok_(settings.MOZILLIANS_API_KEY not in str(msg))

@override_settings(SITE_URL='http://testserver')
@mock.patch('remo.base.views.verify')
@mock.patch('remo.base.views.is_vouched')
@mock.patch('remo.base.views.auth.authenticate')
def test_mozillian_user_with_private_data(self, mocked_authenticate,
mocked_is_vouched,
mocked_verify):
""" Test user creation for user with private data in Mozillians."""
c = Client()
email = u'vouched@example.com'
mocked_verify.return_value = {'email': email}
mocked_is_vouched.return_value = {'is_vouched': True,
'email': email}

def authenticate(*args, **kwargs):
user = User.objects.get(email=email)
user.backend = 'Fake'
return user

mocked_authenticate.side_effect = authenticate
eq_(User.objects.filter(email=email).count(), 0)
c.post('/browserid/login/', data={'assertion': 'xxx'})
user = User.objects.get(email=email)
eq_(user.get_full_name(), u'Anonymous Mozillian')

@mock.patch('remo.profiles.tasks.is_vouched')
def test_mozillian_username_exists(self, mocked_is_vouched):
"""Test that if an Anonymous Mozillians changes his
Expand Down Expand Up @@ -195,32 +114,33 @@ class ViewsTest(TestCase):
def setUp(self):
self.settings_data = {'receive_email_on_add_comment': True}
self.user_edit_settings_url = reverse('edit_settings')
self.failed_url = urlparams(settings.LOGIN_REDIRECT_URL_FAILURE,
bid_login_failed=1)

def _login_attempt(self, email, assertion='assertion123'):
def _login_attempt(self, email, assertion='assertion123', next=None):
if not next:
next = '/'
with mock_browserid(email):
r = self.client.post(
reverse('browserid_login'),
{'assertion': assertion})
return r
post_data = {'assertion': assertion,
'next': next}
return self.client.post('/browserid/login/', post_data)

def test_bad_verification(self):
"""Bad verification -> failure."""
response = self._login_attempt(None)
self.assertRedirects(response, self.failed_url,
target_status_code=200)
eq_(response['content-type'], 'application/json')
redirect = json.loads(response.content)['redirect']
eq_(redirect, settings.LOGIN_REDIRECT_URL_FAILURE)

def test_invalid_login(self):
"""Bad BrowserID form - no assertion -> failure."""
response = self._login_attempt(None, None)
self.assertRedirects(response, self.failed_url,
target_status_code=200)
eq_(response['content-type'], 'application/json')
redirect = json.loads(response.content)['redirect']
eq_(redirect, settings.LOGIN_REDIRECT_URL_FAILURE)

def test_is_vouched(self):
"""Login with vouched email."""
response = self._login_attempt('vouched@mail.com')
eq_(response.status_code, 302)
eq_(response.status_code, 200)
ok_(reverse('dashboard'))

def test_view_main_page(self):
Expand Down

0 comments on commit 7f1746d

Please sign in to comment.