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

« back to all changes in this revision

Viewing changes to scripts/usrmgt-server

  • Committer: drtomc
  • Date: 2008-02-13 01:22:48 UTC
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:trunk:442
util.js: Small fix for make_query_string.

console: get the uid from the session object, rather than looking in /etc/passwd.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#!/usr/bin/python
2
2
 
3
 
import os
4
 
import pysvn
5
 
import subprocess
6
3
import sys
7
 
import urllib
8
 
from functools import partial
9
 
import traceback
10
 
import logging
11
 
import errno
12
4
 
13
 
import conf
14
 
import common.db
15
5
import common.chat
16
6
import common.makeuser
17
 
import common.studpath
18
7
 
19
8
# usage:
20
9
#   usrmgt-server <port> <magic>
21
10
 
22
 
# User management operations:
23
 
#   - Create local user
24
 
#   - [Re]Create jail for a user
25
 
#       - Create a svn repository for a user
26
 
#           - create repository
27
 
#           - svn config
28
 
#           - svn auth
29
 
#       - Checkout repository as home directory
30
 
#       - /etc/passwd entry
31
 
#   - Disable a user's account
32
 
#   - Enable a user's account
33
 
#   - Remove a user
34
 
#   - Rebuild svn config
35
 
#   - Rebuild svn auth file
36
 
#   - Rebuild passwd + push to nodes.
37
 
 
38
11
def create_user(props):
39
 
    """Create the database record for the given user.
40
 
       Expected properties:
41
 
        login       - used as a unix login name and svn repository name.
42
 
                      STRING REQUIRED 
43
 
        unixid      - the unix uid under which execution will take place
44
 
                      on the behalf of the user. Don't use 0! If not specified
45
 
                      or None, one will be allocated from the configured
46
 
                      numeric range.
47
 
                      INT OPTIONAL
48
 
        password    - the clear-text password for the user. If this property is
49
 
                      absent or None, this is an indication that external
50
 
                      authentication should be used (i.e. LDAP).
51
 
                      STRING OPTIONAL
52
 
        email       - the user's email address.
53
 
                      STRING OPTIONAL
54
 
        nick        - the display name to use.
55
 
                      STRING REQUIRED
56
 
        fullname    - The name of the user for results and/or other official
57
 
                      purposes.
58
 
                      STRING REQUIRED
59
 
        rolenm      - The user's role. Must be one of "anyone", "student",
60
 
                      "tutor", "lecturer", "admin".
61
 
                      STRING/ENUM REQUIRED
62
 
        studentid   - If supplied and not None, the student id of the user for
63
 
                      results and/or other official purposes.
64
 
                      STRING OPTIONAL
65
 
       Return Value: the uid associated with the user. INT
66
 
    """
67
 
 
68
 
    if 'unixid' not in props or props['unixid'] is None:
69
 
        # For the time being, just choose a random unixid.
70
 
        # This may result in duplicates, but the unixid is essentially
71
 
        # a monitoring/logging convenience only. Oh, and dups could kill
72
 
        # each other. <sigh>
73
 
        props['unixid'] = random.randrange(5000,10000)
74
 
        # raise NotImplementedError, "No algorithm for creating uids yet!"
75
 
        # unixid = invent-uid
76
 
        # props['unixid'] = unixid
77
 
 
78
 
    common.makeuser.make_user_db(**props)
79
 
 
80
 
    return int(props['unixid'])
81
 
 
82
 
def update_user(props):
83
 
    """Create the database record for the given user.
84
 
       Expected properties:
85
 
        login       - user who is making the change (not necessarily the one
86
 
                      being updated).
87
 
        update      - dict of fields to be updated. The fields are all those
88
 
                      in the login table of the db.
89
 
                      'login' required.
90
 
                      Omitted fields will not be set.
91
 
    """
92
 
    update = props['update']
93
 
    # Note: "login" is special - it is not part of the kwargs to
94
 
    # db.update_user, but the first arg - used to find the user to update.
95
 
    # However it doesn't need any special treatment here.
96
 
 
97
 
    db = common.db.DB()
98
 
    db.update_user(**update)
99
 
    db.close()
100
 
 
101
 
def get_login(login, passwd, _realm, _login, _may_save):
102
 
    """Callback function used by pysvn for authentication.
103
 
    """
104
 
    logging.debug("Getting password for %s (realm %s)" % (login, _realm))
105
 
    return (True, login, passwd, False)
106
 
 
107
 
def activate_user(props):
108
 
    """Create the on-disk stuff for the given user.
109
 
       Sets the state of the user in the db from pending to enabled.
110
 
       Expected properties:
111
 
        login       - the user name for the jail
112
 
                      STRING REQUIRED
113
 
       Return Value: None
114
 
    """
115
 
 
116
 
    login = props['login']
117
 
 
118
 
    db = common.db.DB()
119
 
 
120
 
    try:
121
 
 
122
 
        # FIXME: check we're pending
123
 
 
124
 
        details = db.get_user(login)
125
 
 
126
 
        # make svn config/auth
127
 
 
128
 
        logging.debug("Creating repo")
129
 
        common.makeuser.make_svn_repo(login, throw_on_error=False)
130
 
        logging.debug("Creating svn config")
131
 
        common.makeuser.make_svn_config(login, throw_on_error=False)
132
 
        logging.debug("Creating svn auth")
133
 
        passwd = common.makeuser.make_svn_auth(login, throw_on_error=False)
134
 
        logging.debug("passwd: %s" % passwd)
135
 
 
136
 
        svn = pysvn.Client()
137
 
        svn.callback_get_login = partial(get_login, login, passwd)
138
 
 
139
 
        if conf.svn_addr[-1] != '/':
140
 
            conf.svn_addr = conf.svn_addr + "/"
141
 
    
142
 
        # FIXME: This should be a loop over enrolements.
143
 
        #        We're not going to fix this now because it requires
144
 
        #        a large amount of admin console work to manage subject
145
 
        #        offerings.
146
 
        #        Instead, we're just going to use a single offering with
147
 
        #        a "short" name of "info1".
148
 
        logging.debug("Creating /info1")
149
 
        try:
150
 
            svn.mkdir(conf.svn_addr + login + "/info1",
151
 
                      "Initial creation of work directory for Informatics 1")
152
 
        except Exception, exc:
153
 
            logging.warning("While mkdiring info1: %s" % str(exc))
154
 
            pass
155
 
        logging.debug("Creating /stuff")
156
 
        try:
157
 
            svn.mkdir(conf.svn_addr + login + "/stuff",
158
 
                      "Initial creation of directory for miscellania")
159
 
        except Exception, exc:
160
 
            logging.warning("While mkdiring stuff: %s" % str(exc))
161
 
            pass
162
 
 
163
 
        logging.debug("Creating jail")
164
 
        common.makeuser.make_jail(login, details.unixid)
165
 
 
166
 
        # FIXME: <hack>
167
 
 
168
 
        tcf_path = os.path.join(conf.jail_base, 'template/opt/ivle/lib/conf/conf.py')
169
 
        cf_path = os.path.join(conf.jail_base, login, 'opt/ivle/lib/conf/conf.py')
170
 
 
171
 
        os.remove(cf_path)
172
 
        cf = open(cf_path, "w")
173
 
        cf.write(open(tcf_path, "r").read())
174
 
        cf.write("# The login name for the owner of the jail\n")
175
 
        cf.write("login = %s\n" % repr(login))
176
 
        cf.write("\n")
177
 
        cf.write("# The subversion-only password for the owner of the jail\n")
178
 
        cf.write("svn_pass = %s\n" % repr(passwd))
179
 
        cf.close()
180
 
 
181
 
        # Check out the repositories into the student's home dir
182
 
        # FIXME: Call do_checkout instead of replicating this code.
183
 
        # (do_checkout currently doesn't work)
184
 
        #do_checkout(props)
185
 
 
186
 
        # FIXME: </hack>
187
 
 
188
 
        logging.debug("Checking out directories in the jail")
189
 
        try:
190
 
            svn.checkout(conf.svn_addr + login + "/stuff",
191
 
                         common.studpath.url_to_local(login + "/stuff")[1])
192
 
            os.system("chown -R %d:%d %s" \
193
 
                    % (details.unixid, details.unixid,
194
 
                       common.studpath.url_to_local(login + "/stuff")[1]))
195
 
        except Exception, exc:
196
 
            logging.warning("While mkdiring stuff: %s" % str(exc))
197
 
            pass
198
 
        try:
199
 
            svn.checkout(conf.svn_addr + login + "/info1",
200
 
                         common.studpath.url_to_local(login + "/info1")[1])
201
 
            os.system("chown -R %d:%d %s" \
202
 
                    % (details.unixid, details.unixid,
203
 
                       common.studpath.url_to_local(login + "/info1")[1]))
204
 
        except Exception, exc:
205
 
            logging.warning("While mkdiring info1: %s" % str(exc))
206
 
            pass
207
 
 
208
 
        # FIXME: should this be nicer?
209
 
        os.system("chown -R %d:%d %s" \
210
 
                % (details.unixid, details.unixid,
211
 
                   common.studpath.url_to_local(login)[1]))
212
 
 
213
 
 
214
 
        logging.info("Enabling user")
215
 
        db.update_user(login, state='enabled')
216
 
 
217
 
        return {"response": "okay"}
218
 
 
219
 
    finally:
220
 
        db.close()
221
 
 
222
 
def do_checkout(props):
223
 
    """Create the default contents of a user's jail by checking out from the
224
 
    repositories.
225
 
    If any directory already exists, just fail silently (so this is not a
226
 
    "wipe-and-checkout", merely a checkout if it failed or something).
227
 
       Expected properties:
228
 
        login       - the user name for the jail
229
 
                      STRING REQUIRED
230
 
       Return Value: None
231
 
    """
232
 
    # XXX / FIXME: This doesn't work - cannot get passwd
233
 
    # (activate_me creates passwd, other svn stuff gets it from jailconf - we
234
 
    # can't access either at this point).
235
 
 
236
 
    login = props['login']
237
 
    svn = pysvn.Client()
238
 
    svn.callback_get_login = partial(get_login, login, passwd)
239
 
 
240
 
    if conf.svn_addr[-1] != '/':
241
 
        conf.svn_addr = conf.svn_addr + "/"
242
 
 
243
 
    # FIXME: </hack>
244
 
 
245
 
    logging.debug("Checking out directories in the jail")
246
 
    try:
247
 
        svn.checkout(conf.svn_addr + login + "/stuff",
248
 
                     common.studpath.url_to_local(login + "/stuff")[1])
249
 
        os.system("chown -R %d:%d %s" \
250
 
                % (details.unixid, details.unixid,
251
 
                   common.studpath.url_to_local(login + "/stuff")[1]))
252
 
    except Exception, exc:
253
 
        logging.warning("While mkdiring stuff: %s" % str(exc))
254
 
        pass
255
 
    try:
256
 
        svn.checkout(conf.svn_addr + login + "/info1",
257
 
                     common.studpath.url_to_local(login + "/info1")[1])
258
 
        os.system("chown -R %d:%d %s" \
259
 
                % (details.unixid, details.unixid,
260
 
                   common.studpath.url_to_local(login + "/info1")[1]))
261
 
    except Exception, exc:
262
 
        logging.warning("While mkdiring info1: %s" % str(exc))
263
 
        pass
264
 
 
265
 
    return {"response": "okay"}
266
 
 
267
 
actions = {
268
 
        'create_user':create_user,
269
 
        'update_user':update_user,
270
 
        'activate_user':activate_user,
271
 
        'do_checkout':do_checkout,
272
 
    }
273
 
 
274
 
def initializer():
275
 
    try:
276
 
        pidfile = open('/var/run/usrmgt-server.pid', 'w')
277
 
        pidfile.write('%d\n' % os.getpid())
278
 
        pidfile.close()
279
 
    except IOError, (errno, strerror):
280
 
        print "Couldn't write PID file. IO error(%s): %s" % (errno, strerror)
281
 
        sys.exit(1)
282
 
 
283
 
def dispatch(props):
284
 
    logging.debug(repr(props))
285
 
    action = props.keys()[0]
286
 
    return actions[action](props[action])
 
12
 
 
13
    if 'uid' not in props:
 
14
        uid = invent-uid
 
15
        props['uid'] = uid
 
16
 
 
17
    common.makeuser.make_user_db(props['username'], props['uid'],
 
18
                                 props['password'], props['nick'],
 
19
                                 props['fullname'], props['rolenm'],
 
20
                                 props['studentid'])
 
21
 
 
22
    common.makeuser.make_jail(props['username'], props['uid'])
 
23
 
 
24
    # eventually, we're going to want to grant shell access, in which
 
25
    # case we'll need to add the uid to the password file. Magic to do
 
26
    # that should go here.
 
27
 
 
28
    return props['uid']
287
29
 
288
30
if __name__ == "__main__":
289
 
    if len(sys.argv) <3:
290
 
        print >>sys.stderr, "Usage: usrmgt-server <port> <magic>"
291
 
        sys.exit(1)
292
31
    port = int(sys.argv[1])
293
32
    magic = sys.argv[2]
294
33
 
295
 
    pid = os.getpid()
296
 
 
297
 
    logging.basicConfig(filename="/var/log/usrmgt.log", level=logging.INFO)
298
 
    logging.info("Starting usrmgt server on port %d (pid = %d)" % (port, pid))
299
 
 
300
 
    common.chat.start_server(port, magic, True, dispatch, initializer)
 
34
    common.chat.start_server(port, magic, False, create_user)