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

zopefoundation / Products.PluggableAuthService / 5303493172

pending completion
5303493172

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

28.4
/src/Products/PluggableAuthService/plugins/DelegatingMultiPlugin.py
1
##############################################################################
2
#
3
# Copyright (c) 2001 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
""" DelegatingMultiPlugin   Shim to use any User Folder with the
1✔
15
                            PluggableAuthenticationService
16
"""
17

18
import copy
1✔
19

20
from AccessControl import AuthEncoding
1✔
21
from AccessControl import ClassSecurityInfo
1✔
22
from AccessControl.class_init import InitializeClass
1✔
23
from AccessControl.SpecialUsers import emergency_user
1✔
24
from Acquisition import aq_base
1✔
25
from OFS.Folder import Folder
1✔
26
from Products.PageTemplates.PageTemplateFile import PageTemplateFile
1✔
27
from zope.interface import Interface
1✔
28

29
from ..interfaces.plugins import IAuthenticationPlugin
1✔
30
from ..interfaces.plugins import ICredentialsResetPlugin
1✔
31
from ..interfaces.plugins import ICredentialsUpdatePlugin
1✔
32
from ..interfaces.plugins import IPropertiesPlugin
1✔
33
from ..interfaces.plugins import IRolesPlugin
1✔
34
from ..plugins.BasePlugin import BasePlugin
1✔
35
from ..utils import classImplements
1✔
36

37

38
class IDelegatingMultiPlugin(Interface):
1✔
39
    """ Marker interface.
40
    """
41

42

43
manage_addDelegatingMultiPluginForm = PageTemplateFile(
1✔
44
    'www/dmpAdd', globals(), __name__='manage_addDelegatingMultiPluginForm')
45

46

47
def manage_addDelegatingMultiPlugin(self, id, title='', delegate_path='',
1✔
48
                                    REQUEST=None):
49
    """ Factory method to instantiate a DelegatingMultiPlugin """
50
    # Make sure we really are working in our container (the
51
    # PluggableAuthService object)
52
    self = self.this()
×
53

54
    # Instantiate the folderish adapter object
55
    lmp = DelegatingMultiPlugin(id, title=title, delegate_path=delegate_path)
×
56
    self._setObject(id, lmp)
×
57

58
    if REQUEST is not None:
×
59
        REQUEST.RESPONSE.redirect('%s/manage_main' % self.absolute_url())
×
60

61

62
class DelegatingMultiPlugin(Folder, BasePlugin):
1✔
63
    """ The adapter that mediates between the PAS and the DelegatingUserFolder
64
    """
65
    security = ClassSecurityInfo()
1✔
66
    meta_type = 'Delegating Multi Plugin'
1✔
67
    zmi_icon = 'fas fa-external-link-alt'
1✔
68

69
    manage_options = BasePlugin.manage_options[:1] + Folder.manage_options
1✔
70

71
    _properties = ({'id': 'delegate', 'label': 'Delegate Path',
1✔
72
                    'type': 'string', 'mode': 'w'},)
73

74
    def __init__(self, id, title='', delegate_path=''):
1✔
75
        """ Initialize a new instance """
76
        self.id = id
1✔
77
        self.title = title
1✔
78
        self.delegate = delegate_path
1✔
79

80
    @security.private
1✔
81
    def _getUserFolder(self):
1✔
82
        """ Safely retrieve a User Folder to work with """
83
        uf = getattr(aq_base(self), 'acl_users', None)
×
84

85
        if uf is None and self.delegate:
×
86
            uf = self.unrestrictedTraverse(self.delegate)
×
87

88
        return uf
×
89

90
    @security.private
1✔
91
    def authenticateCredentials(self, credentials):
1✔
92
        """ Fulfill AuthenticationPlugin requirements """
93
        acl = self._getUserFolder()
×
94
        login = credentials.get('login', '')
×
95
        password = credentials.get('password', '')
×
96

97
        if not acl or not login or not password:
×
98
            return (None, None)
×
99

100
        if login == emergency_user.getUserName() and \
×
101
                AuthEncoding.pw_validate(emergency_user._getPassword(),
102
                                         password):
103
            return (login, login)
×
104

105
        user = acl.getUser(login)
×
106

107
        if user is None:
×
108
            return (None, None)
×
109

110
        elif user and AuthEncoding.pw_validate(user._getPassword(), password):
×
111
            return (user.getId(), login)
×
112

113
        return (None, None)
×
114

115
    @security.private
1✔
116
    def updateCredentials(self, request, response, login, new_password):
1✔
117
        """ Fulfill CredentialsUpdatePlugin requirements """
118
        # Need to at least remove user from cache
119
        pass
×
120

121
    @security.private
1✔
122
    def resetCredentials(self, request, response):
1✔
123
        """ Fulfill CredentialsResetPlugin requirements """
124
        # Remove user from cache?
125
        pass
×
126

127
    @security.private
1✔
128
    def getPropertiesForUser(self, user, request=None):
1✔
129
        """ Fullfill PropertiesPlugin requirements """
130
        acl = self._getUserFolder()
×
131

132
        if acl is None:
×
133
            return {}
×
134

135
        user = acl.getUserById(user.getId())
×
136

137
        if user is None:
×
138
            return {}
×
139

140
        # WAAA
141
        return copy.deepcopy(user.__dict__)
×
142

143
    @security.private
1✔
144
    def getRolesForPrincipal(self, user, request=None):
1✔
145
        """ Fullfill RolesPlugin requirements """
146
        acl = self._getUserFolder()
×
147

148
        if acl is None:
×
149
            return ()
×
150

151
        user = acl.getUserById(user.getId())
×
152

153
        if user is None:
×
154
            return ()
×
155

156
        return tuple(user.getRoles())
×
157

158
    @security.private
1✔
159
    def enumerateUsers(self, id=None, login=None, exact_match=0, sort_by=None,
1✔
160
                       max_results=None, **kw):
161
        """ Fulfill the EnumerationPlugin requirements """
162
        result = []
×
163
        acl = self._getUserFolder()
×
164
        plugin_id = self.getId()
×
165
        edit_url = '{}/{}/manage_userrecords'.format(plugin_id, acl.getId())
×
166

167
        if acl is None:
×
168
            return ()
×
169

170
        if exact_match:
×
171
            if id:
×
172
                user = acl.getUserById(id)
×
173
            elif login:
×
174
                user = acl.getUser(login)
×
175
            else:
176
                msg = 'Exact Match specified but no ID or Login given'
×
177
                raise ValueError(msg)
×
178

179
            if user is not None:
×
180
                result.append({'id': user.getId(), 'login': user.getUserName(),
×
181
                               'pluginid': plugin_id,
182
                               'editurl': '%s' % edit_url})
183
        else:
184
            # WAAAAA!!!!
185
            all_users = acl.getUsers()
×
186

187
            for user in all_users:
×
188
                if id:
×
189
                    if user.getId().find(id) != -1:
×
190
                        result.append({'login': user.getUserName(),
×
191
                                       'id': user.getId(),
192
                                       'pluginid': plugin_id})
193
                elif login:
×
194
                    if user.getUserName().find(login) != -1:
×
195
                        result.append({'login': user.getUserName(),
×
196
                                       'id': user.getId(),
197
                                       'pluginid': plugin_id})
198

199
            if sort_by is not None:
×
200
                result = sorted(key=lambda x: x.get(sort_by, '').lower())
×
201

202
            if max_results is not None:
×
203
                try:
×
204
                    max_results = int(max_results)
×
205
                    result = result[:max_results + 1]
×
206
                except ValueError:
×
207
                    pass
×
208

209
        return tuple(result)
×
210

211

212
classImplements(DelegatingMultiPlugin, IDelegatingMultiPlugin,
1✔
213
                IAuthenticationPlugin, IRolesPlugin,
214
                ICredentialsUpdatePlugin, ICredentialsResetPlugin,
215
                IPropertiesPlugin)
216

217

218
InitializeClass(DelegatingMultiPlugin)
1✔
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