30
from storm.expr import Select, Max
31
from ivle.database import ProjectGroup, User
33
from ivle.database import (User, ProjectGroup, Assessed, ProjectSubmission,
34
Project, ProjectSet, Offering, Enrolment, Subject, Semester)
33
36
def chown_to_webserver(filename):
34
37
"""chown a directory and its contents to the web server.
72
75
""" % {'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'))
112
""" % {'login': login, 'id': psid, 'path': pspath})
114
for viewer_login in offering_viewers_cache[offeringid]:
115
# We don't want to override the owner's write privilege,
116
# so we don't add them to the read-only ACL.
117
if login != viewer_login:
118
f.write("%s = r\n" % viewer_login)
75
121
os.rename(temp_name, conf_name)
76
122
chown_to_webserver(conf_name)
100
147
f.write("[%s:/]\n" % reponame)
148
if group.id not in group_members_cache:
149
group_members_cache[group.id] = set()
101
150
for user in group.members:
151
group_members_cache[group.id].add(user.login)
102
152
f.write("%s = rw\n" % user.login)
155
# Now we need to grant offering tutors and lecturers access to the latest
156
# submissions in their offerings. There are much prettier ways to do this,
157
# but a lot of browser requests call this function, so it needs to be
158
# fast. We can grab all of the paths needing authorisation directives with
159
# a single query, and we cache the list of viewers for each offering.
160
offering_viewers_cache = {}
161
for (ssn, year, sem, name, psid, pspath, gid, offeringid) in store.find(
162
(Subject.short_name, Semester.year, Semester.semester,
163
ProjectGroup.name, ProjectSubmission.id, ProjectSubmission.path,
164
ProjectGroup.id, Offering.id),
165
Assessed.id == ProjectSubmission.assessed_id,
166
ProjectGroup.id == Assessed.project_group_id,
167
Project.id == Assessed.project_id,
168
ProjectSet.id == Project.project_set_id,
169
Offering.id == ProjectSet.offering_id,
170
Subject.id == Offering.subject_id,
171
Semester.id == Offering.semester_id,
172
ProjectSubmission.date_submitted == Select(
173
Max(ProjectSubmission.date_submitted),
174
ProjectSubmission.assessed_id == Assessed.id,
175
tables=ProjectSubmission
179
reponame = "_".join([ssn, year, sem, name])
181
# Do we already have the list of logins authorised for this offering
182
# cached? If not, get it.
183
if offeringid not in offering_viewers_cache:
184
offering_viewers_cache[offeringid] = list(store.find(
186
User.id == Enrolment.user_id,
187
Enrolment.offering_id == offeringid,
188
Enrolment.role.is_in((u'tutor', u'lecturer'))
195
""" % {'repo': reponame, 'id': psid, 'path': pspath})
197
for viewer_login in offering_viewers_cache[offeringid]:
198
# Skip existing group members, or they can't write to it any more.
199
if viewer_login not in group_members_cache[gid]:
200
f.write("%s = r\n" % viewer_login)
106
203
os.rename(temp_name, conf_name)
107
204
chown_to_webserver(conf_name)
178
276
# NOTE that shutil.move changed in Python 2.6, it now moves a
179
277
# directory INTO the target (like `mv`), which it didn't use to do.
180
278
# This code works regardless.
181
shutil.move(homedir, homebackup)
279
shutil.move(userhomedir, homebackup)
182
280
shutil.rmtree(userdir)
184
shutil.move(homebackup, homedir)
282
shutil.move(homebackup, userhomedir)
185
283
# Change the ownership of all the files to the right unixid
186
284
logging.debug("chown %s's home directory files to uid %d"
187
285
%(user.login, user.unixid))
213
313
@param svn_pass: User's SVN password.
214
314
@param sys_config: An ivle.config.Config object (the system-wide config).
216
conf_path = os.path.join(user_jail_dir, "etc/ivle/ivle.conf")
217
os.makedirs(os.path.dirname(conf_path))
316
conf_path = os.path.join(user_jail_dir, "home/.ivle.conf")
317
if not os.path.exists(os.path.dirname(conf_path)):
318
os.makedirs(os.path.dirname(conf_path))
219
320
# In the "in-jail" version of conf, we don't need MOST of the details
220
321
# (it would be a security risk to have them here).
239
340
Creates /etc/passwd in the given user's jail. This will be identical to
240
341
that in the template jail, except for the added entry for this user.
242
template_passwd_path = os.path.join(template_dir, "etc/passwd")
243
passwd_path = os.path.join(user_jail_dir, "etc/passwd")
343
template_passwd_path = os.path.join(template_dir, "home/.passwd")
344
passwd_path = os.path.join(user_jail_dir, "home/.passwd")
244
345
passwd_dir = os.path.dirname(passwd_path)
245
346
if not os.path.exists(passwd_dir):
246
347
os.makedirs(passwd_dir)