Skip to content

Commit

Permalink
Added user creation, including tests
Browse files Browse the repository at this point in the history
  • Loading branch information
reinout committed Nov 18, 2016
1 parent e842372 commit 0c9a4e4
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 8 deletions.
34 changes: 31 additions & 3 deletions lizard_auth_client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,8 +760,36 @@ def sso_search_user_by_email(email):
params = {
'message': signed_message,
'key': settings.SSO_KEY,
'timeout': 10,
}
r = requests.get(url, params=params)
r = requests.get(url, params=params, timeout=10)
r.raise_for_status()
return r.json()['user']


def sso_create_user(first_name, last_name, email, username):
"""
Return a user dict, if successful.
"""
from lizard_auth_client.conf import settings

payload = {
'iss': settings.SSO_KEY,
'exp': datetime.datetime.utcnow() + datetime.timedelta(
minutes=settings.SSO_JWT_EXPIRATION_MINUTES),
'first_name': first_name,
'last_name': last_name,
'email': email,
'username': username,
'language': settings.SSO_INVITATION_LANGUAGE,
}
signed_message = jwt.encode(payload, settings.SSO_SECRET,
algorithm=settings.SSO_JWT_ALGORITHM)
url = sso_server_url('new-user')
data = {
'message': signed_message,
'key': settings.SSO_KEY,
}
r = requests.post(url, data=data, timeout=10
)
r.raise_for_status()
return r.json()
return r.json()['user']
4 changes: 3 additions & 1 deletion lizard_auth_client/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ class SSOAppConf(AppConf):
# Required settings for the v2 API. Should include ``/api2/``.
SERVER_API_START_URL = ''

# Extra setting for the v2 API.
# Extra setting for the v2 API. Invitation language is the language used
# by the SSO in the email when inviting the new user.
ALLOW_ONLY_KNOWN_USERS = True
SSO_INVITATION_LANGUAGE = 'en'

# Role syncing from signals.py. V1 API only
CLIENT_SUPERUSER_ROLES = []
Expand Down
60 changes: 57 additions & 3 deletions lizard_auth_client/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@
from __future__ import unicode_literals

from django import forms
from lizard_auth_client import client
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _
from lizard_auth_client import client
from requests import HTTPError

import logging


logger = logging.getLogger(__name__)


class SearchEmailForm(forms.Form):

email = forms.EmailField(
required=True,
label=_('Email'),
)

def clean(self):
Expand All @@ -19,9 +26,56 @@ def clean(self):
user_dict = client.sso_search_user_by_email(
self.cleaned_data['email'])
except HTTPError as e:
logger.info("Error when searching user on the SSO: %s",
e.response.text)
if e.response.status_code == 404:
raise ValidationError(
{'email': "User with email %s not found" % self.cleaned_data['email']})
raise ValidationError(e)
user = client.construct_user(user_dict['user'])
print("Added user %s" % user)
user = client.construct_user(user_dict)
logger.info("Added SSO user %s locally", user)


class CreateNewUserForm(forms.Form):

first_name = forms.CharField(
max_length=30,
label=_('First name'),
required=True
)
last_name = forms.CharField(
max_length=30,
label=_('Last name'),
required=True
)
email = forms.EmailField(
required=True,
label=_('Email'),
)
username = forms.CharField(
max_length=128,
label=_('Username'),
)

def clean(self):

try:
user_dict = client.sso_create_user(
self.cleaned_data['first_name'],
self.cleaned_data['last_name'],
self.cleaned_data['email'],
self.cleaned_data['username'])
except HTTPError as e:
logger.warn("Error when creating user on the SSO: %s",
e.response.text)
if e.response.status_code == 400:
# According to lizard-auth-server, this normally means a
# duplicate username. Assuming we've send a correct message.
raise ValidationError(
{'username': ("Username %s already used" %
self.cleaned_data['username'])}
)
raise ValidationError(e)
user = client.construct_user(user_dict)
logger.info("Created user %s on the SSO and added it locally",
user)
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ <h1>{{ view.title }}</h1>

<div>
<a href="{% url 'lizard_auth_client.search_new_user' %}">
Search new user by email
Add new user by searching by email on the SSO.
</a>
</div>
<div>
<a href="{% url 'lizard_auth_client.create_new_user' %}">
Create new user on the SSO + add locally.
</a>
</div>

Expand Down
36 changes: 36 additions & 0 deletions lizard_auth_client/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,42 @@ def mock_post(url, timeout, data):
issuer=key)
self.assertEqual('someone', decoded['username'])

def test_search_user(self):

def mock_get(url, params, timeout):
result = mock.Mock()
result.json.return_value = {'user': {'a': 'dict'}}
return result

def mock_server_url(what):
return 'http:/some/where/'

with mock.patch('requests.get', mock_get):
with mock.patch('lizard_auth_client.client.sso_server_url',
mock_server_url):
self.assertEquals(
{'a': 'dict'},
client.sso_search_user_by_email('some@example.org'))

def test_create_user(self):

def mock_post(url, data, timeout):
result = mock.Mock()
result.json.return_value = {'user': {'a': 'dict'}}
return result

def mock_server_url(what):
return 'http:/some/where/'

with mock.patch('requests.post', mock_post):
with mock.patch('lizard_auth_client.client.sso_server_url',
mock_server_url):
self.assertEquals(
{'a': 'dict'},
client.sso_create_user('some', 'name',
'some@example.org',
'somename'))


class V2ViewsTest(TestCase):

Expand Down
3 changes: 3 additions & 0 deletions lizard_auth_client/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ def check_settings():
url(r'^sso/search_new_user/$',
views.SearchNewUserView.as_view(),
name='lizard_auth_client.search_new_user'),
url(r'^sso/create_new_user/$',
views.CreateNewUserView.as_view(),
name='lizard_auth_client.create_new_user'),
url(r'^sso/disallowed_user/$',
views.DisallowedUserView.as_view(),
name='lizard_auth_client.disallowed_user'),
Expand Down
8 changes: 8 additions & 0 deletions lizard_auth_client/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from lizard_auth_client.client import sso_server_url
from lizard_auth_client.conf import settings
from lizard_auth_client.forms import SearchEmailForm
from lizard_auth_client.forms import CreateNewUserForm

import datetime
import json
Expand Down Expand Up @@ -500,6 +501,13 @@ class SearchNewUserView(FormView):
title = "Search new user by email"


class CreateNewUserView(FormView):
template_name = 'lizard_auth_client/form.html'
form_class = CreateNewUserForm
success_url = reverse_lazy('lizard_auth_client.user_overview')
title = "Create new user on the SSO"


class DisallowedUserView(TemplateView):
template_name = 'lizard_auth_client/disallowed-user.html'
title = "Not allowed"
Expand Down

0 comments on commit 0c9a4e4

Please sign in to comment.