diff --git a/greg/management/commands/import_sponsors_from_cerebrum.py b/greg/management/commands/import_sponsors_from_cerebrum.py index 6b720771460f64a1da9d67c495013909f714de48..f3f2c7cf4b51ed583ca8f9d719286d32c8d62128 100644 --- a/greg/management/commands/import_sponsors_from_cerebrum.py +++ b/greg/management/commands/import_sponsors_from_cerebrum.py @@ -6,6 +6,10 @@ populate Sponsors and SponsorOrganizationalUnits. This script does only remove the SponsorOrganizationalUnit. The Sponsor objects are kept, even with no units + +Any unit with an OuIdentifier with name legacy_stedkode and value +present in the settings variable CEREBRUM_MANUAL_SPONSOR_UNITS will be +skipped and is expected to have their Sponsors created manually. """ from typing import Optional, Tuple @@ -28,6 +32,7 @@ class Command(BaseCommand): CEREBRUM_SOURCE = "cerebrum" CEREBRUM_FEIDE_INST = "uio.no" CEREBRUM_NAME_SOURCE_PRIORITY = ["Cached", "Override", "DFO_SAP", "FS", "Manual"] + CEREBRUM_STEDKODE_IDENTIFIER_NAME = "legacy_stedkode" def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) @@ -40,6 +45,7 @@ class Command(BaseCommand): organizational_unit=unit, source=self.CEREBRUM_SOURCE, automatic=True, + defaults={"hierarchical_access": settings.CEREBRUM_HIERARCHICAL_ACCESS}, ) if created: logger.info("sponsor_ou_link_create", sponsor=sponsor.id, sunit=sunit.id) @@ -119,12 +125,17 @@ class Command(BaseCommand): active_units = OrganizationalUnit.objects.filter( active=True, deleted=False, + ).exclude( + identifiers__name=self.CEREBRUM_STEDKODE_IDENTIFIER_NAME, + identifiers__value__in=settings.CEREBRUM_MANUAL_SPONSOR_UNITS, ) logger.info("import_start", nr_of_units=len(active_units)) for unit in active_units: logger.bind(unit=unit.id) - sko = unit.identifiers.filter(name="legacy_stedkode").first() + sko = unit.identifiers.filter( + name=self.CEREBRUM_STEDKODE_IDENTIFIER_NAME + ).first() if not sko: logger.warning("orgreg_unit_missing_legacy_stedkode") continue diff --git a/greg/tests/conftest.py b/greg/tests/conftest.py index db81a828d3662732d54c287cbb81d8cdda0c0079..bd45a28353221005e5372e3d20cb990f0bb0f993 100644 --- a/greg/tests/conftest.py +++ b/greg/tests/conftest.py @@ -158,15 +158,19 @@ def role_type_test_guest() -> RoleType: @pytest.fixture def unit_foo() -> OrganizationalUnit: ou = OrganizationalUnit.objects.create(name_en="foo_unit") + OuIdentifier.objects.create( + source="orgreg", name="legacy_stedkode", value="12345", orgunit=ou + ) return OrganizationalUnit.objects.get(id=ou.id) @pytest.fixture -def ouidentifier_foo(unit_foo) -> OuIdentifier: - ouid = OuIdentifier.objcets.create( - source="orgreg", name="orgreg", value="12345", orgunit=unit_foo +def unit_foo2() -> OrganizationalUnit: + ou = OrganizationalUnit.objects.create(name_en="foo_unit2") + OuIdentifier.objects.create( + source="orgreg", name="legacy_stedkode", value="23456", orgunit=ou ) - return OuIdentifier.objects.get(id=ouid.id) + return OrganizationalUnit.objects.get(id=ou.id) @pytest.fixture diff --git a/greg/tests/management/test_import_sponsors_from_cerebrum.py b/greg/tests/management/test_import_sponsors_from_cerebrum.py new file mode 100644 index 0000000000000000000000000000000000000000..2bafed211ec5b18a3b015a5b31e3e490d715442f --- /dev/null +++ b/greg/tests/management/test_import_sponsors_from_cerebrum.py @@ -0,0 +1,152 @@ +import datetime +import pytest +from django.conf import settings +from django.core.management import call_command + +from greg.models import Sponsor, SponsorOrganizationalUnit + + +class MockResponse: + def __init__(self, response): + self.response = response + + def json(self): + return self.response + + +@pytest.fixture +def group_response(): + created_at = (datetime.datetime.now() - datetime.timedelta(days=1)).isoformat() + return MockResponse( + f"""{{ + "href": "", + "id": 1, + "name": "", + "description": "", + "created_at": "{created_at}", + "contexts": ["das"], + "visibility": "", + "moderators": "" + }}""" + ) + + +@pytest.fixture +def group_members_response(): + return MockResponse("""{"members":[{"href": "asd", "type": "person", "id": 1}]}""") + + +@pytest.fixture +def group_members_response2(): + return MockResponse("""{"members":[{"href": "asd", "type": "person", "id": 2}]}""") + + +@pytest.fixture +def person_response(): + return MockResponse( + """{ + "contexts": [""], + "href": "", + "names": [ + {"source_system":"DFO_SAP", "variant": "FIRST", "name": "Ola"}, + {"source_system":"DFO_SAP", "variant": "LAST", "name": "Nordmann"} + ], + "id": 1}""" + ) + + +@pytest.fixture +def person_response2(): + return MockResponse( + """{ + "contexts": [""], + "href": "", + "names": [ + {"source_system":"DFO_SAP", "variant": "FIRST", "name": "Kari"}, + {"source_system":"DFO_SAP", "variant": "LAST", "name": "Nordmann"} + ], + "id": 2}""" + ) + + +@pytest.fixture +def account_response(): + return MockResponse( + """{"accounts": [{ + "href": "", + "primary": true, + "id": 1, + "name": "olanord"}]}""" + ) + + +@pytest.fixture +def account_response2(): + return MockResponse( + """{"accounts": [{ + "href": "", + "primary": true, + "id": 2, + "name": "karinor"}]}""" + ) + + +@pytest.mark.django_db +def test_import_sponsors_from_cerebrum( + requests_mock, + group_response, + group_members_response, + group_members_response2, + person_response, + person_response2, + account_response, + account_response2, + sponsor_org_unit, + unit_foo2, +): + """Check that only non manual sponsors are imported and linked""" + settings.CEREBRUM_CLIENT = { + "url": "http://example.com/cerebrum/", + "headers": {"X-Gravitee-Api-Key": "fake-key"}, + } + settings.CEREBRUM_MANUAL_SPONSOR_UNITS = ["12345"] + requests_mock.get( + "http://example.com/cerebrum/v1/groups/adm-leder-12345", + text=group_response.json(), + ) + requests_mock.get( + "http://example.com/cerebrum/v1/groups/adm-leder-12345/members/", + text=group_members_response.json(), + ) + requests_mock.get( + "http://example.com/cerebrum/v1/persons/1", + text=person_response.json(), + ) + requests_mock.get( + "http://example.com/cerebrum/v1/persons/1/accounts", + text=account_response.json(), + ) + + requests_mock.get( + "http://example.com/cerebrum/v1/groups/adm-leder-23456", + text=group_response.json(), + ) + requests_mock.get( + "http://example.com/cerebrum/v1/groups/adm-leder-23456/members/", + text=group_members_response2.json(), + ) + requests_mock.get( + "http://example.com/cerebrum/v1/persons/2", + text=person_response2.json(), + ) + requests_mock.get( + "http://example.com/cerebrum/v1/persons/2/accounts", + text=account_response2.json(), + ) + assert Sponsor.objects.all().count() == 1 + assert SponsorOrganizationalUnit.objects.count() == 1 + call_command("import_sponsors_from_cerebrum") + # One from unit with one sponsor + # One excluded from unit with stedkode in manual list + assert Sponsor.objects.all().count() == 2 + assert SponsorOrganizationalUnit.objects.count() == 2 diff --git a/gregsite/settings/base.py b/gregsite/settings/base.py index 19eaa9e15640ce6c64d5339b39f3dd7005ebcb4f..8ff941739add0caa06383b1f00a714428c9239fe 100644 --- a/gregsite/settings/base.py +++ b/gregsite/settings/base.py @@ -309,6 +309,9 @@ ORGREG_ACRONYMS = [] # scheduled by running the management command ORGREG_SCHEDULE_TYPE = "D" +# List of stedkode for units where Sponsors are handled manually +CEREBRUM_MANUAL_SPONSOR_UNITS = [] + # Settings related to Django-q used for scheduling tasks in the future. # We use it to queue creation of Notification objects related to roles when start/end dates are in the future Q_CLUSTER = {