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

« back to all changes in this revision

Viewing changes to www/apps/userservice/__init__.py

  • Committer: matt.giuca
  • Date: 2009-01-14 10:10:12 UTC
  • mto: This revision was merged to the branch mainline in revision 1090.
  • Revision ID: svn-v3-trunk0:2b9c9e99-6f39-0410-b283-7f802c844ae2:branches%2Fstorm:1132
The new ivle.database.User class is now used in Request and usrmgt, which
    means it is now almost universally used in favour of ivle.user.User (now
    deprecated).

Noticeable change: The minor bug where the change to a user object in the
    database is not reflected in the user's session (eg. changing nick doesn't
    update title until log out).

ivle.dispatch:
    Session now contains 'login' (username string) rather than 'user' (full
        ivle.user.User object). This is a unicode string now.

    req.user is now a ivle.database.User object rather than an ivle.user.User
        object. This makes for a whole lot of really subtle differences, but
        largely conforms to the same interface. Note that strings must now all
        be unicode.

    login: Removed use of ivle.db. Now uses User object.

    html: Now handles unicode login and config options.

ivle.db: Removed update_user. Now replaced with Storm model.

ivle.database: Renamed has_cap back to hasCap (saved for later). Fixed small
    unicode bug.

ivle.makeuser.make_svn_auth now takes a store object.

usrmgt-server: Use new User class.

userservice: Now uses User class internally.
    get_user action now returns ISO 8601 date format, rather than a
        time tuple. (Wasn't being used).
    get_user action no longer transmits local_password (small security risk;
        note that it wasn't possible to see this for any user other than
        yourself unless admin).

ivle.util - added function object_to_dict.

Show diffs side-by-side

added added

removed removed

Lines of Context:
145
145
import pg
146
146
 
147
147
import ivle.db
 
148
import ivle.database
148
149
import ivle.makeuser
149
150
from ivle import (util, chat, caps)
150
151
from ivle.conf import (usrmgt_host, usrmgt_port, usrmgt_magic)
157
158
# TOS
158
159
USER_DECLARATION = "I accept the IVLE Terms of Service"
159
160
 
 
161
# List of fields returned as part of the user JSON dictionary
 
162
# (as returned by the get_user action)
 
163
user_fields_list = (
 
164
    "login", "state", "unixid", "email", "nick", "fullname",
 
165
    "rolenm", "studentid", "acct_exp", "pass_exp", "last_login",
 
166
    "svn_pass"
 
167
)
 
168
 
160
169
def handle(req):
161
170
    """Handler for the Console Service AJAX backend application."""
162
171
    if req.user is None:
194
203
    "accepting" the terms - at least this way requires them to acknowledge
195
204
    their acceptance). It must only be called through a POST request.
196
205
    """
197
 
    db = ivle.db.DB()
198
206
    try:
199
207
        if req.method != "POST":
200
208
            req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
211
219
        # Make sure the user's status is "no_agreement", and set status to
212
220
        # pending, within the one transaction. This ensures we only do this
213
221
        # one time.
214
 
        db.start_transaction()
215
222
        try:
216
 
 
217
 
            user_details = db.get_user(req.user.login)
218
223
            # Check that the user's status is "no_agreement".
219
224
            # (Both to avoid redundant calls, and to stop disabled users from
220
225
            # re-enabling their accounts).
221
 
            if user_details.state != "no_agreement":
 
226
            if req.user.state != "no_agreement":
222
227
                req.throw_error(req.HTTP_BAD_REQUEST,
223
228
                "You have already agreed to the terms.")
224
229
            # Write state "pending" to ensure we don't try this again
225
 
            db.update_user(req.user.login, state="pending")
 
230
            req.user.state = u"pending"
226
231
        except:
227
 
            db.rollback()
 
232
            req.store.rollback()
228
233
            raise
229
 
        db.commit()
 
234
        req.store.commit()
230
235
 
231
236
        # Get the arguments for usermgt.activate_user from the session
232
237
        # (The user must have already logged in to use this app)
235
240
        }
236
241
        msg = {'activate_user': args}
237
242
 
 
243
        # Release our lock on the db so usrmgt can write
 
244
        req.store.rollback()
 
245
 
238
246
        # Try and contact the usrmgt server
239
247
        try:
240
248
            response = chat.chat(usrmgt_host, usrmgt_port, msg, usrmgt_magic)
249
257
            status = 'failure'
250
258
        
251
259
        if status == 'okay':
252
 
            req.user.state = "enabled"
 
260
            req.user.state = u"enabled"
253
261
        else:
254
262
            # Reset the user back to no agreement
255
 
            req.user.state = "no_agreement"
256
 
            db.update_user(req.user.login, state="no_agreement")
257
 
 
258
 
 
259
 
        # Update the users state
260
 
        session = req.get_session()
261
 
        session['user'] = req.user
262
 
        session.save()
 
263
            req.user.state = u"no_agreement"
 
264
            req.store.commit()
263
265
 
264
266
        # Write the response
265
267
        req.content_type = "text/plain"
266
268
        req.write(cjson.encode(response))
267
 
    finally:
268
 
        db.close()
 
269
    except:
 
270
        req.store.rollback()
 
271
        raise
269
272
 
270
273
create_user_fields_required = [
271
274
    'login', 'fullname', 'rolenm'
363
366
        login = req.user.login
364
367
 
365
368
    # Make a dict of fields to update
366
 
    update = {}
367
369
    oldpassword = fields.getfirst('oldpass')
368
370
    
369
371
    for f in fieldlist:
370
372
        val = fields.getfirst(f)
371
373
        if val is not None:
372
 
            update[f] = val
 
374
            # Note: May be rolled back if auth check below fails
 
375
            user = ivle.database.User.get_by_login(req.store, login)
 
376
            setattr(user, f, val.value.decode('utf-8'))
373
377
        else:
374
378
            pass
375
379
 
376
 
    if 'password' in update:
 
380
    # If the user is trying to set a new password, check that they have
 
381
    # entered old password and it authenticates.
 
382
    if fields.getfirst('password') is not None:
377
383
        try:
378
384
            authenticate.authenticate(login, oldpassword)
379
385
        except AuthError:
380
386
            req.headers_out['X-IVLE-Action-Error'] = \
381
387
                urllib.quote("Old password incorrect.")
382
388
            req.status = req.HTTP_BAD_REQUEST
 
389
            # Cancel all the changes made to user (including setting new pass)
 
390
            req.store.rollback()
383
391
            return
384
392
 
385
 
    update['login'] = login
386
 
 
387
 
    db = ivle.db.DB()
388
 
    db.update_user(**update)
389
 
 
390
 
    # Re-read the user's details from the DB so we can update their session
391
 
    # XXX potentially-unsafe session write
392
 
    if login == req.user.login:
393
 
        user = db.get_user(login)
394
 
        session = req.get_session()
395
 
        session.lock()
396
 
        session['user'] = user
397
 
        session.save()
398
 
        session.unlock()
399
 
 
400
 
    db.close()
 
393
    req.store.commit()
401
394
 
402
395
    req.content_type = "text/plain"
403
396
    req.write('')
424
417
        login = req.user.login
425
418
 
426
419
    # Just talk direct to the DB
427
 
    db = ivle.db.DB()
428
 
    user = db.get_user(login)
429
 
    db.close()
430
 
    user = dict(user)
431
 
    if 'role' in user:
432
 
        user['rolenm'] = str(user['role'])
433
 
        del user['role']
434
 
    try:
435
 
        del user['svn_pass']
436
 
    except KeyError:
437
 
        pass
 
420
    user = ivle.database.User.get_by_login(req.store, login)
 
421
    user = ivle.util.object_to_dict(user_fields_list, user)
438
422
    # Convert time stamps to nice strings
439
 
    try:
440
 
        if user['pass_exp'] is not None:
441
 
            user['pass_exp'] = str(user['pass_exp'])
442
 
    except KeyError:
443
 
        pass
444
 
    try:
445
 
        if user['acct_exp'] is not None:
446
 
            user['acct_exp'] = str(user['acct_exp'])
447
 
    except KeyError:
448
 
        pass
449
 
    try:
450
 
        if user['last_login'] is not None:
451
 
            user['last_login'] = str(user['last_login'])
452
 
    except KeyError:
453
 
        pass
 
423
    for k in 'pass_exp', 'acct_exp', 'last_login':
 
424
        if user[k] is not None:
 
425
            user[k] = unicode(user[k])
 
426
 
454
427
    response = cjson.encode(user)
455
428
    req.content_type = "text/plain"
456
429
    req.write(response)
674
647
    # Talk to the DB
675
648
    db = ivle.db.DB()
676
649
    # Other fields
677
 
    createdby = db.get_user_loginid(req.user.login)
 
650
    createdby = req.user.id
678
651
    epoch = time.localtime()
679
652
 
680
653
    # Begin transaction since things can go wrong
804
777
            "Required: login, groupid")
805
778
    groupid = int(groupid)
806
779
 
 
780
    loginid = ivle.database.User.get_by_login(req.store, login).id
 
781
 
807
782
    # Talk to the DB
808
783
    db = ivle.db.DB()
809
 
    try:
810
 
        loginid = db.get_user_loginid(login)
811
 
    except ivle.db.DBException, e:
812
 
        req.throw_error(req.HTTP_BAD_REQUEST, repr(e))
813
784
 
814
785
    # Add assignment to database
815
786
    # We can't use a transaction here, as usrmgt-server needs to see the