Skip to content
Open
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
4 changes: 3 additions & 1 deletion users/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from urllib.parse import urlencode, urlparse

import requests
import sentry_sdk
from django.conf import settings
from django.contrib.auth.hashers import check_password
from django.contrib.auth.password_validation import validate_password
Expand Down Expand Up @@ -928,7 +929,8 @@ def report_integrity(request):
request_id=request_id,
device_id=device_id,
)
except DuplicateSampleRequestError:
except DuplicateSampleRequestError as e:
sentry_sdk.capture_exception(e)
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we can track if there's something funky going on...

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I don't think this is strictly necessary (but fine to do). I don't know that getting a duplicate request is something we need to be concerned about, and I want to be in the habit of keeping sentry full of only actionable errors rather than ones we say "that is fine" about as much as we can.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason I added the sentry logging was so we can know if there's spamming or so going on (i.e. endpoint is hit with the same request_id multiple times) so we can let mobile know to look into it.

return JsonResponse({"result_code": None}, status=200)
except HttpError:
return JsonResponse({"result_code": None}, status=500)
Expand Down
23 changes: 14 additions & 9 deletions utils/app_integrity/google_play_integrity.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,19 @@ def log_sample_request(self, request_id: str, device_id: str):
and passed_account_details_check
)

return DeviceIntegritySample.objects.create(
sample, created = DeviceIntegritySample.objects.get_or_create(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we decide to keep the old vs new values? It seems like we may want to update to the latest.

If we are going to keep the old ones and raise an error on conflict, I think you can leave this as create and let the db error be raised, since we aren't actually doing a get_or_create but create or exception.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively, we could consider just storing both, since it is a new request and new data from the server side.

Copy link
Copy Markdown
Contributor Author

@Charl1996 Charl1996 Sep 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How did we decide to keep the old vs new values? It seems like we may want to update to the latest.

Theoretically there won't ever be a "newest" value (only one), because mobile does not make the request twice for the same request_id. In the fringe case (like the one we had) I highly doubt the outcome of the sample will change, unless mobile explicitly makes a request again for the same device after the user has made updates to their device which would result in a different outcome. And even if the user made updates that now results in a different outcome, that's only one sample in literally thousands, which I think renders it somewhat insignificant...that's why I didn't bother catering for a second-request-scenario too much.

If we are going to keep the old ones and raise an error on conflict, I think you can leave this as create and let the db error be raised

If I let the DB error raise I'd have to catch that and return a sensible result to mobile, but the current implementation essentially mimicks that same behaviour with the custom error. I can update if you feel strong about it, but it's not changing any behaviour (just getting rid of a custom error).

request_id=request_id,
device_id=device_id,
is_demo_user=self.is_demo_user,
google_verdict=raw_verdict,
passed=check_passed,
passed_request_check=passed_request_check,
passed_app_integrity_check=passed_app_integrity_check,
passed_device_integrity_check=passed_device_integrity_check,
passed_account_details_check=passed_account_details_check,
defaults={
"device_id": device_id,
"is_demo_user": self.is_demo_user,
"google_verdict": raw_verdict,
"passed": check_passed,
"passed_request_check": passed_request_check,
"passed_app_integrity_check": passed_app_integrity_check,
"passed_device_integrity_check": passed_device_integrity_check,
"passed_account_details_check": passed_account_details_check,
},
)
if not created:
raise DuplicateSampleRequestError("Duplicate sample request")
return sample