Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion cloudfile_ext/sso/tests/test_eap_oauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,11 @@ def test_changed_uid_or_disagreement_never_merges_accounts(profile, uid_rows):


def test_cfadmin_is_never_reused_by_employee_identity():
# Only the exact built-in account is reserved, not a customer's email prefix.
with pytest.raises(IdentityConflict):
choose_native('123', '1022', 'cfadmin@external.com', ('cfadmin@external.com', '123'), [])
choose_native('123', '1022', 'cfadmin@auth.local', ('cfadmin@auth.local', '123'), [])
assert choose_native('123', '1022', 'cfadmin@external.com',
('cfadmin@external.com', '123'), []) == 'cfadmin@external.com'


@pytest.fixture
Expand Down
9 changes: 8 additions & 1 deletion cloudfile_ext/sso/tests/test_identity_bridge.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,20 @@ def test_employee_profile_does_not_override_exact_uid_binding():

@pytest.mark.parametrize('employee,native', [
('cfadmin', 'native-admin'), ('CFADMIN', 'native-admin'),
('emp-1', 'cfadmin@external.com'), ('emp-1', 'cfadmin@auth.local')])
('emp-1', 'cfadmin@auth.local')])
def test_system_admin_is_excluded_from_employee_projection(employee, native):
# System administration remains independent even if a bad feed includes it.
assert resolve_eap_pairs([{'user_id': 'uid-1', 'employee_no': employee}],
fetch=lambda keys: [('uid-1', native)]) == {}


def test_external_admin_name_is_not_the_reserved_native_account():
# Email prefix alone does not identify the built-in CE administrator.
assert resolve_eap_pairs([{'user_id': 'uid-1', 'employee_no': 'emp-1'}],
fetch=lambda keys: [('uid-1', 'cfadmin@external.com')]) == {
'uid-1': 'cfadmin@external.com'}


def test_employee_reused_for_different_uid_never_merges_native_accounts():
mapped = resolve_eap_pairs([
{'user_id': 'uid-1', 'employee_no': 'emp'},
Expand Down
8 changes: 7 additions & 1 deletion cloudfile_ext/sso/tests/test_token_identity.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def test_legacy_channel_is_rejected():
resolve_employee_token('10220942@auth.local', source(context(), 'legacy'))


@pytest.mark.parametrize('rows', [[], [('381','one@auth.local'), ('381','two@auth.local')], [('381','cfadmin@external.com')]])
@pytest.mark.parametrize('rows', [[], [('381','one@auth.local'), ('381','two@auth.local')], [('381','cfadmin@auth.local')]])
def test_missing_ambiguous_or_system_account_is_rejected(rows):
with pytest.raises(TokenIdentityError):
resolve_employee_token('10220942@auth.local', source(context()), lambda _: rows)
Expand All @@ -46,3 +46,9 @@ def test_employee_recycling_cannot_reuse_old_uid():
# fail rather than inherit that user's token or library permissions.
with pytest.raises(IdentityBridgeError):
resolve_employee_token('10220942@auth.local', source(changed), lambda _: [('381','old@auth.local')])


def test_external_admin_name_is_not_the_reserved_native_account():
# Match the exact built-in account; unrelated customer domains remain valid.
assert resolve_employee_token('10220942@auth.local', source(context()),
lambda _: [('381', 'cfadmin@external.com')]) == 'cfadmin@external.com'
4 changes: 4 additions & 0 deletions cloudfile_ext/v2/tests/test_acl_http.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def test_directory_rules_allow_native_repo_admin_without_system_staff(self):
patch('cloudfile_ext.v2.acl_http.store') as rules, \
patch('seaserv.seafile_api.get_dir_id_by_path', return_value='d' * 40), \
patch('cloudfile_ext.v2.acl_http.settings') as settings:
# Explicit preferred setting avoids auto-created Mock namespace values.
settings.CF_DIRECTORY_PROVIDER = 'external'
settings.CF_ACL_PROVIDER = 'external'
rules.return_value.list_path.return_value = []
result = self.request(DirectoryRules, dict(repo_id=RID, path='/folder'))
Expand Down Expand Up @@ -97,6 +99,8 @@ def test_public_rule_writer_uses_validated_three_permission_cas(self):
with patch('cloudfile_ext.v2.acl_http.require_repo_manage'), \
patch('cloudfile_ext.v2.acl_http.store') as rules, \
patch('cloudfile_ext.v2.acl_http.settings') as settings:
# Explicit preferred setting avoids auto-created Mock namespace values.
settings.CF_DIRECTORY_PROVIDER = 'external'
settings.CF_ACL_PROVIDER = 'external'
rules.return_value.mutate.return_value = request['revision']
result = self.request(DirectoryRules, request, method='post')
Expand Down
6 changes: 6 additions & 0 deletions cloudfile_ext/v2/tests/test_acl_library_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ def test_old_directory_route_and_additive_batch_get(self):
with patch('cloudfile_ext.v2.acl_http.require_repo_manage') as auth, \
patch('cloudfile_ext.v2.acl_http.store') as rules, \
patch('cloudfile_ext.v2.acl_http.settings') as settings:
# Explicit preferred setting avoids auto-created Mock namespace values.
settings.CF_DIRECTORY_PROVIDER = 'external'
settings.CF_ACL_PROVIDER = 'external'
rules.return_value.provider_snapshot.return_value = ((RULE, REVISION),)
result = self.request('get', {'repo_id': RID})
Expand All @@ -50,6 +52,8 @@ def test_batch_put_uses_server_provider_and_one_atomic_store_call(self):
with patch('cloudfile_ext.v2.acl_http.require_repo_manage'), \
patch('cloudfile_ext.v2.acl_http.store') as rules, \
patch('cloudfile_ext.v2.acl_http.settings') as settings:
# Explicit preferred setting avoids auto-created Mock namespace values.
settings.CF_DIRECTORY_PROVIDER = 'external'
settings.CF_ACL_PROVIDER = 'external'
rules.return_value.replace_owned.return_value = dict(
fingerprint='a' * 64, inserted=0, updated=1, deleted=0, unchanged=0)
Expand All @@ -68,6 +72,8 @@ def test_batch_resource_preview_reuses_one_snapshot_and_checks_every_directory(s
patch('cloudfile_ext.v2.acl_http.store') as rules, \
patch('seaserv.seafile_api.get_dir_id_by_path') as exists, \
patch('cloudfile_ext.v2.acl_http.settings') as settings:
# Explicit preferred setting avoids auto-created Mock namespace values.
settings.CF_DIRECTORY_PROVIDER = 'external'
settings.CF_ACL_PROVIDER = 'external'
exists.side_effect = lambda repo, path: 'd' * 40 if path == '/shared' else None
rules.return_value.provider_snapshot.return_value = ((RULE, REVISION),)
Expand Down
8 changes: 7 additions & 1 deletion cloudfile_ext/v2/tests/test_enterprise_subject_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,15 @@ def test_explicit_custom_provider_supports_its_own_directory_contract(self):
CF_ACL_PROVIDER='corp', CF_ACL_SUBJECT_ENSURE='package.directory.refresh')),
('corp', 'package.directory.refresh'))

def test_directory_accepts_explicit_namespace_without_custom_loader(self):
# The built-in Directory adapter needs no custom refresh callback.
self.assertEqual(subject_adapter(SimpleNamespace(
CF_DIRECTORY_URL='https://directory.example.test', CF_ACL_PROVIDER='corp')),
('corp', None))

def test_half_configured_external_provider_never_downgrades_to_ce(self):
for config in (
SimpleNamespace(CF_DIRECTORY_URL='https://directory.example.test', CF_ACL_PROVIDER='corp'),
SimpleNamespace(CF_ACL_PROVIDER='corp'),
SimpleNamespace(CF_ACL_SUBJECT_ENSURE='package.directory.refresh'),
SimpleNamespace(CF_ACL_PROVIDER='native-local',
CF_ACL_SUBJECT_ENSURE='package.directory.refresh'),
Expand Down
Loading