30
from storm.expr import Select, Max
33
from ivle.database import (User, ProjectGroup, Assessed, ProjectSubmission,
34
Project, ProjectSet, Offering, Enrolment, Subject, Semester)
31
from ivle.database import ProjectGroup, User
36
33
def chown_to_webserver(filename):
37
34
"""chown a directory and its contents to the web server.
75
72
""" % {'login': u.login})
77
# Now we need to grant offering tutors and lecturers access to the latest
78
# submissions in their offerings. There are much prettier ways to do this,
79
# but a lot of browser requests call this function, so it needs to be
80
# fast. We can grab all of the paths needing authorisation directives with
81
# a single query, and we cache the list of viewers for each offering.
82
offering_viewers_cache = {}
83
for (login, psid, pspath, offeringid) in store.find(
84
(User.login, ProjectSubmission.id, ProjectSubmission.path,
86
Assessed.id == ProjectSubmission.assessed_id,
87
User.id == Assessed.user_id,
88
Project.id == Assessed.project_id,
89
ProjectSet.id == Project.project_set_id,
90
Offering.id == ProjectSet.id,
91
ProjectSubmission.date_submitted == Select(
92
Max(ProjectSubmission.date_submitted),
93
ProjectSubmission.assessed_id == Assessed.id,
94
tables=ProjectSubmission
98
# Do we already have the list of logins authorised for this offering
99
# cached? If not, get it.
100
if offeringid not in offering_viewers_cache:
101
offering_viewers_cache[offeringid] = list(store.find(
103
User.id == Enrolment.user_id,
104
Enrolment.offering_id == offeringid,
105
Enrolment.role.is_in((u'tutor', u'lecturer')),
106
Enrolment.active == True,
113
""" % {'login': login, 'id': psid, 'path': pspath})
115
for viewer_login in offering_viewers_cache[offeringid]:
116
# We don't want to override the owner's write privilege,
117
# so we don't add them to the read-only ACL.
118
if login != viewer_login:
119
f.write("%s = r\n" % viewer_login)
122
75
os.rename(temp_name, conf_name)
123
76
chown_to_webserver(conf_name)
148
100
f.write("[%s:/]\n" % reponame)
149
if group.id not in group_members_cache:
150
group_members_cache[group.id] = set()
151
101
for user in group.members:
152
group_members_cache[group.id].add(user.login)
153
102
f.write("%s = rw\n" % user.login)
156
# Now we need to grant offering tutors and lecturers access to the latest
157
# submissions in their offerings. There are much prettier ways to do this,
158
# but a lot of browser requests call this function, so it needs to be
159
# fast. We can grab all of the paths needing authorisation directives with
160
# a single query, and we cache the list of viewers for each offering.
161
offering_viewers_cache = {}
162
for (ssn, year, sem, name, psid, pspath, gid, offeringid) in store.find(
163
(Subject.short_name, Semester.year, Semester.semester,
164
ProjectGroup.name, ProjectSubmission.id, ProjectSubmission.path,
165
ProjectGroup.id, Offering.id),
166
Assessed.id == ProjectSubmission.assessed_id,
167
ProjectGroup.id == Assessed.project_group_id,
168
Project.id == Assessed.project_id,
169
ProjectSet.id == Project.project_set_id,
170
Offering.id == ProjectSet.offering_id,
171
Subject.id == Offering.subject_id,
172
Semester.id == Offering.semester_id,
173
ProjectSubmission.date_submitted == Select(
174
Max(ProjectSubmission.date_submitted),
175
ProjectSubmission.assessed_id == Assessed.id,
176
tables=ProjectSubmission
180
reponame = "_".join([ssn, year, sem, name])
182
# Do we already have the list of logins authorised for this offering
183
# cached? If not, get it.
184
if offeringid not in offering_viewers_cache:
185
offering_viewers_cache[offeringid] = list(store.find(
187
User.id == Enrolment.user_id,
188
Enrolment.offering_id == offeringid,
189
Enrolment.role.is_in((u'tutor', u'lecturer')),
190
Enrolment.active == True,
197
""" % {'repo': reponame, 'id': psid, 'path': pspath})
199
for viewer_login in offering_viewers_cache[offeringid]:
200
# Skip existing group members, or they can't write to it any more.
201
if viewer_login not in group_members_cache[gid]:
202
f.write("%s = r\n" % viewer_login)
205
106
os.rename(temp_name, conf_name)
206
107
chown_to_webserver(conf_name)
214
115
# filename is, eg, /var/lib/ivle/svn/ivle.auth
215
116
filename = config['paths']['svn']['auth_ivle']
117
passwd = hashlib.md5(uuid.uuid4().bytes).hexdigest()
216
118
if os.path.exists(filename):
221
123
user = User.get_by_login(store, login)
223
if user.svn_pass is None:
224
passwd = hashlib.md5(uuid.uuid4().bytes).hexdigest()
225
user.svn_pass = unicode(passwd)
124
user.svn_pass = unicode(passwd)
227
126
res = subprocess.call(['htpasswd', '-%smb' % create,
228
filename, login, user.svn_pass])
127
filename, login, passwd])
229
128
if res != 0 and throw_on_error:
230
129
raise Exception("Unable to create ivle-auth for %s" % login)
280
178
# NOTE that shutil.move changed in Python 2.6, it now moves a
281
179
# directory INTO the target (like `mv`), which it didn't use to do.
282
180
# This code works regardless.
283
shutil.move(userhomedir, homebackup)
181
shutil.move(homedir, homebackup)
284
182
shutil.rmtree(userdir)
286
shutil.move(homebackup, userhomedir)
184
shutil.move(homebackup, homedir)
287
185
# Change the ownership of all the files to the right unixid
288
186
logging.debug("chown %s's home directory files to uid %d"
289
187
%(user.login, user.unixid))
317
213
@param svn_pass: User's SVN password.
318
214
@param sys_config: An ivle.config.Config object (the system-wide config).
320
conf_path = os.path.join(user_jail_dir, "home/.ivle.conf")
321
if not os.path.exists(os.path.dirname(conf_path)):
322
os.makedirs(os.path.dirname(conf_path))
216
conf_path = os.path.join(user_jail_dir, "etc/ivle/ivle.conf")
217
os.makedirs(os.path.dirname(conf_path))
324
219
# In the "in-jail" version of conf, we don't need MOST of the details
325
220
# (it would be a security risk to have them here).
344
239
Creates /etc/passwd in the given user's jail. This will be identical to
345
240
that in the template jail, except for the added entry for this user.
347
template_passwd_path = os.path.join(template_dir, "home/.passwd")
348
passwd_path = os.path.join(user_jail_dir, "home/.passwd")
242
template_passwd_path = os.path.join(template_dir, "etc/passwd")
243
passwd_path = os.path.join(user_jail_dir, "etc/passwd")
349
244
passwd_dir = os.path.dirname(passwd_path)
350
245
if not os.path.exists(passwd_dir):
351
246
os.makedirs(passwd_dir)