Passed
Push — master ( eeab6e...dd6af3 )
by Ramon
05:59
created

bika.lims.subscribers.analysisrequest   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 109
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 13
eloc 46
dl 0
loc 109
rs 10
c 0
b 0
f 0

5 Functions

Rating   Name   Duplication   Size   Complexity  
A revoke_permission() 0 7 2
B ObjectModifiedEventHandler() 0 24 6
A AfterTransitionEventHandler() 0 6 1
A gather_roles_for_permission() 0 8 2
A update_internal_use_permissions() 0 25 2
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2019 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from Products.CMFCore.permissions import AccessContentsInformation
22
from Products.CMFCore.permissions import ListFolderContents
23
from Products.CMFCore.permissions import View
24
from bika.lims.api import security
25
from bika.lims.interfaces import IInternalUse
26
from zope.interface import alsoProvides
27
from zope.interface import noLongerProvides
28
from zope.lifecycleevent import modified
29
30
31
def ObjectModifiedEventHandler(instance, event):
32
    """Actions to be taken when AnalysisRequest object is modified
33
    """
34
    # If Internal Use value has been modified, apply suitable permissions
35
    internal_use = instance.getInternalUse()
36
    if internal_use != IInternalUse.providedBy(instance):
37
38
        # Update permissions for current sample
39
        update_internal_use_permissions(instance)
40
41
        # Mark/Unmark all analyses with IInternalUse to control their
42
        # visibility in results reports
43
        for analysis in instance.objectValues("Analysis"):
44
            if internal_use:
45
                alsoProvides(analysis, IInternalUse)
46
            else:
47
                noLongerProvides(analysis, IInternalUse)
48
49
        # If internal use is True, cascade same setting to partitions
50
        if internal_use:
51
            for partition in instance.getDescendants():
52
                partition.setInternalUse(internal_use)
53
                # Notify the partition has been modified
54
                modified(partition)
55
56
57
def AfterTransitionEventHandler(instance, event):
58
    """Actions to be taken when AnalsysiRequest object has been transitioned.
59
    This function does not superseds workflow.analysisrequest.events, rather it
60
    only updates the permissions in accordance with InternalUse value
61
    """
62
    update_internal_use_permissions(instance)
63
64
65
def update_internal_use_permissions(analysis_request):
66
    """Updates the permissions for the AnalysisRequest object passed in
67
    accordance with the value set for field InternalUse
68
    """
69
    if analysis_request.getInternalUse():
70
        # Revoke basic permissions from Owner (the client contact)
71
        revoke_permission(View, "Owner", analysis_request)
72
        revoke_permission(ListFolderContents, "Owner", analysis_request)
73
        revoke_permission(AccessContentsInformation, "Owner", analysis_request)
74
75
        # Mark the Sample for Internal use only
76
        alsoProvides(analysis_request, IInternalUse)
77
78
    else:
79
        # Restore basic permissions (acquired=1)
80
        analysis_request.manage_permission(View, [], acquire=1)
81
        analysis_request.manage_permission(ListFolderContents, [], acquire=1)
82
        analysis_request.manage_permission(AccessContentsInformation, [],
83
                                           acquire=1)
84
85
        # Unmark the Sample
86
        noLongerProvides(analysis_request, IInternalUse)
87
88
    analysis_request.reindexObjectSecurity()
89
    analysis_request.reindexObject(idxs="getInternalUse")
90
91
92
def gather_roles_for_permission(permission, obj):
93
    """Extract all the effective roles for a given permission and object,
94
    acquired roles included
95
    """
96
    roles = security.get_roles_for_permission(permission, obj)
97
    if obj.acquiredRolesAreUsedBy(permission):
98
        roles.extend(gather_roles_for_permission(permission, obj.aq_parent))
99
    return list(set(roles))
100
101
102
def revoke_permission(permission, role, obj):
103
    """Revokes a permission for a given role and object
104
    """
105
    roles = gather_roles_for_permission(permission, obj)
106
    if role in roles:
107
        roles.remove(role)
108
    obj.manage_permission(permission, roles)