diff --git a/kobo/apps/openrosa/apps/api/tests/viewsets/test_xform_submission_api.py b/kobo/apps/openrosa/apps/api/tests/viewsets/test_xform_submission_api.py index ea6ab542d8..7aabf6b42d 100644 --- a/kobo/apps/openrosa/apps/api/tests/viewsets/test_xform_submission_api.py +++ b/kobo/apps/openrosa/apps/api/tests/viewsets/test_xform_submission_api.py @@ -387,9 +387,9 @@ def test_post_submission_json_without_submission_key(self): ) def test_submission_blocking_flag(self): - # Set 'submissions_suspended' True in the profile metadata to test if + # Set 'submissions_suspended' True in the profile to test if # submission do fail with the flag set - self.xform.user.profile.metadata['submissions_suspended'] = True + self.xform.user.profile.submissions_suspended = True self.xform.user.profile.save() # No need auth for this test @@ -430,7 +430,7 @@ def test_submission_blocking_flag(self): f.seek(0) # check that users can submit data again when flag is removed - self.xform.user.profile.metadata['submissions_suspended'] = False + self.xform.user.profile.submissions_suspended = False self.xform.user.profile.save() request = self.factory.post( diff --git a/kobo/apps/openrosa/apps/logger/management/commands/populate_submission_counters.py b/kobo/apps/openrosa/apps/logger/management/commands/populate_submission_counters.py index cbaf2f0142..3c7309ec3d 100644 --- a/kobo/apps/openrosa/apps/logger/management/commands/populate_submission_counters.py +++ b/kobo/apps/openrosa/apps/logger/management/commands/populate_submission_counters.py @@ -212,15 +212,15 @@ def suspend_submissions_for_user(self, user: settings.AUTH_USER_MODEL): user_profile.metadata = {} # Set the flag `submissions_suspended` to true if it is not already. - if not user_profile.metadata.get('submissions_suspended'): + if not user_profile.submissions_suspended: # We are using the flag `submissions_suspended` to prevent # new submissions from coming in while the # counters are being calculated. - user_profile.metadata['submissions_suspended'] = True - user_profile.save(update_fields=['metadata']) + user_profile.submissions_suspended = True + user_profile.save(update_fields=['submissions_suspended']) def release_old_locks(self): - updates = {'submissions_suspended': False} + updates = {} if self._force: updates['counters_updates_status'] = 'not-complete' @@ -231,12 +231,12 @@ def release_old_locks(self): 'metadata', updates=updates, ), + submissions_suspended=False ) def update_user_profile(self, user: settings.AUTH_USER_MODEL): # Update user's profile (and lock the related row) updates = { - 'submissions_suspended': False, 'counters_updates_status': 'complete', } UserProfile.objects.filter( @@ -246,4 +246,5 @@ def update_user_profile(self, user: settings.AUTH_USER_MODEL): 'metadata', updates=updates, ), + submissions_suspended=False, ) diff --git a/kobo/apps/openrosa/apps/logger/management/commands/update_attachment_storage_bytes.py b/kobo/apps/openrosa/apps/logger/management/commands/update_attachment_storage_bytes.py index 0f6e328964..b73b43dfbb 100644 --- a/kobo/apps/openrosa/apps/logger/management/commands/update_attachment_storage_bytes.py +++ b/kobo/apps/openrosa/apps/logger/management/commands/update_attachment_storage_bytes.py @@ -199,24 +199,19 @@ def _lock_user_profile(self, user: settings.AUTH_USER_MODEL): user_profile.metadata = {} # Set the flag to true if it was never set. - if not user_profile.metadata.get('submissions_suspended'): + if not user_profile.submissions_suspended: # We are using the flag `submissions_suspended` to prevent # new submissions from coming in while the # `attachment_storage_bytes` is being calculated. - user_profile.metadata['submissions_suspended'] = True - user_profile.save(update_fields=['metadata']) + user_profile.submissions_suspended = True + user_profile.save(update_fields=['submissions_suspended']) def _release_locks(self): # Release any locks on the users' profile from getting submissions if self._verbosity > 1: self.stdout.write('Releasing submission locks…') - UserProfile.objects.all().update( - metadata=ReplaceValues( - 'metadata', - updates={'submissions_suspended': False}, - ), - ) + UserProfile.objects.all().update(submissions_suspended=False) def _reset_user_profile_counters(self): @@ -251,7 +246,6 @@ def _update_user_profile(self, user: settings.AUTH_USER_MODEL): # Update user's profile (and lock the related row) updates = { - 'submissions_suspended': False, 'attachments_counting_status': 'complete', } @@ -271,4 +265,5 @@ def _update_user_profile(self, user: settings.AUTH_USER_MODEL): 'metadata', updates=updates, ), + submissions_suspended=False, ) diff --git a/kobo/apps/openrosa/apps/logger/migrations/0029_populate_daily_xform_counters_for_year.py b/kobo/apps/openrosa/apps/logger/migrations/0029_populate_daily_xform_counters_for_year.py index 920bc32709..306c43076c 100644 --- a/kobo/apps/openrosa/apps/logger/migrations/0029_populate_daily_xform_counters_for_year.py +++ b/kobo/apps/openrosa/apps/logger/migrations/0029_populate_daily_xform_counters_for_year.py @@ -32,7 +32,7 @@ class Migration(migrations.Migration): dependencies = [ ('logger', '0028_add_user_to_daily_submission_counters'), - ('main', '0012_add_validate_password_flag_to_profile'), + ('main', '0017_userprofile_submissions_suspended'), ] # We don't do anything when migrating in reverse diff --git a/kobo/apps/openrosa/apps/logger/models/instance.py b/kobo/apps/openrosa/apps/logger/models/instance.py index ee45fa6477..d841655970 100644 --- a/kobo/apps/openrosa/apps/logger/models/instance.py +++ b/kobo/apps/openrosa/apps/logger/models/instance.py @@ -135,7 +135,7 @@ def check_active(self, force): # wrapped in try/except UserProfile = apps.get_model('main', 'UserProfile') # noqa - Avoid circular imports if profile := UserProfile.objects.filter(user=self.xform.user).first(): - if profile.metadata.get('submissions_suspended', False): + if profile.submissions_suspended is False: raise TemporarilyUnavailableError() return diff --git a/kobo/apps/openrosa/apps/main/migrations/0017_userprofile_submissions_suspended.py b/kobo/apps/openrosa/apps/main/migrations/0017_userprofile_submissions_suspended.py new file mode 100644 index 0000000000..6c02250634 --- /dev/null +++ b/kobo/apps/openrosa/apps/main/migrations/0017_userprofile_submissions_suspended.py @@ -0,0 +1,21 @@ +# Generated by Django 4.2.15 on 2024-09-02 21:41 + +from django.db import migrations, models +import kobo.apps.openrosa.apps.main.models.meta_data +import kpi.deployment_backends.kc_access.storage +import kpi.fields.file + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0016_drop_old_restservice_tables'), + ] + + operations = [ + migrations.AddField( + model_name='userprofile', + name='submissions_suspended', + field=models.BooleanField(default=False), + ), + ] diff --git a/kobo/apps/openrosa/apps/main/models/user_profile.py b/kobo/apps/openrosa/apps/main/models/user_profile.py index 7460ad11fb..4a73c168de 100644 --- a/kobo/apps/openrosa/apps/main/models/user_profile.py +++ b/kobo/apps/openrosa/apps/main/models/user_profile.py @@ -37,6 +37,7 @@ class UserProfile(models.Model): metadata = models.JSONField(default=dict, blank=True) is_mfa_active = LazyDefaultBooleanField(default=False) validated_password = models.BooleanField(default=True) + submissions_suspended = models.BooleanField(default=False) class Meta: app_label = 'main' diff --git a/kpi/deployment_backends/openrosa_backend.py b/kpi/deployment_backends/openrosa_backend.py index 53579d5a4b..5c5b22c8ac 100644 --- a/kpi/deployment_backends/openrosa_backend.py +++ b/kpi/deployment_backends/openrosa_backend.py @@ -1312,23 +1312,13 @@ def xform_id_string(self): def suspend_submissions(user_ids: list[int]): UserProfile.objects.filter( user_id__in=user_ids - ).update( - metadata=UpdateJSONFieldAttributes( - 'metadata', - updates={'submissions_suspended': True}, - ), - ) + ).update(submissions_suspended=True) try: yield finally: UserProfile.objects.filter( user_id__in=user_ids - ).update( - metadata=UpdateJSONFieldAttributes( - 'metadata', - updates={'submissions_suspended': False}, - ), - ) + ).update(submissions_suspended=False) def transfer_submissions_ownership( self, previous_owner_username: str