summaryrefslogtreecommitdiff
path: root/tests/unit/core/test_web_api.py
blob: f440417f4249d57836327c7265e5806f5ed85200 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import base64

from twisted.cred import portal
from twisted.trial import unittest
from twisted.web.test.test_web import DummyRequest
from twisted.web import resource

from leap.bitmask.core import _web


def b64encode(s):
    return base64.b64encode(s).strip()


class APIMixin:
    """
    L{TestCase} mixin class which defines a number of tests for
    L{basic.BasicCredentialFactory}.  Because this mixin defines C{setUp}, it
    must be inherited before L{TestCase}.
    """
    def setUp(self):
        self.request = self.makeRequest()

        api = AuthTestResource()
        self.realm = _web.HttpPasswordRealm(api)
        tokens = {'testuser': 'token'}
        checker = _web.TokenDictChecker(tokens)
        self.portal = portal.Portal(self.realm, [checker])

    def makeRequest(self, method=b'GET', clientAddress=None):
        """
        Create a request object to be passed to
        TokenCredentialFactory.decode along with a response value.
        Override this in a subclass.
        """
        raise NotImplementedError("%r did not implement makeRequest" % (
                                  self.__class__,))


class WhitelistedResourceTests(APIMixin, unittest.TestCase):

    def makeRequest(self, method=b'GET', clientAddress=None, path='/'):
        """
        Create a L{DummyRequest} (change me to create a
        L{twisted.web.http.Request} instead).
        """
        request = DummyRequest(b'/')
        request.method = method
        request.client = clientAddress
        request.path = path
        return request

    def test_render_returns_unauthorized_by_default(self):
        """
        By default, a Whitelisted resource renders with a 401 response code and
        a I{WWW-Authenticate} header and puts a simple unauthorized message
        into the response body.
        """
        protected = _web.WhitelistHTTPAuthSessionWrapper(
            self.portal,
            [_web.TokenCredentialFactory('localhost')])
        request = self.makeRequest(method='POST', path='/')
        request.render(protected)
        assert request.responseCode == 401

        auth_header = request.responseHeaders.getRawHeaders(
            b'www-authenticate')
        assert auth_header == [b'token realm="localhost"']
        assert b'Unauthorized' == b''.join(request.written)

    def test_whitelisted_resource_does_render(self):
        protected = _web.WhitelistHTTPAuthSessionWrapper(
            self.portal,
            [_web.TokenCredentialFactory('localhost')],
            whitelist=['/whitelisted'])
        request = self.makeRequest(method='GET', path='/whitelisted')
        request.render(protected)
        assert b'dummyGET' == b''.join(request.written)

    def test_good_token_authenticates(self):
        protected = _web.WhitelistHTTPAuthSessionWrapper(
            self.portal,
            [_web.TokenCredentialFactory('localhost')],
            whitelist=[])
        request = self.makeRequest(method='GET', path='/')
        authorization = b64encode(b'testuser:token')
        request.requestHeaders.addRawHeader(b'authorization',
                                            b'Token ' + authorization)
        request.render(protected)
        assert b'dummyGET' == b''.join(request.written)

    def test_session_does_not_use_cookies(self):
        # TODO
        pass


class AuthTestResource(resource.Resource):

    isLeaf = True

    def render_GET(self, request):
        return "dummyGET"

    def render_POST(self, request):
        return "dummyPOST"