From 27ada00b1327299ee4702333d8c7ff2e152ae662 Mon Sep 17 00:00:00 2001
From: frekk <frekk@ucc.asn.au>
Date: Wed, 29 May 2019 02:05:13 +0800
Subject: [PATCH] add some simple and placeholder management commands

including a hook for ucc-adduser-ad to update MemberDB with usernames
and a script to mark users in MemberDB as having accounts based on
actual lists of users from AD.
---
 .../management/commands/lockaccounts.py       | 11 ++++++
 .../management/commands/ucc-adduser-hook.py   | 35 ++++++++++++++++++
 .../management/commands/update-users-ldap.py  | 36 +++++++++++++++++++
 3 files changed, 82 insertions(+)
 create mode 100644 src/memberdb/management/commands/lockaccounts.py
 create mode 100644 src/memberdb/management/commands/ucc-adduser-hook.py
 create mode 100644 src/memberdb/management/commands/update-users-ldap.py

diff --git a/src/memberdb/management/commands/lockaccounts.py b/src/memberdb/management/commands/lockaccounts.py
new file mode 100644
index 0000000..d6dcdbe
--- /dev/null
+++ b/src/memberdb/management/commands/lockaccounts.py
@@ -0,0 +1,11 @@
+from django.core.management.base import BaseCommand, CommandError
+from datetime import datetime
+
+class Command(BaseCommand):
+    help = 'Locks unpaid accounts for the current year'
+
+    def add_arguments(self, parser):
+        parser.add_argument('year', nargs='?', type=int, default=datetime.now().year)
+
+    def handle(self, *args, **options):
+        self.stdout.write(self.style.SUCCESS('Not implemented: locking accounts for year %d' % options['year']))
\ No newline at end of file
diff --git a/src/memberdb/management/commands/ucc-adduser-hook.py b/src/memberdb/management/commands/ucc-adduser-hook.py
new file mode 100644
index 0000000..1ec22ef
--- /dev/null
+++ b/src/memberdb/management/commands/ucc-adduser-hook.py
@@ -0,0 +1,35 @@
+from django.core.management.base import BaseCommand, CommandError
+from memberdb.models import Member, Membership
+import sys
+
+class Command(BaseCommand):
+    help = 'Hook to be called by `ucc-adduser-ad` to make sure usernames are properly matched with new accounts'
+
+    def add_arguments(self, parser):
+        # usage: manage.py ucc-adduser-hook <member-id> <username>
+        parser.add_argument('memberid', nargs=1, type=int)
+        parser.add_argument('username', nargs=1)
+
+    def handle(self, *args, **options):
+        mid = options['memberid'][0]
+        username = options['username'][0]
+        self.stdout.write('Updating Member record id %d for new user %s' % (mid, username))
+
+        try:
+            m = Member.objects.get(id=mid)
+            self.stdout.write('Found Member record: %s' % str(m))
+
+            if m.memberships.count() > 1:
+                self.stdout.write('Suspicious: given member id has multiple renewal records')
+
+            if m.username is not None and m.username == username:
+                self.stdout.write('Congrats! Username was already correct!')
+                return
+            else:
+                # update username
+                m.username = username
+                m.save()
+
+        except Member.DoesNotExist:
+            # exit with error code
+            sys.exit(1)
diff --git a/src/memberdb/management/commands/update-users-ldap.py b/src/memberdb/management/commands/update-users-ldap.py
new file mode 100644
index 0000000..46adb41
--- /dev/null
+++ b/src/memberdb/management/commands/update-users-ldap.py
@@ -0,0 +1,36 @@
+from django.core.management.base import BaseCommand, CommandError
+from memberdb.models import Member, Membership
+from memberdb.account_backend import enumerate_users
+import sys
+
+class Command(BaseCommand):
+    """
+    try to keep the database in sync with AD, make sure Member records are more or less correct
+    when it comes to the existence of a user account in AD
+    """
+    
+    help = 'Search for users in LDAP and mark Member records as having accounts if usernames match'
+
+    def add_arguments(self, parser):
+        pass
+
+    def handle(self, *args, **options):
+        self.stderr.write("Enumerating users...")
+        users = enumerate_users()
+
+        num_updated = 0
+        for u in users:
+            try:
+                m = Member.objects.get(username=u)
+                # clean the member tokens and mark as having an account
+                m.login_token = None
+                m.has_account = True
+                num_updated += 1
+                self.stdout.write("updated user %s: has Member record" % u)
+                m.save()
+            except Member.MultipleObjectsReturned:
+                pass
+            except Member.DoesNotExist:
+                pass
+
+        self.stderr.write("Done, got %d users total, %d updated" % (len(users), num_updated))
-- 
GitLab