~azzar1/unity/add-show-desktop-key

1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
1
# IVLE - Informatics Virtual Learning Environment
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
2
# Copyright (C) 2007-2009 The University of Melbourne
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
3
#
4
# This program is free software; you can redistribute it and/or modify
5
# it under the terms of the GNU General Public License as published by
6
# the Free Software Foundation; either version 2 of the License, or
7
# (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
18
"""User and group filesystem management helpers."""
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
19
1197 by Matt Giuca
ivle.chat, ivle.database, ivle.makeuser: Replaced use of md5 library with
20
import hashlib
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
21
import os
22
import stat
23
import shutil
24
import time
25
import uuid
26
import warnings
27
import logging
1239 by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call.
28
import subprocess
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
29
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
30
import ivle.config
31
from ivle.database import ProjectGroup, User
1080.1.44 by William Grant
ivle.makeuser: Port rebuild_svn_group_config() to Storm.
32
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
33
def chown_to_webserver(filename):
1239 by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call.
34
    """chown a directory and its contents to the web server.
35
36
    Recursively chowns a file or directory so the web server user owns it.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
37
    Assumes root.
38
    """
1239 by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call.
39
    subprocess.call(['chown', '-R', 'www-data:www-data', filename])
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
40
41
def make_svn_repo(path, throw_on_error=True):
1239 by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call.
42
    """Create a Subversion repository at the given path."""
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
43
    try:
1239 by William Grant
Replace some of ivle.makeuser's os.system calls with subprocess.call.
44
        res = subprocess.call(['svnadmin', 'create', path])
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
45
        if res != 0 and throw_on_error:
46
            raise Exception("Cannot create repository: %s" % path)
47
    except Exception, exc:
48
        print repr(exc)
49
        if throw_on_error:
50
            raise
51
52
    chown_to_webserver(path)
53
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
54
def rebuild_svn_config(store, config):
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
55
    """Build the complete SVN configuration file.
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
56
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
57
    @param config: An ivle.config.Config object.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
58
    """
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
59
    users = store.find(User)
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
60
    conf_name = config['paths']['svn']['conf']
61
    temp_name = conf_name + ".new"
62
    f = open(temp_name, "w")
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
63
    f.write("""\
64
# IVLE SVN repository authorisation configuration
65
# Generated: %(time)s
66
""" % {'time': time.asctime()})
67
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
68
    for u in users:
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
69
        f.write("""
70
[%(login)s:/]
71
%(login)s = rw
72
""" % {'login': u.login})
73
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
74
    f.close()
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
75
    os.rename(temp_name, conf_name)
76
    chown_to_webserver(conf_name)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
77
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
78
def rebuild_svn_group_config(store, config):
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
79
    """Build the complete SVN configuration file for groups
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
80
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
81
    @param config: An ivle.config.Config object.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
82
    """
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
83
    conf_name = config['paths']['svn']['group_conf']
84
    temp_name = conf_name + ".new"
85
    f = open(temp_name, "w")
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
86
87
    f.write("""\
88
# IVLE SVN group repository authorisation configuration
89
# Generated: %(time)s
90
91
""" % {'time': time.asctime()})
92
1080.1.44 by William Grant
ivle.makeuser: Port rebuild_svn_group_config() to Storm.
93
    for group in store.find(ProjectGroup):
94
        offering = group.project_set.offering
95
        reponame = "_".join([offering.subject.short_name,
96
                             offering.semester.year,
97
                             offering.semester.semester,
98
                             group.name])
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
99
100
        f.write("[%s:/]\n" % reponame)
1080.1.44 by William Grant
ivle.makeuser: Port rebuild_svn_group_config() to Storm.
101
        for user in group.members:
102
            f.write("%s = rw\n" % user.login)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
103
        f.write("\n")
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
104
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
105
    f.close()
1229 by Matt Giuca
ivle.makeuser: rebuild_svn_config and rebuild_svn_group_config now require a
106
    os.rename(temp_name, conf_name)
107
    chown_to_webserver(conf_name)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
108
1230 by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument.
109
def make_svn_auth(store, login, config, throw_on_error=True):
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
110
    """Create a Subversion password for a user.
111
112
    Generates a new random Subversion password, and assigns it to the user.
113
    The password is added to Apache's Subversion authentication file.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
114
    """
1230 by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument.
115
    # filename is, eg, /var/lib/ivle/svn/ivle.auth
116
    filename = config['paths']['svn']['auth_ivle']
1197 by Matt Giuca
ivle.chat, ivle.database, ivle.makeuser: Replaced use of md5 library with
117
    passwd = hashlib.md5(uuid.uuid4().bytes).hexdigest()
1230 by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument.
118
    if os.path.exists(filename):
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
119
        create = ""
120
    else:
121
        create = "c"
122
1242 by William Grant
Use some multiline strings to make ivle.makeuser prettier.
123
    user = User.get_by_login(store, login)
1080.1.7 by matt.giuca
The new ivle.database.User class is now used in Request and usrmgt, which
124
    user.svn_pass = unicode(passwd)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
125
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
126
    res = subprocess.call(['htpasswd', '-%smb' % create,
127
                           filename, login, passwd])
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
128
    if res != 0 and throw_on_error:
129
        raise Exception("Unable to create ivle-auth for %s" % login)
130
131
    # Make sure the file is owned by the web server
132
    if create == "c":
1230 by Matt Giuca
ivle.makeuser: make_svn_auth now requires a config argument.
133
        chown_to_webserver(filename)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
134
135
    return passwd
136
1231 by Matt Giuca
ivle.makeuser: make_jail now requires a config argument.
137
def make_jail(user, config, force=True):
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
138
    """Create or update a user's jail.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
139
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
140
    Only the user-specific parts of the jail are created here - everything
141
    else is expected to be part of another aufs branch.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
142
143
    Returns the path to the user's home directory.
144
145
    Chowns the user's directory within the jail to the given UID.
146
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
147
    @param force: If False, raise an exception if the user already has a jail.
148
                  If True (default), rebuild the jail preserving /home.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
149
    """
150
    # MUST run as root or some of this may fail
151
    if os.getuid() != 0:
152
        raise Exception("Must run make_jail as root")
153
    
154
    # tempdir is for putting backup homes in
1231 by Matt Giuca
ivle.makeuser: make_jail now requires a config argument.
155
    jail_src_base = config['paths']['jails']['src']
156
    tempdir = os.path.join(jail_src_base, '__temp__')
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
157
    if not os.path.exists(tempdir):
158
        os.makedirs(tempdir)
159
    elif not os.path.isdir(tempdir):
160
        os.unlink(tempdir)
161
        os.mkdir(tempdir)
1231 by Matt Giuca
ivle.makeuser: make_jail now requires a config argument.
162
    userdir = os.path.join(jail_src_base, user.login)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
163
    homedir = os.path.join(userdir, 'home')
1080.1.19 by me at id
ivle.makeuser.make_jail: Just take an ivle.database.User, rather than some
164
    userhomedir = os.path.join(homedir, user.login)   # Return value
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
165
166
    if os.path.exists(userdir):
167
        if not force:
168
            raise Exception("User's jail already exists")
169
        # User jail already exists. Blow it away but preserve their home
170
        # directory. It should be all that is there anyway, but you never
171
        # know!
172
        # Ignore warnings about the use of tmpnam
173
        warnings.simplefilter('ignore')
174
        homebackup = os.tempnam(tempdir)
175
        warnings.resetwarnings()
1186 by Matt Giuca
ivle.makeuser: Fixed odd code which would create the home directory, then
176
        # Back up the /home directory, delete the entire jail, recreate the
177
        # jail directory tree, then copy the /home back
178
        # NOTE that shutil.move changed in Python 2.6, it now moves a
179
        # directory INTO the target (like `mv`), which it didn't use to do.
180
        # This code works regardless.
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
181
        shutil.move(homedir, homebackup)
182
        shutil.rmtree(userdir)
1186 by Matt Giuca
ivle.makeuser: Fixed odd code which would create the home directory, then
183
        os.makedirs(userdir)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
184
        shutil.move(homebackup, homedir)
185
        # Change the ownership of all the files to the right unixid
186
        logging.debug("chown %s's home directory files to uid %d"
1080.1.19 by me at id
ivle.makeuser.make_jail: Just take an ivle.database.User, rather than some
187
            %(user.login, user.unixid))
1114 by William Grant
ivle.makeuser.make_jail() no longer uses os.walk() to recursively set
188
        os.spawnvp(os.P_WAIT, 'chown', ['chown', '-R', '%d:%d' % (user.unixid,
189
                                        user.unixid), userhomedir])
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
190
    else:
191
        # No user jail exists
192
        # Set up the user's home directory
193
        os.makedirs(userhomedir)
194
        # Chown (and set the GID to the same as the UID).
1080.1.19 by me at id
ivle.makeuser.make_jail: Just take an ivle.database.User, rather than some
195
        os.chown(userhomedir, user.unixid, user.unixid)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
196
        # Chmod to rwxr-xr-x (755)
197
        os.chmod(userhomedir, 0755)
198
1232 by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument.
199
    make_ivle_conf(user.login, userdir, user.svn_pass, config)
1231 by Matt Giuca
ivle.makeuser: make_jail now requires a config argument.
200
    make_etc_passwd(user.login, userdir, config['paths']['jails']['template'],
201
                    user.unixid)
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
202
203
    return userhomedir
204
1232 by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument.
205
def make_ivle_conf(username, user_jail_dir, svn_pass, sys_config):
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
206
    """Generate an ivle.conf for a user's jail.
207
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
208
    Creates (overwriting any existing file, and creating directories) a
1187 by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead.
209
    file /etc/ivle/ivle.conf in a given user's jail.
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
210
1232 by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument.
211
    @param username: Username.
1236 by Matt Giuca
Fixed docstring in makeuser (don't refer to ivle.conf).
212
    @param user_jail_dir: User's jail dir, ie. ['jails']['src'] + username
1232 by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument.
213
    @param svn_pass: User's SVN password.
214
    @param sys_config: An ivle.config.Config object (the system-wide config).
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
215
    """
1187 by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead.
216
    conf_path = os.path.join(user_jail_dir, "etc/ivle/ivle.conf")
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
217
    os.makedirs(os.path.dirname(conf_path))
218
1092.1.1 by William Grant
[Uber-commit of holiday work because I lacked a local copy of the branch.]
219
    # In the "in-jail" version of conf, we don't need MOST of the details
220
    # (it would be a security risk to have them here).
1187 by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead.
221
    # So we just write root_dir.
222
    conf_obj = ivle.config.Config(blank=True)
223
    conf_obj.filename = conf_path
1232 by Matt Giuca
ivle.makeuser: make_ivle_conf now requires a config argument.
224
    conf_obj['urls']['root'] = sys_config['urls']['root']
225
    conf_obj['urls']['public_host'] = sys_config['urls']['public_host']
226
    conf_obj['urls']['svn_addr'] = sys_config['urls']['svn_addr']
1187 by Matt Giuca
Stopped clobbering conf.py within the jail, using a proper ivle.conf instead.
227
    conf_obj['user_info']['login'] = username
228
    conf_obj['user_info']['svn_pass'] = svn_pass
229
    conf_obj.write()
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
230
231
    # Make this file world-readable
232
    # (chmod 644 conf_path)
233
    os.chmod(conf_path, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP
234
                        | stat.S_IROTH)
235
236
def make_etc_passwd(username, user_jail_dir, template_dir, unixid):
1240 by William Grant
Remove a couple of unused functions from ivle.makeuser, and clean up docstrings
237
    """Create a passwd file for a user's jail.
238
1079 by William Grant
Merge setup-refactor branch. This completely breaks existing installations;
239
    Creates /etc/passwd in the given user's jail. This will be identical to
240
    that in the template jail, except for the added entry for this user.
241
    """
242
    template_passwd_path = os.path.join(template_dir, "etc/passwd")
243
    passwd_path = os.path.join(user_jail_dir, "etc/passwd")
244
    passwd_dir = os.path.dirname(passwd_path)
245
    if not os.path.exists(passwd_dir):
246
        os.makedirs(passwd_dir)
247
    shutil.copy(template_passwd_path, passwd_path)
248
    passwd_file = open(passwd_path, 'a')
249
    passwd_file.write('%s:x:%d:%d::/home/%s:/bin/bash'
250
                      % (username, unixid, unixid, username))
251
    passwd_file.close()