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

zopefoundation / zope.authentication / 3775723097

pending completion
3775723097

push

github

Michael Howitz
Fix tox lint run + isort imports.

27 of 41 branches covered (65.85%)

Branch coverage included in aggregate %.

16 of 16 new or added lines in 4 files covered. (100.0%)

154 of 188 relevant lines covered (81.91%)

0.82 hits per line

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

74.74
/src/zope/authentication/principal.py
1
##############################################################################
2
#
3
# Copyright (c) 2009 Zope Foundation and Contributors.
4
# All Rights Reserved.
5
#
6
# This software is subject to the provisions of the Zope Public License,
7
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this 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
"""Principal source and helper function
1✔
15
"""
16
import base64
1✔
17

18
from zope.authentication.interfaces import IAuthentication
1✔
19
from zope.authentication.interfaces import IPrincipalSource
1✔
20
from zope.authentication.interfaces import PrincipalLookupError
1✔
21
from zope.browser.interfaces import ITerms
1✔
22
from zope.component import adapter
1✔
23
from zope.component import getUtility
1✔
24
from zope.component import queryNextUtility
1✔
25
from zope.interface import Interface
1✔
26
from zope.interface import implementer
1✔
27
from zope.schema.interfaces import ISourceQueriables
1✔
28

29

30
try:
1✔
31
    unicode
1✔
32
except NameError:
1✔
33
    # Py3: define unicode.
34
    unicode = str
1✔
35

36

37
def checkPrincipal(context, principal_id):
1✔
38
    """Utility function to check if there's a principal for given principal id.
39

40
    Raises :exc:`ValueError` when principal doesn't exists for given context
41
    and principal id.
42

43
    To test it, let's create and register a dummy authentication utility.
44

45
      >>> from zope.authentication.interfaces import IAuthentication
46
      >>> from zope.authentication.interfaces import PrincipalLookupError
47
      >>> from zope.interface import implementer
48
      >>> @implementer(IAuthentication)
49
      ... class DummyUtility(object):
50
      ...
51
      ...     def getPrincipal(self, id):
52
      ...         if id == 'bob':
53
      ...             return id
54
      ...         raise PrincipalLookupError(id)
55

56
      >>> from zope.component import provideUtility
57
      >>> provideUtility(DummyUtility())
58

59
    Now, let's check the behaviour of this function.
60

61
      >>> from zope.authentication.principal import checkPrincipal
62
      >>> checkPrincipal(None, 'bob')
63
      >>> checkPrincipal(None, 'dan')
64
      Traceback (most recent call last):
65
      ...
66
      ValueError: ('Undefined principal id', 'dan')
67

68
    """
69
    auth = getUtility(IAuthentication, context=context)
1✔
70
    try:
1✔
71
        if auth.getPrincipal(principal_id):
1!
72
            return
1✔
73
    except PrincipalLookupError:
1✔
74
        pass
1✔
75
    raise ValueError("Undefined principal id", principal_id)
1✔
76

77

78
@implementer(IPrincipalSource, ISourceQueriables)
1✔
79
class PrincipalSource(object):
1✔
80
    """Generic Principal Source
81

82
    Implements :class:`zope.authentication.interfaces.IPrincipalSource`
83
    and :class:`zope.schema.interfaces.ISourceQueriables`.
84
    """
85

86
    def __contains__(self, id):
1✔
87
        """Test for the existence of a user.
88

89
        We want to check whether the system knows about a particular
90
        principal, which is referenced via its id. The source will go through
91
        the most local authentication utility to look for the
92
        principal. Whether the utility consults other utilities to give an
93
        answer is up to the utility itself.
94

95
        First we need to create a dummy utility that will return a user, if
96
        the id is 'bob'.
97

98
        >>> from zope.authentication.interfaces import IAuthentication
99
        >>> from zope.interface import implementer
100
        >>> @implementer(IAuthentication)
101
        ... class DummyUtility(object):
102
        ...     def getPrincipal(self, id):
103
        ...         if id == 'bob':
104
        ...             return id
105
        ...         raise PrincipalLookupError(id)
106

107
        Let's register our dummy auth utility.
108

109
        >>> from zope.component import provideUtility
110
        >>> provideUtility(DummyUtility())
111

112
        Now initialize the principal source and test the method
113

114
        >>> from zope.authentication.principal import PrincipalSource
115
        >>> source = PrincipalSource()
116
        >>> 'jim' in source
117
        False
118
        >>> 'bob' in source
119
        True
120
        """
121
        auth = getUtility(IAuthentication)
1✔
122
        try:
1✔
123
            auth.getPrincipal(id)
1✔
124
        except PrincipalLookupError:
1✔
125
            return False
1✔
126
        else:
127
            return True
1✔
128

129
    def getQueriables(self):
1✔
130
        """Returns an iteratable of queriables.
131

132
        Queriables are responsible for providing interfaces to search for
133
        principals by a set of given parameters (can be different for the
134
        various queriables). This method will walk up through all of the
135
        authentication utilities to look for queriables.
136

137
        >>> from zope.schema.interfaces import ISourceQueriables
138
        >>> @implementer(IAuthentication)
139
        ... class DummyUtility1(object):
140
        ...     __parent__ = None
141
        ...     def __repr__(self): return 'dummy1'
142
        >>> dummy1 = DummyUtility1()
143

144
        >>> @implementer(ISourceQueriables, IAuthentication)
145
        ... class DummyUtility2(object):
146
        ...     __parent__ = None
147
        ...     def getQueriables(self):
148
        ...         return ('1', 1), ('2', 2), ('3', 3)
149
        >>> dummy2 = DummyUtility2()
150

151
        >>> @implementer(IAuthentication)
152
        ... class DummyUtility3(DummyUtility2):
153
        ...     def getQueriables(self):
154
        ...         return ('4', 4),
155
        >>> dummy3 = DummyUtility3()
156

157
        >>> from zope.authentication.tests.utils import testingNextUtility
158
        >>> testingNextUtility(dummy1, dummy2, IAuthentication)
159
        >>> testingNextUtility(dummy2, dummy3, IAuthentication)
160

161
        >>> from zope.component import provideUtility
162
        >>> provideUtility(dummy1)
163

164
        >>> from zope.authentication.principal import PrincipalSource
165
        >>> source = PrincipalSource()
166
        >>> list(source.getQueriables())
167
        [(u'0', dummy1), (u'1.1', 1), (u'1.2', 2), (u'1.3', 3), (u'2.4', 4)]
168
        """
169
        i = 0
1✔
170
        auth = getUtility(IAuthentication)
1✔
171
        yielded = []
1✔
172
        while True:
173
            queriables = ISourceQueriables(auth, None)
1✔
174
            if queriables is None:
1✔
175
                yield unicode(i), auth
1✔
176
            else:
177
                for qid, queriable in queriables.getQueriables():
1✔
178
                    # ensure that we dont return same yielded utility more
179
                    # then once
180
                    if queriable not in yielded:
1!
181
                        yield unicode(i)+'.'+unicode(qid), queriable
1✔
182
                        yielded.append(queriable)
1✔
183
            auth = queryNextUtility(auth, IAuthentication)
1✔
184
            if auth is None:
1✔
185
                break
1✔
186
            i += 1
1✔
187

188

189
@implementer(ITerms)
1✔
190
@adapter(IPrincipalSource, Interface)
1✔
191
class PrincipalTerms(object):
1✔
192
    """
193
    Implementation of :class:`zope.browser.interfaces.ITerms` given a
194
    :class:`zope.authentication.interfaces.IPrincipalSource` and
195
    request object.
196
    """
197

198
    def __init__(self, context, request):
1✔
199
        self.context = context
×
200

201
    def _encode(self, id):
1✔
202
        # Py3: In Python 2, principal_id can be a str, but in Python 3 it is
203
        # always unicode/str.
204
        if isinstance(id, unicode):
×
205
            id = id.encode('utf-8')
×
206

207
        res = base64.b64encode(id).strip().replace(b'=', b'_')
×
208
        return res.decode()
×
209

210
    def _decode(self, token):
1✔
211
        return base64.b64decode(
×
212
            token.replace('_', '=').encode()).decode('utf-8')
213

214
    def getTerm(self, principal_id):
1✔
215
        """Return a :class:`PrincipalTerm` for the given ID.
216

217
        If no such principal can be found, raises :exc:`LooupError`.
218
        """
219
        if principal_id not in self.context:
×
220
            raise LookupError(principal_id)
×
221

222
        auth = getUtility(IAuthentication)
×
223
        principal = auth.getPrincipal(principal_id)
×
224

225
        if principal is None:
×
226
            # TODO: is this a possible case?
227
            raise LookupError(principal_id)
×
228

229
        return PrincipalTerm(self._encode(principal_id), principal.title)
×
230

231
    def getValue(self, token):
1✔
232
        """Return the principal ID given its token."""
233
        return self._decode(token)
×
234

235

236
class PrincipalTerm(object):
1✔
237
    """
238
    A principal term.
239

240
    We have a ``token`` based on the encoded principal ID, and a ``title``.
241
    """
242

243
    def __init__(self, token, title):
1✔
244
        self.token = token
×
245
        self.title = title
×
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