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

« back to all changes in this revision

Viewing changes to ivle/makeuser.py

  • Committer: Matt Giuca
  • Date: 2009-03-24 06:50:39 UTC
  • mto: This revision was merged to the branch mainline in revision 1322.
  • Revision ID: matt.giuca@gmail.com-20090324065039-5c6xkjeb8x2f5d01
doc/conf.py: Renamed project from "ivle" to "IVLE". (Turns out this is a
    friendly name).

Show diffs side-by-side

added added

removed removed

Lines of Context:
45
45
import filecmp
46
46
import logging
47
47
import ivle.conf
48
 
import ivle.db
49
48
import ivle.pulldown_subj
50
49
 
 
50
from ivle.database import ProjectGroup
 
51
 
51
52
def chown_to_webserver(filename):
52
53
    """
53
54
    Chowns a file so the web server user owns it.
73
74
 
74
75
    chown_to_webserver(path)
75
76
 
76
 
def rebuild_svn_config():
 
77
def rebuild_svn_config(store):
77
78
    """Build the complete SVN configuration file.
78
79
    """
79
 
    conn = ivle.db.DB()
80
 
    users = conn.get_users()
 
80
    users = store.find(ivle.database.User)
81
81
    groups = {}
82
 
    for u in users:
83
 
        role = str(u.role)
84
 
        if role not in groups:
85
 
            groups[role] = []
86
 
        groups[role].append(u.login)
 
82
    # TODO: Populate groups with per-offering tutors/lecturers/etc.
87
83
    f = open(ivle.conf.svn_conf + ".new", "w")
88
84
    f.write("# IVLE SVN Repositories Configuration\n")
89
85
    f.write("# Auto-generated on %s\n" % time.asctime())
103
99
    os.rename(ivle.conf.svn_conf + ".new", ivle.conf.svn_conf)
104
100
    chown_to_webserver(ivle.conf.svn_conf)
105
101
 
106
 
def rebuild_svn_group_config():
 
102
def rebuild_svn_group_config(store):
107
103
    """Build the complete SVN configuration file for groups
108
104
    """
109
 
    conn = ivle.db.DB()
110
 
    groups = conn.get_all('project_group',
111
 
        ['groupid', 'groupnm', 'projectsetid'])
112
105
    f = open(ivle.conf.svn_group_conf + ".new", "w")
113
106
    f.write("# IVLE SVN Group Repositories Configuration\n")
114
107
    f.write("# Auto-generated on %s\n" % time.asctime())
115
108
    f.write("\n")
116
 
    for g in groups:
117
 
        projectsetid = g['projectsetid']
118
 
        offeringinfo = conn.get_offering_info(projectsetid)
119
 
        subj_short_name = offeringinfo['subj_short_name']
120
 
        year = offeringinfo['year']
121
 
        semester = offeringinfo['semester']
122
 
        reponame = "_".join([subj_short_name, year, semester, g['groupnm']])
 
109
    for group in store.find(ProjectGroup):
 
110
        offering = group.project_set.offering
 
111
        reponame = "_".join([offering.subject.short_name,
 
112
                             offering.semester.year,
 
113
                             offering.semester.semester,
 
114
                             group.name])
123
115
        f.write("[%s:/]\n"%reponame)
124
 
        users = conn.get_projectgroup_members(g['groupid'])
125
 
        for u in users:
126
 
            f.write("%s = rw\n"%u['login'])
 
116
        for user in group.members:
 
117
            f.write("%s = rw\n" % user.login)
127
118
        f.write("\n")
128
119
    f.close()
129
120
    os.rename(ivle.conf.svn_group_conf + ".new", ivle.conf.svn_group_conf)
130
121
    chown_to_webserver(ivle.conf.svn_group_conf)
131
122
 
132
 
def make_svn_auth(login, throw_on_error=True):
 
123
def make_svn_auth(store, login, throw_on_error=True):
133
124
    """Setup svn authentication for the given user.
134
 
       FIXME: create local.auth entry
 
125
       Uses the given DB store object. Does not commit to the db.
135
126
    """
136
127
    passwd = md5.new(uuid.uuid4().bytes).digest().encode('hex')
137
128
    if os.path.exists(ivle.conf.svn_auth_ivle):
139
130
    else:
140
131
        create = "c"
141
132
 
142
 
    ivle.db.DB().update_user(login, svn_pass=passwd)
 
133
    user = ivle.database.User.get_by_login(store, login)
 
134
    user.svn_pass = unicode(passwd)
143
135
 
144
136
    res = os.system("htpasswd -%smb %s %s %s" % (create,
145
137
                                              ivle.conf.svn_auth_ivle,
182
174
    return (to_add, to_remove)
183
175
 
184
176
 
185
 
def make_jail(username, uid, force=True, svn_pass=None):
 
177
def make_jail(user, force=True):
186
178
    """Creates a new user's jail space, in the jail directory as configured in
187
179
    conf.py.
188
180
 
193
185
 
194
186
    Chowns the user's directory within the jail to the given UID.
195
187
 
196
 
    Note: This takes separate username and uid arguments. The UID need not
197
 
    *necessarily* correspond to a Unix username at all, if all you are
198
 
    planning to do is setuid to it. This allows the caller the freedom of
199
 
    deciding the binding between username and uid, if any.
200
 
 
201
188
    force: If false, exception if jail already exists for this user.
202
189
    If true (default), overwrites it, but preserves home directory.
203
 
 
204
 
    svn_pass: If provided this will be a string, the randomly-generated
205
 
    Subversion password for this user (if you happen to already have it).
206
 
    If not provided, it will be read from the database.
207
190
    """
208
191
    # MUST run as root or some of this may fail
209
192
    if os.getuid() != 0:
210
193
        raise Exception("Must run make_jail as root")
211
194
    
212
195
    # tempdir is for putting backup homes in
213
 
    tempdir = os.path.join(ivle.conf.jail_base, '__temp__')
 
196
    tempdir = os.path.join(ivle.conf.jail_src_base, '__temp__')
214
197
    if not os.path.exists(tempdir):
215
198
        os.makedirs(tempdir)
216
199
    elif not os.path.isdir(tempdir):
217
200
        os.unlink(tempdir)
218
201
        os.mkdir(tempdir)
219
 
    userdir = os.path.join(ivle.conf.jail_src_base, username)
 
202
    userdir = os.path.join(ivle.conf.jail_src_base, user.login)
220
203
    homedir = os.path.join(userdir, 'home')
221
 
    userhomedir = os.path.join(homedir, username)   # Return value
 
204
    userhomedir = os.path.join(homedir, user.login)   # Return value
222
205
 
223
206
    if os.path.exists(userdir):
224
207
        if not force:
239
222
        shutil.move(homebackup, homedir)
240
223
        # Change the ownership of all the files to the right unixid
241
224
        logging.debug("chown %s's home directory files to uid %d"
242
 
            %(username, uid))
243
 
        os.chown(userhomedir, uid, uid)
244
 
        for root, dirs, files in os.walk(userhomedir):
245
 
            for fsobj in dirs + files:
246
 
                os.chown(os.path.join(root, fsobj), uid, uid)
 
225
            %(user.login, user.unixid))
 
226
        os.spawnvp(os.P_WAIT, 'chown', ['chown', '-R', '%d:%d' % (user.unixid,
 
227
                                        user.unixid), userhomedir])
247
228
    else:
248
229
        # No user jail exists
249
230
        # Set up the user's home directory
250
231
        os.makedirs(userhomedir)
251
232
        # Chown (and set the GID to the same as the UID).
252
 
        os.chown(userhomedir, uid, uid)
 
233
        os.chown(userhomedir, user.unixid, user.unixid)
253
234
        # Chmod to rwxr-xr-x (755)
254
235
        os.chmod(userhomedir, 0755)
255
236
 
256
 
    # There are 2 special files which need to be generated specific to this
257
 
    # user: ${python_site_packages}/lib/conf/conf.py and /etc/passwd.
258
 
    # "__" username "__" users are exempt (special)
259
 
    if not (username.startswith("__") and username.endswith("__")):
260
 
        make_conf_py(username, userdir, ivle.conf.jail_system, svn_pass)
261
 
        make_etc_passwd(username, userdir, ivle.conf.jail_system, uid)
 
237
    make_conf_py(user.login, userdir, user.svn_pass)
 
238
    make_etc_passwd(user.login, userdir, ivle.conf.jail_system, user.unixid)
262
239
 
263
240
    return userhomedir
264
241
 
265
 
def make_conf_py(username, user_jail_dir, staging_dir, svn_pass=None):
 
242
def make_conf_py(username, user_jail_dir, svn_pass):
266
243
    """
267
244
    Creates (overwriting any existing file, and creating directories) a
268
245
    file ${python_site_packages}/ivle/conf/conf.py in a given user's jail.
269
246
    username: Username.
270
247
    user_jail_dir: User's jail dir, ie. ivle.conf.jail_base + username
271
 
    staging_dir: The dir with the staging copy of the jail. (With the
272
 
        template conf.py file).
273
 
    svn_pass: As with make_jail. User's SVN password, but if not supplied,
274
 
        will look up in the DB.
 
248
    svn_pass: User's SVN password.
275
249
    """
276
 
    template_conf_path = os.path.join(staging_dir,
277
 
            ivle.conf.python_site_packages[1:], "ivle/conf/conf.py")
278
250
    conf_path = os.path.join(user_jail_dir,
279
251
            ivle.conf.python_site_packages[1:], "ivle/conf/conf.py")
280
252
    os.makedirs(os.path.dirname(conf_path))
281
253
 
282
 
    # If svn_pass isn't supplied, grab it from the DB
283
 
    if svn_pass is None:
284
 
        dbconn = ivle.db.DB()
285
 
        svn_pass = dbconn.get_user(username).svn_pass
286
 
        dbconn.close()
287
 
 
288
 
    # Read the contents of the template conf file
289
 
    try:
290
 
        template_conf_file = open(template_conf_path, "r")
291
 
        template_conf_data = template_conf_file.read()
292
 
        template_conf_file.close()
293
 
    except:
294
 
        # Couldn't open template conf.py for some reason
295
 
        # Just treat it as empty file
296
 
        template_conf_data = ("# Warning: Problem building config script.\n"
297
 
                              "# Could not find template conf.py file.\n")
298
 
 
 
254
    # In the "in-jail" version of conf, we don't need MOST of the details
 
255
    # (it would be a security risk to have them here).
 
256
    # So we just write root_dir, and jail_base is "/".
 
257
    # (jail_base being "/" means "jail-relative" paths are relative to "/"
 
258
    # when inside the jail.)
 
259
 
 
260
    # XXX: jail_base is wrong and shouldn't be here. Unfortunately, jail code
 
261
    #      uses ivle.studpath.url_to_{local,jailpaths}, both of which use
 
262
    #      jail_base. Note that they don't use the bits of the return value
 
263
    #      that depend on jail_base, so it can be any string.
299
264
    conf_file = open(conf_path, "w")
300
 
    conf_file.write(template_conf_data)
301
 
    conf_file.write("\n# The login name for the owner of the jail\n")
302
 
    conf_file.write("login = %s\n" % repr(username))
303
 
    conf_file.write("\n")
304
 
    conf_file.write("# The subversion-only password for the owner of "
305
 
        "the jail\n")
306
 
    conf_file.write("svn_pass = %s\n" % repr(svn_pass))
 
265
    conf_file.write("""# IVLE jail configuration
 
266
 
 
267
# In URL space, where in the site is IVLE located. (All URLs will be prefixed
 
268
# with this).
 
269
# eg. "/" or "/ivle".
 
270
root_dir = %(root_dir)r
 
271
 
 
272
# This value is not relevant inside the jail, but must remain for now. See
 
273
# the XXX in ivle.makeuser.make_conf_py.
 
274
jail_base = '/'
 
275
 
 
276
# The hostname for serving publicly accessible pages
 
277
public_host = %(public_host)r
 
278
 
 
279
# The URL under which the Subversion repositories are located.
 
280
svn_addr = %(svn_addr)r
 
281
 
 
282
# The login name for the owner of the jail
 
283
login = %(username)r
 
284
 
 
285
# The subversion-only password for the owner of the jail
 
286
svn_pass = %(svn_pass)r
 
287
""" % {'root_dir': ivle.conf.root_dir,
 
288
       'public_host': ivle.conf.public_host,
 
289
       'svn_addr': ivle.conf.svn_addr,
 
290
       'username': username,
 
291
       'svn_pass': svn_pass,
 
292
      })
307
293
    conf_file.close()
308
294
 
309
295
    # Make this file world-readable
327
313
                      % (username, unixid, unixid, username))
328
314
    passwd_file.close()
329
315
 
330
 
def make_user_db(throw_on_error = True, **kwargs):
331
 
    """Creates a user's entry in the database, filling in all the fields.
332
 
    All arguments must be keyword args. They are the fields in the table.
333
 
    However, instead of supplying a "passhash", you must supply a
334
 
    "password" argument, which will be hashed internally.
335
 
    Also do not supply a state. All users are created in the "no_agreement"
336
 
    state.
337
 
    Also pulls the user's subjects using the configured subject pulldown
338
 
    module, and adds enrolments to the DB.
339
 
    Throws an exception if the user already exists.
340
 
    """
341
 
    dbconn = ivle.db.DB()
342
 
    dbconn.create_user(**kwargs)
343
 
    dbconn.close()
344
 
 
345
 
    if kwargs['password']:
346
 
        if os.path.exists(ivle.conf.svn_auth_local):
347
 
            create = ""
348
 
        else:
349
 
            create = "c"
350
 
        res = os.system("htpasswd -%smb %s %s %s" % (create,
351
 
                                                     ivle.conf.svn_auth_local,
352
 
                                                     kwargs['login'],
353
 
                                                     kwargs['password']))
354
 
        if res != 0 and throw_on_error:
355
 
            raise Exception("Unable to create local-auth for %s" % kwargs['login'])
356
 
 
357
 
    # Make sure the file is owned by the web server
358
 
    if create == "c":
359
 
        chown_to_webserver(ivle.conf.svn_auth_local)
360
 
 
361
 
    # Pulldown subjects and add enrolments
362
 
    ivle.pulldown_subj.enrol_user(kwargs['login'])
363
 
 
364
316
def mount_jail(login):
365
317
    # This is where we'll mount to...
366
318
    destdir = os.path.join(ivle.conf.jail_base, login)