diff --git a/.github/workflows/run-tests.yaml b/.github/workflows/run-tests.yaml index 6acda0fb1..378f5f15e 100644 --- a/.github/workflows/run-tests.yaml +++ b/.github/workflows/run-tests.yaml @@ -14,7 +14,7 @@ jobs: python-version: ["3.10"] env: PIP_INDEX_URL: https://pypi.sunet.se/simple/ - NEO4J_VERSION: 4.0-enterprise + NEO4J_VERSION: 4.4-enterprise steps: - uses: actions/checkout@v4 diff --git a/.jenkins.yaml b/.jenkins.yaml index fe540aa0f..fed2acec5 100644 --- a/.jenkins.yaml +++ b/.jenkins.yaml @@ -8,11 +8,11 @@ pre_build_script: - "docker pull docker.sunet.se/eduid/redis:latest" - "docker pull docker.sunet.se/eduid/mongodb:latest" - "docker pull docker.sunet.se/eduid/smtpdfix:latest" - - "docker pull neo4j:4.0-enterprise" + - "docker pull neo4j:4.4-enterprise" # pillow requires libjpeg and gs - "apt-get install -y libjpeg-dev libfreetype6-dev ghostscript libcairo2-dev" environment_variables: - NEO4J_VERSION: "4.0-enterprise" + NEO4J_VERSION: "4.4-enterprise" script: - "python3.10 -m venv venv" - ". venv/bin/activate" diff --git a/src/eduid/graphdb/groupdb/db.py b/src/eduid/graphdb/groupdb/db.py index b887550b1..938d5d3d8 100644 --- a/src/eduid/graphdb/groupdb/db.py +++ b/src/eduid/graphdb/groupdb/db.py @@ -53,12 +53,20 @@ def db_setup(self): "CREATE CONSTRAINT ON (n:User) ASSERT n.identifier IS UNIQUE", # Replaced by CREATE CONSTRAINT [name] FOR (node:Label) REQUIRE node.prop IS UNIQUE ] - for statment in statements: + for statement in statements: try: - session.run(statment) + session.run(statement) except ClientError as e: assert e.message is not None # please mypy - if "An equivalent constraint already exists" not in e.message: + acceptable_error_codes = [ + "Neo.ClientError.Schema.ConstraintAlreadyExists", + "Neo.ClientError.Schema.EquivalentSchemaRuleAlreadyExists", + ] + # e.message check is neo4j <= 4.1, e.code is neo4j >= 4.4 + if ( + "An equivalent constraint already exists" not in e.message + and e.code not in acceptable_error_codes + ): raise e # Constraints already set up pass diff --git a/src/eduid/graphdb/testing.py b/src/eduid/graphdb/testing.py index c5021c0c9..06586f641 100644 --- a/src/eduid/graphdb/testing.py +++ b/src/eduid/graphdb/testing.py @@ -16,7 +16,7 @@ # Run tests with different Neo4j docker image versions using environment variables -NEO4J_VERSION = environ.get("NEO4J_VERSION", "4.1-enterprise") +NEO4J_VERSION = environ.get("NEO4J_VERSION", "4.4-enterprise") logger = logging.getLogger(__name__) logger.info(f"NEO4J_VERSION={NEO4J_VERSION}") @@ -37,7 +37,7 @@ class Neo4jTemporaryInstance(EduidTemporaryInstance): _bolt_port: int DEFAULT_USERNAME = "neo4j" - DEFAULT_PASSWORD = "testing" + DEFAULT_PASSWORD = "testingtesting" def __init__(self, max_retry_seconds: int = 60, neo4j_version: str = NEO4J_VERSION): self._http_port = random.randint(40000, 43000) diff --git a/src/eduid/graphdb/tests/test_db.py b/src/eduid/graphdb/tests/test_db.py index 677798d07..2d7f665ad 100644 --- a/src/eduid/graphdb/tests/test_db.py +++ b/src/eduid/graphdb/tests/test_db.py @@ -28,7 +28,7 @@ def db_setup(self): def test_base_db(self): db_uri = self.neo4jdb.db_uri - config = {"encrypted": False, "auth": basic_auth("neo4j", "testing")} + config = {"encrypted": False, "auth": basic_auth("neo4j", "testingtesting")} test_db = self.TestDB(db_uri=db_uri, config=config) with test_db._db.driver.session() as session: session.run("CREATE (n:Test $props)", props={"name": "test node", "testing": True}) diff --git a/src/eduid/graphdb/tests/test_groupdb.py b/src/eduid/graphdb/tests/test_groupdb.py index e5bf168de..1fc713d21 100644 --- a/src/eduid/graphdb/tests/test_groupdb.py +++ b/src/eduid/graphdb/tests/test_groupdb.py @@ -13,7 +13,7 @@ class TestGroupDB(Neo4jTestCase): def setUp(self) -> None: - self.db_config = {"encrypted": False, "auth": basic_auth("neo4j", "testing")} + self.db_config = {"encrypted": False, "auth": basic_auth("neo4j", "testingtesting")} self.group_db = GroupDB(db_uri=self.neo4jdb.db_uri, scope="__testing__", config=self.db_config) self.group1: dict[str, str | list | None] = { "identifier": "test1", diff --git a/src/eduid/webapp/freja_eid/helpers.py b/src/eduid/webapp/freja_eid/helpers.py index adede6d61..6ce1d0e7a 100644 --- a/src/eduid/webapp/freja_eid/helpers.py +++ b/src/eduid/webapp/freja_eid/helpers.py @@ -85,7 +85,7 @@ class FrejaEIDDocumentUserInfo(UserInfoBase): given_name: str name: str personal_identity_number: str | None = Field( - alias="https:/frejaeid.com/oidc/claims/personalIdentityNumber", default=None + alias="https://frejaeid.com/oidc/claims/personalIdentityNumber", default=None ) date_of_birth: date = Field(alias="birthdate") registration_level: FrejaRegistrationLevel = Field(alias="https://frejaeid.com/oidc/claims/registrationLevel") diff --git a/src/eduid/webapp/freja_eid/tests/test_app.py b/src/eduid/webapp/freja_eid/tests/test_app.py index 39a7f820e..59b4c8c99 100644 --- a/src/eduid/webapp/freja_eid/tests/test_app.py +++ b/src/eduid/webapp/freja_eid/tests/test_app.py @@ -14,7 +14,13 @@ from eduid.webapp.common.proofing.messages import ProofingMsg from eduid.webapp.common.proofing.testing import ProofingTests from eduid.webapp.freja_eid.app import FrejaEIDApp, freja_eid_init_app -from eduid.webapp.freja_eid.helpers import FrejaDocument, FrejaDocumentType, FrejaEIDDocumentUserInfo, FrejaEIDMsg +from eduid.webapp.freja_eid.helpers import ( + FrejaDocument, + FrejaDocumentType, + FrejaEIDDocumentUserInfo, + FrejaEIDMsg, + FrejaEIDTokenResponse, +) __author__ = "lundberg" @@ -246,6 +252,60 @@ def _start_auth(self, mock_metadata: MagicMock, endpoint: str, data: dict[str, A def test_app_starts(self): assert self.app.conf.app_name == "testing" + @staticmethod + def test_parse_token_response(): + token_response_swedish = { + "access_token": "access_token", + "token_type": "Bearer", + "expires_in": 599, + "scope": "space delimited scopes", + "id_token": "id_token", + "expires_at": 1726060986, + "userinfo": { + "sub": "subject_identifier", + "https://frejaeid.com/oidc/claims/country": "SE", + "birthdate": "1981-07-01", + "kid": "oidc_signing_kid", + "iss": "https://eid-provider.example.com/oidc/", + "https://frejaeid.com/oidc/claims/registrationLevel": "PLUS", + "https://frejaeid.com/oidc/claims/personalIdentityNumber": "198107011481", + "given_name": "Sven", + "nonce": "some_nonce", + "aud": "test", + "name": "Sven Svensson", + "https://frejaeid.com/oidc/claims/document": { + "type": "PASS", + "country": "SE", + "serialNumber": "791840288", + "expirationDate": "2029-09-11", + }, + "https://frejaeid.com/oidc/claims/relyingPartyUserId": "relying_party_user_id", + "exp": 1726063987, + "https://frejaeid.com/oidc/claims/transactionReference": "transaction_reference", + "iat": 1726060387, + "family_name": "Svensson", + "jti": "61ec03e5-ec08-4ac2-bd54-6256994fb784", + }, + } + parsed_token_response = FrejaEIDTokenResponse(**token_response_swedish) + assert parsed_token_response is not None + assert parsed_token_response.userinfo is not None + assert parsed_token_response.userinfo.iss == "https://eid-provider.example.com/oidc/" + assert parsed_token_response.userinfo.aud == "test" + assert parsed_token_response.userinfo.registration_level == FrejaRegistrationLevel.PLUS + assert parsed_token_response.userinfo.personal_identity_number == "198107011481" + assert parsed_token_response.userinfo.name == "Sven Svensson" + assert parsed_token_response.userinfo.family_name == "Svensson" + assert parsed_token_response.userinfo.given_name == "Sven" + assert parsed_token_response.userinfo.date_of_birth == date(year=1981, month=7, day=1) + assert parsed_token_response.userinfo.document is not None + assert parsed_token_response.userinfo.document.type == FrejaDocumentType.PASSPORT + assert parsed_token_response.userinfo.document.country == "SE" + assert parsed_token_response.userinfo.document.serial_number == "791840288" + assert parsed_token_response.userinfo.document.expiration_date == date(year=2029, month=9, day=11) + assert parsed_token_response.userinfo.transaction_id == "transaction_reference" + assert parsed_token_response.userinfo.user_id == "relying_party_user_id" + def test_authenticate(self): response = self.browser.get("/") self.assertEqual(response.status_code, 302) # Redirect to token service @@ -270,10 +330,8 @@ def test_verify_identity_request(self): ], f"{query['scope']} != {[' '.join(self.app.conf.freja_eid_client.scopes)]}" assert query["code_challenge_method"] == ["S256"] - @patch("eduid.common.rpc.msg_relay.MsgRelay.get_all_navet_data") @patch("eduid.common.rpc.am_relay.AmRelay.request_user_sync") - def test_verify_nin_identity(self, mock_request_user_sync: MagicMock, mock_get_all_navet_data: MagicMock): - mock_get_all_navet_data.return_value = self._get_all_navet_data() + def test_verify_nin_identity(self, mock_request_user_sync: MagicMock): mock_request_user_sync.side_effect = self.request_user_sync eppn = self.unverified_test_user.eppn