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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: William Grant
  • Date: 2010-02-11 12:17:37 UTC
  • Revision ID: grantw@unimelb.edu.au-20100211121737-1zsmpp8i8rbyliku
Add a subject listing with new/edit icons.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
 
26
26
import hashlib
27
27
import datetime
28
 
import os
29
28
 
30
29
from storm.locals import create_database, Store, Int, Unicode, DateTime, \
31
30
                         Reference, ReferenceSet, Bool, Storm, Desc
216
215
            Semester.id == Offering.semester_id,
217
216
            (not active_only) or (Semester.state == u'current'),
218
217
            Enrolment.offering_id == Offering.id,
219
 
            Enrolment.user_id == self.id,
220
 
            Enrolment.active == True)
 
218
            Enrolment.user_id == self.id)
221
219
 
222
220
    @staticmethod
223
221
    def hash_password(password):
229
227
        """Find a user in a store by login name."""
230
228
        return store.find(cls, cls.login == unicode(login)).one()
231
229
 
232
 
    def get_permissions(self, user, config):
 
230
    def get_permissions(self, user):
233
231
        """Determine privileges held by a user over this object.
234
232
 
235
233
        If the user requesting privileges is this user or an admin,
259
257
    def __repr__(self):
260
258
        return "<%s '%s'>" % (type(self).__name__, self.short_name)
261
259
 
262
 
    def get_permissions(self, user, config):
 
260
    def get_permissions(self, user):
263
261
        """Determine privileges held by a user over this object.
264
262
 
265
263
        If the user requesting privileges is an admin, they may edit.
373
371
                               Enrolment.offering_id == self.id).one()
374
372
        Store.of(enrolment).remove(enrolment)
375
373
 
376
 
    def get_permissions(self, user, config):
 
374
    def get_permissions(self, user):
377
375
        perms = set()
378
376
        if user is not None:
379
377
            enrolment = self.get_enrolment(user)
380
378
            if enrolment or user.admin:
381
379
                perms.add('view')
382
 
            if enrolment and enrolment.role == u'tutor':
383
 
                perms.add('view_project_submissions')
384
 
                # Site-specific policy on the role of tutors
385
 
                if config['policy']['tutors_can_enrol_students']:
386
 
                    perms.add('enrol')
387
 
                    perms.add('enrol_student')
388
 
                if config['policy']['tutors_can_edit_worksheets']:
389
 
                    perms.add('edit_worksheets')
390
 
                if config['policy']['tutors_can_admin_groups']:
391
 
                    perms.add('admin_groups')
392
 
            if (enrolment and enrolment.role in (u'lecturer')) or user.admin:
393
 
                perms.add('view_project_submissions')
394
 
                perms.add('admin_groups')
395
 
                perms.add('edit_worksheets')
396
 
                perms.add('edit')           # Can edit projects & details
 
380
            if (enrolment and enrolment.role in (u'tutor', u'lecturer')) \
 
381
               or user.admin:
 
382
                perms.add('edit')
 
383
                # XXX Bug #493945 -- should tutors have these permissions?
 
384
                # Potentially move into the next category (lecturer & admin)
397
385
                perms.add('enrol')          # Can see enrolment screen at all
398
386
                perms.add('enrol_student')  # Can enrol students
 
387
            if (enrolment and enrolment.role in (u'lecturer')) or user.admin:
399
388
                perms.add('enrol_tutor')    # Can enrol tutors
400
389
            if user.admin:
401
390
                perms.add('enrol_lecturer') # Can enrol lecturers
426
415
        # XXX: Respect extensions.
427
416
        return self.projects.find(Project.deadline > datetime.datetime.now())
428
417
 
429
 
    def clone_worksheets(self, source):
430
 
        """Clone all worksheets from the specified source to this offering."""
431
 
        import ivle.worksheet.utils
432
 
        for worksheet in source.worksheets:
433
 
            newws = Worksheet()
434
 
            newws.seq_no = worksheet.seq_no
435
 
            newws.identifier = worksheet.identifier
436
 
            newws.name = worksheet.name
437
 
            newws.assessable = worksheet.assessable
438
 
            newws.data = worksheet.data
439
 
            newws.format = worksheet.format
440
 
            newws.offering = self
441
 
            Store.of(self).add(newws)
442
 
            ivle.worksheet.utils.update_exerciselist(newws)
443
 
 
444
 
 
445
418
class Enrolment(Storm):
446
419
    """An enrolment of a user in an offering.
447
420
 
473
446
        return "<%s %r in %r>" % (type(self).__name__, self.user,
474
447
                                  self.offering)
475
448
 
476
 
    def get_permissions(self, user, config):
477
 
        # A user can edit any enrolment that they could have created.
478
 
        perms = set()
479
 
        if ('enrol_' + str(self.role)) in self.offering.get_permissions(
480
 
            user, config):
481
 
            perms.add('edit')
482
 
        return perms
483
 
 
484
 
    def delete(self):
485
 
        """Delete this enrolment."""
486
 
        Store.of(self).remove(self)
487
 
 
488
 
 
489
449
# PROJECTS #
490
450
 
491
451
class ProjectSet(Storm):
511
471
        return "<%s %d in %r>" % (type(self).__name__, self.id,
512
472
                                  self.offering)
513
473
 
514
 
    def get_permissions(self, user, config):
515
 
        return self.offering.get_permissions(user, config)
 
474
    def get_permissions(self, user):
 
475
        return self.offering.get_permissions(user)
516
476
 
517
477
    def get_groups_for_user(self, user):
518
478
        """List all groups in this offering of which the user is a member."""
608
568
 
609
569
        a = Assessed.get(Store.of(self), principal, self)
610
570
        ps = ProjectSubmission()
611
 
        # Raise SubmissionError if the path is illegal
612
 
        ps.path = ProjectSubmission.test_and_normalise_path(path)
 
571
        ps.path = path
613
572
        ps.revision = revision
614
573
        ps.date_submitted = datetime.datetime.now()
615
574
        ps.assessed = a
617
576
 
618
577
        return ps
619
578
 
620
 
    def get_permissions(self, user, config):
621
 
        return self.project_set.offering.get_permissions(user, config)
 
579
    def get_permissions(self, user):
 
580
        return self.project_set.offering.get_permissions(user)
622
581
 
623
582
    @property
624
583
    def latest_submissions(self):
702
661
            (not active_only) or (Semester.state == u'current'))
703
662
 
704
663
 
705
 
    def get_permissions(self, user, config):
 
664
    def get_permissions(self, user):
706
665
        if user.admin or user in self.members:
707
666
            return set(['submit_project'])
708
667
        else:
815
774
    approver = Reference(approver_id, User.id)
816
775
    notes = Unicode()
817
776
 
818
 
class SubmissionError(Exception):
819
 
    """Denotes a validation error during submission."""
820
 
    pass
821
 
 
822
777
class ProjectSubmission(Storm):
823
778
    """A submission from a user or group repository to a particular project.
824
779
 
854
809
        return "/files/%s/%s/%s?r=%d" % (user.login,
855
810
            self.assessed.checkout_location, submitpath, self.revision)
856
811
 
857
 
    @staticmethod
858
 
    def test_and_normalise_path(path):
859
 
        """Test that path is valid, and normalise it. This prevents possible
860
 
        injections using malicious paths.
861
 
        Returns the updated path, if successful.
862
 
        Raises SubmissionError if invalid.
863
 
        """
864
 
        # Ensure the path is absolute to prevent being tacked onto working
865
 
        # directories.
866
 
        # Prevent '\n' because it will break all sorts of things.
867
 
        # Prevent '[' and ']' because they can be used to inject into the
868
 
        # svn.conf.
869
 
        # Normalise to avoid resulting in ".." path segments.
870
 
        if not os.path.isabs(path):
871
 
            raise SubmissionError("Path is not absolute")
872
 
        if any(c in path for c in "\n[]"):
873
 
            raise SubmissionError("Path must not contain '\\n', '[' or ']'")
874
 
        return os.path.normpath(path)
875
 
 
876
812
# WORKSHEETS AND EXERCISES #
877
813
 
878
814
class Exercise(Storm):
908
844
    def __repr__(self):
909
845
        return "<%s %s>" % (type(self).__name__, self.name)
910
846
 
911
 
    def get_permissions(self, user, config):
912
 
        return self.global_permissions(user, config)
913
 
 
914
 
    @staticmethod
915
 
    def global_permissions(user, config):
916
 
        """Gets the set of permissions this user has over *all* exercises.
917
 
        This is used to determine who may view the exercises list, and create
918
 
        new exercises."""
 
847
    def get_permissions(self, user):
919
848
        perms = set()
920
849
        roles = set()
921
850
        if user is not None:
925
854
            elif u'lecturer' in set((e.role for e in user.active_enrolments)):
926
855
                perms.add('edit')
927
856
                perms.add('view')
928
 
            elif (config['policy']['tutors_can_edit_worksheets']
929
 
            and u'tutor' in set((e.role for e in user.active_enrolments))):
930
 
                # Site-specific policy on the role of tutors
 
857
            elif u'tutor' in set((e.role for e in user.active_enrolments)):
931
858
                perms.add('edit')
932
859
                perms.add('view')
933
860
 
994
921
        store.find(WorksheetExercise,
995
922
            WorksheetExercise.worksheet == self).remove()
996
923
 
997
 
    def get_permissions(self, user, config):
998
 
        # Almost the same permissions as for the offering itself
999
 
        perms = self.offering.get_permissions(user, config)
1000
 
        # However, "edit" permission is derived from the "edit_worksheets"
1001
 
        # permission of the offering
1002
 
        if 'edit_worksheets' in perms:
1003
 
            perms.add('edit')
1004
 
        else:
1005
 
            perms.discard('edit')
1006
 
        return perms
 
924
    def get_permissions(self, user):
 
925
        return self.offering.get_permissions(user)
1007
926
 
1008
927
    def get_xml(self):
1009
928
        """Returns the xml of this worksheet, converts from rst if required."""
1054
973
        return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
1055
974
                                  self.worksheet.identifier)
1056
975
 
1057
 
    def get_permissions(self, user, config):
1058
 
        return self.worksheet.get_permissions(user, config)
 
976
    def get_permissions(self, user):
 
977
        return self.worksheet.get_permissions(user)
1059
978
 
1060
979
 
1061
980
class ExerciseSave(Storm):
1108
1027
    complete = Bool()
1109
1028
    active = Bool()
1110
1029
 
1111
 
    def get_permissions(self, user, config):
 
1030
    def get_permissions(self, user):
1112
1031
        return set(['view']) if user is self.user else set()
1113
1032
 
1114
1033
class TestSuite(Storm):