• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zopefoundation / Products.PluggableAuthService / 5235276870

pending completion
5235276870

push

github

web-flow
Drop support for Python 2.7, 3.5, 3.6. (#116)

* Drop zserver extra in setup.py. Thus dropping FTP support.
* Drop support for Zope < 5.
Co-authored-by: Jens Vagelpohl <jens@plyp.com>

1288 of 1745 branches covered (73.81%)

Branch coverage included in aggregate %.

127 of 127 new or added lines in 30 files covered. (100.0%)

9619 of 10349 relevant lines covered (92.95%)

0.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

88.89
/src/Products/PluggableAuthService/plugins/NotCompetentHelper.py
1
##############################################################################
2
#
3
# Copyright (c) 2012 Zope Foundation and Contributors
4
#
5
# This software is subject to the provisions of the Zope Public License,
6
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this
7
# distribution.
8
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11
# FOR A PARTICULAR PURPOSE.
12
#
13
##############################################################################
14
""" NotCompetentHelper   `INotCompetent` plugin utilities
1✔
15

16
`INotCompetent` plugins are usually used to prevent shadowing of users
17
authenticated by higher level user folders. This module provides
18
an `INotCompetent` plugin base class which can check for authentications
19
by higher level user folders and the class `NotCompetent_byRoles`
20
to prevent shadowing of higher level authentications with
21
specified roles.
22
"""
23

24
from AccessControl import ClassSecurityInfo
1✔
25
from AccessControl.Permissions import manage_users
1✔
26
from AccessControl.users import nobody
1✔
27
from Acquisition import aq_base
1✔
28
from Acquisition import aq_inner
1✔
29
from Acquisition import aq_parent
1✔
30
from OFS.PropertyManager import PropertyManager
1✔
31
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
1✔
32
from ZPublisher.BaseRequest import UNSPECIFIED_ROLES
1✔
33
from ZPublisher.HTTPResponse import HTTPResponse as Response
1✔
34

35
from ..interfaces.plugins import INotCompetentPlugin
1✔
36
from ..plugins.BasePlugin import BasePlugin
1✔
37
from ..utils import classImplements
1✔
38

39

40
class HigherLevelUserFolderAccessMixin:
1✔
41
    """mixin class for access to higher level user folders
42

43
       requires to be mixed with a `BasePlugin`.
44
    """
45

46
    def _generateHigherLevelUserFolders(self):
1✔
47
        folder = aq_parent(aq_inner(self._getPAS()))
1✔
48
        while True:
49
            folder = aq_parent(aq_inner(folder))
1✔
50
            if folder is None:
1✔
51
                return
1✔
52
            uf = getattr(folder, '__allow_groups__', None)
1✔
53
            validate = getattr(aq_base(uf), 'validate', None)
1✔
54
            if validate is not None:
1✔
55
                yield uf
1✔
56

57
    def _getHigherLevelUser(self, request, roles=None):
1✔
58
        if roles:
1✔
59
            accessed = self._getPAS()._getObjectContext(
1✔
60
                request['PUBLISHED'], request)[1]
61
        req_roles = request.roles
1✔
62
        auth = request._auth
1✔
63
        # save response and install new one to prevent side effects
64
        saved_response = request.response
1✔
65
        try:
1✔
66
            request.response = Response()
1✔
67
            for uf in self._generateHigherLevelUserFolders():
1✔
68
                if req_roles is UNSPECIFIED_ROLES:
1✔
69
                    u = uf.validate(request, auth)
1✔
70
                else:
71
                    u = uf.validate(request, auth, req_roles)
1✔
72
                if u is None or u is nobody:
1!
73
                    continue
×
74
                # this user folder has authenticated a user able to perform
75
                # the request
76
                if roles:
1✔
77
                    # check in addition that is has one of *roles*
78
                    if not u.allowed(accessed, roles):
1✔
79
                        # reject this user
80
                        continue
1✔
81
                return u
1✔
82
        finally:
83
            request.response = saved_response
1✔
84

85

86
class NotCompetentBase(BasePlugin, HigherLevelUserFolderAccessMixin):
1✔
87
    """abstract `INotCompententPlugin` base class.
88

89
    with access to higher level user folders.
90
    """
91

92
    security = ClassSecurityInfo()
1✔
93
    security.declareObjectProtected(manage_users)
1✔
94

95
    def __init__(self, id, title=''):
1✔
96
        self.id = id
1✔
97
        self.title = title
1✔
98

99
    @security.private
1✔
100
    def isNotCompetentToAuthenticate(self, request):
1✔
101
        raise NotImplementedError()
102

103

104
classImplements(NotCompetentBase, INotCompetentPlugin)
1✔
105

106

107
class NotCompetent_byRoles(NotCompetentBase):
1✔
108
    """`INotCompetentPlugin` to prevent authentication shadowing by roles.
109
    """
110

111
    meta_type = 'prevent authentication shadowing by roles'
1✔
112

113
    _properties = (
1✔
114
        PropertyManager._properties +
115
        (dict(id='roles', label='roles (empty means all roles)',
116
              type='lines', mode='rw'),))
117
    roles = ()
1✔
118

119
    manage_options = (
1✔
120
        (NotCompetentBase.manage_options[0],)
121
        + PropertyManager.manage_options
122
        + NotCompetentBase.manage_options[1:-1])
123

124
    def isNotCompetentToAuthenticate(self, request):
1✔
125
        return self._getHigherLevelUser(request, self.roles) is not None
1✔
126

127

128
manage_addNotCompetent_byRolesForm = PageTemplateFile(
1✔
129
    'www/ncbrAdd', globals(), __name__='manage_addNotCompetent_byRolesForm')
130

131

132
def manage_addNotCompetent_byRoles(self, id, title='', REQUEST=None):
1✔
133
    """ Factory method to instantiate a NotCompetent_byRoles """
134
    obj = NotCompetent_byRoles(id, title=title)
×
135
    self._setObject(id, obj)
×
136

137
    if REQUEST is not None:
×
138
        qs = 'manage_tabs_message=NotCompetent_byRoles+added.'
×
139
        my_url = self.absolute_url()
×
140
        REQUEST['RESPONSE'].redirect(f'{my_url}/manage_workspace?{qs}')
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc