Changeset 7334


Ignore:
Timestamp:
12 Dec 2011, 14:11:21 (13 years ago)
Author:
Henrik Bettermann
Message:

Implement local CourseAdviser? roles. These roles can be assigned in departments and certificates. There are 6 different roles, one for each study level. getRolesForPrincipal grants the additional waeup.StudentsCourseAdviser? role only if the current level of a student corresponds with the level number in the external role name.

To do: Assign local roles on CertificateManageFormPage?. Add browser tests.

Location:
main/waeup.sirp/trunk/src/waeup/sirp
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.sirp/trunk/src/waeup/sirp/browser/pages.py

    r7333 r7334  
    14071407            yield(dict(url=url, name=key, container=val))
    14081408
    1409 class ShowStudentsPage(SIRPPage):
     1409class ShowStudentsInDepartmentPage(SIRPPage):
    14101410    """Page that lists all students in the department.
    14111411    """
    14121412    grok.context(IDepartment)
    14131413    grok.require('waeup.showStudents')
    1414     grok.name('showstudents')
     1414    grok.name('showdepstudents')
     1415    grok.template('showstudentspage')
    14151416    pnav = 1
    14161417    label = 'Students'
     
    14291430        datatable.need()
    14301431        return
     1432
     1433class ShowStudentsInCertificatePage(ShowStudentsInDepartmentPage):
     1434    """Page that lists all students studying a certificate.
     1435    """
     1436    grok.context(ICertificate)
     1437    grok.require('waeup.showStudents')
     1438    grok.name('showcertstudents')
     1439    pnav = 1
     1440    label = 'Students'
     1441
     1442    @property
     1443    def getStudents(self):
     1444        hitlist = searchstudents(query=self.context.code,
     1445            searchtype='certcode', view=self)
     1446        return hitlist
    14311447
    14321448class DepartmentManageFormPage(SIRPEditFormPage):
  • main/waeup.sirp/trunk/src/waeup/sirp/browser/viewlets.py

    r7333 r7334  
    434434    icon = 'actionicon_student.png'
    435435    text = 'Show students'
    436     target = 'showstudents'
     436    target = 'showdepstudents'
    437437
    438438class ManageCourseActionButton(ManageActionButton):
     
    449449    grok.view(CertificatePage)
    450450    text = 'Manage certificate'
     451
     452class ShowCertificateStudentsActionButton(ManageActionButton):
     453    """ 'Show students' button for certificates.
     454    """
     455    grok.context(ICertificate)
     456    grok.view(CertificatePage)
     457    grok.require('waeup.showStudents')
     458    icon = 'actionicon_student.png'
     459    text = 'Show students'
     460    target = 'showcertstudents'
    451461
    452462class ManageCertificateCourseActionButton(ManageActionButton):
  • main/waeup.sirp/trunk/src/waeup/sirp/permissions.py

    r7321 r7334  
    8282    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
    8383
    84 class CourseAdviser(grok.Role):
    85     """The course adviser role is meant for the
    86     assignment of dynamic roles only.
    87     """
    88     grok.name('waeup.local.CourseAdviser')
    89     grok.title(u'Course Adviser')
    90     grok.permissions('waeup.showStudents')
     84class CourseAdviser100(grok.Role):
     85    """The course adviser role is meant for the
     86    assignment of dynamic roles only.
     87    """
     88    grok.name('waeup.local.CourseAdviser100')
     89    grok.title(u'Course Adviser 100L')
     90    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
     91
     92class CourseAdviser200(grok.Role):
     93    """The course adviser role is meant for the
     94    assignment of dynamic roles only.
     95    """
     96    grok.name('waeup.local.CourseAdviser200')
     97    grok.title(u'Course Adviser 200L')
     98    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
     99
     100class CourseAdviser300(grok.Role):
     101    """The course adviser role is meant for the
     102    assignment of dynamic roles only.
     103    """
     104    grok.name('waeup.local.CourseAdviser300')
     105    grok.title(u'Course Adviser 300L')
     106    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
     107
     108class CourseAdviser400(grok.Role):
     109    """The course adviser role is meant for the
     110    assignment of dynamic roles only.
     111    """
     112    grok.name('waeup.local.CourseAdviser400')
     113    grok.title(u'Course Adviser 400L')
     114    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
     115
     116class CourseAdviser500(grok.Role):
     117    """The course adviser role is meant for the
     118    assignment of dynamic roles only.
     119    """
     120    grok.name('waeup.local.CourseAdviser500')
     121    grok.title(u'Course Adviser 500L')
     122    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
     123
     124class CourseAdviser600(grok.Role):
     125    """The course adviser role is meant for the
     126    assignment of dynamic roles only.
     127    """
     128    grok.name('waeup.local.CourseAdviser600')
     129    grok.title(u'Course Adviser 600L')
     130    grok.permissions('waeup.showStudents', 'waeup.viewAcademics')
    91131
    92132class Owner(grok.Role):
     
    194234        to assign each role to).
    195235        """
    196         return [
    197             dict(
     236        list_of_dict = [dict(
    198237                name=name,
    199238                title=role.title,
    200239                description=role.description)
    201             for name, role in self._roles]
     240                for name, role in self._roles]
     241        return sorted(list_of_dict, key=lambda x: x['name'])
    202242
    203243def get_users_with_local_roles(context):
  • main/waeup.sirp/trunk/src/waeup/sirp/permissions.txt

    r7321 r7334  
    3939    >>> from waeup.sirp.permissions import get_waeup_roles
    4040    >>> len(list(get_waeup_roles()))
    41     10
     41    11
    4242
    4343    >>> len(list(get_waeup_roles(also_local=True)))
    44     16
     44    22
    4545
    4646
     
    5353    >>> from waeup.sirp.permissions import get_waeup_role_names
    5454    >>> list(get_waeup_role_names())
    55     [u'waeup.ACManager', u'waeup.AcademicsOfficer',
    56      u'waeup.AccommodationOfficer', u'waeup.Applicant',
     55    [u'waeup.ACManager',
     56     u'waeup.AcademicsOfficer',
     57     u'waeup.AccommodationOfficer',
     58     u'waeup.Applicant',
    5759     u'waeup.ApplicationsOfficer',
    58      u'waeup.PortalManager', u'waeup.Student',
    59      u'waeup.StudentsClearanceOfficer', u'waeup.StudentsManager',
     60     u'waeup.PortalManager',
     61     u'waeup.Student',
     62     u'waeup.StudentsClearanceOfficer',
     63     u'waeup.StudentsCourseAdviser',
     64     u'waeup.StudentsManager',
    6065     u'waeup.StudentsOfficer']
    6166
  • main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py

    r7329 r7334  
    594594
    595595    def render(self):
    596         self.redirect(self.url(self.context, 'view_clearance'))
    597596        return
    598597
     
    615614        else:
    616615            self.flash('Student is in the wrong state.')
     616            self.redirect(self.url(self.context,'view_clearance'))
    617617            return
    618618        args = {'subject':message}
     
    857857    target = 'manage'
    858858
     859class StudentValidateCoursesActionButton(ManageActionButton):
     860    grok.order(3)
     861    grok.context(IStudentStudyLevel)
     862    grok.view(StudyLevelDisplayFormPage)
     863    grok.require('waeup.validateStudent')
     864    text = 'Validate courses'
     865    target = 'validate_courses'
     866    icon = 'actionicon_accept.png'
     867
     868    @property
     869    def target_url(self):
     870        if self.context.getStudent().state != REGISTERED or \
     871            str(self.context.__parent__.current_level) != self.context.__name__:
     872            return ''
     873        return self.view.url(self.view.context, self.target)
     874
     875class StudentRejectCoursesActionButton(ManageActionButton):
     876    grok.order(4)
     877    grok.context(IStudentStudyLevel)
     878    grok.view(StudyLevelDisplayFormPage)
     879    grok.require('waeup.validateStudent')
     880    text = 'Reject courses'
     881    target = 'reject_courses'
     882    icon = 'actionicon_reject.png'
     883
     884    @property
     885    def target_url(self):
     886        if self.context.getStudent().state not in (VALIDATED, REGISTERED) or \
     887            str(self.context.__parent__.current_level) != self.context.__name__:
     888            return ''
     889        return self.view.url(self.view.context, self.target)
     890
    859891class StudyLevelManageFormPage(SIRPEditFormPage):
    860892    """ Page to edit the student study level data
     
    915947            self.flash('Successfully removed: %s' % ', '.join(deleted))
    916948        self.redirect(self.url(self.context, u'@@manage')+'#tab-2')
     949        return
     950
     951class ValidateCoursesPage(grok.View):
     952    """ Validate course list by course adviser
     953    """
     954    grok.context(IStudentStudyLevel)
     955    grok.name('validate_courses')
     956    grok.require('waeup.validateStudent')
     957
     958    def update(self):
     959        if str(self.context.__parent__.current_level) != self.context.__name__:
     960            self.flash('This level does not correspond current level.')
     961        elif self.context.getStudent().state == REGISTERED:
     962            IWorkflowInfo(self.context.getStudent()).fireTransition('validate_courses')
     963            self.flash('Course list has been registered.')
     964        else:
     965            self.flash('Student is in the wrong state.')
     966        self.redirect(self.url(self.context))
     967        return
     968
     969    def render(self):
     970        return
     971
     972class RejectCoursesPage(grok.View):
     973    """ Reject course list by course adviser
     974    """
     975    grok.context(IStudentStudyLevel)
     976    grok.name('reject_courses')
     977    grok.require('waeup.validateStudent')
     978
     979    def update(self):
     980        if str(self.context.__parent__.current_level) != self.context.__name__:
     981            self.flash('This level does not correspond current level.')
     982            self.redirect(self.url(self.context))
     983            return
     984        elif self.context.getStudent().state == VALIDATED:
     985            IWorkflowInfo(self.context.getStudent()).fireTransition('reset8')
     986            message = 'Course list request has been annulled'
     987            self.flash(message)
     988        elif self.context.getStudent().state == REGISTERED:
     989            IWorkflowInfo(self.context.getStudent()).fireTransition('reset7')
     990            message = 'Course list request has been rejected'
     991            self.flash(message)
     992        else:
     993            self.flash('Student is in the wrong state.')
     994            self.redirect(self.url(self.context))
     995            return
     996        args = {'subject':message}
     997        self.redirect(self.url(self.context.getStudent()) +
     998            '/contactstudent?%s' % urlencode(args))
     999        return
     1000
     1001    def render(self):
    9171002        return
    9181003
  • main/waeup.sirp/trunk/src/waeup/sirp/students/dynamicroles.py

    r7256 r7334  
    4646    rolename_mapping = {
    4747        'waeup.local.ClearanceOfficer':'waeup.StudentsClearanceOfficer',
    48         'waeup.local.CourseAdviser100':'waeup.StudentsCourseAdviser100',
    49         'waeup.local.CourseAdviser200':'waeup.StudentsCourseAdviser200',
    50         'waeup.local.CourseAdviser300':'waeup.StudentsCourseAdviser300',
    51         'waeup.local.CourseAdviser400':'waeup.StudentsCourseAdviser400',
    52         'waeup.local.CourseAdviser500':'waeup.StudentsCourseAdviser500',
    53         'waeup.local.CourseAdviser600':'waeup.StudentsCourseAdviser600'
     48        'waeup.local.CourseAdviser100':'waeup.StudentsCourseAdviser',
     49        'waeup.local.CourseAdviser200':'waeup.StudentsCourseAdviser',
     50        'waeup.local.CourseAdviser300':'waeup.StudentsCourseAdviser',
     51        'waeup.local.CourseAdviser400':'waeup.StudentsCourseAdviser',
     52        'waeup.local.CourseAdviser500':'waeup.StudentsCourseAdviser',
     53        'waeup.local.CourseAdviser600':'waeup.StudentsCourseAdviser'
    5454        }
    5555
     
    100100            obj = getattr(
    101101                self._context[self.subcontainer], self.extra_attrib, None)
     102            current_level = getattr(
     103                self._context[self.subcontainer], 'current_level', None)
    102104        else:
    103105            obj = getattr(self._context, self.extra_attrib, None)
     106            current_level = None
    104107        # lookup local roles for connected course and all parent
    105108        # objects. This way we fake 'role inheritance'.
     
    113116                    # permissions (allow, deny or unset) for the
    114117                    # passed in principal id.
    115                     result.append(
    116                         (self.rolename_mapping[role_id], setting))
     118                    # Make an exception for Course Advisers:
     119                    # Grant additional role only if external role corresponds
     120                    # with current_level of student.
     121                    if not current_level or \
     122                        'CourseAdviser' not in  role_id or \
     123                        str(current_level) in role_id:
     124                        result.append(
     125                            (self.rolename_mapping[role_id], setting))
    117126                    return result
    118127            obj = getattr(obj, '__parent__', None)
  • main/waeup.sirp/trunk/src/waeup/sirp/students/permissions.py

    r7240 r7334  
    5353    grok.name('waeup.clearStudent')
    5454
     55class ValidateStudent(grok.Permission):
     56    grok.name('waeup.validateStudent')
     57
    5558# Local role
    5659class StudentRecordOwner(grok.Role):
     
    8386    grok.title(u'Clearance Officer (all students)')
    8487    grok.permissions('waeup.clearStudent','waeup.viewStudent')
     88
     89class StudentsCourseAdviser(grok.Role):
     90    grok.name('waeup.StudentsCourseAdviser')
     91    grok.title(u'Course Adviser (all students)')
     92    grok.permissions('waeup.validateStudent','waeup.viewStudent')
  • main/waeup.sirp/trunk/src/waeup/sirp/university/certificate.py

    r7321 r7334  
    3232    """
    3333    grok.implements(ICertificate, ICertificateAdd)
     34
     35    @property       # Make this method read_only and looking like an attr.
     36    def local_roles(cls):
     37        return ['waeup.local.CourseAdviser100',
     38                'waeup.local.CourseAdviser200',
     39                'waeup.local.CourseAdviser300',
     40                'waeup.local.CourseAdviser400',
     41                'waeup.local.CourseAdviser500',
     42                'waeup.local.CourseAdviser600',
     43                ]
    3444
    3545    def __init__(self, code=u'NA', title=u'Unnamed Certificate',
  • main/waeup.sirp/trunk/src/waeup/sirp/university/department.py

    r7333 r7334  
    3333    def local_roles(cls):
    3434        return ['waeup.local.DepartmentManager',
    35                 'waeup.local.ClearanceOfficer',]
     35                'waeup.local.ClearanceOfficer',
     36                'waeup.local.CourseAdviser100',
     37                'waeup.local.CourseAdviser200',
     38                'waeup.local.CourseAdviser300',
     39                'waeup.local.CourseAdviser400',
     40                'waeup.local.CourseAdviser500',
     41                'waeup.local.CourseAdviser600',
     42                ]
    3643
    3744    # A simple counter for ids.
  • main/waeup.sirp/trunk/src/waeup/sirp/university/faculty.py

    r7195 r7334  
    3434    def local_roles(cls):
    3535        return ['waeup.local.DepartmentManager',
    36                 'waeup.local.ClearanceOfficer',]
     36                'waeup.local.ClearanceOfficer',
     37                'waeup.local.CourseAdviser100',
     38                'waeup.local.CourseAdviser200',
     39                'waeup.local.CourseAdviser300',
     40                'waeup.local.CourseAdviser400',
     41                'waeup.local.CourseAdviser500',
     42                'waeup.local.CourseAdviser600',
     43                ]
    3744
    3845    def __init__(self,
Note: See TracChangeset for help on using the changeset viewer.