add one-time script

pull/27/head
Max Erenberg 1 year ago
parent 743d63efb0
commit b355ec6db4
  1. 5
      ceo_common/interfaces/IUser.py
  2. 21
      ceod/model/User.py
  3. 17
      ceod/model/utils.py
  4. 37
      one_time_scripts/is_club_rep.py

@ -36,11 +36,6 @@ class IUser(Interface):
Returns False if this is the Unix user for a member.
"""
def should_be_club_rep(self) -> bool:
"""
Returns True iff this user's most recent term was a non-member term.
"""
def add_to_ldap():
"""
Add a new record to LDAP for this user.

@ -6,10 +6,10 @@ import ldap3
from zope import component
from zope.interface import implementer
from .utils import should_be_club_rep
from .validators import is_valid_shell, is_valid_term
from ceo_common.interfaces import ILDAPService, IKerberosService, IFileService, \
IUser, IConfig, IMailmanService
from ceo_common.model import Term
@implementer(IUser)
@ -55,7 +55,11 @@ class User:
self.mail_local_addresses = mail_local_addresses or []
self._is_club = is_club
if is_club_rep is None:
self.is_club_rep = self.should_be_club_rep()
if is_club:
# not a real user
self.is_club_rep = False
else:
self.is_club_rep = should_be_club_rep(terms, non_member_terms)
else:
self.is_club_rep = is_club_rep
self.ldap3_entry = ldap3_entry
@ -93,19 +97,6 @@ class User:
def is_club(self) -> bool:
return self._is_club
def should_be_club_rep(self) -> bool:
if self._is_club:
# not a real user
return False
if not self.terms:
# no member terms => was only ever a club rep
return True
if not self.non_member_terms:
# no non-member terms => was only ever a member
return False
# decide using the most recent term (member or non-member)
return max(map(Term, self.non_member_terms)) > max(map(Term, self.terms))
def add_to_ldap(self):
self.ldap_srv.add_user(self)

@ -1,4 +1,6 @@
from typing import Dict, List
from typing import Dict, List, Union
from ceo_common.model import Term
def bytes_to_strings(data: Dict[str, List[bytes]]) -> Dict[str, List[str]]:
@ -25,3 +27,16 @@ def dn_to_uid(dn: str) -> str:
-> 'ctdalek'
"""
return dn.split(',', 1)[0].split('=')[1]
def should_be_club_rep(terms: Union[None, List[str]],
non_member_terms: Union[None, List[str]]) -> bool:
"""Returns True iff a user's most recent term was a non-member term."""
if not non_member_terms:
# no non-member terms => was only ever a member
return False
if not terms:
# no member terms => was only ever a club rep
return True
# decide using the most recent term (member or non-member)
return max(map(Term, non_member_terms)) > max(map(Term, terms))

@ -0,0 +1,37 @@
#!/usr/bin/env python3
"""
This is a script which adds the isClubRep attribute to all LDAP user records
whose most recent nonMemberTerm is later than their most recent (member) term.
GSSAPI is used for LDAP authentication, so make sure to run `kinit` first.
Also, make sure to run this script from the top-level of the git directory
(see the sys.path hack below).
"""
import os
import sys
import ldap3
sys.path.append(os.getcwd())
from ceod.model.utils import should_be_club_rep
# modify as necessary
LDAP_URI = "ldaps://auth1.csclub.uwaterloo.ca"
LDAP_MEMBERS_BASE = "ou=People,dc=csclub,dc=uwaterloo,dc=ca"
conn = ldap3.Connection(
LDAP_URI, authentication=ldap3.SASL, sasl_mechanism=ldap3.KERBEROS,
auto_bind=True, raise_exceptions=True)
conn.search(LDAP_MEMBERS_BASE, '(objectClass=member)',
attributes=['uid', 'isClubRep', 'term', 'nonMemberTerm'])
total_records_updated = 0
for entry in conn.entries:
if not should_be_club_rep(entry.term.values, entry.nonMemberTerm.values):
continue
if entry.isClubRep.value:
continue
changes = {'isClubRep': [(ldap3.MODIFY_REPLACE, [True])]}
conn.modify(entry.entry_dn, changes)
print('Modified %s' % entry.uid.value)
total_records_updated += 1
print('Total records updated: %d' % total_records_updated)
Loading…
Cancel
Save