98
98
db.update_user(**update)
101
def get_login(login, passwd, _realm, _login, _may_save):
101
def get_login(login, passwd, realm, existing_login, _may_save):
102
102
"""Callback function used by pysvn for authentication.
103
login, passwd: Credentials of the user attempting to log in.
104
passwd in clear (this should be the user's svn_pass, a
105
randomly-generated permanent password for this user, not their main
107
realm, existing_login, _may_save: The 3 arguments passed by pysvn to
109
The following has been determined empirically, not from docs:
110
existing_login will be the name of the user who owns the process on
111
the first attempt, "" on subsequent attempts. We use this fact.
104
log("Getting password for %s (realm %s)" % (login, _realm))
105
return (True, login, passwd, False)
113
logging.debug("Getting password for %s (realm %s)" % (login, realm))
114
# Only provide credentials on the _first_ attempt.
115
# If we're being asked again, then it means the credentials failed for
116
# some reason and we should just fail. (This is not desirable, but it's
117
# better than being asked an infinite number of times).
118
if existing_login == "":
119
logging.warning("Could not authenticate SVN for %s" % login)
120
return (False, login, passwd, False)
122
return (True, login, passwd, False)
107
124
def activate_user(props):
108
125
"""Create the on-disk stuff for the given user.
126
145
# make svn config/auth
147
logging.debug("Creating repo")
129
148
common.makeuser.make_svn_repo(login, throw_on_error=False)
130
log("Creating svn config")
149
logging.debug("Creating svn config")
131
150
common.makeuser.make_svn_config(login, throw_on_error=False)
132
log("Creating svn auth")
151
logging.debug("Creating svn auth")
133
152
passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
134
log("passwd: %s" % passwd)
153
logging.debug("passwd: %s" % passwd)
136
155
svn = pysvn.Client()
137
156
svn.callback_get_login = partial(get_login, login, passwd)
146
165
# Instead, we're just going to use a single offering with
147
166
# a "short" name of "info1".
148
log("Creating /info1")
167
logging.debug("Creating /info1")
150
169
svn.mkdir(conf.svn_addr + login + "/info1",
151
170
"Initial creation of work directory for Informatics 1")
152
171
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")
172
logging.warning("While mkdiring info1: %s" % str(exc))
174
logging.debug("Creating /stuff")
164
176
svn.mkdir(conf.svn_addr + login + "/stuff",
165
177
"Initial creation of directory for miscellania")
166
178
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))
179
logging.warning("While mkdiring stuff: %s" % str(exc))
182
logging.debug("Creating jail")
183
common.makeuser.make_jail(login, details.unixid, svn_pass=passwd)
185
common.makeuser.mount_jail(login)
187
do_checkout(props, svn_pass=passwd)
210
189
# FIXME: should this be nicer?
211
190
os.system("chown -R %d:%d %s" \
212
191
% (details.unixid, details.unixid,
213
192
common.studpath.url_to_local(login)[1]))
194
logging.info("Enabling user")
217
195
db.update_user(login, state='enabled')
219
197
return {"response": "okay"}
202
def do_checkout(props, svn_pass=None):
203
"""Create the default contents of a user's jail by checking out from the
205
If any directory already exists, just fail silently (so this is not a
206
"wipe-and-checkout", merely a checkout if it failed or something).
208
login - the user name for the jail
212
login = props['login']
215
user = db.get_user(login)
216
# If svn_pass isn't supplied, grab it from the DB
218
svn_pass = user.svn_pass
222
svn.callback_get_login = partial(get_login, login, svn_pass)
224
if conf.svn_addr[-1] != os.sep:
225
conf.svn_addr += os.sep
229
logging.debug("Checking out directories in the jail")
231
svn.checkout(conf.svn_addr + login + "/stuff",
232
common.studpath.url_to_local(login + "/stuff")[1])
233
os.system("chown -R %d:%d %s" \
234
% (user.unixid, user.unixid,
235
common.studpath.url_to_local(login + "/stuff")[1]))
236
except Exception, exc:
237
logging.warning("While mkdiring stuff: %s" % str(exc))
240
svn.checkout(conf.svn_addr + login + "/info1",
241
common.studpath.url_to_local(login + "/info1")[1])
242
os.system("chown -R %d:%d %s" \
243
% (user.unixid, user.unixid,
244
common.studpath.url_to_local(login + "/info1")[1]))
245
except Exception, exc:
246
logging.warning("While mkdiring info1: %s" % str(exc))
251
return {"response": "okay"}
225
254
'create_user':create_user,
226
255
'update_user':update_user,
227
256
'activate_user':activate_user,
257
'do_checkout':do_checkout,
231
"""Writes a message to stderr, but only if DEBUG_PRINT is True.
235
print >>sys.stderr, msg
262
pidfile = open('/var/run/usrmgt-server.pid', 'w')
263
pidfile.write('%d\n' % os.getpid())
265
except IOError, (errno, strerror):
266
print "Couldn't write PID file. IO error(%s): %s" % (errno, strerror)
237
269
def dispatch(props):
270
logging.debug(repr(props))
239
271
action = props.keys()[0]
240
272
return actions[action](props[action])
242
274
if __name__ == "__main__":
276
print >>sys.stderr, "Usage: usrmgt-server <port> <magic>"
243
278
port = int(sys.argv[1])
244
279
magic = sys.argv[2]
246
common.chat.start_server(port, magic, False, dispatch)
283
logging.basicConfig(filename="/var/log/usrmgt.log", level=logging.INFO)
284
logging.info("Starting usrmgt server on port %d (pid = %d)" % (port, pid))
286
common.chat.start_server(port, magic, True, dispatch, initializer)