From 885deadf8c64f97a7f4430d422476679269b3764 Mon Sep 17 00:00:00 2001 From: larisa17 Date: Mon, 9 Dec 2024 14:38:34 +0200 Subject: [PATCH] add new flow for deduplication --- api/registry/atasks.py | 2 +- api/v2/test/test_api_dedup.py | 166 ++++++++++++++++++++++++++++------ 2 files changed, 138 insertions(+), 30 deletions(-) diff --git a/api/registry/atasks.py b/api/registry/atasks.py index 13ef4beef..8cf4ec6cb 100644 --- a/api/registry/atasks.py +++ b/api/registry/atasks.py @@ -130,7 +130,7 @@ async def acalculate_score( provider_name = c_stamp["provider"] if provider_name not in stamps: stamps[provider_name] = { - "score": 0, # Default score for stamps not in stamp_scores + "score": "0", # Default score for stamps not in stamp_scores "dedup": True, "expiration_date": c_stamp["credential"]["expirationDate"], } diff --git a/api/v2/test/test_api_dedup.py b/api/v2/test/test_api_dedup.py index 398410809..4420d6872 100644 --- a/api/v2/test/test_api_dedup.py +++ b/api/v2/test/test_api_dedup.py @@ -24,8 +24,9 @@ wallet_a = web3.eth.account.from_mnemonic( my_mnemonic, account_path="m/44'/60'/0'/0/0" ).address + wallet_b = web3.eth.account.from_mnemonic( - my_mnemonic, account_path="m/44'/60'/0'/0/0" + my_mnemonic, account_path="m/44'/60'/0'/0/1" ).address @@ -52,42 +53,22 @@ class TestApiGetStampsDedupFlagTestCase: "registry.atasks.avalidate_credentials", side_effect=avalidate_credentials_side_effect, ) - def test_get_stamps_no_dedup(self, validate_credential, weight_config): + def test_get_stamps_no_dedup( + self, validate_credential, weight_config, scorer_community, scorer_api_key + ): """ Test get stamps for user with no deduplication & expired stamp Only the valid stamp is returned with the dedup flag set to False """ client = Client() - sample_provider = "LinkedinV2" - sample_provider_hash = "v0.0.0:Ft7mqRdvJ9jNgSSowb9qdcMeOzswOeighIOvk0wn964=" - - expired_provider = "githubContributionActivityGte#30" - expired_provider_hash = "v0.0.0:Ft7mqRdvJ9jNgSSowb9qdcMeOzswOeighIOvk000xxx=" - now = datetime.now(timezone.utc) days_ago = (now - timedelta(days=2)).isoformat() weeks_ago = (now - timedelta(days=30)).isoformat() days_later = (now + timedelta(days=2)).isoformat() - user = User.objects.create_user(username="user", password="userpwd") - account = Account.objects.create(user=user, address=wallet_a) - _scorer = WeightedScorer.objects.create(type=Scorer.Type.WEIGHTED) - - comunity = Community.objects.create( - name="My Community", - description="My Community description", - account=account, - scorer=_scorer, - ) - - (_, api_key) = AccountAPIKey.objects.create_key( - account=account, - name="Token for user 1", - rate_limit="3/30seconds", - analysis_rate_limit="3/30seconds", - historical_endpoint=True, - ) + expired_provider = "githubContributionActivityGte#30" + expired_provider_hash = "v0.0.0:Ft7mqRdvJ9jNgSSowb9qdcMeOzswOeighIOvk000xxx=" expired_stamp = CeramicCache.objects.create( address=wallet_a, @@ -119,6 +100,76 @@ def test_get_stamps_no_dedup(self, validate_credential, weight_config): }, ) + sample_provider = "LinkedinV2" + sample_provider_hash = "v0.0.0:Ft7mqRdvJ9jNgSSowb9qdcMeOzswOeighIOvk0wn964=" + + sample_stamp = CeramicCache.objects.create( + address=wallet_a, + provider=sample_provider, + stamp={ + "type": ["VerifiableCredential"], + "proof": { + "jws": "eyJhbGciOiJFZERTQSIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..34uD8jKn2N_yE8pY4ErzVD8pJruZq7qJaCxx8y0SReY2liZJatfeQUv1nqmZH19a-svOyfHt_VbmKvh6A5vwBw", + "type": "Ed25519Signature2018", + "created": days_ago, + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkghvGHLobLEdj1bgRLhS4LPGJAvbMA1tn2zcRyqmYU5LC#z6MkghvGHLobLEdj1bgRLhS4LPGJAvbMA1tn2zcRyqmYU5LC", + }, + "issuer": "did:key:z6MkghvGHLobLEdj1bgRLhS4LPGJAvbMA1tn2zcRyqmYU5LC", + "@context": ["https://www.w3.org/2018/credentials/v1"], + "issuanceDate": days_ago, + "expirationDate": days_later, + "credentialSubject": { + "id": f"did:pkh:eip155:1:{wallet_a}", + "hash": sample_provider_hash, + "@context": [ + { + "hash": "https://schema.org/Text", + "provider": sample_provider, + } + ], + "provider": sample_provider, + }, + }, + ) + + response = client.get( + f"{self.base_url}/{scorer_community.pk}/score/{wallet_a}", + HTTP_AUTHORIZATION="Token " + scorer_api_key, + ) + response_data = response.json() + assert response.status_code == 200 + assert response_data["error"] is None + assert response_data["stamps"] == { + sample_provider: { + "score": GITCOIN_PASSPORT_WEIGHTS[sample_provider], + "dedup": False, + "expiration_date": days_later, + } + } + + @patch( + "registry.atasks.avalidate_credentials", + side_effect=avalidate_credentials_side_effect, + ) + def test_get_stamps_with_dedup( + self, validate_credential, weight_config, scorer_community, scorer_api_key + ): + """ + Test the following flow: + - wallet A has a valid stamp & checks that the get score returs the proper stamp + - wallet B claims the same stamp (same hash => it is deduped) the get score for wallet B returns the score is 0 & the dedup flag is set to True + - wallet A checks the score again, there are no changes in the returned stamps. + """ + + client = Client() + now = datetime.now(timezone.utc) + days_ago = (now - timedelta(days=2)).isoformat() + days_later = (now + timedelta(days=2)).isoformat() + + sample_provider = "LinkedinV2" + sample_provider_hash = "v0.0.0:Ft7mqRdvJ9jNgSSowb9qdcMeOzswOeighIOvk0wn964=" + sample_stamp = CeramicCache.objects.create( address=wallet_a, provider=sample_provider, @@ -148,13 +199,70 @@ def test_get_stamps_no_dedup(self, validate_credential, weight_config): }, }, ) + response = client.get( + f"{self.base_url}/{scorer_community.pk}/score/{wallet_a}", + HTTP_AUTHORIZATION="Token " + scorer_api_key, + ) + response_data = response.json() + assert response.status_code == 200 + assert response_data["error"] is None + assert response_data["stamps"] == { + sample_provider: { + "score": GITCOIN_PASSPORT_WEIGHTS[sample_provider], + "dedup": False, + "expiration_date": days_later, + } + } + + dedup_stamp = CeramicCache.objects.create( + address=wallet_b, + provider=sample_provider, + stamp={ + "type": ["VerifiableCredential"], + "proof": { + "jws": "eyJhbGciOiJFZERTQSIsImNyaXQiOlsiYjY0Il0sImI2NCI6ZmFsc2V9..34uD8jKn2N_yE8pY4ErzVD8pJruZq7qJaCxx8y0SReY2liZJatfeQUv1nqmZH19a-svOyfHt_VbmKvh6A5vwBw", + "type": "Ed25519Signature2018", + "created": days_ago, + "proofPurpose": "assertionMethod", + "verificationMethod": "did:key:z6MkghvGHLobLEdj1bgRLhS4LPGJAvbMA1tn2zcRyqmYU5LC#z6MkghvGHLobLEdj1bgRLhS4LPGJAvbMA1tn2zcRyqmYU5LC", + }, + "issuer": "did:key:z6MkghvGHLobLEdj1bgRLhS4LPGJAvbMA1tn2zcRyqmYU5LC", + "@context": ["https://www.w3.org/2018/credentials/v1"], + "issuanceDate": days_ago, + "expirationDate": days_later, + "credentialSubject": { + "id": f"did:pkh:eip155:1:{wallet_b}", + "hash": sample_provider_hash, + "@context": [ + { + "hash": "https://schema.org/Text", + "provider": sample_provider, + } + ], + "provider": sample_provider, + }, + }, + ) response = client.get( - f"{self.base_url}/{comunity.pk}/score/{wallet_a}", - HTTP_AUTHORIZATION="Token " + api_key, + f"{self.base_url}/{scorer_community.pk}/score/{wallet_b}", + HTTP_AUTHORIZATION="Token " + scorer_api_key, + ) + response_data = response.json() + assert response.status_code == 200 + assert response_data["error"] is None + assert response_data["stamps"] == { + sample_provider: { + "score": "0", + "dedup": True, + "expiration_date": days_later, + } + } + response = client.get( + f"{self.base_url}/{scorer_community.pk}/score/{wallet_a}", + HTTP_AUTHORIZATION="Token " + scorer_api_key, ) response_data = response.json() - print("response_data 123123", response_data) assert response.status_code == 200 assert response_data["error"] is None assert response_data["stamps"] == {