11 |
11 |
|
12 |
12 |
pytestmark = pytest.mark.django_db
|
13 |
13 |
|
14 |
|
idp = {
|
15 |
|
'METADATA': open('tests/metadata.xml').read(),
|
16 |
|
}
|
17 |
|
saml_attributes = {
|
18 |
|
'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
|
19 |
|
'name_id_content': 'x' * 32,
|
20 |
|
'issuer': 'http://idp5/metadata',
|
21 |
|
'username': ['foobar'],
|
22 |
|
'email': ['test@example.net'],
|
23 |
|
'first_name': ['Foo'],
|
24 |
|
'last_name': ['Bar'],
|
25 |
|
'is_superuser': ['true'],
|
26 |
|
'group': ['GroupA', 'GroupB', 'GroupC'],
|
27 |
|
}
|
28 |
|
|
29 |
|
|
30 |
|
def test_format_username(settings):
|
|
14 |
User = auth.get_user_model()
|
|
15 |
|
|
16 |
|
|
17 |
@pytest.fixture
|
|
18 |
def idp():
|
|
19 |
return {
|
|
20 |
'METADATA': open('tests/metadata.xml').read(),
|
|
21 |
}
|
|
22 |
|
|
23 |
|
|
24 |
@pytest.fixture
|
|
25 |
def saml_attributes():
|
|
26 |
return {
|
|
27 |
'name_id_format': lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT,
|
|
28 |
'name_id_content': 'x' * 32,
|
|
29 |
'issuer': 'http://idp5/metadata',
|
|
30 |
'username': ['foobar'],
|
|
31 |
'email': ['test@example.net'],
|
|
32 |
'first_name': ['Foo'],
|
|
33 |
'last_name': ['Bar'],
|
|
34 |
'is_superuser': ['true'],
|
|
35 |
'group': ['GroupA', 'GroupB', 'GroupC'],
|
|
36 |
}
|
|
37 |
|
|
38 |
|
|
39 |
@pytest.fixture
|
|
40 |
def john(db):
|
|
41 |
return User.objects.create(username='john.doe', email='john.doe@example.com')
|
|
42 |
|
|
43 |
|
|
44 |
@pytest.fixture
|
|
45 |
def jane(db):
|
|
46 |
return User.objects.create(username='jane.doe', email='john.doe@example.com')
|
|
47 |
|
|
48 |
|
|
49 |
def test_format_username(settings, idp, saml_attributes):
|
31 |
50 |
adapter = DefaultAdapter()
|
32 |
51 |
assert adapter.format_username(idp, {}) is None
|
33 |
52 |
assert adapter.format_username(idp, saml_attributes) == ('x' * 32 + '@saml')[:30]
|
... | ... | |
37 |
56 |
assert adapter.format_username(idp, saml_attributes) == 'foobar'
|
38 |
57 |
|
39 |
58 |
|
40 |
|
def test_lookup_user(settings):
|
41 |
|
User = auth.get_user_model()
|
|
59 |
def test_lookup_user(settings, idp, saml_attributes):
|
42 |
60 |
adapter = DefaultAdapter()
|
43 |
61 |
user = adapter.lookup_user(idp, saml_attributes)
|
44 |
62 |
assert user is not None
|
... | ... | |
55 |
73 |
assert User.objects.count() == 0
|
56 |
74 |
|
57 |
75 |
|
58 |
|
def test_lookup_user_transaction(transactional_db, concurrency):
|
|
76 |
def test_lookup_user_transaction(transactional_db, concurrency, idp, saml_attributes):
|
59 |
77 |
adapter = DefaultAdapter()
|
60 |
78 |
p = ThreadPool(concurrency)
|
61 |
79 |
|
... | ... | |
81 |
99 |
assert len(set(user.pk for user in users)) == 1
|
82 |
100 |
|
83 |
101 |
|
84 |
|
def test_provision_user_attributes(settings, django_user_model, caplog):
|
|
102 |
def test_provision_user_attributes(settings, django_user_model, idp, saml_attributes, caplog):
|
85 |
103 |
settings.MELLON_IDENTITY_PROVIDERS = [idp]
|
86 |
104 |
settings.MELLON_ATTRIBUTE_MAPPING = {
|
87 |
105 |
'email': u'{attributes[email][0]}',
|
... | ... | |
102 |
120 |
assert 'set field email' in caplog.text
|
103 |
121 |
|
104 |
122 |
|
105 |
|
def test_provision_user_groups(settings, django_user_model, caplog):
|
|
123 |
def test_provision_user_groups(settings, django_user_model, idp, saml_attributes, caplog):
|
106 |
124 |
settings.MELLON_IDENTITY_PROVIDERS = [idp]
|
107 |
125 |
settings.MELLON_GROUP_ATTRIBUTE = 'group'
|
108 |
126 |
user = SAMLBackend().authenticate(saml_attributes=saml_attributes)
|
... | ... | |
118 |
136 |
user = SAMLBackend().authenticate(saml_attributes=saml_attributes2)
|
119 |
137 |
assert user.groups.count() == 2
|
120 |
138 |
assert set(user.groups.values_list('name', flat=True)) == set(saml_attributes2['group'])
|
121 |
|
assert len(caplog.records) == 5
|
|
139 |
assert len(caplog.records) == 6
|
122 |
140 |
assert 'removing group GroupA' in caplog.records[-1].message
|
123 |
141 |
|
124 |
142 |
|
125 |
|
def test_provision_is_superuser(settings, django_user_model, caplog):
|
|
143 |
def test_provision_is_superuser(settings, django_user_model, idp, saml_attributes, caplog):
|
126 |
144 |
settings.MELLON_IDENTITY_PROVIDERS = [idp]
|
127 |
145 |
settings.MELLON_SUPERUSER_MAPPING = {
|
128 |
146 |
'is_superuser': 'true',
|
... | ... | |
137 |
155 |
assert not 'flag is_staff and is_superuser removed' in caplog.text
|
138 |
156 |
|
139 |
157 |
|
140 |
|
def test_provision_absent_attribute(settings, django_user_model, caplog):
|
|
158 |
def test_provision_absent_attribute(settings, django_user_model, idp, saml_attributes, caplog):
|
141 |
159 |
settings.MELLON_IDENTITY_PROVIDERS = [idp]
|
142 |
160 |
settings.MELLON_ATTRIBUTE_MAPPING = {
|
143 |
161 |
'email': '{attributes[email][0]}',
|
... | ... | |
155 |
173 |
assert 'set field last_name' in caplog.text
|
156 |
174 |
|
157 |
175 |
|
158 |
|
def test_provision_long_attribute(settings, django_user_model, caplog):
|
|
176 |
def test_provision_long_attribute(settings, django_user_model, idp, saml_attributes, caplog):
|
159 |
177 |
settings.MELLON_IDENTITY_PROVIDERS = [idp]
|
160 |
178 |
settings.MELLON_ATTRIBUTE_MAPPING = {
|
161 |
179 |
'email': '{attributes[email][0]}',
|
... | ... | |
174 |
192 |
assert 'set field email' in caplog.text
|
175 |
193 |
|
176 |
194 |
|
177 |
|
def test_lookup_user_transient_with_email(private_settings):
|
|
195 |
def test_lookup_user_transient_with_email(private_settings, idp, saml_attributes):
|
178 |
196 |
private_settings.MELLON_TRANSIENT_FEDERATION_ATTRIBUTE = 'email'
|
179 |
|
User = auth.get_user_model()
|
180 |
197 |
adapter = DefaultAdapter()
|
181 |
|
saml_attributes2 = saml_attributes.copy()
|
182 |
|
saml_attributes2['name_id_format'] = lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT
|
|
198 |
saml_attributes['name_id_format'] = lasso.SAML2_NAME_IDENTIFIER_FORMAT_TRANSIENT
|
183 |
199 |
assert User.objects.count() == 0
|
184 |
|
user = adapter.lookup_user(idp, saml_attributes2)
|
|
200 |
user = adapter.lookup_user(idp, saml_attributes)
|
185 |
201 |
assert user is not None
|
186 |
202 |
assert user.saml_identifiers.count() == 1
|
187 |
|
assert user.saml_identifiers.first().name_id == saml_attributes2['email'][0]
|
|
203 |
assert user.saml_identifiers.first().name_id == saml_attributes['email'][0]
|
188 |
204 |
|
189 |
|
user2 = adapter.lookup_user(idp, saml_attributes2)
|
|
205 |
user2 = adapter.lookup_user(idp, saml_attributes)
|
190 |
206 |
assert user.id == user2.id
|
191 |
207 |
|
192 |
208 |
User.objects.all().delete()
|
... | ... | |
196 |
212 |
user = adapter.lookup_user(idp, saml_attributes)
|
197 |
213 |
assert user is None
|
198 |
214 |
assert User.objects.count() == 0
|
|
215 |
|
|
216 |
|
|
217 |
def test_lookup_user_by_attributes_bad_setting1(settings, idp, saml_attributes, caplog):
|
|
218 |
settings.MELLON_PROVISION = False
|
|
219 |
|
|
220 |
adapter = DefaultAdapter()
|
|
221 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = 'coin'
|
|
222 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
223 |
assert caplog.records[-1].message.endswith('it must be a list')
|
|
224 |
|
|
225 |
|
|
226 |
def test_lookup_user_by_attributes_bad_setting2(settings, idp, saml_attributes, caplog):
|
|
227 |
settings.MELLON_PROVISION = False
|
|
228 |
|
|
229 |
adapter = DefaultAdapter()
|
|
230 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = ['coin']
|
|
231 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
232 |
assert caplog.records[-1].message.endswith('it must be a list of dicts')
|
|
233 |
|
|
234 |
|
|
235 |
def test_lookup_user_by_attributes_bad_setting3(settings, idp, saml_attributes, caplog):
|
|
236 |
settings.MELLON_PROVISION = False
|
|
237 |
|
|
238 |
adapter = DefaultAdapter()
|
|
239 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [{}]
|
|
240 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
241 |
assert caplog.records[-1].message.endswith('user_field is missing')
|
|
242 |
|
|
243 |
|
|
244 |
def test_lookup_user_by_attributes_bad_setting4(settings, idp, saml_attributes, caplog):
|
|
245 |
settings.MELLON_PROVISION = False
|
|
246 |
|
|
247 |
adapter = DefaultAdapter()
|
|
248 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [{'user_field': 'username'}]
|
|
249 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
250 |
assert caplog.records[-1].message.endswith('saml_attribute is missing')
|
|
251 |
|
|
252 |
|
|
253 |
def test_lookup_user_by_attributes_not_found(settings, idp, saml_attributes, caplog):
|
|
254 |
settings.MELLON_PROVISION = False
|
|
255 |
|
|
256 |
adapter = DefaultAdapter()
|
|
257 |
caplog.set_level('DEBUG')
|
|
258 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [{'user_field': 'username', 'saml_attribute': 'saml_at1'}]
|
|
259 |
saml_attributes['saml_at1'] = ['john.doe']
|
|
260 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
261 |
assert caplog.records[-2].message.endswith(': not found')
|
|
262 |
|
|
263 |
|
|
264 |
def test_lookup_user_by_attributes_too_many1(settings, idp, saml_attributes, john, jane, caplog):
|
|
265 |
settings.MELLON_PROVISION = False
|
|
266 |
|
|
267 |
adapter = DefaultAdapter()
|
|
268 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [{'user_field': 'email', 'saml_attribute': 'saml_at1'}]
|
|
269 |
saml_attributes['saml_at1'] = ['john.doe@example.com']
|
|
270 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
271 |
assert 'too many users found(2)' in caplog.records[-1].message
|
|
272 |
|
|
273 |
|
|
274 |
def test_lookup_user_by_attributes_too_manyi2(settings, idp, saml_attributes, john, jane, caplog):
|
|
275 |
settings.MELLON_PROVISION = False
|
|
276 |
|
|
277 |
adapter = DefaultAdapter()
|
|
278 |
saml_attributes['saml_at1'] = ['john.doe']
|
|
279 |
saml_attributes['saml_at2'] = ['jane.doe']
|
|
280 |
|
|
281 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [
|
|
282 |
{'user_field': 'username', 'saml_attribute': 'saml_at1'},
|
|
283 |
{'user_field': 'username', 'saml_attribute': 'saml_at2'},
|
|
284 |
]
|
|
285 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
286 |
assert 'too many users found(2)' in caplog.records[-1].message
|
|
287 |
|
|
288 |
|
|
289 |
def test_lookup_user_by_attributes_found(settings, idp, saml_attributes, john, jane, caplog):
|
|
290 |
settings.MELLON_PROVISION = False
|
|
291 |
|
|
292 |
adapter = DefaultAdapter()
|
|
293 |
saml_attributes['saml_at1'] = ['john.doe']
|
|
294 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [
|
|
295 |
{'user_field': 'username', 'saml_attribute': 'saml_at1'},
|
|
296 |
]
|
|
297 |
assert adapter.lookup_user(idp, saml_attributes) == john
|
|
298 |
|
|
299 |
|
|
300 |
def test_lookup_user_by_attributes_ignore_case(settings, idp, saml_attributes, john, jane, caplog):
|
|
301 |
settings.MELLON_PROVISION = False
|
|
302 |
|
|
303 |
adapter = DefaultAdapter()
|
|
304 |
saml_attributes['saml_at1'] = ['Jane.Doe']
|
|
305 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [
|
|
306 |
{'user_field': 'username', 'saml_attribute': 'saml_at1'},
|
|
307 |
]
|
|
308 |
assert adapter.lookup_user(idp, saml_attributes) is None
|
|
309 |
|
|
310 |
settings.MELLON_LOOKUP_BY_ATTRIBUTES = [
|
|
311 |
{'user_field': 'username', 'saml_attribute': 'saml_at1', 'ignore-case': True},
|
|
312 |
]
|
|
313 |
assert adapter.lookup_user(idp, saml_attributes) == jane
|
199 |
|
-
|