Skip to content

Commit 070b376

Browse files
authored
Merge pull request #11650 from Ostap-Zherebetskyi/feature/sso_availability_data_migrations
[ENG-10633] Create a data migration script/command that populates existing institutions with respective `sso_availability` choices
2 parents e67647a + 7d6a4a3 commit 070b376

2 files changed

Lines changed: 262 additions & 0 deletions

File tree

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from django.core.management.base import BaseCommand
2+
from django.db import transaction
3+
from django.db.models import Q
4+
5+
from osf.models.institution import Institution, SSOAvailability, IntegrationType
6+
7+
8+
class Command(BaseCommand):
9+
help = 'Backfill sso_availability using fast DB-level updates'
10+
11+
def add_arguments(self, parser):
12+
parser.add_argument(
13+
'--dry-run',
14+
action='store_true',
15+
help='Show how many rows would be updated without applying changes',
16+
)
17+
18+
def handle(self, *args, **options):
19+
dry_run = options['dry_run']
20+
21+
# Build querysets
22+
qs_no_protocol = Institution.objects.filter(
23+
delegation_protocol=IntegrationType.NONE.value
24+
).exclude(
25+
sso_availability=SSOAvailability.UNAVAILABLE.value
26+
)
27+
28+
qs_inactive_with_protocol = Institution.objects.filter(
29+
~Q(delegation_protocol=IntegrationType.NONE.value),
30+
deactivated__isnull=False
31+
).exclude(
32+
sso_availability=SSOAvailability.HIDDEN.value
33+
)
34+
35+
qs_active_with_protocol = Institution.objects.filter(
36+
~Q(delegation_protocol=IntegrationType.NONE.value),
37+
deactivated__isnull=True
38+
).exclude(
39+
sso_availability=SSOAvailability.PUBLIC.value
40+
)
41+
42+
count_no_protocol = qs_no_protocol.count()
43+
count_inactive = qs_inactive_with_protocol.count()
44+
count_active = qs_active_with_protocol.count()
45+
46+
total = count_no_protocol + count_inactive + count_active
47+
48+
self.stdout.write('Planned updates:')
49+
self.stdout.write(f" No protocol → UNAVAILABLE: {count_no_protocol}")
50+
self.stdout.write(f" Inactive + protocol → HIDDEN: {count_inactive}")
51+
self.stdout.write(f" Active + protocol → PUBLIC: {count_active}")
52+
self.stdout.write(f" TOTAL: {total}")
53+
54+
if dry_run:
55+
self.stdout.write(self.style.WARNING('Dry run, no changes applied.'))
56+
return
57+
58+
with transaction.atomic():
59+
updated_no_protocol = qs_no_protocol.update(
60+
sso_availability=SSOAvailability.UNAVAILABLE.value
61+
)
62+
63+
updated_inactive = qs_inactive_with_protocol.update(
64+
sso_availability=SSOAvailability.HIDDEN.value
65+
)
66+
67+
updated_active = qs_active_with_protocol.update(
68+
sso_availability=SSOAvailability.PUBLIC.value
69+
)
70+
71+
self.stdout.write(
72+
self.style.SUCCESS(
73+
'Done:\n'
74+
f" UNAVAILABLE: {updated_no_protocol}\n"
75+
f" HIDDEN: {updated_inactive}\n"
76+
f" PUBLIC: {updated_active}\n"
77+
f" TOTAL: {updated_no_protocol + updated_inactive + updated_active}"
78+
)
79+
)

0 commit comments

Comments
 (0)