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

« back to all changes in this revision

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

  • Committer: William Grant
  • Date: 2009-01-22 04:47:42 UTC
  • mfrom: (1080.1.93 storm)
  • Revision ID: grantw@unimelb.edu.au-20090122044742-sa8gnww0ma2bm2rv
Merge Storm branch. ivle.db is dead. Watch out for the schema change.

Show diffs side-by-side

added added

removed removed

Lines of Context:
139
139
 
140
140
import os
141
141
import sys
142
 
import time
 
142
import datetime
143
143
 
144
144
import cjson
145
145
import pg
146
146
 
147
 
import ivle.db
148
 
import ivle.makeuser
 
147
import ivle.database
149
148
from ivle import (util, chat, caps)
150
149
from ivle.conf import (usrmgt_host, usrmgt_port, usrmgt_magic)
151
 
 
152
 
from ivle.auth import authenticate
153
 
from ivle.auth.autherror import AuthError
 
150
import ivle.pulldown_subj
 
151
 
 
152
from ivle.rpc.decorators import require_method, require_cap
 
153
 
 
154
from ivle.auth import AuthError, authenticate
154
155
import urllib
155
156
 
156
157
# The user must send this declaration message to ensure they acknowledge the
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:
176
185
        "%s is not a valid userservice action." % repr(req.path))
177
186
    func(req, fields)
178
187
 
 
188
@require_method('POST')
179
189
def handle_activate_me(req, fields):
180
190
    """Create the jail, svn, etc, for the currently logged in user (this is
181
191
    put in the queue for usermgt to do).
194
204
    "accepting" the terms - at least this way requires them to acknowledge
195
205
    their acceptance). It must only be called through a POST request.
196
206
    """
197
 
    db = ivle.db.DB()
198
207
    try:
199
 
        if req.method != "POST":
200
 
            req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
201
 
            "Only POST requests are valid methods to activate_me.")
202
208
        try:
203
209
            declaration = fields.getfirst('declaration')
204
210
        except AttributeError:
211
217
        # Make sure the user's status is "no_agreement", and set status to
212
218
        # pending, within the one transaction. This ensures we only do this
213
219
        # one time.
214
 
        db.start_transaction()
215
220
        try:
216
 
 
217
 
            user_details = db.get_user(req.user.login)
218
221
            # Check that the user's status is "no_agreement".
219
222
            # (Both to avoid redundant calls, and to stop disabled users from
220
223
            # re-enabling their accounts).
221
 
            if user_details.state != "no_agreement":
 
224
            if req.user.state != "no_agreement":
222
225
                req.throw_error(req.HTTP_BAD_REQUEST,
223
226
                "You have already agreed to the terms.")
224
227
            # Write state "pending" to ensure we don't try this again
225
 
            db.update_user(req.user.login, state="pending")
 
228
            req.user.state = u"pending"
226
229
        except:
227
 
            db.rollback()
 
230
            req.store.rollback()
228
231
            raise
229
 
        db.commit()
 
232
        req.store.commit()
230
233
 
231
234
        # Get the arguments for usermgt.activate_user from the session
232
235
        # (The user must have already logged in to use this app)
235
238
        }
236
239
        msg = {'activate_user': args}
237
240
 
 
241
        # Release our lock on the db so usrmgt can write
 
242
        req.store.rollback()
 
243
 
238
244
        # Try and contact the usrmgt server
239
245
        try:
240
246
            response = chat.chat(usrmgt_host, usrmgt_port, msg, usrmgt_magic)
249
255
            status = 'failure'
250
256
        
251
257
        if status == 'okay':
252
 
            req.user.state = "enabled"
 
258
            req.user.state = u"enabled"
253
259
        else:
254
260
            # 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()
 
261
            req.user.state = u"no_agreement"
 
262
            req.store.commit()
263
263
 
264
264
        # Write the response
265
265
        req.content_type = "text/plain"
266
266
        req.write(cjson.encode(response))
267
 
    finally:
268
 
        db.close()
 
267
    except:
 
268
        req.store.rollback()
 
269
        raise
269
270
 
270
271
create_user_fields_required = [
271
272
    'login', 'fullname', 'rolenm'
273
274
create_user_fields_optional = [
274
275
    'password', 'nick', 'email', 'studentid'
275
276
]
 
277
 
 
278
@require_method('POST')
 
279
@require_cap(caps.CAP_UPDATEUSER)
276
280
def handle_create_user(req, fields):
277
281
    """Create a new user, whose state is no_agreement.
278
282
    This does not create the user's jail, just an entry in the database which
299
303
                      STRING OPTIONAL
300
304
       Return Value: the uid associated with the user. INT
301
305
    """
302
 
    if req.method != "POST":
303
 
        req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
304
 
            "Only POST requests are valid methods to create_user.")
305
 
    # Check if this user has CAP_UPDATEUSER
306
 
    if not req.user.hasCap(caps.CAP_UPDATEUSER):
307
 
        req.throw_error(req.HTTP_FORBIDDEN,
308
 
        "You do not have permission to create users.")
309
 
 
310
306
    # Make a dict of fields to create
311
307
    create = {}
312
308
    for f in create_user_fields_required:
323
319
        else:
324
320
            pass
325
321
 
326
 
    ivle.makeuser.make_user_db(**create)
327
 
    user = ivle.db.DB().get_user(create["login"])
 
322
    user = ivle.database.User(**create)
 
323
    req.store.add(user)
 
324
    ivle.pulldown_subj.enrol_user(req.store, user)
 
325
    req.store.commit()
 
326
 
328
327
    req.content_type = "text/plain"
329
328
    req.write(str(user.unixid))
330
329
 
335
334
    'password', 'nick', 'email', 'rolenm', 'unixid', 'fullname',
336
335
    'studentid'
337
336
]
 
337
 
 
338
@require_method('POST')
338
339
def handle_update_user(req, fields):
339
340
    """Update a user's account details.
340
341
    This can be done in a limited form by any user, on their own account,
341
342
    or with full powers by a user with CAP_UPDATEUSER on any account.
342
343
    """
343
 
    if req.method != "POST":
344
 
        req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
345
 
        "Only POST requests are valid methods to update_user.")
346
 
 
347
344
    # Only give full powers if this user has CAP_UPDATEUSER
348
345
    fullpowers = req.user.hasCap(caps.CAP_UPDATEUSER)
349
346
    # List of fields that may be changed
362
359
        # If login not specified, update yourself
363
360
        login = req.user.login
364
361
 
 
362
    user = ivle.database.User.get_by_login(req.store, login)
 
363
 
365
364
    # Make a dict of fields to update
366
 
    update = {}
367
365
    oldpassword = fields.getfirst('oldpass')
368
 
    
369
366
    for f in fieldlist:
370
367
        val = fields.getfirst(f)
371
368
        if val is not None:
372
 
            update[f] = val
 
369
            # Note: May be rolled back if auth check below fails
 
370
            setattr(user, f, val.value.decode('utf-8'))
373
371
        else:
374
372
            pass
375
373
 
376
 
    if 'password' in update:
 
374
    # If the user is trying to set a new password, check that they have
 
375
    # entered old password and it authenticates.
 
376
    if fields.getfirst('password') is not None:
377
377
        try:
378
378
            authenticate.authenticate(login, oldpassword)
379
379
        except AuthError:
380
380
            req.headers_out['X-IVLE-Action-Error'] = \
381
381
                urllib.quote("Old password incorrect.")
382
382
            req.status = req.HTTP_BAD_REQUEST
 
383
            # Cancel all the changes made to user (including setting new pass)
 
384
            req.store.rollback()
383
385
            return
384
386
 
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()
 
387
    req.store.commit()
401
388
 
402
389
    req.content_type = "text/plain"
403
390
    req.write('')
424
411
        login = req.user.login
425
412
 
426
413
    # 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
 
414
    user = ivle.database.User.get_by_login(req.store, login)
 
415
    user = ivle.util.object_to_dict(user_fields_list, user)
438
416
    # 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
 
417
    for k in 'pass_exp', 'acct_exp', 'last_login':
 
418
        if user[k] is not None:
 
419
            user[k] = unicode(user[k])
 
420
 
454
421
    response = cjson.encode(user)
455
422
    req.content_type = "text/plain"
456
423
    req.write(response)
466
433
    ##fullpowers = req.user.hasCap(caps.CAP_GETUSER)
467
434
 
468
435
    try:
469
 
        login = fields.getfirst('login')
470
 
        if login is None:
 
436
        user = ivle.database.User.get_by_login(req.store,
 
437
                    fields.getfirst('login'))
 
438
        if user is None:
471
439
            raise AttributeError()
472
 
        if not fullpowers and login != req.user.login:
 
440
        if not fullpowers and user != req.user:
473
441
            # Not allowed to edit other users
474
442
            req.throw_error(req.HTTP_FORBIDDEN,
475
443
            "You do not have permission to see another user's subjects.")
476
444
    except AttributeError:
477
445
        # If login not specified, update yourself
478
 
        login = req.user.login
 
446
        user = req.user
479
447
 
480
 
    # Just talk direct to the DB
481
 
    db = ivle.db.DB()
482
 
    enrolments = db.get_enrolment(login)
483
 
    for e in enrolments:
484
 
        e['groups'] = db.get_enrolment_groups(login, e['offeringid'])
485
 
    db.close()
486
 
    response = cjson.encode(enrolments)
 
448
    dict_enrolments = []
 
449
    for e in user.active_enrolments:
 
450
        dict_enrolments.append({
 
451
            'offeringid':      e.offering.id,
 
452
            'subj_code':       e.offering.subject.code,
 
453
            'subj_name':       e.offering.subject.name,
 
454
            'subj_short_name': e.offering.subject.short_name,
 
455
            'url':             e.offering.subject.url,
 
456
            'year':            e.offering.semester.year,
 
457
            'semester':        e.offering.semester.semester,
 
458
            'groups':          [{'name': group.name,
 
459
                                 'nick': group.nick} for group in e.groups]
 
460
        })
 
461
    response = cjson.encode(dict_enrolments)
487
462
    req.content_type = "text/plain"
488
463
    req.write(response)
489
464
 
503
478
    except:
504
479
        req.throw_error(req.HTTP_BAD_REQUEST,
505
480
            "subjectid must be a integer")
506
 
    
507
 
    db = ivle.db.DB()
508
 
    try:
509
 
        offerings = db.get_offering_semesters(subjectid)
510
 
    finally:
511
 
        db.close()
512
 
 
513
 
    response = cjson.encode([o for o in offerings if o['active']])
 
481
 
 
482
    subject = req.store.get(ivle.database.Subject, subjectid)
 
483
 
 
484
    response = cjson.encode([{'offeringid': offering.id,
 
485
                              'subj_name': offering.subject.name,
 
486
                              'year': offering.semester.year,
 
487
                              'semester': offering.semester.semester,
 
488
                              'active': offering.semester.active
 
489
                             } for offering in subject.offerings
 
490
                                    if offering.semester.active])
514
491
    req.content_type = "text/plain"
515
492
    req.write(response)
516
493
 
530
507
    except:
531
508
        req.throw_error(req.HTTP_BAD_REQUEST,
532
509
            "offeringid must be a integer")
533
 
    
534
 
    db = ivle.db.DB()
535
 
    try:
536
 
        projectsets = db.get_projectsets_by_offering(offeringid)
537
 
        for p in projectsets:
538
 
            p['groups'] = db.get_groups_by_projectset(p['projectsetid'])
539
 
    except Exception, e:
540
 
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR, repr(e))
541
 
    finally:
542
 
        db.close()
543
 
 
544
 
    response = cjson.encode(projectsets)
545
 
    req.write(response)
546
 
 
547
 
def handle_create_project_set(req, fields):
548
 
    """Required cap: CAP_MANAGEPROJECTS
549
 
    Creates a project set for a offering - returns the projectsetid
550
 
    Required:
551
 
        offeringid, max_students_per_group
552
 
    """
553
 
    
554
 
    if req.method != "POST":
555
 
        req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
556
 
            "Only POST requests are valid methods to create_user.")
557
 
    # Check if this user has CAP_MANAGEPROJECTS
558
 
    if not req.user.hasCap(caps.CAP_MANAGEPROJECTS):
559
 
        req.throw_error(req.HTTP_FORBIDDEN,
560
 
        "You do not have permission to manage projects.")
561
 
    # Get required fields
562
 
    offeringid = fields.getfirst('offeringid')
563
 
    max_students_per_group = fields.getfirst('max_students_per_group')
564
 
    if offeringid is None or max_students_per_group is None:
565
 
        req.throw_error(req.HTTP_BAD_REQUEST,
566
 
            "Required: offeringid, max_students_per_group")
567
 
 
568
 
    # Talk to the DB
569
 
    db = ivle.db.DB()
570
 
    dbquery = db.return_insert(
571
 
        {
572
 
            'offeringid': offeringid,
573
 
            'max_students_per_group': max_students_per_group,
574
 
        },
575
 
        "project_set",
576
 
        frozenset(["offeringid", "max_students_per_group"]),
577
 
        ["projectsetid"],
578
 
    )
579
 
    db.close()
580
 
    
581
 
    response = cjson.encode(dbquery.dictresult()[0])
582
 
 
583
 
    req.content_type = "text/plain"
584
 
    req.write(response)
585
 
 
586
 
def handle_create_project(req, fields):
587
 
    """Required cap: CAP_MANAGEPROJECTS
588
 
    Creates a project in a specific project set
589
 
    Required:
590
 
        projectsetid
591
 
    Optional:
592
 
        synopsis, url, deadline
593
 
    Returns:
594
 
        projectid
595
 
    """
596
 
    
597
 
    if req.method != "POST":
598
 
        req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
599
 
            "Only POST requests are valid methods to create_user.")
600
 
    # Check if this user has CAP_MANAGEPROJECTS
601
 
    if not req.user.hasCap(caps.CAP_MANAGEPROJECTS):
602
 
        req.throw_error(req.HTTP_FORBIDDEN,
603
 
        "You do not have permission to manage projects.")
604
 
    # Get required fields
605
 
    projectsetid = fields.getfirst('projectsetid')
606
 
    if projectsetid is None:
607
 
        req.throw_error(req.HTTP_BAD_REQUEST,
608
 
            "Required: projectsetid")
609
 
    # Get optional fields
610
 
    synopsis = fields.getfirst('synopsis')
611
 
    url = fields.getfirst('url')
612
 
    deadline = fields.getfirst('deadline')
613
 
    if deadline is not None:
614
 
        try:
615
 
            deadline = util.parse_iso8601(deadline).timetuple()
616
 
        except ValueError, e:
617
 
            req.throw_error(req.HTTP_BAD_REQUEST, e.message)
618
 
 
619
 
    # Talk to the DB
620
 
    db = ivle.db.DB()
621
 
    try:
622
 
        dbquery = db.return_insert(
623
 
            {
624
 
                'projectsetid': projectsetid,
625
 
                'synopsis': synopsis,
626
 
                'url': url,
627
 
                'deadline': deadline,
628
 
            },
629
 
            "project", # table
630
 
            frozenset(["projectsetid", "synopsis", "url", "deadline"]),
631
 
            ["projectid"], # returns
632
 
        )
633
 
    except Exception, e:
634
 
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR, repr(e))
635
 
    finally:
636
 
        db.close()
637
 
    
638
 
    response = cjson.encode(dbquery.dictresult()[0])
639
 
 
640
 
    req.content_type = "text/plain"
641
 
    req.write(response)
642
 
 
 
510
 
 
511
    offering = req.store.get(ivle.database.Offering, offeringid)
 
512
 
 
513
    dict_projectsets = []
 
514
    try:
 
515
        for p in offering.project_sets:
 
516
            dict_projectsets.append({
 
517
                'projectsetid': p.id,
 
518
                'max_students_per_group': p.max_students_per_group,
 
519
                'groups': [{'groupid': g.id,
 
520
                            'groupnm': g.name,
 
521
                            'nick': g.nick} for g in p.project_groups]
 
522
            })
 
523
    except Exception, e:
 
524
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR, repr(e))
 
525
 
 
526
    response = cjson.encode(dict_projectsets)
 
527
    req.write(response)
 
528
 
 
529
@require_method('POST')
 
530
@require_cap(caps.CAP_MANAGEGROUPS)
643
531
def handle_create_group(req, fields):
644
532
    """Required cap: CAP_MANAGEGROUPS
645
533
    Creates a project group in a specific project set
650
538
    Returns:
651
539
        groupid
652
540
    """
653
 
    if req.method != "POST":
654
 
        req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
655
 
            "Only POST requests are valid methods to create_user.")
656
 
    # Check if this is allowed to manage groups
657
 
    if not req.user.hasCap(caps.CAP_MANAGEGROUPS):
658
 
        req.throw_error(req.HTTP_FORBIDDEN,
659
 
        "You do not have permission to manage groups.")
660
541
    # Get required fields
661
 
    projectsetid = fields.getfirst('projectsetid')
662
 
    groupnm = fields.getfirst('groupnm')
 
542
    projectsetid = fields.getfirst('projectsetid').value
 
543
    groupnm = fields.getfirst('groupnm').value
663
544
    if projectsetid is None or groupnm is None:
664
545
        req.throw_error(req.HTTP_BAD_REQUEST,
665
546
            "Required: projectsetid, groupnm")
 
547
    groupnm = unicode(groupnm)
666
548
    try:
667
549
        projectsetid = int(projectsetid)
668
550
    except:
669
551
        req.throw_error(req.HTTP_BAD_REQUEST,
670
552
            "projectsetid must be an int")
671
553
    # Get optional fields
672
 
    nick = fields.getfirst('nick')
673
 
 
674
 
    # Talk to the DB
675
 
    db = ivle.db.DB()
676
 
    # Other fields
677
 
    createdby = db.get_user_loginid(req.user.login)
678
 
    epoch = time.localtime()
 
554
    nick = fields.getfirst('nick').value
 
555
    if nick is not None:
 
556
        nick = unicode(nick)
679
557
 
680
558
    # Begin transaction since things can go wrong
681
 
    db.start_transaction()
682
559
    try:
683
 
        dbquery = db.return_insert(
684
 
            {
685
 
                'groupnm': groupnm,
686
 
                'projectsetid': projectsetid,
687
 
                'nick': nick,
688
 
                'createdby': createdby,
689
 
                'epoch': epoch,
690
 
            },
691
 
            "project_group", # table
692
 
            frozenset(["groupnm", "projectsetid", "nick", "createdby",
693
 
                "epoch"]), # fields
694
 
            ["groupid"], # returns
695
 
        )
696
 
 
697
 
        singlerow = dbquery.dictresult()[0]
698
 
        groupid = singlerow['groupid']
 
560
        group = ivle.database.ProjectGroup(name=groupnm,
 
561
                                           project_set_id=projectsetid,
 
562
                                           nick=nick,
 
563
                                           created_by=req.user,
 
564
                                           epoch=datetime.datetime.now())
 
565
        req.store.add(group)
699
566
 
700
 
        # Create the groups repository
701
 
        # Get the arguments for usermgt.activate_user from the session
702
 
        # (The user must have already logged in to use this app)
703
 
    
704
 
        # Find the rest of the parameters we need
705
 
        offeringinfo = db.get_offering_info(projectsetid)
706
 
                
707
 
        subj_short_name = offeringinfo['subj_short_name']
708
 
        year = offeringinfo['year']
709
 
        semester = offeringinfo['semester']
 
567
        # Create the group repository
 
568
        # Yes, this is ugly, and it would be nice to just pass in the groupid,
 
569
        # but the object isn't visible to the extra transaction in
 
570
        # usrmgt-server until we commit, which we only do once the repo is
 
571
        # created.
 
572
        offering = group.project_set.offering
710
573
 
711
574
        args = {
712
 
            "subj_short_name": subj_short_name,
713
 
            "year": year,
714
 
            "semester": semester,
715
 
            "groupnm": groupnm,
 
575
            "subj_short_name": offering.subject.short_name,
 
576
            "year": offering.semester.year,
 
577
            "semester": offering.semester.semester,
 
578
            "groupnm": group.name,
716
579
        }
717
580
        msg = {'create_group_repository': args}
718
581
 
728
591
                "Failure creating repository: %s"%str(usrmgt))
729
592
    
730
593
        # Everything went OK. Lock it in
731
 
        db.commit()
 
594
        req.store.commit()
732
595
 
733
596
    except Exception, e:
734
 
        db.rollback()
735
597
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR, repr(e))
736
 
    finally:
737
 
        db.close()
738
 
 
739
 
    response = cjson.encode(singlerow)
740
598
 
741
599
    req.content_type = "text/plain"
742
 
    req.write(response)
 
600
    req.write('')
743
601
 
744
602
def handle_get_group_membership(req, fields):
745
603
    """ Required cap: None
759
617
    except:
760
618
        req.throw_error(req.HTTP_BAD_REQUEST,
761
619
            "groupid must be an int")
 
620
    group = req.store.get(ivle.database.ProjectGroup, groupid)
 
621
 
762
622
    try:
763
623
        offeringid = int(offeringid)
764
624
    except:
765
625
        req.throw_error(req.HTTP_BAD_REQUEST,
766
626
            "offeringid must be an int")
767
 
 
768
 
    db = ivle.db.DB()
769
 
    try:
770
 
        offeringmembers = db.get_offering_members(offeringid)
771
 
        groupmembers = db.get_projectgroup_members(groupid)
772
 
    finally:
773
 
        db.close()
774
 
    
 
627
    offering = req.store.get(ivle.database.Offering, offeringid)
 
628
 
 
629
 
 
630
    offeringmembers = [{'login': user.login,
 
631
                        'fullname': user.fullname
 
632
                       } for user in offering.members.order_by(
 
633
                            ivle.database.User.login)
 
634
                      ]
 
635
    groupmembers = [{'login': user.login,
 
636
                        'fullname': user.fullname
 
637
                       } for user in group.members.order_by(
 
638
                            ivle.database.User.login)
 
639
                      ]
 
640
 
775
641
    # Make sure we don't include members in both lists
776
642
    for member in groupmembers:
777
643
        if member in offeringmembers:
783
649
    req.content_type = "text/plain"
784
650
    req.write(response)
785
651
 
 
652
@require_method('POST')
 
653
@require_cap(caps.CAP_MANAGEGROUPS)
786
654
def handle_assign_group(req, fields):
787
655
    """ Required cap: CAP_MANAGEGROUPS
788
656
    Assigns a user to a project group
789
657
    Required:
790
658
        login, groupid
791
659
    """
792
 
    if req.method != "POST":
793
 
        req.throw_error(req.HTTP_METHOD_NOT_ALLOWED,
794
 
            "Only POST requests are valid methods to create_user.")
795
 
    # Check if this user is allowed to manage groups
796
 
    if not req.user.hasCap(caps.CAP_MANAGEGROUPS):
797
 
        req.throw_error(req.HTTP_FORBIDDEN,
798
 
        "You do not have permission to manage groups.")
799
660
    # Get required fields
800
661
    login = fields.getfirst('login')
801
662
    groupid = fields.getfirst('groupid')
802
663
    if login is None or groupid is None:
803
664
        req.throw_error(req.HTTP_BAD_REQUEST,
804
665
            "Required: login, groupid")
805
 
    groupid = int(groupid)
806
 
 
807
 
    # Talk to the DB
808
 
    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
 
 
814
 
    # Add assignment to database
815
 
    # We can't use a transaction here, as usrmgt-server needs to see the
816
 
    # changes!
817
 
    try:
818
 
        dbquery = db.insert(
819
 
            {
820
 
                'loginid': loginid,
821
 
                'groupid': groupid,
822
 
            },
823
 
            "group_member", # table
824
 
            frozenset(["loginid", "groupid"]), # fields
825
 
        )
 
666
 
 
667
    group = req.store.get(ivle.database.ProjectGroup, int(groupid))
 
668
    user = ivle.database.User.get_by_login(req.store, login)
 
669
 
 
670
    # Add membership to database
 
671
    # We can't keep a transaction open until the end here, as usrmgt-server
 
672
    # needs to see the changes!
 
673
    try:
 
674
        group.members.add(user)
 
675
        req.store.commit()
826
676
 
827
677
        # Rebuild the svn config file
828
678
        # Contact the usrmgt server
838
688
                    "Failure creating repository: %s"%str(usrmgt))
839
689
    except Exception, e:
840
690
        req.throw_error(req.HTTP_INTERNAL_SERVER_ERROR, repr(e))
841
 
    finally:
842
 
        db.close()
843
691
 
844
692
    return(cjson.encode({'response': 'okay'}))
845
693
 
854
702
    "get_active_offerings": handle_get_active_offerings,
855
703
    "get_project_groups": handle_get_project_groups,
856
704
    "get_group_membership": handle_get_group_membership,
857
 
    "create_project_set": handle_create_project_set,
858
 
    "create_project": handle_create_project,
859
705
    "create_group": handle_create_group,
860
706
    "assign_group": handle_assign_group,
861
707
}