script de correction du journal GLC
This commit is contained in:
parent
7d519ff647
commit
76d04af320
|
@ -0,0 +1,12 @@
|
|||
TENANT=moncompte-rec.grandlyon.com
|
||||
|
||||
HOST=grandlyon-cut-test-sso-1
|
||||
|
||||
SCRIPT=fix_journal.py
|
||||
|
||||
all:
|
||||
scp $(SCRIPT) $(HOST):/tmp
|
||||
ssh $(HOST) sudo authentic2-multitenant-manage tenant_command runscript -d $(TENANT) /tmp/$(SCRIPT)
|
||||
|
||||
shell:
|
||||
ssh $(HOST)
|
|
@ -0,0 +1,268 @@
|
|||
import collections
|
||||
import datetime
|
||||
import sys
|
||||
|
||||
sys.stdout.reconfigure(line_buffering=True)
|
||||
|
||||
from authentic2.apps.journal.models import Event, EventType
|
||||
from authentic2.custom_user.models import User
|
||||
from authentic2.models import Attribute, AttributeValue
|
||||
from authentic2_auth_fc.models import FcAccount
|
||||
from django.db import connection, transaction
|
||||
from django.utils.timezone import localtime, make_aware
|
||||
|
||||
registration_type = EventType.objects.get(name="user.registration")
|
||||
validated_attribute = Attribute.objects.get(name="validated")
|
||||
qs = User.objects.filter(
|
||||
ou__slug="usagers",
|
||||
date_joined__gt=make_aware(datetime.datetime(2019, 4, 1)),
|
||||
fc_accounts__isnull=False,
|
||||
)
|
||||
user_ids = set(qs.values_list("id", flat=True))
|
||||
atvs = AttributeValue.objects.filter(attribute=validated_attribute, content="1", object_id__in=user_ids)
|
||||
validated_user_ids = set(atvs.values_list("object_id", flat=True))
|
||||
events = (
|
||||
Event.objects.filter(user_id__in=user_ids, type__name__in=["user.registration", "user.login"])
|
||||
.select_related("type")
|
||||
.order_by(
|
||||
"type__name",
|
||||
"user_id",
|
||||
"timestamp",
|
||||
)
|
||||
.distinct("type__name", "user_id")
|
||||
)
|
||||
registration = {}
|
||||
first_login = {}
|
||||
|
||||
for event in events.iterator():
|
||||
if event.type.name == "user.registration":
|
||||
registration[event.user_id] = event
|
||||
if (
|
||||
event.type.name == "user.login"
|
||||
and event.user_id not in first_login
|
||||
and event.data["how"] == "france-connect"
|
||||
):
|
||||
first_login[event.user_id] = event
|
||||
|
||||
counter = collections.Counter()
|
||||
|
||||
date_joined = dict(User.objects.filter(id__in=user_ids).values_list("id", "date_joined"))
|
||||
fc_accounts = dict(FcAccount.objects.values_list("user_id", "id"))
|
||||
fc_accounts_created = dict(FcAccount.objects.values_list("user_id", "created"))
|
||||
|
||||
print(f"{len(user_ids)} accounts to fix.")
|
||||
print()
|
||||
|
||||
delay = 240
|
||||
|
||||
count = 0
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
user_id in registration
|
||||
and registration[user_id].data["how"] == "france-connect"
|
||||
and user_id in validated_user_ids
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
count += 1
|
||||
print(f"Removed {count} valid user ids.")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
|
||||
|
||||
count = 0
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
user_id in registration
|
||||
and registration[user_id].data["how"] != "france-connect"
|
||||
and user_id in validated_user_ids
|
||||
and abs((fc_accounts_created[user_id] - date_joined[user_id]).total_seconds()) > 10
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
count += 1
|
||||
print(f"Removed {count} valid user ids linked after registration.")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
|
||||
count = 0
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
(user_id not in registration or registration[user_id].data['how'] != 'france-connect')
|
||||
and (
|
||||
user_id not in first_login
|
||||
or abs((first_login[user_id].timestamp - date_joined[user_id]).total_seconds()) > delay
|
||||
or date_joined[user_id] < make_aware(datetime.datetime(2022, 4, 1))
|
||||
)
|
||||
and user_id in validated_user_ids
|
||||
and (
|
||||
abs((fc_accounts_created[user_id] - date_joined[user_id]).total_seconds()) > delay
|
||||
or date_joined[user_id] < make_aware(datetime.datetime(2022, 4, 1))
|
||||
)
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
count += 1
|
||||
print(f"Removed {count} old accounts linked to FC later.")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
|
||||
# for accounts with a first login through FC and no registration event and no validation
|
||||
user_ids_to_validate = set()
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
user_id in first_login
|
||||
and first_login[user_id].data["how"] == "france-connect"
|
||||
and abs((first_login[user_id].timestamp - date_joined[user_id]).total_seconds()) < delay
|
||||
and user_id not in registration
|
||||
and user_id not in validated_user_ids
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
user_ids_to_validate.add(user_id)
|
||||
|
||||
if user_ids_to_validate:
|
||||
print(
|
||||
f"{len(user_ids_to_validate)} registered through FC but not validated and needing a registration event."
|
||||
)
|
||||
for i, user in enumerate(User.objects.filter(id__in=user_ids_to_validate)):
|
||||
print(f"\r[{i+1:06d}/{len(user_ids_to_validate):06d}] validating... ", end="")
|
||||
with transaction.atomic():
|
||||
data = {
|
||||
"how": "france-connect",
|
||||
}
|
||||
if "service_name" in first_login[user.id].data:
|
||||
data["service_name"] = first_login[user.id].data["service_name"]
|
||||
reg = Event.objects.create(
|
||||
type=registration_type,
|
||||
timestamp=user.date_joined,
|
||||
user_id=user.id,
|
||||
session_id=first_login[user.id].session_id,
|
||||
references=first_login[user.id].references,
|
||||
data=data,
|
||||
api=False,
|
||||
)
|
||||
user.attributes.validated = True
|
||||
user.attributes.validation_context = "FC"
|
||||
user.attributes.validation_date = localtime(fc_accounts_created[user.id]).date()
|
||||
if "service_name" in first_login[user.id].data:
|
||||
user.attributes.validation_partner = data["service_name"]
|
||||
print("DONE")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
else:
|
||||
print("No account registered through FC not validated and missing registration event..\n")
|
||||
user_ids_to_validate = set()
|
||||
|
||||
|
||||
# for accounts with more than 24h between join and FC creation just validate
|
||||
user_ids_to_validate = set()
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
user_id not in validated_user_ids
|
||||
and (abs((fc_accounts_created[user_id] - date_joined[user_id]).total_seconds()) > delay)
|
||||
or (user_id in registration and registration[user_id].data["how"] == "france-connect")
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
user_ids_to_validate.add(user_id)
|
||||
|
||||
if user_ids_to_validate:
|
||||
print(
|
||||
f"{len(user_ids_to_validate)} registered by mail or FC but validated with FC and just needing validation"
|
||||
)
|
||||
for i, user in enumerate(User.objects.filter(id__in=user_ids_to_validate).order_by("id")):
|
||||
print(
|
||||
f"\r[{i+1:06d}/{len(user_ids_to_validate):06d}] validating {user.id}... ",
|
||||
end="",
|
||||
)
|
||||
with transaction.atomic():
|
||||
user.attributes.validated = True
|
||||
user.attributes.validation_context = "FC"
|
||||
user.attributes.validation_date = localtime(fc_accounts_created[user.id]).date()
|
||||
if user.id in registration and "service_name" in registration[user.id].data:
|
||||
user.attributes.validation_partner = registration[user.id].data["service_name"]
|
||||
print("DONE")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
else:
|
||||
print("No account just missing validation.\n")
|
||||
user_ids_to_validate = set()
|
||||
|
||||
|
||||
# for accounts with more than 24h between join and FC creation just validate
|
||||
user_ids_to_modify_reg_and_validate = set()
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
abs((fc_accounts_created[user_id] - date_joined[user_id]).total_seconds()) <= delay
|
||||
and user_id in registration
|
||||
and registration[user_id].data["how"] != "france-connect"
|
||||
and user_id not in validated_user_ids
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
user_ids_to_modify_reg_and_validate.add(user_id)
|
||||
|
||||
if user_ids_to_modify_reg_and_validate:
|
||||
print(
|
||||
f"{len(user_ids_to_modify_reg_and_validate)} linked to FC near the registration but registration event is wrong."
|
||||
)
|
||||
for i, user in enumerate(User.objects.filter(id__in=user_ids_to_modify_reg_and_validate)):
|
||||
print(
|
||||
f"\r[{i+1:06d}/{len(user_ids_to_modify_reg_and_validate):06d}] fixing registration and validating... ",
|
||||
end="",
|
||||
)
|
||||
continue
|
||||
with transaction.atomic():
|
||||
registration[user.id].data["how"] = "france-connect"
|
||||
registration[user.id].save()
|
||||
user.attributes.validated = True
|
||||
user.attributes.validation_context = "FC"
|
||||
user.attributes.validation_date = localtime(fc_accounts_created[user.id]).date()
|
||||
transaction.set_rollback(True)
|
||||
print("DONE\n")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
else:
|
||||
print("No account with wrong registration event.\n")
|
||||
user_ids_to_modify_reg_and_validate = set()
|
||||
|
||||
|
||||
# for accounts with more than 24h between join and FC creation just validate
|
||||
create_reg_and_validate = set()
|
||||
for user_id in sorted(user_ids):
|
||||
if (
|
||||
abs((fc_accounts_created[user_id] - date_joined[user_id]).total_seconds()) <= delay
|
||||
and user_id not in registration
|
||||
and user_id in first_login
|
||||
and abs((first_login[user_id].timestamp - fc_accounts_created[user_id]).total_seconds()) < delay
|
||||
and first_login[user_id].data["how"] == "france-connect"
|
||||
):
|
||||
user_ids.remove(user_id)
|
||||
create_reg_and_validate.add(user_id)
|
||||
|
||||
if create_reg_and_validate:
|
||||
print(f"{len(create_reg_and_validate)} registered by FC but without registration event and to validate.")
|
||||
for i, user in enumerate(User.objects.filter(id__in=create_reg_and_validate).order_by("id")):
|
||||
print(
|
||||
f"\r[{i+1:06d}/{len(create_reg_and_validate):06d}] creating registration and validating {user.id}... ",
|
||||
end="",
|
||||
)
|
||||
continue
|
||||
with transaction.atomic():
|
||||
data = {
|
||||
"how": "france-connect",
|
||||
}
|
||||
if "service_name" in first_login[user.id].data:
|
||||
data["service_name"] = first_login[user.id].data["service_name"]
|
||||
reg = Event.objects.create(
|
||||
type=registration_type,
|
||||
timestamp=user.date_joined,
|
||||
user_id=user.id,
|
||||
session_id=first_login[user.id].session_id,
|
||||
references=first_login[user.id].references,
|
||||
data=data,
|
||||
api=False,
|
||||
)
|
||||
user.attributes.validated = True
|
||||
user.attributes.validation_context = "FC"
|
||||
user.attributes.validation_date = localtime(fc_accounts_created[user.id]).date()
|
||||
transaction.set_rollback(True)
|
||||
print("DONE\n")
|
||||
print(f"{len(user_ids)} remaining accounts to fix.\n")
|
||||
else:
|
||||
print("No account with needing registration creation.\n")
|
||||
create_reg_and_validate = set()
|
||||
|
||||
if user_ids:
|
||||
print(f'Some remaining accounts: {", ".join(list(map(str, sorted(user_ids, reverse=True)))[:10])}')
|
||||
|
||||
raise SystemExit(0)
|
Loading…
Reference in New Issue