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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
#!/usr/bin/python

import os
import pysvn
import subprocess
import sys
import urllib
from functools import partial

import conf
import common.db
import common.chat
import common.makeuser
import common.studpath

# usage:
#   usrmgt-server <port> <magic>

# User management operations:
#   - Create local user
#   - [Re]Create jail for a user
#       - Create a svn repository for a user
#           - create repository
#           - svn config
#           - svn auth
#       - Checkout repository as home directory
#       - /etc/passwd entry
#   - Disable a user's account
#   - Enable a user's account
#   - Remove a user
#   - Rebuild svn config
#   - Rebuild svn auth file
#   - Rebuild passwd + push to nodes.


def create_user(props):
    """Create the database record for the given user.
       Expected properties:
        username    - used as a unix login name and svn repository name.
                      STRING REQUIRED 
        uid         - the unix uid under which execution will take place
                      on the behalf of the user. Don't use 0! If not specified
                      or None, one will be allocated from the configured
                      numeric range.
                      INT OPTIONAL
        password    - the clear-text password for the user. If this property is
                      absent or None, this is an indication that external
                      authentication should be used (i.e. LDAP).
                      STRING OPTIONAL
        email       - the user's email address.
                      STRING OPTIONAL
        nick        - the display name to use.
                      STRING REQUIRED
        fullname    - The name of the user for results and/or other official
                      purposes.
                      STRING REQUIRED
        rolenm      - The user's role. Must be one of "anyone", "student",
                      "tutor", "lecturer", "admin".
                      STRING/ENUM REQUIRED
        studentid   - If supplied and not None, the student id of the user for
                      results and/or other official purposes.
                      STRING OPTIONAL
       Return Value: the uid associated with the user. INT
    """

    # FIXME: the IVLE server must check that an admin is doing this!

    if 'uid' not in props or props['uid'] is None:
        raise NotImplementedError, "No algorithm for creating uids yet!"
        # uid = invent-uid
        # props['uid'] = uid

    username = props['username']
    uid = props['uid']
    try:
        password = props['password']
    except KeyError:
        password = None
    try:
        email = props['email']
    except KeyError:
        email = None
    nick = props['nick']
    fullname = props['fullname']
    rolenm = props['rolenm']
    try:
        studentid = props['studentid']
    except KeyError:
        studentid = None
    common.makeuser.make_user_db(username, uid, password, email, nick,
                                 fullname, rolenm, studentid)

    return uid

def get_login(login, passwd, _realm, _login, _may_save):
    """Callback function used by pysvn for authentication.
    """
    # print >> sys.stderr, "Getting password for %s (realm %s)" % (login, _realm)
    return (True, login, passwd, False)

def activate_user(props):
    """Create the on-disk stuff for the given user.
       Sets the state of the user in the db from pending to enabled.
       Expected properties:
        login       - the user name for the jail
                      STRING REQUIRED
       Return Value: None
    """

    login = props['login']

    db = common.db.DB()

    try:

        # FIXME: check we're pending

        details = db.get_user(login)

        # make svn config/auth

        # print >> sys.stderr, "Creating repo"
        common.makeuser.make_svn_repo(login, throw_on_error=False)
        # print >> sys.stderr, "Creating svn config"
        common.makeuser.make_svn_config(login, throw_on_error=False)
        # print >> sys.stderr, "Creating svn auth"
        passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
        # print >> sys.stderr, "passwd: %s" % passwd

        svn = pysvn.Client()
        svn.callback_get_login = partial(get_login, login, passwd)
    
        # FIXME: This should be a loop over enrolements.
        #        We're not going to fix this now because it requires
        #        a large amount of admin console work to manage subject
        #        offerings.
        #        Instead, we're just going to use a single offering with
        #        a "short" name of "info1".
        # print >> sys.stderr, "Creating /info1"
        try:
            svn.mkdir(conf.svn_addr + login + "/info1",
                      "Initial creation of work directory for Informatics 1")
        except Exception, exc:
            pass
        # print >> sys.stderr, "Creating /submissions"
        try:
            svn.mkdir(conf.svn_addr + login + "/submissions",
                      "Initial creation of submissions directory")
        except Exception, exc:
            pass
        # print >> sys.stderr, "Creating /stuff"
        try:
            svn.mkdir(conf.svn_addr + login + "/stuff",
                      "Initial creation of directory for miscellania")
        except Exception, exc:
            pass

        # print >> sys.stderr, "Creating jail"
        common.makeuser.make_jail(login, details.unixid)

        # FIXME: <hack>

        tcf_path = os.path.join(conf.jail_base, 'template/opt/ivle/lib/conf/conf.py')
        cf_path = os.path.join(conf.jail_base, login, 'opt/ivle/lib/conf/conf.py')

        os.remove(cf_path)
        cf = open(cf_path, "w")
        cf.write(open(tcf_path, "r").read())
        cf.write("# The login name for the owner of the jail\n")
        cf.write("login = %s\n" % repr(login))
        cf.write("\n")
        cf.write("# The subversion-only password for the owner of the jail\n")
        cf.write("svn_pass = %s\n" % repr(passwd))
        cf.close()

        # FIXME: </hack>

        # print >> sys.stderr, "Checking out directories in the jail"
        try:
            svn.checkout(conf.svn_addr + "/" + login + "/stuff",
                         common.studpath.url_to_local(login + "/stuff")[1])
        except Exception, exc:
            pass
        try:
            svn.checkout(conf.svn_addr + "/" + login + "/submissions",
                         common.studpath.url_to_local(login + "/submissions")[1])
        except Exception, exc:
            pass
        try:
            svn.checkout(conf.svn_addr + "/" + login + "/info1",
                         common.studpath.url_to_local(login + "/info1")[1])
        except Exception, exc:
            pass

        # FIXME: should this be nicer?
        os.system("chown -R %d:%d %s" \
                % (details.unixid, details.unixid,
                   common.studpath.url_to_local(login)[1]))


        # print >> sys.stderr, "Enabling user"
        db.update_user(login, state='enabled')

        return {"response": "okay"}
    
    except Exception, exc:
        print >> sys.stderr, exc

    finally:
        db.close()

actions = {
        'create_user':create_user,
        'activate_user':activate_user
    }

def dispatch(props):
    # print >> sys.stderr, repr(props)
    action = props.keys()[0]
    return actions[action](props[action])

if __name__ == "__main__":
    port = int(sys.argv[1])
    magic = sys.argv[2]

    common.chat.start_server(port, magic, False, dispatch)