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)
115
212
# filename is, eg, /var/lib/ivle/svn/ivle.auth
116
213
filename = config['paths']['svn']['auth_ivle']
117
passwd = hashlib.md5(uuid.uuid4().bytes).hexdigest()
118
214
if os.path.exists(filename):
123
219
user = User.get_by_login(store, login)
124
user.svn_pass = unicode(passwd)
221
if user.svn_pass is None:
222
passwd = hashlib.md5(uuid.uuid4().bytes).hexdigest()
223
user.svn_pass = unicode(passwd)
126
225
res = subprocess.call(['htpasswd', '-%smb' % create,
127
filename, login, passwd])
226
filename, login, user.svn_pass])
128
227
if res != 0 and throw_on_error:
129
228
raise Exception("Unable to create ivle-auth for %s" % login)
178
278
# NOTE that shutil.move changed in Python 2.6, it now moves a
179
279
# directory INTO the target (like `mv`), which it didn't use to do.
180
280
# This code works regardless.
181
shutil.move(homedir, homebackup)
281
shutil.move(userhomedir, homebackup)
182
282
shutil.rmtree(userdir)
184
shutil.move(homebackup, homedir)
284
shutil.move(homebackup, userhomedir)
185
285
# Change the ownership of all the files to the right unixid
186
286
logging.debug("chown %s's home directory files to uid %d"
187
287
%(user.login, user.unixid))
213
315
@param svn_pass: User's SVN password.
214
316
@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))
318
conf_path = os.path.join(user_jail_dir, "home/.ivle.conf")
319
if not os.path.exists(os.path.dirname(conf_path)):
320
os.makedirs(os.path.dirname(conf_path))
219
322
# In the "in-jail" version of conf, we don't need MOST of the details
220
323
# (it would be a security risk to have them here).
239
342
Creates /etc/passwd in the given user's jail. This will be identical to
240
343
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")
345
template_passwd_path = os.path.join(template_dir, "home/.passwd")
346
passwd_path = os.path.join(user_jail_dir, "home/.passwd")
244
347
passwd_dir = os.path.dirname(passwd_path)
245
348
if not os.path.exists(passwd_dir):
246
349
os.makedirs(passwd_dir)