8
from functools import partial
14
import common.makeuser
15
import common.studpath
18
# usrmgt-server <port> <magic>
20
# User management operations:
22
# - [Re]Create jail for a user
23
# - Create a svn repository for a user
27
# - Checkout repository as home directory
29
# - Disable a user's account
30
# - Enable a user's account
32
# - Rebuild svn config
33
# - Rebuild svn auth file
34
# - Rebuild passwd + push to nodes.
38
def create_user(props):
39
"""Create the database record for the given user.
41
login - used as a unix login name and svn repository name.
43
unixid - the unix uid under which execution will take place
44
on the behalf of the user. Don't use 0! If not specified
45
or None, one will be allocated from the configured
48
password - the clear-text password for the user. If this property is
49
absent or None, this is an indication that external
50
authentication should be used (i.e. LDAP).
52
email - the user's email address.
54
nick - the display name to use.
56
fullname - The name of the user for results and/or other official
59
rolenm - The user's role. Must be one of "anyone", "student",
60
"tutor", "lecturer", "admin".
62
studentid - If supplied and not None, the student id of the user for
63
results and/or other official purposes.
65
Return Value: the uid associated with the user. INT
68
if 'unixid' not in props or props['unixid'] is None:
69
# For the time being, just choose a random unixid.
70
# This may result in duplicates, but the unixid is essentially
71
# a monitoring/logging convenience only. Oh, and dups could kill
73
props['unixid'] = random.randrange(5000,10000)
74
# raise NotImplementedError, "No algorithm for creating uids yet!"
76
# props['unixid'] = unixid
78
common.makeuser.make_user_db(**props)
80
return int(props['unixid'])
82
def update_user(props):
83
"""Create the database record for the given user.
85
login - user who is making the change (not necessarily the one
87
update - dict of fields to be updated. The fields are all those
88
in the login table of the db.
90
Omitted fields will not be set.
92
update = props['update']
93
# Note: "login" is special - it is not part of the kwargs to
94
# db.update_user, but the first arg - used to find the user to update.
95
# However it doesn't need any special treatment here.
98
db.update_user(**update)
101
def get_login(login, passwd, _realm, _login, _may_save):
102
"""Callback function used by pysvn for authentication.
104
log("Getting password for %s (realm %s)" % (login, _realm))
105
return (True, login, passwd, False)
107
def activate_user(props):
108
"""Create the on-disk stuff for the given user.
109
Sets the state of the user in the db from pending to enabled.
111
login - the user name for the jail
116
login = props['login']
122
# FIXME: check we're pending
124
details = db.get_user(login)
126
# make svn config/auth
129
common.makeuser.make_svn_repo(login, throw_on_error=False)
130
log("Creating svn config")
131
common.makeuser.make_svn_config(login, throw_on_error=False)
132
log("Creating svn auth")
133
passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
134
log("passwd: %s" % passwd)
137
svn.callback_get_login = partial(get_login, login, passwd)
139
if conf.svn_addr[-1] != '/':
140
conf.svn_addr = conf.svn_addr + "/"
142
# FIXME: This should be a loop over enrolements.
143
# We're not going to fix this now because it requires
144
# a large amount of admin console work to manage subject
146
# Instead, we're just going to use a single offering with
147
# a "short" name of "info1".
148
log("Creating /info1")
150
svn.mkdir(conf.svn_addr + login + "/info1",
151
"Initial creation of work directory for Informatics 1")
152
except Exception, exc:
153
log("While mkdiring info1: %s" % str(exc))
155
log("Creating /submissions")
157
svn.mkdir(conf.svn_addr + login + "/submissions",
158
"Initial creation of submissions directory")
159
except Exception, exc:
160
log("While mkdiring submissions: %s" % str(exc))
162
log("Creating /stuff")
164
svn.mkdir(conf.svn_addr + login + "/stuff",
165
"Initial creation of directory for miscellania")
166
except Exception, exc:
167
log("While mkdiring stuff: %s" % str(exc))
171
common.makeuser.make_jail(login, details.unixid)
175
tcf_path = os.path.join(conf.jail_base, 'template/opt/ivle/lib/conf/conf.py')
176
cf_path = os.path.join(conf.jail_base, login, 'opt/ivle/lib/conf/conf.py')
179
cf = open(cf_path, "w")
180
cf.write(open(tcf_path, "r").read())
181
cf.write("# The login name for the owner of the jail\n")
182
cf.write("login = %s\n" % repr(login))
184
cf.write("# The subversion-only password for the owner of the jail\n")
185
cf.write("svn_pass = %s\n" % repr(passwd))
190
log("Checking out directories in the jail")
192
svn.checkout(conf.svn_addr + login + "/stuff",
193
common.studpath.url_to_local(login + "/stuff")[1])
194
except Exception, exc:
195
log("While mkdiring stuff: %s" % str(exc))
198
svn.checkout(conf.svn_addr + login + "/submissions",
199
common.studpath.url_to_local(login + "/submissions")[1])
200
except Exception, exc:
201
log("While mkdiring submissions: %s" % str(exc))
204
svn.checkout(conf.svn_addr + login + "/info1",
205
common.studpath.url_to_local(login + "/info1")[1])
206
except Exception, exc:
207
log("While mkdiring info1: %s" % str(exc))
210
# FIXME: should this be nicer?
211
os.system("chown -R %d:%d %s" \
212
% (details.unixid, details.unixid,
213
common.studpath.url_to_local(login)[1]))
217
db.update_user(login, state='enabled')
219
return {"response": "okay"}
225
'create_user':create_user,
226
'update_user':update_user,
227
'activate_user':activate_user,
231
"""Writes a message to stderr, but only if DEBUG_PRINT is True.
235
print >>sys.stderr, msg
239
action = props.keys()[0]
240
return actions[action](props[action])
242
if __name__ == "__main__":
243
port = int(sys.argv[1])
246
common.chat.start_server(port, magic, False, dispatch)