From fcad034b738915269acfceca0203fc48517b2230 Mon Sep 17 00:00:00 2001
From: Tanner Prestegard <tanner.prestegard@ligo.org>
Date: Tue, 24 Apr 2018 14:27:58 -0500
Subject: [PATCH] migration to deactivate old gracedb processor accounts and
 add a new EM follow-up account

---
 .../0005_update_emfollow_accounts.py          | 96 +++++++++++++++++++
 .../auth/0015_update_emfollow_accounts.py     | 58 +++++++++++
 .../guardian/0003_update_emfollow_accounts.py | 81 ++++++++++++++++
 3 files changed, 235 insertions(+)
 create mode 100644 gracedb/ligoauth/migrations/0005_update_emfollow_accounts.py
 create mode 100644 gracedb/migrations/auth/0015_update_emfollow_accounts.py
 create mode 100644 gracedb/migrations/guardian/0003_update_emfollow_accounts.py

diff --git a/gracedb/ligoauth/migrations/0005_update_emfollow_accounts.py b/gracedb/ligoauth/migrations/0005_update_emfollow_accounts.py
new file mode 100644
index 000000000..8382f725e
--- /dev/null
+++ b/gracedb/ligoauth/migrations/0005_update_emfollow_accounts.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2018-04-24 16:12
+#
+# This migration adds a new "emfollow" user which will be used for
+# EM follow-up activities.  The old EM follow-up accounts will be deactivated
+# and their X509Certs will be deleted.
+
+from __future__ import unicode_literals
+
+from django.db import migrations
+from django.conf import settings
+
+OLD_ACCOUNTS = {
+    'gdb-processor': {
+        'email': 'gdb_processor@gravity.phys.uwm.edu',
+        'last_name': 'GDB Processor',
+        'certs': [
+            '/DC=org/DC=ligo/O=LIGO/OU=Services/CN=gdb_processor/pcdev2.phys.uwm.edu',
+            '/DC=org/DC=ligo/O=LIGO/OU=Services/CN=gdb-processor/marlin.phys.uwm.edu',
+        ],
+    },
+    'gracedb.processor': {
+        'email': 'alexander.urban@ligo.org',
+        'last_name': 'GraceDB Processor',
+        'certs': [
+            '/DC=org/DC=ligo/O=LIGO/OU=Services/CN=gracedb.processor/ldas-grid.ligo.caltech.edu',
+            '/DC=org/DC=ligo/O=LIGO/OU=Services/CN=gracedb.processor/emfollow.ligo.caltech.edu',
+        ],
+    },
+}
+
+NEW_ACCOUNT = {
+    'username': 'emfollow',
+    'last_name': 'LIGO/Virgo EM Follow-Up',
+    'email': 'leo.singer@ligo.org',
+}
+
+NEW_CERTS = [
+    '/DC=org/DC=ligo/O=LIGO/OU=Services/CN=emfollow/emfollow.ligo.caltech.edu'
+]
+
+def deactivate_old_and_add_new_accounts(apps, schema_editor):
+    LocalUser = apps.get_model('ligoauth', 'LocalUser')
+    X509Cert = apps.get_model('ligoauth', 'X509Cert')
+    Group = apps.get_model('auth', 'Group')
+
+    # Mark old users as inactive and delete their certificates
+    for username in OLD_ACCOUNTS.keys():
+        user = LocalUser.objects.get(username=username)
+        for subject in OLD_ACCOUNTS[username]['certs']:
+            cert = user.x509cert_set.get(subject=subject)
+            cert.delete()
+        user.is_active = False
+        user.save()
+
+    # Create new EM follow-up user
+    new_user = LocalUser.objects.create(**NEW_ACCOUNT)
+
+    # Create and add certificate for new account
+    for subject in NEW_CERTS:
+        new_user.x509cert_set.create(subject=subject)
+
+    # Add user to LVC group
+    group = Group.objects.get(name=settings.LVC_GROUP)
+    group.user_set.add(new_user)
+
+def activate_old_and_remove_new_accounts(apps, schema_editor):
+    LocalUser = apps.get_model('ligoauth', 'LocalUser')
+    X509Cert = apps.get_model('ligoauth', 'X509Cert')
+
+    # Activate old accounts and add their X509 certificates
+    for username in OLD_ACCOUNTS.keys():
+        user = LocalUser.objects.get(username=username)
+        for subject in OLD_ACCOUNTS[username]['certs']:
+            cert = user.x509cert_set.create(subject=subject)
+        user.is_active = True
+        user.save()
+
+    # Delete new EM follow-up user and certs
+    new_user = LocalUser.objects.get(username=NEW_ACCOUNT['username'])
+    for subject in NEW_CERTS:
+        cert = new_user.x509cert_set.get(subject=subject)
+        cert.delete()
+    new_user.delete()
+
+    # Create and add certificate for new account
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('ligoauth', '0004_update_gstlal_spiir_account'),
+    ]
+
+    operations = [
+        migrations.RunPython(deactivate_old_and_add_new_accounts,
+            activate_old_and_remove_new_accounts),
+    ]
diff --git a/gracedb/migrations/auth/0015_update_emfollow_accounts.py b/gracedb/migrations/auth/0015_update_emfollow_accounts.py
new file mode 100644
index 000000000..6da3934da
--- /dev/null
+++ b/gracedb/migrations/auth/0015_update_emfollow_accounts.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2017-11-02 19:26
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+# Gives users table-level permissions which allows the addition and deletion
+# of row-level permissions (again, used for exposing/hiding events).
+
+# List of usernames
+OLD_USER = 'gracedb.processor'
+NEW_USER = 'emfollow'
+
+# List of permission codenames
+PERMS = [
+    'add_groupobjectpermission',
+    'delete_groupobjectpermission',
+]
+
+def add_perms(apps, schema_editor):
+    User = apps.get_model('auth', 'User')
+    Permission = apps.get_model('auth', 'Permission')
+
+    # Get users
+    old_user = User.objects.get(username=OLD_USER)
+    new_user = User.objects.get(username=NEW_USER)
+
+    # Add/remove perms
+    for perm in PERMS:
+        perm = Permission.objects.get(codename=perm)
+        old_user.user_permissions.remove(perm)
+        new_user.user_permissions.add(perm)
+
+
+def remove_perms(apps, schema_editor):
+    User = apps.get_model('auth', 'User')
+    Permission = apps.get_model('auth', 'Permission')
+
+    # Get users
+    old_user = User.objects.get(username=OLD_USER)
+    new_user = User.objects.get(username=NEW_USER)
+
+    # Add/remove perms
+    for perm in PERMS:
+        perm = Permission.objects.get(codename=perm)
+        old_user.user_permissions.add(perm)
+        new_user.user_permissions.remove(perm)
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('auth', '0014_add_user_permissions_on_groupobjectpermissions'),
+        ('ligoauth', '0005_update_emfollow_accounts'),
+    ]
+
+    operations = [
+        migrations.RunPython(add_perms, remove_perms)
+    ]
diff --git a/gracedb/migrations/guardian/0003_update_emfollow_accounts.py b/gracedb/migrations/guardian/0003_update_emfollow_accounts.py
new file mode 100644
index 000000000..3f799dbfb
--- /dev/null
+++ b/gracedb/migrations/guardian/0003_update_emfollow_accounts.py
@@ -0,0 +1,81 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.5 on 2018-04-25 01:51
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+OLD_ACCOUNTS = {
+    'gdb-processor': ['CWB', 'Fermi', 'gstlal', 'HardwareInjection', 'SNEWS',
+        'Swift'],
+    'gracedb.processor': ['CWB2G', 'Fermi', 'gstlal', 'SNEWS', 'Swift'],
+}
+
+NEW_ACCOUNT_USERNAME = 'emfollow'
+NEW_ACCOUNT_PIPELINES = list(set([item for items in OLD_ACCOUNTS.values() for
+    item in items]))
+
+
+def update_perms(apps, schema_editor):
+    LocalUser = apps.get_model('ligoauth', 'LocalUser')
+    UserObjectPermission = apps.get_model('guardian', 'UserObjectPermission')
+    Pipeline = apps.get_model('events', 'Pipeline')
+    Permission = apps.get_model('auth', 'Permission')
+    ContentType = apps.get_model('contenttypes', 'ContentType')
+
+    perm = Permission.objects.get(codename='populate_pipeline')
+    ctype = ContentType.objects.get_for_model(Pipeline)
+
+    # Remove UOPs from old accounts which allow pipeline population
+    for username, pipelines in OLD_ACCOUNTS.iteritems():
+        user = LocalUser.objects.get(username=username)
+        for pipeline_name in pipelines:
+            pipeline = Pipeline.objects.get(name=pipeline_name)
+            uop = UserObjectPermission.objects.get(user=user,
+                permission=perm, content_type=ctype, object_pk=pipeline.id)
+            uop.delete()
+
+    # Add these UOPs to new acccount
+    user = LocalUser.objects.get(username=NEW_ACCOUNT_USERNAME)
+    for pipeline_name in NEW_ACCOUNT_PIPELINES:
+        pipeline = Pipeline.objects.get(name=pipeline_name)
+        uop = UserObjectPermission.objects.create(user=user, permission=perm,
+            content_type=ctype, object_pk = pipeline.id)
+
+
+def revert_perms(apps, schema_editor):
+    LocalUser = apps.get_model('ligoauth', 'LocalUser')
+    UserObjectPermission = apps.get_model('guardian', 'UserObjectPermission')
+    Pipeline = apps.get_model('events', 'Pipeline')
+    Permission = apps.get_model('auth', 'Permission')
+    ContentType = apps.get_model('contenttypes', 'ContentType')
+
+    perm = Permission.objects.get(codename='populate_pipeline')
+    ctype = ContentType.objects.get_for_model(Pipeline)
+
+    # Re-add UOPs to old accounts which allow pipeline population
+    for username, pipelines in OLD_ACCOUNTS.iteritems():
+        user = LocalUser.objects.get(username=username)
+        for pipeline_name in pipelines:
+            pipeline = Pipeline.objects.get(name=pipeline_name)
+            uop = UserObjectPermission.objects.create(user=user,
+                permission=perm, content_type=ctype, object_pk = pipeline.id)
+
+    # Remove these UOPs from new acccount
+    user = LocalUser.objects.get(username=NEW_ACCOUNT_USERNAME)
+    for pipeline_name in NEW_ACCOUNT_PIPELINES:
+        pipeline = Pipeline.objects.get(name=pipeline_name)
+        uop = UserObjectPermission.objects.get(user=user, permission=perm,
+            content_type=ctype, object_pk = pipeline.id)
+        uop.delete()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('guardian', '0002_authorize_users_to_populate_pipelines'),
+        ('ligoauth', '0005_update_emfollow_accounts'),
+    ]
+
+    operations = [
+        migrations.RunPython(update_perms, revert_perms),
+    ]
-- 
GitLab