add one-time script
continuous-integration/drone/pr Build is failing Details

This commit is contained in:
Max Erenberg 2021-10-23 02:15:59 -04:00
parent 743d63efb0
commit b355ec6db4
4 changed files with 59 additions and 21 deletions

View File

@ -36,11 +36,6 @@ class IUser(Interface):
Returns False if this is the Unix user for a member. 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(): def add_to_ldap():
""" """
Add a new record to LDAP for this user. Add a new record to LDAP for this user.

View File

@ -6,10 +6,10 @@ import ldap3
from zope import component from zope import component
from zope.interface import implementer from zope.interface import implementer
from .utils import should_be_club_rep
from .validators import is_valid_shell, is_valid_term from .validators import is_valid_shell, is_valid_term
from ceo_common.interfaces import ILDAPService, IKerberosService, IFileService, \ from ceo_common.interfaces import ILDAPService, IKerberosService, IFileService, \
IUser, IConfig, IMailmanService IUser, IConfig, IMailmanService
from ceo_common.model import Term
@implementer(IUser) @implementer(IUser)
@ -55,7 +55,11 @@ class User:
self.mail_local_addresses = mail_local_addresses or [] self.mail_local_addresses = mail_local_addresses or []
self._is_club = is_club self._is_club = is_club
if is_club_rep is None: 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: else:
self.is_club_rep = is_club_rep self.is_club_rep = is_club_rep
self.ldap3_entry = ldap3_entry self.ldap3_entry = ldap3_entry
@ -93,19 +97,6 @@ class User:
def is_club(self) -> bool: def is_club(self) -> bool:
return self._is_club 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): def add_to_ldap(self):
self.ldap_srv.add_user(self) self.ldap_srv.add_user(self)

View File

@ -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]]: 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' -> 'ctdalek'
""" """
return dn.split(',', 1)[0].split('=')[1] 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))

View File

@ -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)