Skip to content

Commit

Permalink
[staged-updates] should fix app version history
Browse files Browse the repository at this point in the history
  • Loading branch information
biblicabeebli committed Apr 8, 2024
1 parent 14ce977 commit f1ba9d1
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 11 deletions.
15 changes: 11 additions & 4 deletions authentication/participant_authentication.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,9 @@ def validate_post(request: HttpRequest, require_password: bool, registration: bo
except UnreadablePostError:
return abort(500)

last_version_code = session_participant.last_version_code
prior_version_code = session_participant.last_version_code
prior_version_name = session_participant.last_version_name
prior_os_version = session_participant.last_os_version

# device tracking/info database updates
tracking_updates = {}
Expand All @@ -92,9 +94,14 @@ def validate_post(request: HttpRequest, require_password: bool, registration: bo
session_participant.update_only(**tracking_updates)

# attrubute is udptaded in update_only
if last_version_code != session_participant.last_version_code:
log(f"os version changed: {last_version_code}")
session_participant.generate_device_status_report_history(last_version_code)
session_participant.refresh_from_db()
if (prior_version_code != session_participant.last_version_code or
prior_version_name != session_participant.last_version_name or
prior_os_version != session_participant.last_os_version):
# log(f"os version changed: {last_version_code} to {session_participant.last_version_code}")
session_participant.generate_app_version_history(
prior_version_code, prior_version_name, prior_os_version
)

# we generate a log of the device status report, we do compress the data tho.
if session_participant.enable_extensive_device_info_tracking:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Generated by Django 4.2.11 on 2024-04-08 05:29

from django.db import migrations, models

# I screwed up the initial implementation of the AppVersionHistory model, but it never generated
# any data so we can just delete it and re-create it.

def create_initial_appversion_history(apps, schema_editor):
AppVersionHistory = apps.get_model('database', 'AppVersionHistory')
AppVersionHistory.objects.all().delete()

Participant = apps.get_model('database', 'Participant')

values = ("pk", "last_version_code", "last_version_name", "last_os_version")
query = Participant.objects.all().values_list(*values)
bulk_creations = []
for pk, last_version_code, last_version_name, last_os_version in query:
bulk_creations.append(AppVersionHistory(
participant_id=pk,
app_version_code=last_version_code or "missing",
app_version_name=last_version_name or "missing",
os_version=last_os_version or "missing",
))
AppVersionHistory.objects.bulk_create(bulk_creations)


class Migration(migrations.Migration):

dependencies = [
('database', '0118_filetoprocess_app_version_appversionhistory'),
]

operations = [
migrations.RemoveField(
model_name='appversionhistory',
name='app_version',
),
migrations.AddField(
model_name='appversionhistory',
name='app_version_code',
field=models.CharField(default='migrated', max_length=16),
preserve_default=False,
),
migrations.AddField(
model_name='appversionhistory',
name='app_version_name',
field=models.CharField(default='migrated', max_length=16),
preserve_default=False,
),
migrations.AddField(
model_name='appversionhistory',
name='os_version',
field=models.CharField(default='migrated', max_length=16),
preserve_default=False,
),
migrations.RunPython(create_initial_appversion_history, reverse_code=migrations.RunPython.noop),
]
16 changes: 12 additions & 4 deletions database/user_models_participant.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class Participant(AbstractPasswordUser):

# retired participants are blocked from uploading further data.
permanently_retired = models.BooleanField(default=False)
# easy enrolement disables the need for a password at registration (ignores the password)
easy_enrollment = models.BooleanField(default=False)

# Participant experiments, beta features - these fields literally may not be used Anywhere, some
Expand All @@ -118,6 +119,7 @@ class Participant(AbstractPasswordUser):
enable_developer_datastream = models.BooleanField(default=False)
enable_beta_features = models.BooleanField(default=False)
enable_extensive_device_info_tracking = models.BooleanField(default=False)

EXPERIMENT_FIELDS = (
"enable_heartbeat",
# "enable_aggressive_background_persistence",
Expand Down Expand Up @@ -305,9 +307,14 @@ def get_identifiers(self):
######################################### LOGGING ##############################################
################################################################################################

def generate_app_version_history(self, last_version_code: str):
def generate_app_version_history(self, version_code: str, version_name: str, os_version: str):
""" Creates an AppVersionHistory object. """
AppVersionHistory.objects.create(participant=self, app_version=self.last_version_code)
AppVersionHistory.objects.create(
participant=self,
app_version_code=version_code or "missing",
app_version_name=version_name or "missing",
os_version=os_version or "missing",
)

def generate_device_status_report_history(self, url: str):
# this is just stupid but a mistake ages ago means we have to do this.
Expand Down Expand Up @@ -523,8 +530,9 @@ class ParticipantActionLog(UtilityModel):

class AppVersionHistory(TimestampedModel):
participant = models.ForeignKey(Participant, null=False, on_delete=models.PROTECT, related_name="app_version_history")
app_version = models.CharField(max_length=16, blank=False, null=False)

app_version_code = models.CharField(max_length=16, blank=False, null=False)
app_version_name = models.CharField(max_length=16, blank=False, null=False)
os_version = models.CharField(max_length=16, blank=False, null=False)

# device status report history
class DeviceStatusReportHistory(UtilityModel):
Expand Down
26 changes: 25 additions & 1 deletion tests/test_mobile_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from database.data_access_models import FileToProcess
from database.schedule_models import AbsoluteSchedule, ScheduledEvent, WeeklySchedule
from database.system_models import GenericEvent
from database.user_models_participant import AppHeartbeats
from database.user_models_participant import AppHeartbeats, AppVersionHistory
from libs.rsa import get_RSA_cipher
from libs.schedules import (get_start_and_end_of_java_timings_week,
repopulate_absolute_survey_schedule_events, repopulate_relative_survey_schedule_events)
Expand Down Expand Up @@ -79,6 +79,30 @@ def test_no_surveys(self):
resp = self.smart_post_status_code(200)
self.assertEqual(resp.content, b"[]")

def test_version_code_update_triggers_app_version_code_history(self):
self.default_participant.update_only(last_version_code="1.0.0")
self.assertFalse(AppVersionHistory.objects.exists())
self.smart_post_status_code(200, version_code="1.0.1")
self.default_participant.refresh_from_db()
self.assertEqual(self.default_participant.last_version_code, "1.0.1")
self.assertTrue(AppVersionHistory.objects.exists())

def test_version_code_update_triggers_app_version_name_history(self):
self.default_participant.update_only(last_version_name="1.0.0")
self.assertFalse(AppVersionHistory.objects.exists())
self.smart_post_status_code(200, version_name="1.0.1")
self.default_participant.refresh_from_db()
self.assertEqual(self.default_participant.last_version_name, "1.0.1")
self.assertTrue(AppVersionHistory.objects.exists())

def test_version_code_update_triggers_os_version_history(self):
self.default_participant.update_only(last_os_version="1.0.0")
self.assertFalse(AppVersionHistory.objects.exists())
self.smart_post_status_code(200, os_version="1.0.1")
self.default_participant.refresh_from_db()
self.assertEqual(self.default_participant.last_os_version, "1.0.1")
self.assertTrue(AppVersionHistory.objects.exists())

def test_basic_survey(self):
self.assertIsNone(self.default_participant.last_get_latest_surveys)
self.default_survey
Expand Down
3 changes: 1 addition & 2 deletions tests/test_unittests.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,7 @@ def test_confirm_DeviceStatusReportHistory(self):

@data_purge_mock_s3_calls
def test_confirm_AppVersionHistory(self):
self.default_participant.update_only(last_version_code="10")
self.default_participant.generate_app_version_history("11")
self.default_participant.generate_app_version_history("11", "11", "11")
self.default_participant_deletion_event
self.assertEqual(AppVersionHistory.objects.count(), 1)
run_next_queued_participant_data_deletion()
Expand Down

0 comments on commit f1ba9d1

Please sign in to comment.