Test on old migrations are useless and they will break after squashing all migrations.
This commit is contained in:
parent
8cdbd3de56
commit
03a79037f5
|
@ -733,129 +733,6 @@ def test_change_email(settings, app, franceconnect, mailoutbox, freezer):
|
|||
assert User.objects.get().email == 'jane.doe@example.com'
|
||||
|
||||
|
||||
def test_fc_authenticator_data_migration(migration, settings):
|
||||
app = 'authentic2_auth_fc'
|
||||
migrate_from = [(app, '0005_fcauthenticator')]
|
||||
migrate_to = [(app, '0006_auto_20220525_1409')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
FcAuthenticator = old_apps.get_model(app, 'FcAuthenticator')
|
||||
|
||||
settings.AUTH_FRONTENDS_KWARGS = {
|
||||
'fc': {'priority': 3, 'show_condition': "'backoffice' not in login_hint"}
|
||||
}
|
||||
settings.A2_FC_ENABLE = True
|
||||
settings.A2_FC_CLIENT_ID = '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6k'
|
||||
settings.A2_FC_CLIENT_SECRET = '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6z'
|
||||
settings.A2_FC_AUTHORIZE_URL = 'https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize'
|
||||
settings.A2_FC_SCOPES = ['profile', 'email', 'birthdate']
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
FcAuthenticator = new_apps.get_model(app, 'FcAuthenticator')
|
||||
authenticator = FcAuthenticator.objects.get()
|
||||
assert authenticator.slug == 'fc-authenticator'
|
||||
assert authenticator.order == 3
|
||||
assert authenticator.show_condition == "'backoffice' not in login_hint"
|
||||
assert authenticator.enabled is True
|
||||
assert authenticator.platform == 'test'
|
||||
assert authenticator.client_id == '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6k'
|
||||
assert authenticator.client_secret == '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6z'
|
||||
assert authenticator.scopes == ['profile', 'email', 'birthdate']
|
||||
|
||||
# 0007 should have no effect
|
||||
new_apps = migration.apply([(app, '0007_auto_20220615_1002')])
|
||||
FcAuthenticator = new_apps.get_model(app, 'FcAuthenticator')
|
||||
assert FcAuthenticator.objects.get().pk == authenticator.pk
|
||||
|
||||
|
||||
def test_fc_authenticator_data_migration_defaults(migration, settings):
|
||||
app = 'authentic2_auth_fc'
|
||||
migrate_from = [(app, '0005_fcauthenticator')]
|
||||
migrate_to = [(app, '0006_auto_20220525_1409')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
FcAuthenticator = old_apps.get_model(app, 'FcAuthenticator')
|
||||
|
||||
settings.A2_FC_ENABLE = False
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
FcAuthenticator = new_apps.get_model(app, 'FcAuthenticator')
|
||||
authenticator = FcAuthenticator.objects.get()
|
||||
assert authenticator.slug == 'fc-authenticator'
|
||||
assert authenticator.order == -1
|
||||
assert authenticator.show_condition == ''
|
||||
assert authenticator.enabled is False
|
||||
assert authenticator.platform == 'test'
|
||||
assert authenticator.client_id == ''
|
||||
assert authenticator.client_secret == ''
|
||||
assert authenticator.scopes == ['profile', 'email']
|
||||
|
||||
|
||||
def test_fc_authenticator_data_migration_empty_configuration(migration, settings):
|
||||
app = 'authentic2_auth_fc'
|
||||
migrate_from = [(app, '0005_fcauthenticator')]
|
||||
migrate_to = [(app, '0006_auto_20220525_1409')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
FcAuthenticator = old_apps.get_model(app, 'FcAuthenticator')
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
FcAuthenticator = new_apps.get_model(app, 'FcAuthenticator')
|
||||
assert not FcAuthenticator.objects.exists()
|
||||
|
||||
|
||||
def test_fc_authenticator_data_migration_bad_settings(migration, settings):
|
||||
app = 'authentic2_auth_fc'
|
||||
migrate_from = [(app, '0005_fcauthenticator')]
|
||||
migrate_to = [(app, '0006_auto_20220525_1409')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
FcAuthenticator = old_apps.get_model(app, 'FcAuthenticator')
|
||||
|
||||
settings.AUTH_FRONTENDS_KWARGS = {'fc': {'priority': None, 'show_condition': None}}
|
||||
settings.A2_FC_ENABLE = False
|
||||
settings.A2_FC_CLIENT_ID = 'x' * 260
|
||||
settings.A2_FC_CLIENT_SECRET = None
|
||||
settings.A2_FC_AUTHORIZE_URL = 'https://fcp.integ01.dev-franceconnect.fr/api/v1/authorize'
|
||||
settings.A2_FC_SCOPES = None
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
FcAuthenticator = new_apps.get_model(app, 'FcAuthenticator')
|
||||
authenticator = FcAuthenticator.objects.get()
|
||||
assert authenticator.slug == 'fc-authenticator'
|
||||
assert authenticator.order == -1
|
||||
assert authenticator.show_condition == ''
|
||||
assert authenticator.enabled is False
|
||||
assert authenticator.platform == 'test'
|
||||
assert authenticator.client_id == 'x' * 256
|
||||
assert authenticator.client_secret == ''
|
||||
assert authenticator.scopes == ['profile', 'email']
|
||||
|
||||
|
||||
def test_fc_authenticator_data_migration_fixup(migration, settings):
|
||||
app = 'authentic2_auth_fc'
|
||||
migrate_from = [(app, '0006_auto_20220525_1409')]
|
||||
migrate_to = [(app, '0007_auto_20220615_1002')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
FcAuthenticator = old_apps.get_model(app, 'FcAuthenticator')
|
||||
|
||||
# authenticator was not created by 0006
|
||||
assert not FcAuthenticator.objects.exists()
|
||||
|
||||
settings.A2_FC_ENABLE = True
|
||||
settings.A2_FC_CLIENT_ID = '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6k'
|
||||
settings.A2_FC_CLIENT_SECRET = '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6z'
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
FcAuthenticator = new_apps.get_model(app, 'FcAuthenticator')
|
||||
|
||||
# authenticator was created by 0007
|
||||
authenticator = FcAuthenticator.objects.get()
|
||||
assert authenticator.slug == 'fc-authenticator'
|
||||
assert authenticator.client_id == '211286433e39cce01db448d80181bdfd005554b19cd51b3fe7943f6b3b86ab6k'
|
||||
|
||||
|
||||
def test_bad_email_handling(settings, app, franceconnect, caplog):
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
# authentic2 - authentic2 authentication for FranceConnect
|
||||
# Copyright (C) 2020 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/>.
|
||||
|
||||
|
||||
def test_migration_0003_0004_fcaccount_order(migration):
|
||||
migrate_from = [('authentic2_auth_fc', '0002_auto_20200416_1439')]
|
||||
# it's a two-parts migration, as it contains data and schema changes.
|
||||
migrate_to = [('authentic2_auth_fc', '0004_fcaccount_order2')]
|
||||
|
||||
old_apps = migration.before(migrate_from, at_end=False)
|
||||
|
||||
User = old_apps.get_model('custom_user', 'User')
|
||||
FcAccount = old_apps.get_model('authentic2_auth_fc', 'FcAccount')
|
||||
user1 = User.objects.create(username='user1')
|
||||
user2 = User.objects.create(username='user2')
|
||||
user3 = User.objects.create(username='user3')
|
||||
FcAccount.objects.create(user=user1, sub='sub1')
|
||||
FcAccount.objects.create(user=user1, sub='sub2')
|
||||
FcAccount.objects.create(user=user2, sub='sub2')
|
||||
FcAccount.objects.create(user=user2, sub='sub3')
|
||||
FcAccount.objects.create(user=user3, sub='sub3')
|
||||
assert len(set(FcAccount.objects.values_list('user_id', flat=True))) == 3
|
||||
assert len(set(FcAccount.objects.values_list('sub', flat=True))) == 3
|
||||
assert FcAccount.objects.count() == 5
|
||||
|
||||
# execute migration
|
||||
new_apps = migration.apply(migrate_to)
|
||||
FcAccount = new_apps.get_model('authentic2_auth_fc', 'FcAccount')
|
||||
assert len(set(FcAccount.objects.values_list('user_id', 'order'))) == 5
|
||||
assert len(set(FcAccount.objects.values_list('sub', 'order'))) == 5
|
|
@ -1308,78 +1308,6 @@ def test_auth_time_is_null(app, caplog, code, oidc_provider, oidc_provider_jwkse
|
|||
assert User.objects.count() == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'auth_frontend_kwargs',
|
||||
[
|
||||
{'oidc': {'priority': 3, 'show_condition': '"backoffice" not in login_hint'}},
|
||||
{'oidc': {'show_condition': {'baz': '"backoffice" not in login_hint', 'bar': 'True'}}},
|
||||
],
|
||||
)
|
||||
def test_oidc_provider_authenticator_data_migration(auth_frontend_kwargs, migration, settings):
|
||||
settings.AUTH_FRONTENDS_KWARGS = auth_frontend_kwargs
|
||||
|
||||
app = 'authentic2_auth_oidc'
|
||||
migrate_from = [(app, '0008_auto_20201102_1142')]
|
||||
migrate_to = [(app, '0012_auto_20220524_1147')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
OIDCProvider = old_apps.get_model(app, 'OIDCProvider')
|
||||
OIDCClaimMapping = old_apps.get_model(app, 'OIDCClaimMapping')
|
||||
OIDCAccount = old_apps.get_model(app, 'OIDCAccount')
|
||||
OrganizationalUnit = old_apps.get_model('a2_rbac', 'OrganizationalUnit')
|
||||
User = old_apps.get_model('custom_user', 'User')
|
||||
ou1 = OrganizationalUnit.objects.create(name='OU1', slug='ou1')
|
||||
issuer = 'https://baz.example.com'
|
||||
first_provider = OIDCProvider.objects.create(
|
||||
name='Baz',
|
||||
slug='baz',
|
||||
ou=ou1,
|
||||
show=True,
|
||||
issuer=issuer,
|
||||
authorization_endpoint='%s/authorize' % issuer,
|
||||
token_endpoint='%s/token' % issuer,
|
||||
end_session_endpoint='%s/logout' % issuer,
|
||||
userinfo_endpoint='%s/user_info' % issuer,
|
||||
token_revocation_endpoint='%s/revoke' % issuer,
|
||||
)
|
||||
second_provider = OIDCProvider.objects.create(name='Second', slug='second', ou=ou1)
|
||||
second_provider_claim_mapping = OIDCClaimMapping.objects.create(
|
||||
provider=second_provider, claim='second_provider', attribute='username'
|
||||
)
|
||||
user1 = User.objects.create()
|
||||
second_provider_account = OIDCAccount.objects.create(
|
||||
user=user1, provider=second_provider, sub='second_provider'
|
||||
)
|
||||
first_provider_claim_mapping = OIDCClaimMapping.objects.create(
|
||||
provider=first_provider, claim='first_provider', attribute='username'
|
||||
)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
OIDCProvider = new_apps.get_model(app, 'OIDCProvider')
|
||||
BaseAuthenticator = new_apps.get_model('authenticators', 'BaseAuthenticator')
|
||||
|
||||
authenticator = OIDCProvider.objects.get(slug='baz')
|
||||
assert authenticator.name == 'Baz'
|
||||
assert authenticator.ou.pk == ou1.pk
|
||||
assert authenticator.enabled is True
|
||||
assert authenticator.order == auth_frontend_kwargs['oidc'].get('priority', 2)
|
||||
assert authenticator.show_condition == '"backoffice" not in login_hint'
|
||||
assert authenticator.authorization_endpoint == '%s/authorize' % issuer
|
||||
assert authenticator.claim_mappings.count() == 1
|
||||
assert authenticator.claim_mappings.get().pk == first_provider_claim_mapping.pk
|
||||
assert not authenticator.accounts.exists()
|
||||
|
||||
base_authenticator = BaseAuthenticator.objects.get(slug='baz')
|
||||
assert authenticator.uuid == base_authenticator.uuid
|
||||
|
||||
second_authenticator = OIDCProvider.objects.get(slug='second')
|
||||
assert second_authenticator.name == 'Second'
|
||||
assert second_authenticator.claim_mappings.count() == 1
|
||||
assert second_authenticator.claim_mappings.get().pk == second_provider_claim_mapping.pk
|
||||
assert second_authenticator.accounts.count() == 1
|
||||
assert second_authenticator.accounts.get().pk == second_provider_account.pk
|
||||
|
||||
|
||||
def test_only_idtoken_claims(app, caplog, code, oidc_provider, oidc_provider_jwkset):
|
||||
oidc_provider.claim_mappings.update(idtoken_claim=True)
|
||||
response = app.get('/').maybe_follow()
|
||||
|
|
|
@ -125,39 +125,6 @@ class TestAddRole:
|
|||
assert role_random not in user.roles.all()
|
||||
|
||||
|
||||
def test_addroleaction_migration(role_random, migration):
|
||||
SAMLAuthenticator.objects.create(
|
||||
enabled=True,
|
||||
metadata='meta1.xml',
|
||||
slug='idp1',
|
||||
)
|
||||
|
||||
old_apps = migration.before([('authenticators', '0016_alter_addroleaction_condition')])
|
||||
AddRoleAction = old_apps.get_model('authenticators', 'AddRoleAction')
|
||||
BaseAuthenticator = old_apps.get_model('authenticators', 'BaseAuthenticator')
|
||||
Role = old_apps.get_model('a2_rbac', 'Role')
|
||||
base_authenticator = BaseAuthenticator.objects.get(slug='idp1')
|
||||
role = Role.objects.get(slug=role_random.slug)
|
||||
ara = AddRoleAction.objects.create(
|
||||
authenticator=base_authenticator, role=role, attribute_name='groups', attribute_value='Test'
|
||||
)
|
||||
ara_nocondition = AddRoleAction.objects.create(authenticator=base_authenticator, role=role)
|
||||
|
||||
new_apps = migration.apply([('authenticators', '0017_auto_20230927_1517')]) # buggy migration
|
||||
AddRoleAction = new_apps.get_model('authenticators', 'AddRoleAction')
|
||||
ara = AddRoleAction.objects.get(id=ara.id)
|
||||
ara_nocondition = AddRoleAction.objects.get(id=ara_nocondition.id)
|
||||
assert ara.condition == 'attributes.groups in "Test"'
|
||||
assert ara_nocondition.condition == 'attributes. in ""' # buggy condition
|
||||
|
||||
new_apps = migration.apply([('authenticators', '0019_fix_addroleaction_condition')])
|
||||
AddRoleAction = new_apps.get_model('authenticators', 'AddRoleAction')
|
||||
ara = AddRoleAction.objects.get(id=ara.id)
|
||||
ara_nocondition = AddRoleAction.objects.get(id=ara_nocondition.id)
|
||||
assert ara.condition == 'attributes.groups in "Test"'
|
||||
assert ara_nocondition.condition == '' # fixed
|
||||
|
||||
|
||||
def test_apply_attribute_mapping_missing_attribute_exception(
|
||||
adapter, idp, saml_attributes, title_attribute, user, rf
|
||||
):
|
||||
|
|
|
@ -1,428 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2022 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 os
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration(migration, settings):
|
||||
app = 'authentic2_auth_saml'
|
||||
migrate_from = [(app, '0001_initial')]
|
||||
migrate_to = [(app, '0002_auto_20220608_1559')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model(app, 'SAMLAuthenticator')
|
||||
|
||||
settings.A2_AUTH_SAML_ENABLE = True
|
||||
settings.MELLON_METADATA_CACHE_TIME = 42
|
||||
settings.MELLON_METADATA_HTTP_TIMEOUT = 42
|
||||
settings.MELLON_PROVISION = False
|
||||
settings.MELLON_VERIFY_SSL_CERTIFICATE = True
|
||||
settings.MELLON_TRANSIENT_FEDERATION_ATTRIBUTE = None
|
||||
settings.MELLON_USERNAME_TEMPLATE = 'test'
|
||||
settings.MELLON_NAME_ID_POLICY_ALLOW_CREATE = False
|
||||
settings.MELLON_FORCE_AUTHN = True
|
||||
settings.MELLON_ADD_AUTHNREQUEST_NEXT_URL_EXTENSION = False
|
||||
settings.MELLON_GROUP_ATTRIBUTE = 'role'
|
||||
settings.MELLON_CREATE_GROUP = True
|
||||
settings.MELLON_ERROR_URL = 'https://example.com/error/'
|
||||
settings.MELLON_AUTHN_CLASSREF = ('class1', 'class2')
|
||||
settings.MELLON_LOGIN_HINTS = ['hint1', 'hint2']
|
||||
settings.AUTH_FRONTENDS_KWARGS = {
|
||||
'saml': {
|
||||
'priority': 1,
|
||||
'show_condition': {
|
||||
'0': 'first condition',
|
||||
'1': 'second condition',
|
||||
},
|
||||
}
|
||||
}
|
||||
settings.MELLON_IDENTITY_PROVIDERS = [
|
||||
{
|
||||
'METADATA': os.path.join(os.path.dirname(__file__), 'metadata.xml'),
|
||||
'REALM': 'test',
|
||||
'METADATA_CACHE_TIME': 43,
|
||||
'METADATA_HTTP_TIMEOUT': 43,
|
||||
'PROVISION': True,
|
||||
'LOOKUP_BY_ATTRIBUTES': [],
|
||||
},
|
||||
{
|
||||
'METADATA_PATH': os.path.join(os.path.dirname(__file__), 'metadata.xml'),
|
||||
'NAME_ID_POLICY_ALLOW_CREATE': True,
|
||||
'FORCE_AUTHN': False,
|
||||
'ADD_AUTHNREQUEST_NEXT_URL_EXTENSION': True,
|
||||
'A2_ATTRIBUTE_MAPPING': [
|
||||
{
|
||||
'attribute': 'email',
|
||||
'saml_attribute': 'mail',
|
||||
},
|
||||
],
|
||||
'LOOKUP_BY_ATTRIBUTES': [{'saml_attribute': 'email', 'user_field': 'email'}],
|
||||
},
|
||||
{
|
||||
'METADATA_URL': 'https://example.com/metadata.xml',
|
||||
'SLUG': 'third',
|
||||
'ATTRIBUTE_MAPPING': {'email': 'attributes[mail][0]'},
|
||||
'SUPERUSER_MAPPING': {'roles': 'Admin'},
|
||||
},
|
||||
]
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model(app, 'SAMLAuthenticator')
|
||||
first_authenticator, second_authenticator, third_authenticator = SAMLAuthenticator.objects.all()
|
||||
assert first_authenticator.slug == '0'
|
||||
assert first_authenticator.order == 1
|
||||
assert first_authenticator.show_condition == 'first condition'
|
||||
assert first_authenticator.enabled is True
|
||||
assert first_authenticator.metadata_path == os.path.join(os.path.dirname(__file__), 'metadata.xml')
|
||||
assert first_authenticator.metadata_url == ''
|
||||
assert first_authenticator.metadata_cache_time == 43
|
||||
assert first_authenticator.metadata_http_timeout == 43
|
||||
assert first_authenticator.provision is True
|
||||
assert first_authenticator.verify_ssl_certificate is True
|
||||
assert first_authenticator.transient_federation_attribute == ''
|
||||
assert first_authenticator.realm == 'test'
|
||||
assert first_authenticator.username_template == 'test'
|
||||
assert first_authenticator.name_id_policy_format == ''
|
||||
assert first_authenticator.name_id_policy_allow_create is False
|
||||
assert first_authenticator.force_authn is True
|
||||
assert first_authenticator.add_authnrequest_next_url_extension is False
|
||||
assert first_authenticator.group_attribute == 'role'
|
||||
assert first_authenticator.create_group is True
|
||||
assert first_authenticator.error_url == 'https://example.com/error/'
|
||||
assert first_authenticator.error_redirect_after_timeout == 120
|
||||
assert first_authenticator.authn_classref == 'class1, class2'
|
||||
assert first_authenticator.login_hints == 'hint1, hint2'
|
||||
assert first_authenticator.lookup_by_attributes == []
|
||||
assert first_authenticator.a2_attribute_mapping == []
|
||||
assert first_authenticator.attribute_mapping == {}
|
||||
assert first_authenticator.superuser_mapping == {}
|
||||
|
||||
assert second_authenticator.slug == '1'
|
||||
assert second_authenticator.order == 1
|
||||
assert second_authenticator.show_condition == 'second condition'
|
||||
assert second_authenticator.enabled is True
|
||||
assert second_authenticator.metadata_path == os.path.join(os.path.dirname(__file__), 'metadata.xml')
|
||||
assert second_authenticator.metadata_url == ''
|
||||
assert second_authenticator.metadata_cache_time == 42
|
||||
assert second_authenticator.metadata_http_timeout == 42
|
||||
assert second_authenticator.provision is False
|
||||
assert second_authenticator.verify_ssl_certificate is True
|
||||
assert second_authenticator.transient_federation_attribute == ''
|
||||
assert second_authenticator.realm == 'saml'
|
||||
assert second_authenticator.username_template == 'test'
|
||||
assert second_authenticator.name_id_policy_format == ''
|
||||
assert second_authenticator.name_id_policy_allow_create is True
|
||||
assert second_authenticator.force_authn is False
|
||||
assert second_authenticator.add_authnrequest_next_url_extension is True
|
||||
assert second_authenticator.group_attribute == 'role'
|
||||
assert second_authenticator.create_group is True
|
||||
assert second_authenticator.error_url == 'https://example.com/error/'
|
||||
assert second_authenticator.error_redirect_after_timeout == 120
|
||||
assert second_authenticator.authn_classref == 'class1, class2'
|
||||
assert second_authenticator.login_hints == 'hint1, hint2'
|
||||
assert second_authenticator.lookup_by_attributes == [{'saml_attribute': 'email', 'user_field': 'email'}]
|
||||
assert second_authenticator.a2_attribute_mapping == [
|
||||
{
|
||||
'attribute': 'email',
|
||||
'saml_attribute': 'mail',
|
||||
},
|
||||
]
|
||||
assert first_authenticator.attribute_mapping == {}
|
||||
assert first_authenticator.superuser_mapping == {}
|
||||
|
||||
assert third_authenticator.slug == 'third'
|
||||
assert third_authenticator.order == 1
|
||||
assert third_authenticator.show_condition == ''
|
||||
assert third_authenticator.enabled is True
|
||||
assert third_authenticator.metadata_path == ''
|
||||
assert third_authenticator.metadata_url == 'https://example.com/metadata.xml'
|
||||
assert third_authenticator.metadata_cache_time == 42
|
||||
assert third_authenticator.metadata_http_timeout == 42
|
||||
assert third_authenticator.provision is False
|
||||
assert third_authenticator.verify_ssl_certificate is True
|
||||
assert third_authenticator.transient_federation_attribute == ''
|
||||
assert third_authenticator.realm == 'saml'
|
||||
assert third_authenticator.username_template == 'test'
|
||||
assert third_authenticator.name_id_policy_format == ''
|
||||
assert third_authenticator.name_id_policy_format == ''
|
||||
assert third_authenticator.name_id_policy_allow_create is False
|
||||
assert third_authenticator.force_authn is True
|
||||
assert third_authenticator.group_attribute == 'role'
|
||||
assert third_authenticator.create_group is True
|
||||
assert third_authenticator.error_url == 'https://example.com/error/'
|
||||
assert third_authenticator.error_redirect_after_timeout == 120
|
||||
assert third_authenticator.authn_classref == 'class1, class2'
|
||||
assert third_authenticator.login_hints == 'hint1, hint2'
|
||||
assert third_authenticator.lookup_by_attributes == [
|
||||
{'saml_attribute': 'email', 'user_field': 'email', 'ignore-case': True},
|
||||
{'saml_attribute': 'username', 'user_field': 'username'},
|
||||
]
|
||||
assert third_authenticator.a2_attribute_mapping == []
|
||||
assert third_authenticator.attribute_mapping == {'email': 'attributes[mail][0]'}
|
||||
assert third_authenticator.superuser_mapping == {'roles': 'Admin'}
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration_empty_configuration(migration, settings):
|
||||
app = 'authentic2_auth_saml'
|
||||
migrate_from = [(app, '0001_initial')]
|
||||
migrate_to = [(app, '0002_auto_20220608_1559')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model(app, 'SAMLAuthenticator')
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model(app, 'SAMLAuthenticator')
|
||||
assert not SAMLAuthenticator.objects.exists()
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration_bad_settings(migration, settings):
|
||||
app = 'authentic2_auth_saml'
|
||||
migrate_from = [(app, '0001_initial')]
|
||||
migrate_to = [(app, '0002_auto_20220608_1559')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model(app, 'SAMLAuthenticator')
|
||||
|
||||
settings.AUTH_FRONTENDS_KWARGS = {'saml': {'priority': None, 'show_condition': None}}
|
||||
settings.MELLON_METADATA_CACHE_TIME = 2**16
|
||||
settings.MELLON_METADATA_HTTP_TIMEOUT = -1
|
||||
settings.MELLON_PROVISION = None
|
||||
settings.MELLON_USERNAME_TEMPLATE = 42
|
||||
settings.MELLON_GROUP_ATTRIBUTE = None
|
||||
settings.MELLON_ERROR_URL = 'a' * 500
|
||||
settings.MELLON_AUTHN_CLASSREF = 'not-a-list'
|
||||
settings.MELLON_IDENTITY_PROVIDERS = [
|
||||
{
|
||||
'METADATA': os.path.join(os.path.dirname(__file__), 'metadata.xml'),
|
||||
'ERROR_REDIRECT_AFTER_TIMEOUT': -1,
|
||||
'SUPERUSER_MAPPING': 'not-a-dict',
|
||||
},
|
||||
]
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model(app, 'SAMLAuthenticator')
|
||||
authenticator = SAMLAuthenticator.objects.get()
|
||||
assert authenticator.slug == '0'
|
||||
assert authenticator.order == 3
|
||||
assert authenticator.show_condition == ''
|
||||
assert authenticator.enabled is False
|
||||
assert authenticator.metadata_cache_time == 3600
|
||||
assert authenticator.metadata_http_timeout == 10
|
||||
assert authenticator.provision is True
|
||||
assert authenticator.username_template == '{attributes[name_id_content]}@{realm}'
|
||||
assert authenticator.group_attribute == ''
|
||||
assert authenticator.error_url == 'a' * 200
|
||||
assert authenticator.error_redirect_after_timeout == 120
|
||||
assert authenticator.authn_classref == ''
|
||||
assert authenticator.superuser_mapping == {}
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration_json_fields(migration, settings):
|
||||
migrate_from = [
|
||||
(
|
||||
'authentic2_auth_saml',
|
||||
'0005_addroleaction_renameattributeaction_samlattributelookup_setattributeaction',
|
||||
),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
migrate_to = [
|
||||
('authentic2_auth_saml', '0006_migrate_jsonfields'),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
Role = old_apps.get_model('a2_rbac', 'Role')
|
||||
OU = old_apps.get_model('a2_rbac', 'OrganizationalUnit')
|
||||
|
||||
ou = OU.objects.create(name='Test OU', slug='test-ou')
|
||||
role = Role.objects.create(name='Test role', slug='test-role', ou=ou)
|
||||
|
||||
SAMLAuthenticator.objects.create(
|
||||
metadata='meta1.xml',
|
||||
slug='idp1',
|
||||
lookup_by_attributes=[
|
||||
{'saml_attribute': 'email', 'user_field': 'email'},
|
||||
{'saml_attribute': 'saml_name', 'user_field': 'first_name', 'ignore-case': True},
|
||||
],
|
||||
a2_attribute_mapping=[
|
||||
{
|
||||
'attribute': 'email',
|
||||
'saml_attribute': 'mail',
|
||||
'mandatory': True,
|
||||
},
|
||||
{'action': 'rename', 'from': 'a' * 1025, 'to': 'first_name'},
|
||||
{
|
||||
'attribute': 'first_name',
|
||||
'saml_attribute': 'first_name',
|
||||
},
|
||||
{
|
||||
'attribute': 'invalid',
|
||||
'saml_attribute': '',
|
||||
},
|
||||
{
|
||||
'attribute': 'invalid',
|
||||
'saml_attribute': None,
|
||||
},
|
||||
{
|
||||
'attribute': 'invalid',
|
||||
},
|
||||
{
|
||||
'action': 'add-role',
|
||||
'role': {
|
||||
'name': role.name,
|
||||
'ou': {
|
||||
'name': role.ou.name,
|
||||
},
|
||||
},
|
||||
'condition': "roles == 'A'",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
authenticator = SAMLAuthenticator.objects.get()
|
||||
|
||||
attribute_lookup1, attribute_lookup2 = authenticator.attribute_lookups.all().order_by('pk')
|
||||
assert attribute_lookup1.saml_attribute == 'email'
|
||||
assert attribute_lookup1.user_field == 'email'
|
||||
assert attribute_lookup1.ignore_case is False
|
||||
assert attribute_lookup2.saml_attribute == 'saml_name'
|
||||
assert attribute_lookup2.user_field == 'first_name'
|
||||
assert attribute_lookup2.ignore_case is True
|
||||
|
||||
set_attribute1, set_attribute2 = authenticator.set_attribute_actions.all().order_by('pk')
|
||||
assert set_attribute1.attribute == 'email'
|
||||
assert set_attribute1.saml_attribute == 'mail'
|
||||
assert set_attribute1.mandatory is True
|
||||
assert set_attribute2.attribute == 'first_name'
|
||||
assert set_attribute2.saml_attribute == 'first_name'
|
||||
assert set_attribute2.mandatory is False
|
||||
|
||||
rename_attribute = authenticator.rename_attribute_actions.get()
|
||||
assert rename_attribute.from_name == 'a' * 1024
|
||||
assert rename_attribute.to_name == 'first_name'
|
||||
|
||||
add_role = authenticator.add_role_actions.get()
|
||||
assert add_role.role.pk == role.pk
|
||||
assert add_role.condition == "roles == 'A'"
|
||||
assert add_role.mandatory is False
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration_json_fields_log_errors(migration, settings, caplog):
|
||||
migrate_from = [
|
||||
(
|
||||
'authentic2_auth_saml',
|
||||
'0005_addroleaction_renameattributeaction_samlattributelookup_setattributeaction',
|
||||
),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
migrate_to = [
|
||||
('authentic2_auth_saml', '0006_migrate_jsonfields'),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
|
||||
SAMLAuthenticator.objects.create(
|
||||
metadata='meta1.xml',
|
||||
slug='idp1',
|
||||
lookup_by_attributes=[{'saml_attribute': 'email', 'user_field': 'email'}],
|
||||
a2_attribute_mapping=['bad'],
|
||||
)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
|
||||
authenticator = SAMLAuthenticator.objects.get()
|
||||
assert not authenticator.attribute_lookups.exists()
|
||||
|
||||
assert caplog.messages == [
|
||||
'could not create related objects for authenticator SAMLAuthenticator object (%s)' % authenticator.pk,
|
||||
'attribute mapping for SAMLAuthenticator object (%s): ["bad"]' % authenticator.pk,
|
||||
'lookup by attributes for SAMLAuthenticator object (%s): [{"user_field": "email", "saml_attribute": "email"}]'
|
||||
% authenticator.pk,
|
||||
]
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration_rename_attributes(migration, settings):
|
||||
migrate_from = [('authentic2_auth_saml', '0008_auto_20220913_1105')]
|
||||
migrate_to = [('authentic2_auth_saml', '0009_statically_rename_attributes')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
RenameAttributeAction = old_apps.get_model('authentic2_auth_saml', 'RenameAttributeAction')
|
||||
SetAttributeAction = old_apps.get_model('authentic2_auth_saml', 'SetAttributeAction')
|
||||
SAMLAttributeLookup = old_apps.get_model('authentic2_auth_saml', 'SAMLAttributeLookup')
|
||||
|
||||
authenticator = SAMLAuthenticator.objects.create(slug='idp1')
|
||||
RenameAttributeAction.objects.create(
|
||||
authenticator=authenticator, from_name='http://nice/attribute/givenName', to_name='first_name'
|
||||
)
|
||||
SAMLAttributeLookup.objects.create(
|
||||
authenticator=authenticator, user_field='first_name', saml_attribute='first_name'
|
||||
)
|
||||
SAMLAttributeLookup.objects.create(
|
||||
authenticator=authenticator, user_field='title', saml_attribute='title'
|
||||
)
|
||||
SetAttributeAction.objects.create(
|
||||
authenticator=authenticator, user_field='first_name', saml_attribute='first_name'
|
||||
)
|
||||
SetAttributeAction.objects.create(authenticator=authenticator, user_field='title', saml_attribute='title')
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
authenticator = SAMLAuthenticator.objects.get()
|
||||
|
||||
attribute_lookup1, attribute_lookup2 = authenticator.attribute_lookups.all().order_by('pk')
|
||||
assert attribute_lookup1.saml_attribute == 'http://nice/attribute/givenName'
|
||||
assert attribute_lookup1.user_field == 'first_name'
|
||||
assert attribute_lookup2.saml_attribute == 'title'
|
||||
assert attribute_lookup2.user_field == 'title'
|
||||
|
||||
set_attribute1, set_attribute2 = authenticator.set_attribute_actions.all().order_by('pk')
|
||||
assert set_attribute1.saml_attribute == 'http://nice/attribute/givenName'
|
||||
assert set_attribute1.user_field == 'first_name'
|
||||
assert set_attribute2.saml_attribute == 'title'
|
||||
assert set_attribute2.user_field == 'title'
|
||||
|
||||
|
||||
def test_saml_authenticator_data_migration_metadata_file_to_db(migration, settings):
|
||||
migrate_from = [('authentic2_auth_saml', '0012_move_add_role_action')]
|
||||
migrate_to = [('authentic2_auth_saml', '0014_remove_samlauthenticator_metadata_path')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
SAMLAuthenticator = old_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
|
||||
SAMLAuthenticator.objects.create(
|
||||
slug='idp1', metadata_path=os.path.join(os.path.dirname(__file__), 'metadata.xml')
|
||||
)
|
||||
|
||||
SAMLAuthenticator.objects.create(slug='idp2', metadata='xxx')
|
||||
SAMLAuthenticator.objects.create(slug='idp3', metadata_url='https://example.com')
|
||||
SAMLAuthenticator.objects.create(slug='idp4', metadata_path='/unknown/')
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
SAMLAuthenticator = new_apps.get_model('authentic2_auth_saml', 'SAMLAuthenticator')
|
||||
|
||||
authenticator = SAMLAuthenticator.objects.get(slug='idp1')
|
||||
assert authenticator.metadata.startswith('<?xml version="1.0"?>')
|
||||
assert authenticator.metadata.endswith('</EntityDescriptor>\n')
|
||||
|
||||
assert SAMLAuthenticator.objects.filter(slug='idp2', metadata='xxx').count() == 1
|
||||
assert SAMLAuthenticator.objects.filter(slug='idp3', metadata_url='https://example.com').count() == 1
|
|
@ -1,125 +0,0 @@
|
|||
# authentic2 - versatile identity manager
|
||||
# Copyright (C) 2010-2021 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/>.
|
||||
|
||||
|
||||
def test_oidclient_claims_data_migration(migration):
|
||||
app = 'authentic2_idp_oidc'
|
||||
migrate_from = [(app, '0009_auto_20180313_1156')]
|
||||
migrate_to = [(app, '0010_oidcclaim')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
OIDCClient = old_apps.get_model('authentic2_idp_oidc', 'OIDCClient')
|
||||
|
||||
client = OIDCClient(name='test', slug='test', redirect_uris='https://example.net/')
|
||||
client.save()
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
OIDCClient = new_apps.get_model('authentic2_idp_oidc', 'OIDCClient')
|
||||
OIDCClaim = new_apps.get_model('authentic2_idp_oidc', 'OIDCClaim')
|
||||
|
||||
client = OIDCClient.objects.first()
|
||||
assert OIDCClaim.objects.filter(client=client.id).count() == 5
|
||||
|
||||
|
||||
def test_oidclient_preferred_username_as_identifier_data_migration(migration):
|
||||
app = 'authentic2_idp_oidc'
|
||||
migrate_from = [(app, '0010_oidcclaim')]
|
||||
migrate_to = [(app, '0011_auto_20180808_1546')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
OIDCClient = old_apps.get_model('authentic2_idp_oidc', 'OIDCClient')
|
||||
OIDCClaim = old_apps.get_model('authentic2_idp_oidc', 'OIDCClaim')
|
||||
|
||||
client1 = OIDCClient.objects.create(name='test', slug='test', redirect_uris='https://example.net/')
|
||||
client2 = OIDCClient.objects.create(name='test1', slug='test1', redirect_uris='https://example.net/')
|
||||
client3 = OIDCClient.objects.create(name='test2', slug='test2', redirect_uris='https://example.net/')
|
||||
client4 = OIDCClient.objects.create(name='test3', slug='test3', redirect_uris='https://example.net/')
|
||||
for client in (client1, client2, client3, client4):
|
||||
if client.name == 'test1':
|
||||
continue
|
||||
if client.name == 'test3':
|
||||
OIDCClaim.objects.create(
|
||||
client=client, name='preferred_username', value='django_user_full_name', scopes='profile'
|
||||
)
|
||||
else:
|
||||
OIDCClaim.objects.create(
|
||||
client=client, name='preferred_username', value='django_user_username', scopes='profile'
|
||||
)
|
||||
OIDCClaim.objects.create(
|
||||
client=client, name='given_name', value='django_user_first_name', scopes='profile'
|
||||
)
|
||||
OIDCClaim.objects.create(
|
||||
client=client, name='family_name', value='django_user_last_name', scopes='profile'
|
||||
)
|
||||
if client.name == 'test2':
|
||||
continue
|
||||
OIDCClaim.objects.create(client=client, name='email', value='django_user_email', scopes='email')
|
||||
OIDCClaim.objects.create(
|
||||
client=client, name='email_verified', value='django_user_email_verified', scopes='email'
|
||||
)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
OIDCClient = new_apps.get_model('authentic2_idp_oidc', 'OIDCClient')
|
||||
|
||||
client = OIDCClient.objects.first()
|
||||
for client in OIDCClient.objects.all():
|
||||
claims = client.oidcclaim_set.all()
|
||||
if client.name == 'test':
|
||||
assert claims.count() == 5
|
||||
assert sorted(claims.values_list('name', flat=True)) == [
|
||||
'email',
|
||||
'email_verified',
|
||||
'family_name',
|
||||
'given_name',
|
||||
'preferred_username',
|
||||
]
|
||||
assert sorted(claims.values_list('value', flat=True)) == [
|
||||
'django_user_email',
|
||||
'django_user_email_verified',
|
||||
'django_user_first_name',
|
||||
'django_user_identifier',
|
||||
'django_user_last_name',
|
||||
]
|
||||
elif client.name == 'test2':
|
||||
assert claims.count() == 3
|
||||
assert sorted(claims.values_list('name', flat=True)) == [
|
||||
'family_name',
|
||||
'given_name',
|
||||
'preferred_username',
|
||||
]
|
||||
assert sorted(claims.values_list('value', flat=True)) == [
|
||||
'django_user_first_name',
|
||||
'django_user_last_name',
|
||||
'django_user_username',
|
||||
]
|
||||
elif client.name == 'test3':
|
||||
assert claims.count() == 5
|
||||
assert sorted(claims.values_list('name', flat=True)) == [
|
||||
'email',
|
||||
'email_verified',
|
||||
'family_name',
|
||||
'given_name',
|
||||
'preferred_username',
|
||||
]
|
||||
assert sorted(claims.values_list('value', flat=True)) == [
|
||||
'django_user_email',
|
||||
'django_user_email_verified',
|
||||
'django_user_first_name',
|
||||
'django_user_full_name',
|
||||
'django_user_last_name',
|
||||
]
|
||||
else:
|
||||
assert claims.count() == 0
|
|
@ -19,7 +19,7 @@ from django.contrib.contenttypes.models import ContentType
|
|||
from django.core.exceptions import ValidationError
|
||||
from django.core.management import call_command
|
||||
|
||||
from authentic2.a2_rbac.models import CHANGE_OP, MANAGE_MEMBERS_OP, Operation
|
||||
from authentic2.a2_rbac.models import CHANGE_OP, Operation
|
||||
from authentic2.a2_rbac.models import OrganizationalUnit as OU
|
||||
from authentic2.a2_rbac.models import Permission, Role
|
||||
from authentic2.a2_rbac.utils import get_default_ou
|
||||
|
@ -542,48 +542,6 @@ def test_update_content_types_roles(transactional_db, simple_user):
|
|||
assert [x for x in simple_user.get_all_permissions() if x == 'custom_user.manage_authorizations_user']
|
||||
|
||||
|
||||
@pytest.mark.parametrize('new_perm_exists', [True, False])
|
||||
def test_update_self_admin_perm_migration(migration, new_perm_exists):
|
||||
old_apps = migration.before([('a2_rbac', '0022_auto_20200402_1101')])
|
||||
Role = old_apps.get_model('a2_rbac', 'Role')
|
||||
old_apps.get_model('a2_rbac', 'OrganizationalUnit')
|
||||
Permission = old_apps.get_model('a2_rbac', 'Permission')
|
||||
Operation = old_apps.get_model('django_rbac', 'Operation')
|
||||
ContentType = old_apps.get_model('contenttypes', 'ContentType')
|
||||
ct = ContentType.objects.get_for_model(Role)
|
||||
change_op, _ = Operation.objects.get_or_create(slug=CHANGE_OP.slug)
|
||||
manage_members_op, _ = Operation.objects.get_or_create(slug=MANAGE_MEMBERS_OP.slug)
|
||||
|
||||
# add old self administration
|
||||
role = Role.objects.create(name='name', slug='slug')
|
||||
self_perm, _ = Permission.objects.get_or_create(operation=change_op, target_ct=ct, target_id=role.pk)
|
||||
role.permissions.add(self_perm)
|
||||
|
||||
if new_perm_exists:
|
||||
new_self_perm, _ = Permission.objects.get_or_create(
|
||||
operation=manage_members_op, target_ct=ct, target_id=role.pk
|
||||
)
|
||||
else:
|
||||
Permission.objects.filter(operation=manage_members_op, target_ct=ct, target_id=role.pk).delete()
|
||||
|
||||
new_apps = migration.apply([('a2_rbac', '0024_fix_self_admin_perm')])
|
||||
Role = new_apps.get_model('a2_rbac', 'Role')
|
||||
Operation = old_apps.get_model('django_rbac', 'Operation')
|
||||
|
||||
role = Role.objects.get(slug='slug')
|
||||
assert role.permissions.count() == 1
|
||||
|
||||
perm = role.permissions.first()
|
||||
assert perm.operation.pk == manage_members_op.pk
|
||||
assert perm.target_ct.pk == ct.pk
|
||||
assert perm.target_id == role.pk
|
||||
|
||||
if new_perm_exists:
|
||||
assert perm.pk == new_self_perm.pk
|
||||
|
||||
assert not Permission.objects.filter(operation=change_op, target_ct=ct, target_id=role.pk).exists()
|
||||
|
||||
|
||||
class TestRole:
|
||||
@scoped_db_fixture(scope='class')
|
||||
def fixture(self):
|
||||
|
@ -707,118 +665,3 @@ class TestRole:
|
|||
def test_direct(self, db, fixture):
|
||||
assert set(fixture.role.children(direct=True)) == {fixture.role, fixture.child}
|
||||
assert fixture.role.children(include_self=False, direct=True).get() == fixture.child
|
||||
|
||||
|
||||
def test_a2_rbac_operation_migration(migration, settings):
|
||||
migrate_from = [
|
||||
('a2_rbac', '0030_organizationalunit_min_password_strength'),
|
||||
('django_rbac', '0009_auto_20221004_1343'),
|
||||
]
|
||||
migrate_to = [('a2_rbac', '0033_remove_old_operation_fk')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
ContentType = old_apps.get_model('contenttypes', 'ContentType')
|
||||
Operation = old_apps.get_model('django_rbac', 'Operation')
|
||||
Permission = old_apps.get_model('a2_rbac', 'Permission')
|
||||
|
||||
# check objects created by signal handlers
|
||||
base_operation = Operation.objects.get(slug='view')
|
||||
base_permission = Permission.objects.filter(operation=base_operation).first()
|
||||
|
||||
# check other objects
|
||||
new_operation = Operation.objects.create(slug='test')
|
||||
Permission.objects.create(
|
||||
operation=new_operation,
|
||||
target_ct=ContentType.objects.get_for_model(ContentType),
|
||||
target_id=ContentType.objects.get_for_model(User).pk,
|
||||
)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
ContentType = new_apps.get_model('contenttypes', 'ContentType')
|
||||
Operation = new_apps.get_model('a2_rbac', 'Operation')
|
||||
Permission = new_apps.get_model('a2_rbac', 'Permission')
|
||||
|
||||
base_operation = Operation.objects.get(slug='view')
|
||||
assert (
|
||||
Permission.objects.filter(
|
||||
operation_id=base_operation,
|
||||
target_ct_id=base_permission.target_ct.pk,
|
||||
target_id=base_permission.target_id,
|
||||
).count()
|
||||
== 1
|
||||
)
|
||||
|
||||
new_operation = Operation.objects.get(slug=new_operation.slug)
|
||||
assert (
|
||||
Permission.objects.filter(
|
||||
operation=new_operation,
|
||||
target_ct=ContentType.objects.get_for_model(ContentType),
|
||||
target_id=ContentType.objects.get_for_model(User).pk,
|
||||
).count()
|
||||
== 1
|
||||
)
|
||||
|
||||
|
||||
def test_a2_rbac_role_attribute_migration(migration, settings):
|
||||
migrate_from = [('a2_rbac', '0034_new_role_fields')]
|
||||
migrate_to = [('a2_rbac', '0036_delete_roleattribute')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
Role = old_apps.get_model('a2_rbac', 'Role')
|
||||
RoleAttribute = old_apps.get_model('a2_rbac', 'RoleAttribute')
|
||||
|
||||
role = Role.objects.create(name='role', slug='1')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='details', value='"abc"')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='emails', value='["a@a.com", "b@b.com"]')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='emails_to_members', value='false')
|
||||
RoleAttribute.objects.create(role=role, kind='string', name='is_superuser', value='true')
|
||||
|
||||
role = Role.objects.create(name='role_default_values', slug='2')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='details', value='""')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='emails', value='[]')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='emails_to_members', value='true')
|
||||
RoleAttribute.objects.create(role=role, kind='string', name='is_superuser', value='false')
|
||||
|
||||
role = Role.objects.create(name='role_no_attribute', slug='3')
|
||||
|
||||
role = Role.objects.create(name='role_bad_attributes', slug='4')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='details', value='bad')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='emails', value='true')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='emails_to_members', value='bad')
|
||||
RoleAttribute.objects.create(role=role, kind='string', name='unknown', value='xxx')
|
||||
|
||||
role = Role.objects.create(name='role_one_attribute', slug='5')
|
||||
RoleAttribute.objects.create(role=role, kind='json', name='details', value='"xxx"')
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
Role = new_apps.get_model('a2_rbac', 'Role')
|
||||
|
||||
role = Role.objects.get(name='role')
|
||||
assert role.details == 'abc'
|
||||
assert role.emails == ['a@a.com', 'b@b.com']
|
||||
assert role.emails_to_members is False
|
||||
assert role.is_superuser is True
|
||||
|
||||
role = Role.objects.get(name='role_default_values')
|
||||
assert role.details == ''
|
||||
assert role.emails == []
|
||||
assert role.emails_to_members is True
|
||||
assert role.is_superuser is False
|
||||
|
||||
role = Role.objects.get(name='role_no_attribute')
|
||||
assert role.details == ''
|
||||
assert role.emails == []
|
||||
assert role.emails_to_members is True
|
||||
assert role.is_superuser is False
|
||||
|
||||
role = Role.objects.get(name='role_bad_attributes')
|
||||
assert role.details == ''
|
||||
assert role.emails == []
|
||||
assert role.emails_to_members is True
|
||||
assert role.is_superuser is False
|
||||
|
||||
role = Role.objects.get(name='role_one_attribute')
|
||||
assert role.details == 'xxx'
|
||||
assert role.emails == []
|
||||
assert role.emails_to_members is True
|
||||
assert role.is_superuser is False
|
||||
|
|
|
@ -602,157 +602,3 @@ def test_button_description(app, db):
|
|||
|
||||
response = app.get('/login/')
|
||||
assert 'This is a test.' in response.text
|
||||
|
||||
|
||||
def test_password_authenticator_data_migration(migration, settings):
|
||||
app = 'authenticators'
|
||||
migrate_from = [(app, '0002_loginpasswordauthenticator')]
|
||||
migrate_to = [(app, '0003_auto_20220413_1504')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
LoginPasswordAuthenticator = old_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
|
||||
settings.AUTH_FRONTENDS_KWARGS = {
|
||||
'password': {'priority': -1, 'show_condition': "'backoffice' not in login_hint"}
|
||||
}
|
||||
settings.A2_LOGIN_FORM_OU_SELECTOR = True
|
||||
settings.A2_AUTH_PASSWORD_ENABLE = False
|
||||
settings.A2_USER_REMEMBER_ME = 42
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
assert authenticator.slug == 'password-authenticator'
|
||||
assert authenticator.order == -1
|
||||
assert authenticator.show_condition == "'backoffice' not in login_hint"
|
||||
assert authenticator.enabled is False
|
||||
assert authenticator.remember_me == 42
|
||||
assert authenticator.include_ou_selector is True
|
||||
|
||||
|
||||
def test_password_authenticator_data_migration_new_settings(migration, settings):
|
||||
app = 'authenticators'
|
||||
migrate_from = [(app, '0008_new_password_settings_fields')]
|
||||
migrate_to = [(app, '0009_migrate_new_password_settings')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
LoginPasswordAuthenticator = old_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
|
||||
settings.A2_PASSWORD_POLICY_MIN_LENGTH = 10
|
||||
settings.A2_PASSWORD_POLICY_REGEX = '^.*ok.*$'
|
||||
settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG = 'not ok'
|
||||
settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_DURATION = 10.5
|
||||
settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_FACTOR = 1
|
||||
settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_MAX_DURATION = 100
|
||||
settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_MIN_DURATION = 200
|
||||
settings.A2_EMAILS_IP_RATELIMIT = '42/h'
|
||||
settings.A2_SMS_IP_RATELIMIT = '43/h'
|
||||
settings.A2_EMAILS_ADDRESS_RATELIMIT = '44/h'
|
||||
settings.A2_SMS_NUMBER_RATELIMIT = '45/h'
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
assert authenticator.password_min_length == 10
|
||||
assert authenticator.password_regex == '^.*ok.*$'
|
||||
assert authenticator.password_regex_error_msg == 'not ok'
|
||||
assert authenticator.login_exponential_retry_timeout_duration == 10.5
|
||||
assert authenticator.login_exponential_retry_timeout_factor == 1
|
||||
assert authenticator.login_exponential_retry_timeout_max_duration == 100
|
||||
assert authenticator.login_exponential_retry_timeout_min_duration == 200
|
||||
assert authenticator.emails_ip_ratelimit == '42/h'
|
||||
assert authenticator.sms_ip_ratelimit == '43/h'
|
||||
assert authenticator.emails_address_ratelimit == '44/h'
|
||||
assert authenticator.sms_number_ratelimit == '45/h'
|
||||
|
||||
|
||||
def test_password_authenticator_data_migration_new_settings_invalid(migration, settings):
|
||||
app = 'authenticators'
|
||||
migrate_from = [(app, '0008_new_password_settings_fields')]
|
||||
migrate_to = [(app, '0009_migrate_new_password_settings')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
LoginPasswordAuthenticator = old_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
|
||||
settings.A2_PASSWORD_POLICY_MIN_LENGTH = 'abc'
|
||||
settings.A2_PASSWORD_POLICY_REGEX = None
|
||||
settings.A2_PASSWORD_POLICY_REGEX_ERROR_MSG = 42
|
||||
settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_DURATION = None
|
||||
settings.A2_LOGIN_EXPONENTIAL_RETRY_TIMEOUT_MAX_DURATION = 10.5
|
||||
settings.A2_EMAILS_IP_RATELIMIT = None
|
||||
settings.A2_SMS_IP_RATELIMIT = 42
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
assert authenticator.password_min_length == 8
|
||||
assert authenticator.password_regex == ''
|
||||
assert authenticator.password_regex_error_msg == ''
|
||||
assert authenticator.login_exponential_retry_timeout_duration == 1
|
||||
assert authenticator.login_exponential_retry_timeout_max_duration == 10
|
||||
assert authenticator.emails_ip_ratelimit == '10/h'
|
||||
assert authenticator.sms_ip_ratelimit == '10/h'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('email,phone', [(True, True), (True, False), (False, True)])
|
||||
def test_password_authenticator_migration_accept_authentication_settings(migration, settings, email, phone):
|
||||
app = 'authenticators'
|
||||
migrate_from = [(app, '0010_auto_20230614_1017')]
|
||||
migrate_to = [(app, '0011_migrate_a2_accept_authentication_settings')]
|
||||
|
||||
migration.before(migrate_from)
|
||||
|
||||
settings.A2_ACCEPT_EMAIL_AUTHENTICATION = email
|
||||
settings.A2_ACCEPT_PHONE_AUTHENTICATION = phone
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
|
||||
assert authenticator.accept_email_authentication == email
|
||||
assert authenticator.accept_phone_authentication == phone
|
||||
|
||||
|
||||
@pytest.mark.parametrize('strength,expected_strength', [(None, 3), ('invalid', 3), (1, 3), (4, 4), (42, 4)])
|
||||
def test_password_authenticator_data_migration_min_password_strength(
|
||||
migration, settings, strength, expected_strength
|
||||
):
|
||||
app = 'authenticators'
|
||||
migrate_from = [
|
||||
(app, '0012_loginpasswordauthenticator_min_password_strength'),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
migrate_to = [(app, '0013_migrate_min_password_strength')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
OU = old_apps.get_model('a2_rbac', 'OrganizationalUnit')
|
||||
|
||||
settings.A2_PASSWORD_POLICY_MIN_STRENGTH = strength
|
||||
|
||||
OU.objects.create(name='OU1', slug='ou1', min_password_strength=2)
|
||||
OU.objects.create(name='OU2', slug='ou2', min_password_strength=None)
|
||||
OU.objects.create(name='OU3', slug='ou3', min_password_strength=3)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
assert authenticator.min_password_strength == expected_strength
|
||||
|
||||
|
||||
def test_password_authenticator_data_migration_min_password_strength_zero(migration, settings):
|
||||
app = 'authenticators'
|
||||
migrate_from = [
|
||||
(app, '0012_loginpasswordauthenticator_min_password_strength'),
|
||||
('a2_rbac', '0036_delete_roleattribute'),
|
||||
]
|
||||
migrate_to = [(app, '0013_migrate_min_password_strength')]
|
||||
|
||||
old_apps = migration.before(migrate_from)
|
||||
OU = old_apps.get_model('a2_rbac', 'OrganizationalUnit')
|
||||
|
||||
OU.objects.create(name='OU1', slug='ou1', min_password_strength=0)
|
||||
|
||||
new_apps = migration.apply(migrate_to)
|
||||
LoginPasswordAuthenticator = new_apps.get_model(app, 'LoginPasswordAuthenticator')
|
||||
authenticator = LoginPasswordAuthenticator.objects.get()
|
||||
assert authenticator.min_password_strength == 0
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
# 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/>.
|
||||
|
||||
from django.contrib.auth.models import AbstractUser
|
||||
from django.utils.timezone import now
|
||||
|
||||
|
||||
def test_migration_custom_user_0021_set_unusable_password(transactional_db, migration):
|
||||
old_apps = migration.before([('custom_user', '0020_deleteduser')])
|
||||
|
||||
User = old_apps.get_model('custom_user', 'User')
|
||||
user = User.objects.create()
|
||||
assert user.password == ''
|
||||
|
||||
new_apps = migration.apply([('custom_user', '0021_set_unusable_password')])
|
||||
User = new_apps.get_model('custom_user', 'User')
|
||||
user = User.objects.get()
|
||||
assert not AbstractUser.has_usable_password(user)
|
||||
|
||||
|
||||
def test_migration_custom_user_0026_remove_user_deleted(transactional_db, migration):
|
||||
old_apps = migration.before([('custom_user', '0025_user_deactivation')])
|
||||
|
||||
User = old_apps.get_model('custom_user', 'User')
|
||||
DeletedUser = old_apps.get_model('custom_user', 'DeletedUser')
|
||||
User.objects.create(deleted=now())
|
||||
User.objects.create()
|
||||
|
||||
assert User.objects.count() == 2
|
||||
assert DeletedUser.objects.count() == 0
|
||||
new_apps = migration.apply([('custom_user', '0026_remove_user_deleted')])
|
||||
User = new_apps.get_model('custom_user', 'User')
|
||||
DeletedUser = new_apps.get_model('custom_user', 'DeletedUser')
|
||||
assert User.objects.count() == 1
|
||||
assert DeletedUser.objects.count() == 1
|
||||
|
||||
|
||||
def test_migration_custom_user_0028_user_email_verified_date(transactional_db, migration):
|
||||
old_apps = migration.before([('custom_user', '0027_user_deactivation_reason')])
|
||||
|
||||
User = old_apps.get_model('custom_user', 'User')
|
||||
User.objects.create(email='john.doe@example.com', email_verified=True)
|
||||
|
||||
new_apps = migration.apply([('custom_user', '0028_user_email_verified_date')])
|
||||
User = new_apps.get_model('custom_user', 'User')
|
||||
user = User.objects.get()
|
||||
assert user.email_verified_date == user.date_joined
|
||||
|
||||
|
||||
def test_migration_custom_user_0047_initialize_services_runtime_settings(transactional_db, migration):
|
||||
old_apps = migration.before([('authentic2', '0046_runtimesetting')])
|
||||
|
||||
Setting = old_apps.get_model('authentic2', 'Setting')
|
||||
assert Setting.objects.count() == 0
|
||||
|
||||
new_apps = migration.apply([('authentic2', '0047_initialize_services_runtime_settings')])
|
||||
Setting = new_apps.get_model('authentic2', 'Setting')
|
||||
assert Setting.objects.count() == 4
|
||||
assert Setting.objects.filter(key__startswith='sso:').count() == 4
|
||||
for setting in Setting.objects.filter(key__startswith='sso:'):
|
||||
assert setting.value == ''
|
||||
|
||||
|
||||
def test_migration_custom_user_0050_initialize_users_advanced_configuration(transactional_db, migration):
|
||||
old_apps = migration.before([('authentic2', '0049_apiclient_allowed_user_attributes')])
|
||||
Setting = old_apps.get_model('authentic2', 'Setting')
|
||||
before = Setting.objects.count()
|
||||
|
||||
new_apps = migration.apply([('authentic2', '0050_initialize_users_advanced_configuration')])
|
||||
Setting = new_apps.get_model('authentic2', 'Setting')
|
||||
assert Setting.objects.count() == before + 1
|
||||
assert Setting.objects.filter(key__startswith='users:').count() == 1
|
||||
assert Setting.objects.get(key='users:backoffice_sidebar_template').value == ''
|
Loading…
Reference in New Issue