Browse Source

move scripts to script dir and useradm to useradm dir

pull/10/head
Cian Butler 4 years ago
parent
commit
ebf168668e
16 changed files with 4052 additions and 6425 deletions
  1. +0
    -411
      rbaccount.py
  2. +0
    -247
      rbconfig.py
  3. +0
    -45
      rberror.py
  4. +0
    -53
      rbopt.py
  5. +0
    -148
      rbuser.py
  6. +0
    -1469
      rbuserdb.py
  7. +0
    -0
      scripts/fixup-rb-dcu-tree.py
  8. +0
    -0
      scripts/lockshell
  9. +0
    -0
      scripts/make-rb-dcu-tree.sh
  10. +0
    -0
      scripts/newyear_ldif.py
  11. +0
    -0
      scripts/rebuild_userdb_reserved.py
  12. +0
    -0
      scripts/remove_dcutree_ldif.py
  13. +0
    -2249
      useradm.py
  14. +0
    -0
     
  15. +1809
    -1803
      useradm/useradm.py
  16. +2243
    -0
      useradm/useradm.py~HEAD

+ 0
- 411
rbaccount.py View File

@@ -1,411 +0,0 @@
#-----------------------------------------------------------------------------#
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

"""RedBrick Account Module; contains RBAccount class."""

# System modules

import grp
import os
import pwd
import random
import re
import shutil
import sys

# RedBrick modules

import rbconfig
from rberror import *
from rbopt import *
from rbuser import *

#-----------------------------------------------------------------------------#
# DATA #
#-----------------------------------------------------------------------------#

__version__ = '$Revision: 1.8 $'
__author__ = 'Cillian Sharkey'

#-----------------------------------------------------------------------------#
# CLASSES #
#-----------------------------------------------------------------------------#

class RBAccount:
"""Class to interface with Unix accounts."""

def __init__(self):
"""Create new RBAccount object."""

self.opt = RBOpt()
def setopt(self, opt):
"""Use given RBOpt object to retrieve options."""

self.opt = opt
#---------------------------------------------------------------------#
# SINGLE ACCOUNT METHODS #
#---------------------------------------------------------------------#
def add(self, usr):
"""Add account."""
# Create home and webtree directory and populate.
#
webtree = rbconfig.gen_webtree(usr.uid)
self.wrapper(os.mkdir, webtree, 0711)
self.wrapper(os.chown, webtree, usr.uidNumber, usr.gidNumber)
self.cmd('%s -Rp %s %s' % (rbconfig.command_cp, rbconfig.dir_skel, usr.homeDirectory))
self.wrapper(os.chmod, usr.homeDirectory, 0711)
self.wrapper(os.symlink, webtree, '%s/public_html' % usr.homeDirectory)
#symlink vuln fix
try:
self.wrapper(os.chown, usr.homeDirectory+'/public_html', usr.uidNumber, usr.gidNumber)
except OSError:
pass

# Add a .forward file in their home directory to point to their
# alternate email address, but only if they're a dcu person and
# have an alternate email that's not a redbrick address.
#
if usr.usertype in rbconfig.usertypes_dcu and usr.altmail and not re.search(r'@.*redbrick\.dcu\.ie', usr.altmail):
forward_file = '%s/.forward' % usr.homeDirectory
fd = self.my_open(forward_file)
fd.write('%s\n' % usr.altmail)
self.my_close(fd)
self.wrapper(os.chmod, forward_file, 0600)

# Change user & group ownership recursively on home directory.
#
self.cmd('%s -Rh %s:%s %s' % (rbconfig.command_chown, usr.uidNumber, usr.usertype, self.shquote(usr.homeDirectory)))

# Set quotas for each filesystem.
#
for fs, (bqs, bqh, iqs, iqh) in rbconfig.gen_quotas(usr.usertype).items():
self.quota_set(usr.uidNumber, fs, bqs, bqh, iqs, iqh)

# Add to redbrick announcement mailing lists.
#
self.list_add('announce-redbrick', '%s@redbrick.dcu.ie' % usr.uid)
self.list_add('redbrick-newsletter', '%s@redbrick.dcu.ie' % usr.uid)
def delete(self, usr):
"""Delete a local Unix account."""

# Zero out quotas.
#
for fs in rbconfig.gen_quotas().keys():
self.quota_delete(usr.uidNumber, fs)
# Remove home directory and webtree. Don't bomb out if the
# directories don't exist (i.e. ignore OSError).
#
try:
self.wrapper(shutil.rmtree, usr.homeDirectory)
except OSError:
pass
try:
self.wrapper(shutil.rmtree, rbconfig.gen_webtree(usr.uid))
except OSError:
pass

# Remove from announce mailing lists.
#
self.list_delete('announce-redbrick', '%s@redbrick.dcu.ie' % usr.uid);
self.list_delete('redbrick-newsletter', '%s@redbrick.dcu.ie' % usr.uid);

for file in rbconfig.gen_extra_user_files(usr.uid):
try:
self.wrapper(os.unlink, file)
except OSError:
pass

def rename(self, oldusr, newusr):
"""Rename an account.
Requires: oldusr.uid, oldusr.homeDirectory, newusr.uid,
newusr.homeDirectory.
"""

# XXX Should check this before we rename user in ldap, have a
# rbaccount.check_userfree? There should never be a file or
# directory in /home or /webtree that doesn't belong to an
# existing user.

if os.path.exists(newusr.homeDirectory):
if not os.path.isdir(newusr.homeDirectory):
try:
self.wrapper(os.unlink, newusr.homeDirectory)
except OSError:
raise RBFatalError("New home directory '%s' already exists, could not unlink existing file." % newusr.homeDirectory)
else:
raise RBFatalError("New home directory '%s' already exists." % newusr.homeDirectory)

oldwebtree = rbconfig.gen_webtree(oldusr.uid)
newwebtree = rbconfig.gen_webtree(newusr.uid)
try:
self.wrapper(os.rename, oldusr.homeDirectory, newusr.homeDirectory)
except OSError, e:
raise RBFatalError("Could not rename home directory [%s]" % e)

try:
self.wrapper(os.rename, oldwebtree, newwebtree)
except OSError, e:
raise RBFatalError("Could not rename webtree directory [%s]" % e)

# Remove and then attempt to rename webtree symlink.
#
webtreelink = '%s/public_html' % newusr.homeDirectory
try:
self.wrapper(os.unlink, webtreelink)
except OSError:
pass
if not os.path.exists(webtreelink):
self.wrapper(os.symlink, newwebtree, webtreelink)

# Rename any extra files that may belong to a user.
#
oldfiles = rbconfig.gen_extra_user_files(oldusr.uid)
newfiles = rbconfig.gen_extra_user_files(newusr.uid)

for i in range(len(oldfiles)):
oldf = oldfiles[i]
newf = newfiles[i]

try:
if os.path.isfile(oldf):
self.wrapper(os.rename, oldf, newf)
except OSError,e :
raise RBFatalError("Could not rename '%s' to '%s' [%s]" % (oldf, newf, e))

# XXX
# Rename their subscription to announce lists in case an email
# alias isn't put in for them or is later removed.
#
self.list_delete('announce-redbrick', "%s@redbrick.dcu.ie" % oldusr.uid);
self.list_delete('redbrick-newsletter', "%s@redbrick.dcu.ie" % oldusr.uid);
self.list_add('announce-redbrick', "%s@redbrick.dcu.ie" % newusr.uid);
self.list_add('redbrick-newsletter', "%s@redbrick.dcu.ie" % newusr.uid);
def convert(self, oldusr, newusr):
"""Convert account to a new usertype (Unix group)."""

if oldusr.usertype == newusr.usertype:
return
# Do supplementary group shit in rbuserdb.
#
#if rbconfig.convert_primary_groups.has_key(usertype):
# group = rbconfig.convert_primary_groups[usertype]
#else:
# group = usertype
#if rbconfig.convert_extra_groups.has_key(usertype):
# groups = '-G ' + rbconfig.convert_extra_groups[usertype]
#else:
# groups = ''
if newusr.usertype == 'committe' and oldusr.usertype not in ('member', 'staff', 'committe'):
raise RBFatalError("Non-members cannot be converted to committee group")
if os.path.exists(newusr.homeDirectory):
if not os.path.isdir(newusr.homeDirectory):
try:
self.wrapper(os.unlink, newusr.homeDirectory)
except OSError:
raise RBFatalError("New home directory '%s' already exists, could not unlink existing file." % newusr.homeDirectory)
else:
raise RBFatalError("New home directory '%s' already exists." % newusr.homeDirectory)

# Rename home directory.
#
try:
self.wrapper(os.rename, oldusr.homeDirectory, newusr.homeDirectory)
except:
raise RBFatalError("Could not rename home directory")
# Change the home directory and webtree ownership to the new
# group. -h on Solaris chgrp makes sure to change the symbolic
# links themselves not the files they point to - very
# important!!
#
self.cmd("%s -Rh %s %s %s" % (rbconfig.command_chgrp, newusr.gidNumber, self.shquote(newusr.homeDirectory), self.shquote(rbconfig.gen_webtree(oldusr.uid))))
# Add/remove from committee mailing list as appropriate.
#
if newusr.usertype == 'committe':
self.list_add('committee', "%s@redbrick.dcu.ie" % oldusr.uid)
elif oldusr.usertype == 'committe':
self.list_delete('committee', "%s@redbrick.dcu.ie" % oldusr.uid)
# Add to admin list. Most admins stay in the root group for a while
# after leaving committee, so removal can be done manually later.
#
if newusr.usertype == 'admin':
self.list_add('rb-admins', "%s@redbrick.dcu.ie" % oldusr.uid)
def disuser(self, username, disuser_period = None):
"""Disable an account with optional automatic re-enabling after
given period."""

#TODO
def reuser(self, username):
"""Re-enable an account."""

#TODO
def quota_set(self, username, fs, bqs, bqh, iqs, iqh):
"""Set given quota for given username on given filesystem.
Format for quota values is the same as that used for quotas
function in rbconfig module."""

self.cmd("%s -r %s %d %d %d %d %s" % (rbconfig.command_setquota, self.shquote(str(username)), bqs, bqh, iqs, iqh, fs))
#self.cmd("%s -b %d -B %d -i %d -I %d %s %s" % (rbconfig.command_setquota, bqs, bqh, iqs, iqh, fs, self.shquote(str(username))))

def quota_delete(self, username, fs):
"""Delete quota for given username on given filesystem."""
self.quota_set(username, fs, 0, 0, 0, 0)
#self.cmd('%s -d %s %s' % (rbconfig.command_setquota, fs, self.shquote(str(username))))

#---------------------------------------------------------------------#
# SINGLE ACCOUNT INFORMATION METHODS #
#---------------------------------------------------------------------#
def show(self, usr):
"""Show account details on standard output."""

print "%13s:" % 'homedir mode',
if os.path.isdir(usr.homeDirectory):
print '%04o' % (os.stat(usr.homeDirectory)[0] & 07777)
else:
print 'Home directory does not exist'
print "%13s: %s" % ('logged in', os.path.exists('%s/%s' % (rbconfig.dir_signaway_state, usr.uid)) and 'true' or 'false')

#---------------------------------------------------------------------#
# USER CHECKING AND INFORMATION RETRIEVAL METHODS #
#---------------------------------------------------------------------#
def check_accountfree(self, usr):
"""Raise RBFatalError if given account name is not free i.e.
has a home directory."""

if os.path.exists(usr.homeDirectory):
raise RBFatalError("Account '%s' already exists (has a home directory)" % usr.uid)

def check_account_byname(self, usr):
"""Raise RBFatalError if given account does not exist."""

if not os.path.exists(usr.homeDirectory):
raise RBFatalError("Account '%s' does not exist (no home directory)" % usr.uid)
#---------------------------------------------------------------------#
# OTHER METHODS #
#---------------------------------------------------------------------#
def list_add(self, list, email):
"""Add email address to mailing list."""

fd = self.my_popen("su -c '%s/bin/add_members -r - %s' list" % (rbconfig.dir_mailman, self.shquote(list)))
fd.write('%s\n' % email)
self.my_close(fd)
def list_delete(self, list, email):
"""Delete email address from a mailing list."""

self.runcmd("su -c '%s/bin/remove_members %s %s' list" % (rbconfig.dir_mailman, self.shquote(list), self.shquote(email)))
#--------------------------------------------------------------------#
# INTERNAL METHODS #
#--------------------------------------------------------------------#
def shquote(self, string):
"""Return a quoted string suitable to use with shell safely."""

return "'" + string.replace("'", r"'\''") + "'"

def runcmd(self, cmd):
"""runcmd(command) -> output, status
Run given command and return command output (stdout & stderr combined)
and exit status.
"""
if self.opt.test:
print >> sys.stderr, "TEST: runcmd:", cmd
return None, None
else:
fd = os.popen(cmd + ' 2>&1')
return fd.read(), fd.close()

def cmd(self, cmd):
"""Run given command and raise a RBError exception returning
the command output if command exit status is non zero."""

output, status = self.runcmd(cmd)
if status:
raise RBFatalError("Command '%s' failed.\n%s" % (cmd, output))
def wrapper(self, function, *keywords, **arguments):
"""Wrapper method for executing other functions.
If test mode is set, print function name and arguments.
Otherwise call function with arguments.
"""

if self.opt.test:
sys.stderr.write("TEST: %s(" % function.__name__)
for i in keywords:
sys.stderr.write("%s, " % (i,))
for k, v in arguments.items():
sys.stderr.write("%s = %s, " % (k, v))
sys.stderr.write(")\n")
else:
return function(*keywords, **arguments)

def my_open(self, file):
"""Return file descriptor to given file for writing."""
if self.opt.test:
print >> sys.stderr, 'TEST: open:', file
return sys.stderr
else:
return open(file, 'w')

def my_popen(self, cmd):
"""Return file descriptor to given command pipe for writing."""
if self.opt.test:
print >> sys.stderr, 'TEST: popen:', cmd
return sys.stderr
else:
return os.popen(cmd, 'w')
def my_close(self, fd):
"""Close given pipe returned by _[p]open."""
if not self.opt.test:
fd.close()
#--------------------------------------------------------------------#
# ERROR HANDLING #
#--------------------------------------------------------------------#

def rberror(self, e):
"""Handle errors."""
if self.opt.override and isinstance(e, RBWarningError):
return

# If we reach here it's either a FATAL error or there was no
# override for a WARNING error, so raise it again to let the
# caller handle it.
#
raise e

+ 0
- 247
rbconfig.py View File

@@ -1,247 +0,0 @@
#-----------------------------------------------------------------------------#
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

"""RedBrick Configuration Module; contains local configuration information."""

# System modules

import os
import random

#---------------------------------------------------------------------#
# DATA #
#---------------------------------------------------------------------#

__version__ = '$Revision: 1.11 $'
__author__ = 'Cillian Sharkey'

# Find out where the rrs directory is.

dir_rrs = (os.path.dirname(__file__) or '.') + '/'

# Maximum length of usernames and groups.

maxlen_uname = 8
maxlen_group = 8

# Default LDAP account attribute values.

ldap_default_objectClass = ['posixAccount', 'top', 'shadowAccount']
ldap_default_hosts = ['paphos', 'metharme']

# RedBrick LDAP settings.

ldap_uri = 'ldap://ldap.internal'
ldap_root_dn = 'cn=root,ou=ldap,o=redbrick'
ldap_rootpw_file = '/etc/ldap.secret'
ldap_tree = 'o=redbrick'
ldap_accounts_tree = 'ou=accounts,o=redbrick'
ldap_group_tree = 'ou=groups,o=redbrick'
ldap_reserved_tree = 'ou=reserved,o=redbrick'

# DCU LDAP settings.

ldap_dcu_uri = 'ldap://ad.dcu.ie'
ldap_dcu_tree = 'o=ad,o=dcu,o=ie'
ldap_dcu_rbdn = 'CN=rblookup,OU=Service Accounts,DC=ad,DC=dcu,DC=ie'
ldap_dcu_rbpw = '/etc/dcu_ldap.secret'
ldap_dcu_students_tree = 'OU=Students,DC=ad,DC=dcu,DC=ie'
#'ou=students,dc=ad,dc=dcu,dc=ie'
ldap_dcu_staff_tree = 'OU=Staff,DC=ad,DC=dcu,DC=ie'
#'ou=staff,dc=ad,dc=dcu,dc=ie'
ldap_dcu_alumni_tree = 'OU=Alumni,DC=ad,DC=dcu,DC=ie'
#'ou=alumni,o=dcu'

# DNS zones RedBrick is authorative for.

dns_zones = (
'redbrick.dcu.ie',
'club.dcu.ie',
'soc.dcu.ie',
)

# Mailman list suffixes.

mailman_list_suffixes = ("-admin", "-bounces", "-confirm", "-join", "-leave", "-owner", "-request", "-subscribe", "-unsubscribe")

# Directory pathnames.

dir_home = '/home'
dir_webtree = '/webtree'
dir_signaway_state = '/local/share/agreement/statedir'
dir_daft = '/local/share/daft'
dir_skel = '/etc/skel'
dir_mailman = '/var/lib/mailman'

# Filenames.

file_uidNumber = dir_rrs + 'uidNumber.txt'
file_pre_sync = dir_rrs + 'presync.txt'
file_rrslog = dir_rrs + 'rrs.log'
file_shells = '/etc/shells'
file_backup_passwd = '/var/backups/passwd.pre-expired'
shell_default = '/usr/local/shells/zsh'
shell_expired = '/usr/local/shells/expired'

# Unix group files: (group file, hostname) pairs.

files_group = (
('/etc/group', 'Deathray'),
('/local/share/var/carbon/group', 'Carbon')
)

# host files: (host file, hostname) pairs.

files_host = (
('/etc/hosts', 'Deathray'),
('/local/share/var/carbon/hosts', 'Carbon')
)

# Email alias files.

files_alias = (
('/etc/mail/exim_aliases.txt', 'Mail alias'),
)

# Commands.

command_setquota = '/usr/sbin/setquota'
command_chown = '/bin/chown'
command_chgrp = '/bin/chgrp'
command_cp = '/bin/cp'
command_sendmail = '/usr/sbin/sendmail'

# Valid account usertypes and descriptions.
#
usertypes = {
'founders': 'RedBrick founder',
'member': 'Normal member',
'associat': 'Graduate/associate member',
'staff': 'DCU staff member',
'society': 'DCU society',
'club': 'DCU club',
'projects': 'RedBrick/DCU/Course project account',
'guest': 'Guest account',
'intersoc': 'Account for society from another college',
'committe': 'Committee member or a position account',
'redbrick': 'RedBrick related account',
'dcu': 'DCU related account'
}

# "Ordered" list of usertypes for listing with the exception of founders.
#
usertypes_list = (
'member', 'associat', 'staff', 'committe',
'society', 'club', 'dcu',
'projects', 'redbrick', 'intersoc', 'guest'
)

# List of paying usertypes.
#
usertypes_paying = ('member', 'associat', 'staff', 'committe', 'guest')

# List of dcu usertypes (i.e. require a id number)
#
usertypes_dcu = ('member', 'associat', 'staff', 'committe')

# Pseudo usertypes for conversion to committee positions.
#
convert_usertypes = {
'admin': 'Elected admin',
'webmaster': 'Elected webmaster',
'helpdesk': 'Elected helpdesk'
}

# Supplementary groups when converting an account to given usertype.
#
# Format: 'usertype': 'a string of comma seperated groups with no spaces'
#
convert_extra_groups = {
'admin': 'root,log',
'webmaster': 'root,log,webgroup',
'helpdesk': 'helpdesk'
}

# Actual primary group to use when converting an account to given usertype
# (typically a 'pseudo-usertype').
#
# Format: 'usertype': 'actual unix group name'
#
convert_primary_groups = {
'admin': 'committe',
'webmaster': 'committe',
'helpdesk': 'committe'
}

#---------------------------------------------------------------------#
# MODULE FUNCTIONS #
#---------------------------------------------------------------------#

def gen_passwd():
"""Generate a random plaintext password.

Alternates between vowels & consonants and decimal digits. We don't use
upper case letters, solves the CAPS LOCK and clueless user problem.
Characters and numbers that are similar in appearance (1, l, O, 0) or
difficult to 'pronounce' (x, q) are not used.
"""

passchars = (
'a e i o u'.split(),
'b c d f g h j k m n p r s t v w y z'.split(),
)
numchars = '2 3 4 5 6 7 8 9'.split()
password = ''
offset = random.randrange(2)
for c in range(8):
password += passchars[(c + offset) % 2][random.randrange(len(passchars[(c + offset) % 2]))]
offset = random.randrange(2) and 8 or 0
password = password[offset:] + numchars[random.randrange(len(numchars))] + numchars[random.randrange(len(numchars))] + password[:offset]
return password

def gen_homedir(username, usertype):
"""Construct a user's home directory path given username and usertype."""
if usertype in ('member', 'associat'):
hash = username[0] + '/'
else:
hash = ''

return '%s/%s/%s%s' % (dir_home, usertype, hash, username)

def gen_webtree(username):
"""Generate a user's webtree path for given username."""

return '%s/%s/%s' % (dir_webtree, username[0], username)

def gen_quotas(usertype = None):
"""Returns a dictionary of quota limits for filesystems (possibly
depending on the given usertype, if any).

The format of the quota dictionary is as follows:

'filesystem': (block quota soft, block quota hard,
inode quota soft, inode quota hard),
...

Block quota is in kilobytes, inode quota is number of inodes.
"""

return {
'/storage': (1000000, 1100000, 800000, 1000000)
}

def gen_extra_user_files(username):
"""Return list of files that may belong to the given user outside of
their main storage areas. For purposes of renaming or deleting."""

# XXX: need files for carbon now aswell.

return (
'%s/%s' % (dir_signaway_state, username),
'/var/mail/%s' % username,
'/var/spool/cron/crontabs/%s' % username
)

+ 0
- 45
rberror.py View File

@@ -1,45 +0,0 @@
#-----------------------------------------------------------------------------#
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

"""RedBrick Error Module; contains RedBrick exception classes."""

#-----------------------------------------------------------------------------#
# DATA #
#-----------------------------------------------------------------------------#

__version__ = '$Revision: 1.2 $'
__author__ = 'Cillian Sharkey'

#-----------------------------------------------------------------------------#
# CLASSES #
#-----------------------------------------------------------------------------#

class RBError(Exception):
"""Base class for RedBrick exceptions"""

def __init__(self, mesg):
"""Create new RBError object with given error message."""

self.mesg = mesg
def __str__(self):
"""Return exception error message."""

return "ERROR: %s" % self.mesg

class RBFatalError(RBError):
"""Class for fatal RedBrick exceptions"""

def __str__(self):
"""Return exception error message."""

return "FATAL: %s" % self.mesg

class RBWarningError(RBError):
"""Class for warning RedBrick exceptions. These can be overrided."""

def __str__(self):
"""Return exception error message."""

return "WARNING: %s" % self.mesg

+ 0
- 53
rbopt.py View File

@@ -1,53 +0,0 @@
#-----------------------------------------------------------------------------#
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

"""RedBrick Options Module; contains RBOpt class."""

#-----------------------------------------------------------------------------#
# DATA #
#-----------------------------------------------------------------------------#

__version__ = '$Revision: 1.5 $'
__author__ = 'Cillian Sharkey'

#-----------------------------------------------------------------------------#
# CLASSES #
#-----------------------------------------------------------------------------#

class RBOpt:
"""Class for storing options to be shared by modules"""

def __init__(self):
"""Create new RBOpt object."""

# Used by all modules.
self.override = None
# Used by useradm, RBUserDB & RBAccount.
self.test = None
# Used by useradm & rrs.
self.mode = None
self.setpasswd = None
# Used by useradm.
self.args = []
self.help = None
self.uid = None
self.dbonly = None
self.aconly = None
self.updatedby = None
self.newbie = None
self.mailuser = None
self.usertype = None
self.cn = None
self.altmail = None
self.id = None
self.course = None
self.year = None
self.yearsPaid = None
self.birthday = None
self.loginShell = None
self.quiet = None
self.rrslog = None
self.presync = None
# Used by rrs.
self.action = None

+ 0
- 148
rbuser.py View File

@@ -1,148 +0,0 @@
#-----------------------------------------------------------------------------#
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

"""RedBrick User Module; contains RBUser class."""

#-----------------------------------------------------------------------------#
# DATA #
#-----------------------------------------------------------------------------#

__version__ = '$Revision: 1.4 $'
__author__ = 'Cillian Sharkey'

#-----------------------------------------------------------------------------#
# CLASSES #
#-----------------------------------------------------------------------------#

class RBUser:
"""Class to represent a user."""
# List of valid LDAP attributes for a user. The order of these is used
# when displaying a user's information.
#
attr_list = (
# Attributes associated with user.

'uid', # Username
'usertype', # XXX NOT IN LDAP: contains primary
# usertype from objectClass list.
# Placed here so it's at start of
# output for user's information.
'objectClass', # List of classes.
'newbie', # New this year (boolean)
'cn', # Full name
'altmail', # Alternate email
'id', # DCU ID number (integer)
'course', # DCU course code
'year', # DCU course year number/code
'yearsPaid', # Number of years paid (integer)
'updatedby', # Username
'updated', # Timestamp
'createdby', # Username
'created', # Timestamp
'birthday', # Date
# Attributes associated with Unix account.
'uidNumber',
'gidNumber',
'gecos',
'loginShell',
'homeDirectory',
'userPassword', # Crypted password.
'host', # List of hosts.
'shadowLastChange' # Last time password was changed.
)

# List of additional user attributes that are NOT in LDAP.
#
attr_misc_list = (
'passwd', # Plaintext password
'oldusertype', # Used when converting usertype?
'bday', # Birthday day
'bmonth', # Birthday month
'byear', # Birthday year
'disuser_period', # at(1) timespec
#XXX remove usr.override
#'override' # Boolean
)

# Union of above lists.
#
attr_list_all = attr_list + attr_misc_list

attr_list_info = (
# Attributes associated with user to be used for the useradm info command

'uid', # Username
'usertype', # XXX NOT IN LDAP: contains primary
# usertype from objectClass list.
# Placed here so it's at start of
# output for user's information.
'newbie', # New this year (boolean)
'cn', # Full name
'altmail', # Alternate email
'id', # DCU ID number (integer)
'course', # DCU course code
'year', # DCU course year number/code
'yearsPaid', # Number of years paid (integer)
'updatedby', # Username
'updated', # Timestamp
'createdby', # Username
'created', # Timestamp
'birthday', # Date
# Attributes associated with Unix account.
'gecos',
'loginShell',
'homeDirectory',
)

# List of attributes that have multiple values (i.e. are lists).
#
attr_list_value = (
'objectClass',
'host'
)

def __init__(self, usr = None, **attrs):
"""Create new RBUser object.

If the optional usr argument is an RBUser object, its
attributes are copied to the new object. Only valid RBUser
attributes (listed in RBUser.attr_list_all) are copied. If any
keywords are given, the new object's attributes are set to
their values accordingly. Keywords override data copied from a
given RBUser object. Any remaining unset attributes are
explicitly set to None or an empty list [] as appropriate, so
that they exist within the object.

"""

if isinstance(usr, RBUser):
for i in self.attr_list_all:
setattr(self, i, getattr(usr, i))
for i in self.attr_list_all:
if attrs.has_key(i):
setattr(self, i, attrs[i])
elif not hasattr(self, i):
# XXX set list attributes to empty list [] or None ??
#if i in self.attr_list_value:
# setattr(self, i, [])
#else:
setattr(self, i, None)
def merge(self, usr, override = 0):
"""Merge attributes from given RBUser object.
For each valid attribute in the given usr object that has
a value (is not None) set this object (self) to that value
if it is currently None or if override is true.
"""

for i in self.attr_list_all:
if hasattr(usr, i) and (getattr(self, i) == None or override) and getattr(usr, i) != None:
setattr(self, i, getattr(usr, i))

+ 0
- 1469
rbuserdb.py
File diff suppressed because it is too large
View File


fixup-rb-dcu-tree.py → scripts/fixup-rb-dcu-tree.py View File


lockshell → scripts/lockshell View File


make-rb-dcu-tree.sh → scripts/make-rb-dcu-tree.sh View File


newyear_ldif.py → scripts/newyear_ldif.py View File


rebuild_userdb_reserved.py → scripts/rebuild_userdb_reserved.py View File


remove_dcutree_ldif.py → scripts/remove_dcutree_ldif.py View File


+ 0
- 2249
useradm.py
File diff suppressed because it is too large
View File


useradm~migrate → View File


+ 1809
- 1803
useradm/useradm.py
File diff suppressed because it is too large
View File


+ 2243
- 0
useradm/useradm.py~HEAD
File diff suppressed because it is too large
View File


Loading…
Cancel
Save