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

« back to all changes in this revision

Viewing changes to ivle/database.py

  • Committer: Matt Giuca
  • Date: 2010-02-12 02:49:17 UTC
  • Revision ID: matt.giuca@gmail.com-20100212024917-z9g1d5v4utr0u2zm
Fixed policy on who is able to view the list of exercises and create a new one. Rather than being 'if you can edit any offering', it is now the same rule as determining whether you can edit exercises.

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')
 
380
            if (enrolment and enrolment.role in (u'tutor', u'lecturer')) \
 
381
               or user.admin:
 
382
                perms.add('edit')
392
383
            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
397
384
                perms.add('enrol')          # Can see enrolment screen at all
398
385
                perms.add('enrol_student')  # Can enrol students
399
386
                perms.add('enrol_tutor')    # Can enrol tutors
426
413
        # XXX: Respect extensions.
427
414
        return self.projects.find(Project.deadline > datetime.datetime.now())
428
415
 
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
416
class Enrolment(Storm):
446
417
    """An enrolment of a user in an offering.
447
418
 
473
444
        return "<%s %r in %r>" % (type(self).__name__, self.user,
474
445
                                  self.offering)
475
446
 
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
447
# PROJECTS #
490
448
 
491
449
class ProjectSet(Storm):
511
469
        return "<%s %d in %r>" % (type(self).__name__, self.id,
512
470
                                  self.offering)
513
471
 
514
 
    def get_permissions(self, user, config):
515
 
        return self.offering.get_permissions(user, config)
 
472
    def get_permissions(self, user):
 
473
        return self.offering.get_permissions(user)
516
474
 
517
475
    def get_groups_for_user(self, user):
518
476
        """List all groups in this offering of which the user is a member."""
608
566
 
609
567
        a = Assessed.get(Store.of(self), principal, self)
610
568
        ps = ProjectSubmission()
611
 
        # Raise SubmissionError if the path is illegal
612
 
        ps.path = ProjectSubmission.test_and_normalise_path(path)
 
569
        ps.path = path
613
570
        ps.revision = revision
614
571
        ps.date_submitted = datetime.datetime.now()
615
572
        ps.assessed = a
617
574
 
618
575
        return ps
619
576
 
620
 
    def get_permissions(self, user, config):
621
 
        return self.project_set.offering.get_permissions(user, config)
 
577
    def get_permissions(self, user):
 
578
        return self.project_set.offering.get_permissions(user)
622
579
 
623
580
    @property
624
581
    def latest_submissions(self):
702
659
            (not active_only) or (Semester.state == u'current'))
703
660
 
704
661
 
705
 
    def get_permissions(self, user, config):
 
662
    def get_permissions(self, user):
706
663
        if user.admin or user in self.members:
707
664
            return set(['submit_project'])
708
665
        else:
815
772
    approver = Reference(approver_id, User.id)
816
773
    notes = Unicode()
817
774
 
818
 
class SubmissionError(Exception):
819
 
    """Denotes a validation error during submission."""
820
 
    pass
821
 
 
822
775
class ProjectSubmission(Storm):
823
776
    """A submission from a user or group repository to a particular project.
824
777
 
854
807
        return "/files/%s/%s/%s?r=%d" % (user.login,
855
808
            self.assessed.checkout_location, submitpath, self.revision)
856
809
 
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
810
# WORKSHEETS AND EXERCISES #
877
811
 
878
812
class Exercise(Storm):
908
842
    def __repr__(self):
909
843
        return "<%s %s>" % (type(self).__name__, self.name)
910
844
 
911
 
    def get_permissions(self, user, config):
912
 
        return self.global_permissions(user, config)
 
845
    def get_permissions(self, user):
 
846
        return self.global_permissions(user)
913
847
 
914
848
    @staticmethod
915
 
    def global_permissions(user, config):
 
849
    def global_permissions(user):
916
850
        """Gets the set of permissions this user has over *all* exercises.
917
851
        This is used to determine who may view the exercises list, and create
918
852
        new exercises."""
925
859
            elif u'lecturer' in set((e.role for e in user.active_enrolments)):
926
860
                perms.add('edit')
927
861
                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
 
862
            elif u'tutor' in set((e.role for e in user.active_enrolments)):
931
863
                perms.add('edit')
932
864
                perms.add('view')
933
865
 
994
926
        store.find(WorksheetExercise,
995
927
            WorksheetExercise.worksheet == self).remove()
996
928
 
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
 
929
    def get_permissions(self, user):
 
930
        return self.offering.get_permissions(user)
1007
931
 
1008
932
    def get_xml(self):
1009
933
        """Returns the xml of this worksheet, converts from rst if required."""
1054
978
        return "<%s %s in %s>" % (type(self).__name__, self.exercise.name,
1055
979
                                  self.worksheet.identifier)
1056
980
 
1057
 
    def get_permissions(self, user, config):
1058
 
        return self.worksheet.get_permissions(user, config)
 
981
    def get_permissions(self, user):
 
982
        return self.worksheet.get_permissions(user)
1059
983
 
1060
984
 
1061
985
class ExerciseSave(Storm):
1108
1032
    complete = Bool()
1109
1033
    active = Bool()
1110
1034
 
1111
 
    def get_permissions(self, user, config):
 
1035
    def get_permissions(self, user):
1112
1036
        return set(['view']) if user is self.user else set()
1113
1037
 
1114
1038
class TestSuite(Storm):