authentic/tests/test_attribute_kinds.py

497 lines
16 KiB
Python

# -*- coding: utf-8 -*-
# authentic2 - versatile identity manager
# Copyright (C) 2010-2019 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import datetime
import os
import PIL.Image
from django.conf import settings
from authentic2.custom_user.models import User
from authentic2.models import Attribute
from .utils import get_link_from_mail
from webtest import Upload
def test_string(db, app, admin, mailoutbox):
Attribute.objects.create(name='nom_de_naissance', label='Nom de naissance', kind='string',
asked_on_registration=True)
qs = User.objects.filter(first_name='John')
response = app.get('/accounts/register/')
form = response.form
form.set('email', 'john.doe@example.com')
response = form.submit().follow()
assert 'john.doe@example.com' in response
url = get_link_from_mail(mailoutbox[0])
response = app.get(url)
form = response.form
assert response.pyquery('#id_nom_de_naissance').attr('maxlength') == '256'
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('nom_de_naissance', '1234567890' * 30)
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_nom_de_naissance')
form = response.form
form.set('nom_de_naissance', u'Noël')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.nom_de_naissance == u'Noël'
qs.delete()
app.authorization = ('Basic', (admin.username, admin.username))
payload = {
'first_name': 'John',
'last_name': 'Doe',
'nom_de_naissance': '1234567890' * 30,
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'nom_de_naissance': u'Noël',
}
app.post_json('/api/users/', params=payload, status=201)
assert qs.get().attributes.nom_de_naissance == u'Noël'
qs.delete()
def test_fr_postcode(db, app, admin, mailoutbox):
def register_john():
response = app.get('/accounts/register/')
form = response.form
form.set('email', 'john.doe@example.com')
response = form.submit().follow()
assert 'john.doe@example.com' in response
return get_link_from_mail(mailoutbox[-1])
Attribute.objects.create(name='postcode', label='postcode', kind='fr_postcode',
asked_on_registration=True)
qs = User.objects.filter(first_name='John')
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('postcode', 'abc')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_postcode')
form = response.form
form.set('postcode', '123')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_postcode')
form = response.form
form.set('postcode', '12345')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.postcode == '12345'
qs.delete()
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('postcode', ' 12345 ')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.postcode == '12345'
qs.delete()
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('postcode', '')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.postcode == ''
qs.delete()
app.authorization = ('Basic', (admin.username, admin.username))
payload = {
'first_name': 'John',
'last_name': 'Doe',
'postcode': ' 1234abc ',
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'postcode': '1234',
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'postcode': '12345',
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.postcode == '12345'
qs.delete()
payload = {
'first_name': 'John',
'last_name': 'Doe',
'postcode': None,
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.postcode is None
qs.delete()
payload = {
'first_name': 'John',
'last_name': 'Doe',
'postcode': '',
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.postcode == ''
qs.delete()
def test_phone_number(db, app, admin, mailoutbox, settings):
settings.A2_EMAILS_ADDRESS_RATELIMIT = None
def register_john():
response = app.get('/accounts/register/')
form = response.form
form.set('email', 'john.doe@example.com')
response = form.submit().follow()
assert 'john.doe@example.com' in response
return get_link_from_mail(mailoutbox[-1])
Attribute.objects.create(name='phone_number', label='phone', kind='phone_number',
asked_on_registration=True)
qs = User.objects.filter(first_name='John')
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('phone_number', 'abc')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_phone_number')
form = response.form
assert response.pyquery('#id_phone_number').attr('maxlength') == '30'
form.set('phone_number', '1234512345' * 10)
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_phone_number')
form = response.form
form.set('phone_number', '12345')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.phone_number == '12345'
qs.delete()
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('phone_number', '+12345')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.phone_number == '+12345'
qs.delete()
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('phone_number', '')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.phone_number == ''
qs.delete()
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('phone_number', ' + 1.2-3 4 5 ')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit().follow()
assert qs.get().attributes.phone_number == '+12345'
qs.delete()
app.authorization = ('Basic', (admin.username, admin.username))
payload = {
'first_name': 'John',
'last_name': 'Doe',
'phone_number': 'abc',
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'phone_number': ' + 1 2 3 4 5 ',
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'phone_number': '12345',
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.phone_number == '12345'
qs.delete()
payload = {
'first_name': 'John',
'last_name': 'Doe',
'phone_number': '+12345',
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.phone_number == '+12345'
qs.delete()
payload = {
'first_name': 'John',
'last_name': 'Doe',
'phone_number': None,
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.phone_number is None
qs.delete()
payload = {
'first_name': 'John',
'last_name': 'Doe',
'phone_number': '',
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.phone_number == ''
qs.delete()
def test_birthdate(db, app, admin, mailoutbox, freezer):
def register_john():
response = app.get('/accounts/register/')
form = response.form
form.set('email', 'john.doe@example.com')
response = form.submit().follow()
assert 'john.doe@example.com' in response
return get_link_from_mail(mailoutbox[-1])
freezer.move_to('2018-01-01')
Attribute.objects.create(name='birthdate', label='birthdate', kind='birthdate',
asked_on_registration=True)
qs = User.objects.filter(first_name='John')
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('birthdate', '2018-01-01')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_birthdate')
form.set('birthdate', '2017-12-31')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
form.submit().follow()
assert qs.get().attributes.birthdate == datetime.date(2017, 12, 31)
qs.delete()
url = register_john()
response = app.get(url)
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('birthdate', '1899-12-31')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_birthdate')
form.set('birthdate', '1900-01-01')
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
form.submit().follow()
assert qs.get().attributes.birthdate == datetime.date(1900, 1, 1)
qs.delete()
def test_birthdate_api(db, app, admin, mailoutbox, freezer):
freezer.move_to('2018-01-01')
Attribute.objects.create(name='birthdate', label='birthdate', kind='birthdate',
asked_on_registration=True)
qs = User.objects.filter(first_name='John')
app.authorization = ('Basic', (admin.username, admin.username))
payload = {
'first_name': 'John',
'last_name': 'Doe',
'birthdate': '2018-01-01',
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'birthdate': '2017-12-31',
}
response = app.post_json('/api/users/', params=payload)
assert qs.get().attributes.birthdate == datetime.date(2017, 12, 31)
qs.delete()
payload = {
'first_name': 'John',
'last_name': 'Doe',
'birthdate': '1899-12-31',
}
app.post_json('/api/users/', params=payload, status=400)
payload = {
'first_name': 'John',
'last_name': 'Doe',
'birthdate': '1900-01-01',
}
app.post_json('/api/users/', params=payload)
assert qs.get().attributes.birthdate == datetime.date(1900, 1, 1)
qs.delete()
def test_profile_image(db, app, admin, mailoutbox):
Attribute.objects.create(name='cityscape_image', label='cityscape', kind='profile_image',
asked_on_registration=True, required=False,
user_visible=True, user_editable=True)
def john():
return User.objects.get(first_name='John')
response = app.get('/accounts/register/')
form = response.form
form.set('email', 'john.doe@example.com')
response = form.submit().follow()
assert 'john.doe@example.com' in response
url = get_link_from_mail(mailoutbox[0])
response = app.get(url)
# verify empty file is refused
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('cityscape_image', Upload('/dev/null'))
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert response.pyquery.find('.form-field-error #id_cityscape_image')
# verify 200x200 image is accepted
form = response.form
form.set('cityscape_image', Upload('tests/200x200.jpg'))
form.set('password1', '12345abcdA')
form.set('password2', '12345abcdA')
response = form.submit()
assert john().attributes.cityscape_image
profile_filename = john().attributes.cityscape_image.name
assert profile_filename.endswith('.jpeg')
# verify API serves absolute URL for profile images
app.authorization = ('Basic', (admin.username, admin.username))
response = app.get('/api/users/%s/' % john().uuid)
assert response.json['cityscape_image'] == 'http://testserver/media/%s' % john().attributes.cityscape_image.name
app.authorization = None
# verify we can clear the image
response = app.get('/accounts/edit/')
form = response.form
form.set('first_name', 'John')
form.set('last_name', 'Doe')
form.set('cityscape_image-clear', True)
response = form.submit()
assert john().attributes.cityscape_image == None
# verify API serves None for empty profile images
app.authorization = ('Basic', (admin.username, admin.username))
response = app.get('/api/users/%s/' % john().uuid)
assert response.json['cityscape_image'] is None
# verify 201x201 image is accepted and resized
response = app.get('/accounts/edit/')
form = response.form
form.set('cityscape_image', Upload('tests/201x201.jpg'))
response = form.submit()
with PIL.Image.open(os.path.join(settings.MEDIA_ROOT, john().attributes.cityscape_image.name)) as image:
assert image.width == 200
assert image.height == 200
assert john().attributes.cityscape_image.name != profile_filename
# verify file input mentions image files
response = app.get('/accounts/edit/')
form = response.form
assert form['cityscape_image'].attrs['accept'] == 'image/*'
def test_multiple_attribute_setter(db, app, simple_user):
nicks = Attribute.objects.create(name='nicknames', label='Nicknames', kind='string',
required=False, multiple=True, user_visible=True, user_editable=True)
simple_user.attributes.nicknames = ['Roger', 'Tony', 'Robie']
simple_user.save()
assert 'Tony' in [atv.content for atv in simple_user.attribute_values.filter(attribute=nicks)]
simple_user.attributes.nicknames = ['Roger', 'Timmy', 'Robie']
simple_user.save()
assert not 'Tony' in [atv.content for atv in simple_user.attribute_values.filter(attribute=nicks)]