Browse Source

fix liniting errors (#40)

* fix liniting errors

* changes based on review
pull/59/head
Cian Butler 4 years ago
committed by Tom Doyle
parent
commit
5b12077870
22 changed files with 1313 additions and 1075 deletions
  1. +13
    -13
      scripts/continous_rrs_backup.sh
  2. +2
    -0
      scripts/fixuidNumber.py
  3. +9
    -8
      scripts/fixup-rb-dcu-tree.py
  4. +3
    -3
      scripts/generate_noob_list.sh
  5. +8
    -7
      scripts/ldif_founder_soc_fix.py
  6. +2
    -2
      scripts/lockshell
  7. +4
    -5
      scripts/make-rb-dcu-tree.sh
  8. +14
    -9
      scripts/newyear_ldapmodify_ldif.py
  9. +8
    -7
      scripts/newyear_ldif.py
  10. +153
    -146
      scripts/rebuild_userdb_reserved.py
  11. +4
    -5
      scripts/remove_dcutree_ldif.py
  12. +61
    -60
      scripts/vote.py
  13. +75
    -50
      useradm/rbaccount.py
  14. +24
    -38
      useradm/rbconfig.py
  15. +6
    -7
      useradm/rberror.py
  16. +6
    -7
      useradm/rbopt.py
  17. +57
    -64
      useradm/rbuser.py
  18. +303
    -241
      useradm/rbuserdb.py
  19. +236
    -139
      useradm/rrs.py
  20. +1
    -1
      useradm/server.py
  21. +6
    -7
      useradm/useradm
  22. +318
    -256
      useradm/useradm.py

+ 13
- 13
scripts/continous_rrs_backup.sh View File

@@ -3,17 +3,17 @@
# Simple way of dumping live ldap database and rrs.log file and copying them
# somewhere else.
#
while [ 1 ]; do
# Can't use slapcat safely as the ldap database is read-write and in use.
ldapsearch -x -w "LDAP-SECRET" -D cn=root,ou=ldap,o=redbrick -h localhost > shrapnel.ldif.bak
# We're paranoid.
sync; sync; sync
# Again with the paranoia.
cp rrs.log rrs.log.bak
# Assumes SSH agent is running.
scp shrapnel.ldif.bak rrs.log.bak carbon:
# More healthy paranoia.
ssh carbon 'cp shrapnel.ldif.bak shrapnel.ldif; cp rrs.log.bak rrs.log'
# Wait 5 minutes.
sleep 300
while true; do
# Can't use slapcat safely as the ldap database is read-write and in use.
ldapsearch -x -w "LDAP-SECRET" -D cn=root,ou=ldap,o=redbrick -h localhost > shrapnel.ldif.bak
# We're paranoid.
sync; sync; sync
# Again with the paranoia.
cp rrs.log rrs.log.bak
# Assumes SSH agent is running.
scp shrapnel.ldif.bak rrs.log.bak carbon:
# More healthy paranoia.
ssh carbon 'cp shrapnel.ldif.bak shrapnel.ldif; cp rrs.log.bak rrs.log'
# Wait 5 minutes.
sleep 300
done

+ 2
- 0
scripts/fixuidNumber.py View File

@@ -1,7 +1,9 @@
#! /usr/bin/env python3

import sys

from ..useradm.rbuserdb import RBUserDB

udb = RBUserDB()
udb.connect()
fd, n = udb.uidNumber_getnext()


+ 9
- 8
scripts/fixup-rb-dcu-tree.py View File

@@ -1,14 +1,15 @@
#! /usr/bin/python

import re, sys
import re
import sys

re_dn = re.compile(r'^(dn: cn=.*?,).*(ou=.*?),o=DCU$')

for i in sys.stdin:
i = i.rstrip()
if i.startswith("dn:"):
print(re.sub(re_dn, r'\1\2,ou=dcu,o=redbrick', i))
print("objectClass: top")
print("objectClass: dcuAccount")
elif not i.startswith('objectClass:'):
print(i)
i = i.rstrip()
if i.startswith("dn:"):
print(re.sub(re_dn, r'\1\2,ou=dcu,o=redbrick', i))
print("objectClass: top")
print("objectClass: dcuAccount")
elif not i.startswith('objectClass:'):
print(i)

+ 3
- 3
scripts/generate_noob_list.sh View File

@@ -1,7 +1,7 @@
#!/bin/bash
#!/usr/bin/env bash

noobs=`/srv/admin/scripts/rrs/useradm list_newbies`
noobs=$(/srv/admin/scripts/rrs/useradm list_newbies)

for noob in $noobs; do
echo $noob@redbrick.dcu.ie >> noob_list.txt
echo "$noob"@redbrick.dcu.ie >> noob_list.txt
done

+ 8
- 7
scripts/ldif_founder_soc_fix.py View File

@@ -1,10 +1,11 @@
#!/usr/bin/python
import sys

for i in sys.stdin:
i = i.rstrip()
if i.startswith("yearsPaid:"):
print("yearsPaid:", int(i.split()[1]) + 9)
elif i.startswith("newbie:"):
print("newbie: FALSE")
else:
print(i)
i = i.rstrip()
if i.startswith("yearsPaid:"):
print("yearsPaid:", int(i.split()[1]) + 9)
elif i.startswith("newbie:"):
print("newbie: FALSE")
else:
print(i)

+ 2
- 2
scripts/lockshell View File

@@ -4,6 +4,6 @@ usernames=$(ls /home/club)

for username in $usernames
do
/srv/admin/scripts/rrs/useradm setshell -o $username /usr/local/shells/nologin
sleep 4
/srv/admin/scripts/rrs/useradm setshell -o "$username" /usr/local/shells/nologin
sleep 4
done

+ 4
- 5
scripts/make-rb-dcu-tree.sh View File

@@ -6,14 +6,13 @@ TREES="students staff alumni"
OUTPUT=rb-dcu-tree.ldif

for i in $TREES; do
echo "Getting $i..."
ldapsearch -LLL -x -h $HOST -b ou=$i,o=dcu objectClass=person $ATTRS > $i
echo "Getting $i..."
ldapsearch -LLL -x -h $HOST -b ou="$i",o=dcu objectClass=person "$ATTRS" > "$i"
done

echo "Generating $OUTPUT"

(
cat << EOF
(cat << EOF
dn: ou=dcu,o=redbrick
ou: dcu
objectClass: organizationalUnit
@@ -39,4 +38,4 @@ objectClass: top
structuralObjectClass: organizationalUnit

EOF
cat $TREES | ./fixup-rb-dcu-tree.py ) > $OUTPUT
./fixup-rb-dcu-tree.py < "$TREES") > $OUTPUT

+ 14
- 9
scripts/newyear_ldapmodify_ldif.py View File

@@ -1,6 +1,6 @@
#!/usr/bin/python3
import sys
import string
import sys

"""
-mak
@@ -8,32 +8,38 @@ This simply takes the ldif generated by newyear_ldif.py
and builds it into an ldapmodify formatted ldif.

To be used with the ldap modify query below
ldapmodify -x -D cn=root,ou=ldap,o=redbrick -y /etc/ldap.secret -f [LDIF_FROM_THIS_SCRIPT]
ldapmodify -x -D cn=root,ou=ldap,o=redbrick -y /etc/ldap.secret \
-f [LDIF_FROM_THIS_SCRIPT]
"""

years_paid = ''
uid = ''

#print modify ldif template
# print modify ldif template


def modifyTemplate(uid, years_paid, newbie, reserved):
if uid != '' and years_paid != '' and reserved == False:
modTemp = "dn: uid="+uid.strip()+"\nchangetype: modify\nreplace: years_paid\nyears_paid: "+years_paid.strip()+"\n"
if uid != '' and years_paid != '' and reserved is False:
modTemp = "dn: uid=" + uid.strip() + \
"\nchangetype: modify\nreplace: years_paid\nyears_paid: " + \
years_paid.strip() + "\n"
if newbie == '1':
modTemp += "-\nreplace: newbie\nnewbie: FALSE\n\n"
else:
modTemp += "\n"
print(modTemp)

#open ldif

# open ldif
with open(sys.argv[1], 'r') as content:
ldif = content.read()
#split by user
# split by user
getdn = string.split(ldif, 'dn: uid=')
for i in range(1, len(getdn)):
thisdn = getdn[i].split('\n')
newbie = 'NONE'
reserved = False
#split by users variables
# split by users variables
for j in range(0, len(thisdn)):
x = thisdn[j].rstrip()
uid = thisdn[0].rstrip()
@@ -44,7 +50,6 @@ for i in range(1, len(getdn)):
years_paid = str(int(x.split()[1])).strip()
elif x.startswith("newbie:"):
newbie = '1'
else: continue
except IndexError:
break
modifyTemplate(uid, years_paid, newbie, reserved)

+ 8
- 7
scripts/newyear_ldif.py View File

@@ -1,10 +1,11 @@
#!/usr/bin/python
import sys

for i in sys.stdin:
i = i.rstrip()
if i.startswith("yearsPaid:"):
print("yearsPaid:", int(i.split()[1]) - 1)
elif i.startswith("newbie:"):
print("newbie: FALSE")
else:
print(i)
i = i.rstrip()
if i.startswith("yearsPaid:"):
print("yearsPaid:", int(i.split()[1]) - 1)
elif i.startswith("newbie:"):
print("newbie: FALSE")
else:
print(i)

+ 153
- 146
scripts/rebuild_userdb_reserved.py View File

@@ -1,9 +1,8 @@
#! /usr/bin/env python

#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

# --------------------------------------------------------------------------- #
"""Rebuild userdb reserved table.

Dynamic reserved entries are comprised of email aliases, mailing list names
@@ -17,13 +16,11 @@ import getopt
import os
import re

# RedBrick modules

from rbuserdb import *

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

__version__ = "$Revision: 1.5 $"
__author__ = "Cillian Sharkey"
@@ -33,150 +30,160 @@ __author__ = "Cillian Sharkey"
entries = {}
ldap_users = {}

#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MAIN #
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #


def add_entry(name, desc):
"""Aggregate descriptions for multiple entries."""
"""Aggregate descriptions for multiple entries."""

if name in ldap_users:
return
if name in entries:
entries[name] += ', ' + desc
else:
entries[name] = desc

if name in ldap_users:
return
if name in entries:
entries[name] += ', ' + desc
else:
entries[name] = desc

def main():
"""Program entry function."""

udb = RBUserDB()
udb.connect()
opt = RBOpt()

opts, args = getopt.getopt(sys.argv[1:], 'T')

for o, a in opts:
if o == '-T':
opt.test = 1
udb.setopt(opt)

print('userdb/reserved:', end=' ')

# Gather new entries.
#
print('Gather', end=' ')

# Get copy of all LDAP user, group and reserved entries in one go to
# speedup queries later on.
#
global ldap_users
for i in udb.list_users():
ldap_users[i] = 1
ldap_groups = {}
for i in udb.list_groups():
ldap_groups[i] = 1
ldap_reserveds = udb.dict_reserved_desc()
ldap_reserveds_static = udb.dict_reserved_static()

# Email aliases.
#
re_alias = re.compile(r'^\s*([^#]{1,%d}):' % rbconfig.maxlen_uname)
for file, desc in rbconfig.files_alias:
fd = open(file, 'r')
for line in fd.readlines():
res = re_alias.search(line)
if res:
add_entry(res.group(1).lower(), desc)
fd.close()
# DNS entries.
#
dns_entries = {}
for zone in rbconfig.dns_zones:
fd = os.popen('dig @136.206.15.53 %s -t axfr' % zone)
re_dns = re.compile(r'^([^#;]*\.)?([^#;]{1,%d})\.%s.\s+\d+\s+IN' % (rbconfig.maxlen_uname, zone))
for line in fd.readlines():
res = re_dns.search(line)
if res:
name = res.group(2).lower()
if name in dns_entries:
continue
dns_entries[name] = 1
add_entry(name, 'DNS entry')
fd.close()

# Do host files.
#
re_host = re.compile(r'^[^#\s]+\s+([^#]+)')
re_hostent = re.compile(r'\s+')
for file, host in rbconfig.files_host:
fd = open(file)
for line in fd.readlines():
res = re_host.search(line.lower())
if not res:
continue
for name in res.group(1).split():
if name and '.' not in name and len(name) <= rbconfig.maxlen_uname and name not in dns_entries:
dns_entries[name] = 1
add_entry(name, '%s Host entry' % host)

# Do Unix group files.
#
for file, host in rbconfig.files_group:
fd = open(file)
for line in fd.readlines():
grp = line.split(':')[0].lower()
if len(grp) <= rbconfig.maxlen_uname and grp not in ldap_groups:
add_entry(grp, '%s Unix group' % host)

print('[%d].' % len(list(entries.keys())), end=' ')

# Delete any dynamic entries in LDAP reserved tree that are not in the
# list we built i.e. unused.
#
print('Purge', end=' ')

purge_dn = []
res = udb.list_reserved_dynamic()
for uid in res:
if uid not in entries:
purge_dn.append('uid=%s,%s' % (uid, rbconfig.ldap_reserved_tree))

for i in purge_dn:
if not opt.test:
udb.ldap.delete_s(i)
else:
print('delete', i)
print('[%d]' % len(purge_dn), end=' ')

# Now add/update entries.
#
print('Populate.', end=' ')

total_mods = total_adds = 0

for k, v in list(entries.items()):
if k in ldap_reserveds:
if k not in ldap_reserveds_static and v != ldap_reserveds[k]:
if not opt.test:
udb.ldap.modify_s('uid=%s,%s' % (k, rbconfig.ldap_reserved_tree), ((ldap.MOD_REPLACE, 'description', v),))
else:
print('modify %-8s [%s] [%s]' % (k, v, ldap_reserveds[k]))
total_mods += 1
else:
if not opt.test:
udb.ldap.add_s('uid=%s,%s' % (k, rbconfig.ldap_reserved_tree), (('uid', k), ('description', v), ('objectClass', ('reserved', 'top'))))
else:
print('add %-8s [%s]' % (k, v))
total_adds += 1

print('Done [%d adds, %d mods]' % (total_adds, total_mods))

udb.close()
"""Program entry function."""

udb = RBUserDB()
udb.connect()
opt = RBOpt()

opts, args = getopt.getopt(sys.argv[1:], 'T')

for o, a in opts:
if o == '-T':
opt.test = 1

udb.setopt(opt)

print('userdb/reserved:', end=' ')

# Gather new entries.
#
print('Gather', end=' ')

# Get copy of all LDAP user, group and reserved entries in one go to
# speedup queries later on.
#
global ldap_users
for i in udb.list_users():
ldap_users[i] = 1
ldap_groups = {}
for i in udb.list_groups():
ldap_groups[i] = 1
ldap_reserveds = udb.dict_reserved_desc()
ldap_reserveds_static = udb.dict_reserved_static()

# Email aliases.
#
re_alias = re.compile(r'^\s*([^#]{1,%d}):' % rbconfig.maxlen_uname)

for file, desc in rbconfig.files_alias:
fd = open(file, 'r')
for line in fd.readlines():
res = re_alias.search(line)
if res:
add_entry(res.group(1).lower(), desc)
fd.close()

# DNS entries.
#
dns_entries = {}
for zone in rbconfig.dns_zones:
fd = os.popen('dig @136.206.15.53 %s -t axfr' % zone)
re_dns = re.compile(r'^([^#;]*\.)?([^#;]{1,%d})\.%s.\s+\d+\s+IN' %
(rbconfig.maxlen_uname, zone))
for line in fd.readlines():
res = re_dns.search(line)
if res:
name = res.group(2).lower()
if name in dns_entries:
continue
dns_entries[name] = 1
add_entry(name, 'DNS entry')
fd.close()

# Do host files.
#
re_host = re.compile(r'^[^#\s]+\s+([^#]+)')
re_hostent = re.compile(r'\s+')

for file, host in rbconfig.files_host:
fd = open(file)
for line in fd.readlines():
res = re_host.search(line.lower())
if not res:
continue
for name in res.group(1).split():
if name and '.' not in name and len(
name
) <= rbconfig.maxlen_uname and name not in dns_entries:
dns_entries[name] = 1
add_entry(name, '%s Host entry' % host)

# Do Unix group files.
#
for file, host in rbconfig.files_group:
fd = open(file)
for line in fd.readlines():
grp = line.split(':')[0].lower()
if len(grp) <= rbconfig.maxlen_uname and grp not in ldap_groups:
add_entry(grp, '%s Unix group' % host)

print('[%d].' % len(list(entries.keys())), end=' ')

# Delete any dynamic entries in LDAP reserved tree that are not in the
# list we built i.e. unused.
#
print('Purge', end=' ')

purge_dn = []
res = udb.list_reserved_dynamic()
for uid in res:
if uid not in entries:
purge_dn.append('uid=%s,%s' % (uid, rbconfig.ldap_reserved_tree))

for i in purge_dn:
if not opt.test:
udb.ldap.delete_s(i)
else:
print('delete', i)
print('[%d]' % len(purge_dn), end=' ')

# Now add/update entries.
#
print('Populate.', end=' ')

total_mods = total_adds = 0

for k, v in list(entries.items()):
if k in ldap_reserveds:
if k not in ldap_reserveds_static and v != ldap_reserveds[k]:
if not opt.test:
udb.ldap.modify_s('uid=%s,%s' %
(k, rbconfig.ldap_reserved_tree),
((ldap.MOD_REPLACE, 'description', v), ))
else:
print('modify %-8s [%s] [%s]' % (k, v, ldap_reserveds[k]))
total_mods += 1
else:
if not opt.test:
udb.ldap.add_s('uid=%s,%s' % (k, rbconfig.ldap_reserved_tree),
(('uid', k), ('description', v),
('objectClass', ('reserved', 'top'))))
else:
print('add %-8s [%s]' % (k, v))
total_adds += 1

print('Done [%d adds, %d mods]' % (total_adds, total_mods))

udb.close()


if __name__ == "__main__":
main()
main()

+ 4
- 5
scripts/remove_dcutree_ldif.py View File

@@ -4,8 +4,7 @@ import sys

dcu = 0
for line in sys.stdin:
if line.startswith('dn:'):
dcu = line.find('ou=dcu') != -1
if not dcu:
print(line, end=' ')

if line.startswith('dn:'):
dcu = line.find('ou=dcu') != -1
if not dcu:
print(line, end=' ')

+ 61
- 60
scripts/vote.py View File

@@ -1,78 +1,79 @@
#!/usr/bin/python

import sys
import readline
import re
import os
import re
import sys

from rbuser import *
from rbuserdb import *
from ..useradm.rberror import RBError
from ..useradm.rbuser import RBUser
from ..useradm.rbuserdb import RBUserDB

voteregister= 'voted.txt'
voteregister = 'voted.txt'

#-----------------------------------------------------------------------------#
# MAIN #
#-----------------------------------------------------------------------------#

def main():
"""Program entry function."""
"""Program entry function."""

voted = {}
voted = {}

if os.path.exists(voteregister):
fd = open(voteregister, 'r')
for line in fd.readlines():
voted[line.rstrip()] = 1
fd.close()
if os.path.exists(voteregister):
fd = open(voteregister, 'r')
for line in fd.readlines():
voted[line.rstrip()] = 1
fd.close()

fd = open(voteregister, 'a')
fd = open(voteregister, 'a')

udb = RBUserDB()
udb.connect()
udb = RBUserDB()
udb.connect()

while 1:
usr = RBUser()
tmp = None
while not tmp:
tmp = input("Please enter Username/Student ID/Student Card: ")
res = re.search(r'\D*\d{2}(\d{8})\d{3}\D*', tmp)
if res:
usr.id = int(res.group(1))
print('CARD', usr.id)
else:
res = re.search(r'^(\d{8})$', tmp)
if res:
usr.id = int(tmp)
print('ID', usr.id)
try:
if usr.id:
udb.get_user_byid(usr)
udb.show(usr)
else:
usr.uid = tmp
udb.get_user_byname(usr)
udb.show(usr)
except RBError:
while 1:
usr = RBUser()
tmp = None
while not tmp:
tmp = input("Please enter Username/Student ID/Student Card: ")
res = re.search(r'\D*\d{2}(\d{8})\d{3}\D*', tmp)
if res:
usr.id = int(res.group(1))
print('CARD', usr.id)
else:
res = re.search(r'^(\d{8})$', tmp)
if res:
usr.id = int(tmp)
print('ID', usr.id)
try:
if usr.id:
udb.get_user_byid(usr)
udb.show(usr)
else:
usr.uid = tmp
udb.get_user_byname(usr)
udb.show(usr)
except RBError:

print('NO SUCH USER YOU FUCKING DICKHEAD')
else:
if usr.uid in voted:
print('\nGO FUCK YOUSELF YOU TWO-VOTING PRICK\n')
continue
print('NO SUCH USER YOU FUCKING DICKHEAD')
else:
if usr.uid in voted:
print('\nGO FUCK YOUSELF YOU TWO-VOTING PRICK\n')
continue

if usr.usertype not in ('member', 'committe', 'staff'):
print('\nTELL THE COCKMUCH TO GET A REAL MEMBER ACCOUNT\n')
elif usr.yearsPaid <= 0:
print('\nTELL THE SCABBY BASTARD TO PISS OFF\n')
else:
fd.write('%s\n' % usr.uid)
fd.flush()
voted[usr.uid] = 1
print('\nBIG VOTE GO NOW!\n')
if usr.usertype not in ('member', 'committe', 'staff'):
print('''
\n
TELL THE COCKMUCH TO GET A REAL MEMBER ACCOUNT
\n
''')
elif usr.yearsPaid <= 0:
print('\nTELL THE SCABBY BASTARD TO PISS OFF\n')
else:
fd.write('%s\n' % usr.uid)
fd.flush()
voted[usr.uid] = 1
print('\nBIG VOTE GO NOW!\n')

fd.close()
sys.exit(0)
fd.close()
sys.exit(0)

if __name__ == "__main__":
main()

if __name__ == "__main__":
main()

+ 75
- 50
useradm/rbaccount.py View File

@@ -1,7 +1,6 @@
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

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

# System modules
@@ -10,22 +9,22 @@ import re
import shutil
import sys

# RedBrick modules

import rbconfig
from rberror import RBFatalError, RBWarningError
from rbopt import RBOpt

#-----------------------------------------------------------------------------#
# RedBrick modules

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

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

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


class RBAccount:
@@ -41,9 +40,9 @@ class RBAccount:

self.opt = opt

#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #
# SINGLE ACCOUNT METHODS #
#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #

def add(self, usr):
"""Add account."""
@@ -53,12 +52,15 @@ class RBAccount:
webtree = rbconfig.gen_webtree(usr.uid)
self.wrapper(os.mkdir, webtree, 0o711)
self.wrapper(os.chown, webtree, usr.uidNumber, usr.gidNumber)
self.cmd('%s -Rp %s %s' % (rbconfig.command_cp, rbconfig.dir_skel, usr.homeDirectory))
self.cmd('%s -Rp %s %s' % (rbconfig.command_cp, rbconfig.dir_skel,
usr.homeDirectory))
self.wrapper(os.chmod, usr.homeDirectory, 0o711)
self.wrapper(os.symlink, webtree, os.path.join(usr.homeDirectory, 'public_html'))
self.wrapper(os.symlink, webtree,
os.path.join(usr.homeDirectory, 'public_html'))
# symlink vuln fix
try:
self.wrapper(os.chown, os.path.join(usr.homeDirectory, 'public_html'),
self.wrapper(os.chown,
os.path.join(usr.homeDirectory, 'public_html'),
usr.uidNumber, usr.gidNumber)
except OSError:
pass
@@ -77,12 +79,15 @@ class RBAccount:

# 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)))
self.cmd('%s -Rh %s:%s %s' %
(rbconfig.command_chown, usr.uidNumber, usr.usertype,
self.shquote(usr.homeDirectory)))

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

# Add to redbrick announcement mailing lists.
@@ -139,10 +144,13 @@ class RBAccount:
try:
self.wrapper(os.unlink, newusr.homeDirectory)
except OSError:
raise RBFatalError(("New home directory '%s' already exists,"
" could not unlink existing file.") % newusr.homeDirectory)
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)
raise RBFatalError("New home directory '%s' already exists." %
newusr.homeDirectory)

oldwebtree = rbconfig.gen_webtree(oldusr.uid)
newwebtree = rbconfig.gen_webtree(newusr.uid)
@@ -180,14 +188,17 @@ class RBAccount:
if os.path.isfile(oldf):
self.wrapper(os.rename, oldf, newf)
except OSError as err:
raise RBFatalError("Could not rename '%s' to '%s' [%s]" % (oldf, newf, err))
raise RBFatalError("Could not rename '%s' to '%s' [%s]" %
(oldf, newf, err))

# fixme
# 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_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)

@@ -209,18 +220,23 @@ class RBAccount:
# 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 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)
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)
raise RBFatalError("New home directory '%s' already exists." %
newusr.homeDirectory)

# Rename home directory.
#
@@ -234,9 +250,10 @@ class RBAccount:
# 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))))
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.
#
@@ -268,17 +285,18 @@ class RBAccount:
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, filesystem))
self.cmd("%s -r %s %d %d %d %d %s" %
(rbconfig.command_setquota, self.shquote(str(username)), bqs,
bqh, iqs, iqh, filesystem))

def quota_delete(self, username, filesystem):
"""Delete quota for given username on given filesystem."""

self.quota_set(username, filesystem, 0, 0, 0, 0)

#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #
# SINGLE ACCOUNT INFORMATION METHODS #
#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #

@classmethod
def show(cls, usr):
@@ -289,12 +307,15 @@ class RBAccount:
print('%04o' % (os.stat(usr.homeDirectory)[0] & 0o7777))
else:
print('Home directory does not exist')
print("%13s: %s" % ('logged in', os.path.exists(os.path.join(
rbconfig.dir_signaway_state, usr.uid)) and 'true' or 'false'))
print("%13s: %s" % (
'logged in',
os.path.exists(
os.path.join(rbconfig.dir_signaway_state, usr.uid)
) and 'true' or 'false'))

#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #
# USER CHECKING AND INFORMATION RETRIEVAL METHODS #
#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #

@classmethod
def check_accountfree(cls, usr):
@@ -302,24 +323,27 @@ class RBAccount:
has a home directory."""

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

@classmethod
def check_account_byname(cls, 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)
raise RBFatalError(
"Account '%s' does not exist (no home directory)" % usr.uid)

#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #
# OTHER METHODS #
#---------------------------------------------------------------------#
# ------------------------------------------------------------------- #

def list_add(self, mail_list, email):
"""Add email address to mailing list."""

list_file = self.my_popen("su -c '%s/bin/add_members -r - %s' list" %
(rbconfig.dir_mailman, self.shquote(mail_list)))
(rbconfig.dir_mailman,
self.shquote(mail_list)))
list_file.write('%s\n' % email)
self.my_close(list_file)

@@ -327,11 +351,12 @@ class RBAccount:
"""Delete email address from a mailing list."""

self.runcmd("su -c '%s/bin/remove_members %s %s' list" %
(rbconfig.dir_mailman, self.shquote(mail_list), self.shquote(email)))
(rbconfig.dir_mailman, self.shquote(mail_list),
self.shquote(email)))

#--------------------------------------------------------------------#
# ------------------------------------------------------------------ #
# INTERNAL METHODS #
#--------------------------------------------------------------------#
# ------------------------------------------------------------------ #

@classmethod
def shquote(cls, string):
@@ -368,7 +393,7 @@ class RBAccount:
if self.opt.test:
sys.stderr.write("TEST: %s(" % function.__name__)
for i in keywords:
sys.stderr.write("%s, " % (i,))
sys.stderr.write("%s, " % (i, ))
for k, msg in list(arguments.items()):
sys.stderr.write("%s = %s, " % (k, msg))
sys.stderr.write(")\n")
@@ -397,9 +422,9 @@ class RBAccount:
if not self.opt.test:
open_file.close()

#--------------------------------------------------------------------#
# ------------------------------------------------------------------ #
# ERROR HANDLING #
#--------------------------------------------------------------------#
# ------------------------------------------------------------------ #

def rberror(self, err):
"""Handle errors."""


+ 24
- 38
useradm/rbconfig.py View File

@@ -1,7 +1,6 @@
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

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

# System modules
@@ -10,9 +9,9 @@ import os
import random
import string

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

__version__ = '$Revision: 1.11 $'
__author__ = 'Cillian Sharkey'
@@ -48,19 +47,18 @@ 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'
# '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'
# 'ou=staff,dc=ad,dc=dcu,dc=ie'
LDAP_DCU_ALUMNI_TREE = 'OU=Alumni,DC=ad,DC=dcu,DC=ie'
#'ou=alumni,o=dcu'
# 'ou=alumni,o=dcu'

# DNS zones RedBrick is authorative for.

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

# Mailman list suffixes.

@@ -88,23 +86,17 @@ SHELL_EXPIRED = '/usr/local/shells/expired'

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

FILES_GROUP = (
('/etc/group', 'Deathray'),
('/local/share/var/carbon/group', 'Carbon')
)
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')
)
FILES_HOST = (('/etc/hosts', 'Deathray'), ('/local/share/var/carbon/hosts',
'Carbon'))

# Email alias files.

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

# Commands.

@@ -133,11 +125,8 @@ USERTYPES = {

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

# List of paying USERTYPES.
#
@@ -176,15 +165,16 @@ CONVERT_PRIMARY_GROUPS = {
'helpdesk': 'committe'
}

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


def gen_passwd():
"""Create a random string and return it for the users password"""
return ''.join(random.SystemRandom().choice(string.ascii_lowercase + string.digits)
for _ in range(12))
return ''.join(
random.SystemRandom().choice(string.ascii_lowercase + string.digits)
for _ in range(12))


def gen_homedir(username, usertype):
@@ -218,9 +208,7 @@ def gen_quotas():

"""

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


def gen_extra_user_files(username):
@@ -229,8 +217,6 @@ def gen_extra_user_files(username):

# fixme: need files for carbon now aswell.

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

+ 6
- 7
useradm/rberror.py View File

@@ -1,19 +1,18 @@
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

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

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

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

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


class RBError(Exception):


+ 6
- 7
useradm/rbopt.py View File

@@ -1,19 +1,18 @@
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

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

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

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

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


class RBOpt:


+ 57
- 64
useradm/rbuser.py View File

@@ -1,19 +1,18 @@
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

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

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

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

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


class RBUser():
@@ -24,49 +23,47 @@ class RBUser():
#
attr_list = (
# Attributes associated with user.

'uid', # Username
'usertype', # fixme 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
'uid', # Username
'usertype', # fixme 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.
'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
'passwd', # Plaintext password
'oldusertype', # Used when converting usertype?
'bday', # Birthday day
'bmonth', # Birthday month
'byear', # Birthday year
'disuser_period', # at(1) timespec
# fixme remove usr.override
#'override' # Boolean
# 'override' # Boolean
)

# Union of above lists.
@@ -74,39 +71,34 @@ class RBUser():
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', # fixme 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 user to be used
# for the useradm info command
'uid', # Username
'usertype', # fixme 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',
)
'homeDirectory', )

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

def __init__(self, usr=None, **attrs):
"""Create new RBUser object.
@@ -133,7 +125,8 @@ class RBUser():
for i in attr:
space = 18 - len(i)
if i in self.attr_list_all and self.__dict__[i] is not None:
output_string += i + ' ' * space + ': ' + str(self.__dict__[i]) + '\n'
output_string += i + ' ' * space + ': ' + str(
self.__dict__[i]) + '\n'
else:
output_string += i + ' ' * space + ': ' + ' ----- ' + '\n'
return output_string


+ 303
- 241
useradm/rbuserdb.py
File diff suppressed because it is too large
View File


+ 236
- 139
useradm/rrs.py View File

@@ -1,7 +1,6 @@
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MODULE DESCRIPTION #
#-----------------------------------------------------------------------------#

# --------------------------------------------------------------------------- #
"""RedBrick Registration System CGI."""

# System modules
@@ -10,61 +9,54 @@ import atexit
import cgi
import cgitb
import os
import time
import re
import sys
import time
from xml.sax.saxutils import quoteattr
import ldap

# RedBrick modules

from rbuserdb import RBUserDB
from rbuser import RBUser
import ldap
from rberror import RBError, RBFatalError, RBWarningError
from rbopt import RBOpt
from rberror import RBError, RBWarningError, RBFatalError
from rbuser import RBUser
from rbuserdb import RBUserDB

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

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

cmds = {
'card': 'Card reader interface',
'add': 'Add new user',
'delete': 'Delete user',
'renew': 'Renew user',
'update': 'Update user',
'rename': 'Rename user',
'convert': 'Convert user to new usertype',
'show': 'Show user information',
'card': 'Card reader interface',
'add': 'Add new user',
'delete': 'Delete user',
'renew': 'Renew user',
'update': 'Update user',
'rename': 'Rename user',
'convert': 'Convert user to new usertype',
'show': 'Show user information',
'freename': 'Check if a username is free',
'search': 'Search user and DCU databases',
'stats': 'Database statistics',
'log': 'Log of all actions'
'search': 'Search user and DCU databases',
'stats': 'Database statistics',
'log': 'Log of all actions'
}

cmds_list = ('card', 'add', 'delete', 'renew', 'update', 'rename', 'convert', 'show', 'freename',
'search', 'stats', 'log')
cmds_list = ('card', 'add', 'delete', 'renew', 'update', 'rename', 'convert',
'show', 'freename', 'search', 'stats', 'log')

cmds_noform = {
'stats': 1,
'log': 1
}
cmds_noform = {'stats': 1, 'log': 1}

cmds_custom = {
'show': 1,
'search': 1
}
cmds_custom = {'show': 1, 'search': 1}

fields = (
('updatedby', 'Updated By', ('card', 'add', 'delete', 'renew', 'update', 'rename', 'convert')),
('cardid', 'DCU card id', ('card',)),
('uid', 'Username', ('card', 'add', 'delete', 'renew', 'update', 'rename', 'convert', 'show',
'search')),
('updatedby', 'Updated By', ('card', 'add', 'delete', 'renew', 'update',
'rename', 'convert')),
('cardid', 'DCU card id', ('card', )),
('uid', 'Username', ('card', 'add', 'delete', 'renew', 'update', 'rename',
'convert', 'show', 'search')),
('newuid', 'New username', ('renew', 'rename', 'freename')),
('newbie', 'New user?', ('update',)),
('newbie', 'New user?', ('update', )),
('birthday', 'Birthday', ('add', 'renew', 'update')),
('id', 'DCU ID', ('add', 'renew', 'update', 'search')),
('usertype', 'Usertype', ('add', 'renew', 'convert')),
@@ -73,10 +65,10 @@ fields = (
('course', 'Course Code', ('add', 'renew', 'update')),
('year', 'Course Year', ('add', 'renew', 'update')),
('yearsPaid', 'Years Paid', ('add', 'renew', 'update')),
('setpasswd', 'Set new password?', ('renew',)),
('override', 'Override errors?', ('card', 'add', 'renew', 'update', 'rename')),
('dummyid', "Use 'dummy' ID?", ('card',)),
)
('setpasswd', 'Set new password?', ('renew', )),
('override', 'Override errors?', ('card', 'add', 'renew', 'update',
'rename')),
('dummyid', "Use 'dummy' ID?", ('card', )), )

# Optional side note for form fields. For a particular mode only, use
# "fieldname.mode".
@@ -96,35 +88,31 @@ fields_note = {
# dialogs instead of a checkbox, as they allow neither yes nor no to be set
# (i.e. None).
#
fields_yesno = {
'setpasswd': 1,
'override': 1,
'dummyid': 1,
'newbie': 1
}
fields_yesno = {'setpasswd': 1, 'override': 1, 'dummyid': 1, 'newbie': 1}

# HTML for custom form input fields.
#
fields_input = {
'cardid': 'class=fixed size=18 maxlength=16',
'cn': 'size=30',
'altmail': 'size=30',
'course': 'size=10 maxlength=50',
'year': 'size=10 maxlength=10'
'cardid': 'class=fixed size=18 maxlength=16',
'cn': 'size=30',
'altmail': 'size=30',
'course': 'size=10 maxlength=50',
'year': 'size=10 maxlength=10'
}

# Global variables.
#
usr = RBUser()
opt = RBOpt()
udb = form = None # Initalised later in main()
udb = form = None # Initalised later in main()
okay = 0
start_done = end_done = 0
error_string = notice_string = okay_string = ''

#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# MAIN #
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #


def main():
"""Program entry function."""
@@ -149,8 +137,8 @@ def main():
if opt.mode not in cmds:
opt.mode = 'card'
opt.action = form.getfirst('action')
#XXX remove usr.override
#usr.override = opt.override = form.getfirst('override') == '1'
# XXX remove usr.override
# usr.override = opt.override = form.getfirst('override') == '1'
opt.override = form.getfirst('override') == '1'

# Start HTML now only for modes that print output *before* html_form is
@@ -183,6 +171,7 @@ def main():
html_form()
sys.exit(0)


def shutdown():
"""Cleanup function registered with atexit."""

@@ -190,6 +179,7 @@ def shutdown():
if udb:
udb.close()


def html_start():
"""Start HTML output."""

@@ -198,8 +188,7 @@ def html_start():
return
start_done = 1

print(\
"""<html>
print("""<html>
<head>
<title>RedBrick Registration System v3.0 - %s</title>
<link rel="stylesheet" href="common.css" type="text/css">
@@ -256,12 +245,11 @@ function check_form (f) {
<div id=menu>
<form name=menuform action='rrs.cgi' method=get>""" % opt.mode.capitalize())
if form.getfirst('updatedby'):
print("<input type=hidden name=updatedby value=%s>" % quoteattr(form.getfirst('updatedby')
or ''))
print("<input type=hidden name=updatedby value=%s>" % quoteattr(
form.getfirst('updatedby') or ''))
for i in cmds_list:
print("<input id=button type=submit name=mode value=%s> " % i)
print(\
"""</form>
print("""</form>
</div>

<div id=top>%s</div>
@@ -269,6 +257,7 @@ function check_form (f) {
<div id=main>
""" % cmds[opt.mode])


def html_form():
"""Output HTML form for current mode."""

@@ -279,17 +268,21 @@ def html_form():
if notice_string or error_string or okay_string:
print("<table align=center id=msgs><tr><td>")
if error_string:
print("<span id=warn>%s</span>" % error_string.replace('\n', '<br>\n'))
print("<span id=warn>%s</span>" % error_string.replace(
'\n', '<br>\n'))
if notice_string:
print("<span id=notice>%s</span>" % notice_string.replace('\n', '<br>\n'))
print("<span id=notice>%s</span>" % notice_string.replace(
'\n', '<br>\n'))
if okay_string:
print("<span id=okay>%s</span>" % okay_string.replace('\n', '<br>\n'))
print("<span id=okay>%s</span>" % okay_string.replace(
'\n', '<br>\n'))
print("</td></tr></table>")

# Modes that never use a form or don't want a form when action has been
# requested and successful.
#
if opt.mode in cmds_noform or (opt.mode in cmds_custom and opt.action and okay):
if opt.mode in cmds_noform or (opt.mode in cmds_custom and opt.action
and okay):
return

if okay:
@@ -306,12 +299,14 @@ def html_form():
for k in list(form.keys()):
if hasattr(usr, k) and getattr(usr, k) is None:
setattr(usr, k, form.getfirst(k))
print(\
"""<form name=mainform onSubmit="javascript:return check_form(this)" action="rrs.cgi" method=get>
<input type=hidden name=mode value=%s>
<input type=hidden name=action value=1>""" % opt.mode)
print("""
<form name=mainform onSubmit="javascript:return check_form(this)"
action="rrs.cgi" method=get>
<input type=hidden name=mode value=%s>
<input type=hidden name=action value=1>""" % opt.mode)

print('<table align=center class=main border=0 cellpadding=1 cellspacing=5>')
print(
'<table align=center class=main border=0 cellpadding=1 cellspacing=5>')

for field, desc, modes in fields:
if opt.mode not in modes:
@@ -321,10 +316,10 @@ def html_form():
#
if field == 'updatedby' and form.getfirst('updatedby'):
print('<input type=hidden name=updatedby value=%s>' %
quoteattr(form.getfirst('updatedby') or ''))
quoteattr(form.getfirst('updatedby') or ''))
else:
usrval = ''
if hasattr(usr, field) and getattr(usr, field) != None:
if hasattr(usr, field) and getattr(usr, field) is not None:
usrval = getattr(usr, field)
if field == 'override':
usrval = opt.override
@@ -336,9 +331,14 @@ def html_form():
print(' <td>', end=' ')

if field in fields_input:
print('<input %s name=%s value=%s>' % (fields_input[field], field, quoteattr(str(usrval))))
print('<input %s name=%s value=%s>' %
(fields_input[field], field, quoteattr(str(usrval))))
elif field in fields_yesno:
print('<input name=%s type=radio value=1%s> Yes <input name=%s type=radio value=0%s> No' % (field, usrval == 1 and ' checked' or '', field, usrval == 0 and ' checked' or ''))
print('''
<input name=%s type=radio value=1%s> Yes <input
name=%s type=radio value=0%s> No
''' % (field, usrval == 1 and ' checked' or '', field,
usrval == 0 and ' checked' or ''))
elif field == 'usertype':
# Show default usertype of member if none set.
if not usr.usertype:
@@ -358,10 +358,18 @@ def html_form():
usr.bday = res.group(3)
usr.bmonth = res.group(2)
usr.byear = res.group(1)
print("<input size=2 maxlength=2 name=bday value='%s'>-<input size=2 maxlength=2 name=bmonth value='%s'>-<input size=4 maxlength=4 name=byear value='%s'>" % (usr.bday or '', usr.bmonth or '', usr.byear or ''))
print('''
<input size=2 maxlength=2 name=bday value='%s'>-<input
size=2 maxlength=2 name=bmonth value='%s'>-<input size=4
maxlength=4 name=byear value='%s'>
''' % (usr.bday or '', usr.bmonth or '', usr.byear or ''))
else:
print("<input class=fixed size=10 maxlength=8 name=%s value=%s" % (field, quoteattr(str(usrval))), end=' ')
if field == 'uid' and usr.uid and opt.mode in ('renew', 'update'):
print(
"<input class=fixed size=10 maxlength=8 name=%s value=%s" %
(field, quoteattr(str(usrval))),
end=' ')
if field == 'uid' and usr.uid and opt.mode in ('renew',
'update'):
print(' readonly', end=' ')
print('>')

@@ -377,6 +385,7 @@ def html_form():
<p><input id=button type=submit value='%s &gt;&gt;'></p>
</form>""" % opt.mode.capitalize())


def html_end():
"""Finish HTML output."""

@@ -389,9 +398,11 @@ def html_end():
</body>
</html>""")

#-----------------------------------------------------------------------------#

# --------------------------------------------------------------------------- #
# MAIN FUNCTIONS #
#-----------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #


def card():
"""Process input from card reader form. Mode will be switched to add or
@@ -403,7 +414,7 @@ def card():

# We have an ID, is it a newbie or a renewal?
#
if usr.id != None:
if usr.id is not None:
try:
udb.check_user_byid(usr.id)
except RBError:
@@ -430,17 +441,18 @@ def card():
raise RBFatalError("DCU Card ID, username or dummy ID must be given")

if newmode == 'add':
if usr.id != None:
if usr.id is not None:
udb.get_userinfo_new(usr)
udb.get_userdefaults_new(usr)
elif newmode == 'renew':
curusr = RBUser()
udb.get_userinfo_renew(usr, curusr, override = 1)
udb.get_userinfo_renew(usr, curusr, override=1)
udb.check_unpaid(curusr)
udb.get_userdefaults_renew(usr)
if newmode:
opt.mode = newmode


def add():
"""Add a new user."""

@@ -469,12 +481,15 @@ def add():
# operation, log it and switch back to card mode.
#
okay = 1
okay_string += 'OKAY: User added: %s %s (%s)' % (usr.usertype, usr.uid, usr.cn)
okay_string += 'OKAY: User added: %s %s (%s)' % (usr.usertype, usr.uid,
usr.cn)
rrs_log_add('add:%s:%s:%s:%s:%s:%s:%s:%s:%s' %
(usr.uid, usr.usertype, usr.id != None and usr.id or '', usr.cn, usr.course or '',
usr.year or '', usr.altmail, usr.birthday or '', usr.yearsPaid))
(usr.uid, usr.usertype, usr.id is not None and usr.id or '',
usr.cn, usr.course or '', usr.year or '', usr.altmail,
usr.birthday or '', usr.yearsPaid))
opt.mode = 'card'


def delete():
"""Delete user."""

@@ -489,6 +504,7 @@ def delete():
okay_string += 'OKAY: User deleted: %s\n' % usr.uid
rrs_log_add('delete:%s' % (usr.uid))


def renew():
"""Renew user."""

@@ -519,11 +535,13 @@ def renew():

udb.renew(usr)

okay_string += 'OKAY: User renewed: %s %s%s\n' % (usr.oldusertype, usr.uid, opt.setpasswd and
' [new password set]' or '')
okay_string += 'OKAY: User renewed: %s %s%s\n' % (
usr.oldusertype, usr.uid,
opt.setpasswd and ' [new password set]' or '')
rrs_log_add('renew:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s:%s' %
(usr.uid, newusr.uid or '', opt.setpasswd and 1 or 0, usr.usertype, usr.id != None
and usr.id or '', usr.cn, usr.course or '', usr.year != None and usr.year or '',
(usr.uid, newusr.uid or '', opt.setpasswd and 1 or 0,
usr.usertype, usr.id is not None and usr.id or '', usr.cn,
usr.course or '', usr.year is not None and usr.year or '',
usr.altmail, usr.birthday or '', usr.yearsPaid))

# NOTE: We don't actually generate/set a password here, just flag it in
@@ -536,7 +554,8 @@ def renew():
#
if usr.oldusertype != usr.usertype:
udb.convert(curusr, usr)
okay_string += 'OKAY: User converted: %s -> %s\n' % (usr.uid, usr.usertype)
okay_string += 'OKAY: User converted: %s -> %s\n' % (usr.uid,
usr.usertype)
rrs_log_add('convert:%s:%s' % (usr.uid, usr.usertype))

# NOTE: If new username is given, rename database entry and log it.
@@ -547,11 +566,13 @@ def renew():
if newusr.uid:
udb.rename(usr, newusr)
okay_string += 'OKAY: User renamed: %s -> %s\n' % (usr.uid, newusr.uid)
rrs_log_add('rename-%s:%s:%s' % (usr.newbie and 'new' or 'existing', usr.uid, newusr.uid))
rrs_log_add('rename-%s:%s:%s' % (usr.newbie and 'new' or 'existing',
usr.uid, newusr.uid))

okay = 1
opt.mode = 'card'


def update():
"""Update user."""

@@ -573,7 +594,12 @@ def update():

okay = 1
okay_string += 'OKAY: User updated: %s\n' % usr.uid
rrs_log_add('update:%s:%s:%s:%s:%s:%s:%s:%s:%s' % (usr.uid, usr.newbie and 1 or 0, usr.id != None and usr.id or '', usr.cn, usr.course or '', usr.year != None and usr.year or '', usr.altmail, usr.birthday or '', usr.yearsPaid))
rrs_log_add('update:%s:%s:%s:%s:%s:%s:%s:%s:%s' %
(usr.uid, usr.newbie and 1 or 0,
usr.id is not None and usr.id or '', usr.cn, usr.course or '',
usr.year is not None and usr.year or '', usr.altmail,
usr.birthday or '', usr.yearsPaid))


def rename():
"""Rename user."""
@@ -590,13 +616,15 @@ def rename():

okay = 1
okay_string += 'OKAY: User renamed: %s -> %s\n' % (usr.uid, newusr.uid)
rrs_log_add('rename-%s:%s:%s' % (usr.newbie and 'new' or 'existing', usr.uid, newusr.uid))
rrs_log_add('rename-%s:%s:%s' % (usr.newbie and 'new' or 'existing',
usr.uid, newusr.uid))


def convert():
"""Convert user."""

global okay, okay_string
newusr = RBUser()
get_updatedby(usr)
get_username(usr)
@@ -605,12 +633,14 @@ def convert():
udb.convert(usr, newusr)

okay = 1
okay_string += 'OKAY: User converted: %s -> %s\n' % (usr.uid, newusr.usertype)
okay_string += 'OKAY: User converted: %s -> %s\n' % (usr.uid,
newusr.usertype)
rrs_log_add('convert:%s:%s' % (usr.uid, newusr.usertype))


def show():
"""Show user's details."""
global okay

get_username(usr)
@@ -620,63 +650,103 @@ def show():
print('</pre>')
okay = 1


def freename():
"""Check if a username is free."""
global okay_string
get_newusername(usr)
if usr.uid:
okay_string += "OKAY: Username '%s' is free.\n" % usr.uid


def search():
"""Search user and/or DCU databases."""
global okay

if form.getfirst('uid'):
uid = form.getfirst('uid')
res = udb.search_users_byusername(uid)
print("<p align=center>User database search for username '%s' - %d match%s</p>" % (uid, len(res), len(res) != 1 and 'es' or ''))
print('''<p align=center
>User database search for username '%s' - %d match%s</p>
''' % (uid, len(res), len(res) != 1 and 'es' or ''))
show_search_results(res)
okay = 1
elif 'id' in form or 'cn' in form:
id = form.getfirst('id')
cn = form.getfirst('cn')
if id != None:
if id is not None:
res = udb.search_users_byid(id)
print("<p align=center>User database search for ID '%s' - %d match%s</p>" % (id, len(res), len(res) != 1 and 'es' or ''))
print('''<p align=center
>User database search for ID '%s' - %d match%s</p>
''' % (id, len(res), len(res) != 1 and 'es' or ''))
else:
res = udb.search_users_byname(cn)
print("<p align=center>User database search for name '%s' - %d match%s</p>" % (cn, len(res), len(res) != 1 and 'es' or ''))
print('''<p align=center
>User database search for name '%s' - %d match%s</p>
''' % (cn, len(res), len(res) != 1 and 'es' or ''))

show_search_results(res)

if id != None:
if id is not None:
res = udb.search_dcu_byid(id)
print("<p align=center>DCU database search for ID '%s' - %d match%s</p>" % (id, len(res), len(res) != 1 and 'es' or ''))
print('''<p align=center
>DCU database search for ID '%s' - %d match%s</p>
''' % (id, len(res), len(res) != 1 and 'es' or ''))
else:
res = udb.search_dcu_byname(cn)
print("<p align=center>DCU database search for name '%s' - %d match%s</p>" % (cn, len(res), len(res) != 1 and 'es' or ''))
print('''<p align=center
>DCU database search for name '%s' - %d match%s</p>
''' % (cn, len(res), len(res) != 1 and 'es' or ''))

show_search_results(res)
okay = 1
else:
raise RBFatalError('No search term given!')


def show_search_results(res):
"""Actual routine to display search results."""

if res:
print('<table align=center class=search>')
print('<tr><td></td><td class=top>Username</td><td class=top>Usertype</td><td class=top>Id</td><td class=top>Name</td><td class=top>Course</td><td class=top>Year</td><td class=top>Email</td></tr>')
print('''
<tr><td></td>
<td class=top>Username</td>
<td class=top>Usertype</td>
<td class=top>Id</td>
<td class=top>Name</td>
<td class=top>Course</td>
<td class=top>Year</td>
<td class=top>Email</td></tr>''')
for uid, usertype, id, cn, course, year, altmail in res:
print('<tr><td class=button>', end=' ')
if uid:
print('<form action=rrs.cgi method=get><input type=hidden name=updatedby value=%s><input type=hidden name=uid value=%s><input type=hidden name=action value=1><input id=button type=submit name=mode value=show></form>' % (quoteattr(form.getfirst('updatedby') or ''), uid), end=' ')
print('</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>' % (uid or '-', usertype or '-', id or '-', cn, course or '-', year or '-', altmail))
print(
'''
<form action=rrs.cgi method=get>
<input type=hidden name=updatedby value=%s>
<input type=hidden name=uid value=%s>
<input type=hidden name=action value=1>
<input id=button type=submit name=mode value=show>
</form>
''' % (quoteattr(form.getfirst('updatedby') or ''), uid),
end=' ')