8
from functools import partial
13
import common.makeuser
14
import common.studpath
17
# usrmgt-server <port> <magic>
19
# User management operations:
21
# - [Re]Create jail for a user
22
# - Create a svn repository for a user
26
# - Checkout repository as home directory
28
# - Disable a user's account
29
# - Enable a user's account
31
# - Rebuild svn config
32
# - Rebuild svn auth file
33
# - Rebuild passwd + push to nodes.
37
def create_user(props):
38
"""Create the database record for the given user.
40
username - used as a unix login name and svn repository name.
42
uid - the unix uid under which execution will take place
43
on the behalf of the user. Don't use 0! If not specified
44
or None, one will be allocated from the configured
47
password - the clear-text password for the user. If this property is
48
absent or None, this is an indication that external
49
authentication should be used (i.e. LDAP).
51
email - the user's email address.
53
nick - the display name to use.
55
fullname - The name of the user for results and/or other official
58
rolenm - The user's role. Must be one of "anyone", "student",
59
"tutor", "lecturer", "admin".
61
studentid - If supplied and not None, the student id of the user for
62
results and/or other official purposes.
64
Return Value: the uid associated with the user. INT
67
# FIXME: the IVLE server must check that an admin is doing this!
69
if 'uid' not in props or props['uid'] is None:
70
# For the time being, just choose a random unixid.
71
# This may result in duplicates, but the unixid is essentially
72
# a monitoring/logging convenience only. Oh, and dups could kill
74
props['uid'] = random.randrange(5000,10000)
75
# raise NotImplementedError, "No algorithm for creating uids yet!"
79
username = props['username']
82
password = props['password']
86
email = props['email']
90
fullname = props['fullname']
91
rolenm = props['rolenm']
93
studentid = props['studentid']
96
common.makeuser.make_user_db(username, uid, password, email, nick,
97
fullname, rolenm, studentid)
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"}
221
except Exception, exc:
222
print >> sys.stderr, exc
228
'create_user':create_user,
229
'activate_user':activate_user
233
"""Writes a message to stderr, but only if DEBUG_PRINT is True.
237
print >>sys.stderr, msg
240
print >> sys.stderr, repr(props)
241
action = props.keys()[0]
242
return actions[action](props[action])
244
if __name__ == "__main__":
245
port = int(sys.argv[1])
248
common.chat.start_server(port, magic, False, dispatch)