Skip to content

Commit 4870989

Browse files
antkrytihorsokhanexoft
authored andcommitted
[ENG-10737] Registrations are failing to auto-approve [privacy] (CenterForOpenScience#11718)
* fix check manual restart approval * minor fixes
1 parent 9c7d5fb commit 4870989

7 files changed

Lines changed: 99 additions & 36 deletions

File tree

osf/management/commands/process_manual_restart_approvals.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from django.utils import timezone
55
from osf.models import Registration
66
from osf.models.admin_log_entry import AdminLogEntry, MANUAL_ARCHIVE_RESTART
7-
from website import settings
87
from scripts.approve_registrations import approve_past_pendings
98

109
logger = logging.getLogger(__name__)
@@ -134,9 +133,9 @@ def should_auto_approve(self, registration):
134133
if approval.is_rejected:
135134
return 'approval was rejected'
136135

137-
time_since_initiation = timezone.now() - approval.initiation_date
138-
if time_since_initiation < settings.REGISTRATION_APPROVAL_TIME:
139-
remaining = settings.REGISTRATION_APPROVAL_TIME - time_since_initiation
136+
auto_approval_time = approval.auto_approval_time
137+
if timezone.now() < auto_approval_time:
138+
remaining = auto_approval_time - timezone.now()
140139
return f'not ready yet ({remaining} remaining)'
141140

142141
if registration.is_stuck_registration:

osf/models/registrations.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ def is_collection(self):
237237

238238
@property
239239
def archive_job(self):
240-
return self.archive_jobs.first() if self.archive_jobs.count() else None
240+
return self.archive_jobs.first()
241241

242242
@property
243243
def sanction(self):

osf/models/sanctions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,10 @@ class RegistrationApproval(SanctionCallbackMixin, EmailApprovableSanction):
878878

879879
initiated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.CASCADE)
880880

881+
@property
882+
def auto_approval_time(self):
883+
return self.initiation_date + osf_settings.REGISTRATION_APPROVAL_TIME
884+
881885
@staticmethod
882886
def find_approval_backlog():
883887
"""

osf_tests/test_archiver.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,22 @@ def test_archive(self, mock_chain, mock_enqueue):
451451
]
452452
)
453453

454+
@mock.patch('website.archiver.tasks.delayed_manual_restart_approval.delay')
455+
@mock.patch('osf.management.commands.force_archive.archive')
456+
@mock.patch('osf.management.commands.force_archive.verify')
457+
def test_force_archive_schedules_manual_restart_approval_check(
458+
self, mock_verify, mock_archive, mock_delayed_check
459+
):
460+
result = force_archive(
461+
registration_id=self.dst._id,
462+
permissible_addons=['osfstorage'],
463+
)
464+
465+
assert result == f'Registration {self.dst._id} archive completed'
466+
mock_verify.assert_called_once()
467+
mock_archive.assert_called_once()
468+
mock_delayed_check.assert_called_once_with(self.dst._id, delay_minutes=5)
469+
454470
def test_stat_addon(self):
455471
with mock.patch.object(BaseStorageAddon, '_get_file_tree') as mock_file_tree:
456472
mock_file_tree.return_value = FILE_TREE

scripts/check_manual_restart_approval.py

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,56 @@
11
import logging
2+
from framework import sentry
23
from framework.celery_tasks import app as celery_app
34
from django.core.management import call_command
5+
from django.utils import timezone
46
from osf.models import Registration
7+
from scripts.approve_registrations import approve_past_pendings
58

69
logger = logging.getLogger(__name__)
710

811

912
@celery_app.task(name='scripts.check_manual_restart_approval')
1013
def check_manual_restart_approval(registration_id):
1114
try:
12-
try:
13-
registration = Registration.objects.get(_id=registration_id)
14-
except Registration.DoesNotExist:
15+
registration = Registration.load(registration_id)
16+
if not registration:
1517
logger.error(f"Registration {registration_id} not found")
1618
return f"Registration {registration_id} not found"
1719

1820
if registration.is_public or registration.is_registration_approved:
1921
return f"Registration {registration_id} already approved/public"
2022

23+
approval = registration.registration_approval
24+
if not approval:
25+
logger.error(f"Registration {registration_id} has no registration approval object")
26+
return f"Registration {registration_id} has no registration approval object"
27+
28+
if approval.is_rejected:
29+
logger.info(f"Registration {registration_id} approval was rejected")
30+
return f"Registration {registration_id} approval was rejected"
31+
2132
if registration.archiving:
22-
logger.info(f"Registration {registration_id} still archiving, retrying in 10 minutes")
33+
logger.debug(f"Registration {registration_id} still archiving, retrying in 10 minutes")
2334
check_manual_restart_approval.apply_async(
2435
args=[registration_id],
2536
countdown=600
2637
)
2738
return f"Registration {registration_id} still archiving, scheduled retry"
2839

29-
logger.info(f"Processing manual restart approval for registration {registration_id}")
40+
if timezone.now() < approval.auto_approval_time:
41+
logger.info(f"Registration {registration_id} not ready for auto-approval yet")
42+
return f"Registration {registration_id} not ready for auto-approval yet"
3043

31-
call_command(
32-
'process_manual_restart_approvals',
33-
registration_id=registration_id,
34-
dry_run=False,
35-
hours_back=24,
36-
verbosity=1
37-
)
44+
logger.debug(f"Processing manual restart approval for registration {registration_id}")
45+
approve_past_pendings([approval], dry_run=False)
3846

3947
return f"Processed manual restart approval check for registration {registration_id}"
4048

4149
except Exception as e:
42-
logger.error(f"Error processing manual restart approval for {registration_id}: {e}")
50+
msg = f"Error processing manual restart approval for {registration_id}: {str(e)}"
51+
logger.error(msg)
52+
sentry.log_message(msg)
53+
sentry.log_exception(e)
4354
raise
4455

4556

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from datetime import timedelta
2+
from unittest import mock
3+
4+
from django.utils import timezone
5+
6+
from osf_tests.factories import RegistrationFactory, UserFactory
7+
from scripts.check_manual_restart_approval import check_manual_restart_approval
8+
from tests.base import OsfTestCase
9+
from website import settings
10+
11+
12+
class TestCheckManualRestartApproval(OsfTestCase):
13+
14+
def setUp(self):
15+
super().setUp()
16+
self.user = UserFactory()
17+
self.registration = RegistrationFactory(creator=self.user, archive=False)
18+
self.registration.require_approval(self.user)
19+
20+
@mock.patch('scripts.check_manual_restart_approval.approve_past_pendings')
21+
def test_skips_if_approval_window_not_elapsed(self, mock_approve):
22+
self.registration.registration_approval.initiation_date = timezone.now() - timedelta(hours=47)
23+
self.registration.registration_approval.save()
24+
25+
result = check_manual_restart_approval(self.registration._id)
26+
27+
assert 'not ready for auto-approval' in result
28+
mock_approve.assert_not_called()
29+
30+
@mock.patch('scripts.check_manual_restart_approval.approve_past_pendings')
31+
def test_approves_when_approval_window_elapsed(self, mock_approve):
32+
self.registration.registration_approval.initiation_date = (
33+
timezone.now() - settings.REGISTRATION_APPROVAL_TIME - timedelta(minutes=1)
34+
)
35+
self.registration.registration_approval.save()
36+
37+
result = check_manual_restart_approval(self.registration._id)
38+
39+
assert 'Processed manual restart approval check' in result
40+
mock_approve.assert_called_once_with([self.registration.registration_approval], dry_run=False)
41+
42+
@mock.patch('scripts.check_manual_restart_approval.Registration.load', return_value=None)
43+
def test_returns_not_found_when_registration_missing(self, mock_load):
44+
result = check_manual_restart_approval('abc12')
45+
46+
assert result == 'Registration abc12 not found'
47+
mock_load.assert_called_once_with('abc12')

website/archiver/tasks.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,6 @@
77
import celery
88
from celery.utils.log import get_task_logger
99

10-
from django.utils import timezone
11-
from datetime import timedelta
12-
1310
from framework.celery_tasks import app as celery_app
1411
from framework.celery_tasks.utils import logged
1512
from framework.exceptions import HTTPError
@@ -38,7 +35,6 @@
3835
from website import settings
3936
from website.app import init_addons
4037

41-
from osf.models.admin_log_entry import AdminLogEntry, MANUAL_ARCHIVE_RESTART
4238
from osf.models import (
4339
ArchiveJob,
4440
AbstractNode,
@@ -445,23 +441,9 @@ def archive_success(self, dst_pk, job_pk):
445441
job.save()
446442
dst.sanction.ask(dst.get_active_contributors_recursive(unique_users=True))
447443

448-
if was_manually_restarted(dst):
449-
logger.info(f'Registration {dst._id} was manually restarted, scheduling approval check')
450-
delayed_manual_restart_approval.delay(dst._id, delay_minutes=5)
451-
452444
dst.update_search()
453445

454446

455-
def was_manually_restarted(registration):
456-
recent_logs = AdminLogEntry.objects.filter(
457-
object_id=registration.pk,
458-
action_flag=MANUAL_ARCHIVE_RESTART,
459-
action_time__gte=timezone.now() - timedelta(hours=48)
460-
)
461-
462-
return recent_logs.exists()
463-
464-
465447
@celery_app.task(bind=True)
466448
def force_archive(self, registration_id, permissible_addons, allow_unconfigured=False, skip_collisions=False, delete_collisions=False):
467449
from osf.management.commands.force_archive import archive, verify
@@ -482,6 +464,10 @@ def force_archive(self, registration_id, permissible_addons, allow_unconfigured=
482464
skip_collisions=skip_collisions,
483465
delete_collisions=delete_collisions,
484466
)
467+
468+
logger.info(f'Registration {registration._id} was manually restarted, scheduling approval check')
469+
delayed_manual_restart_approval.delay(registration._id, delay_minutes=5)
470+
485471
return f'Registration {registration_id} archive completed'
486472

487473
except Exception as exc:

0 commit comments

Comments
 (0)