""" Tests for go_auth.bouncer.
"""

import yaml

from twisted.internet.defer import inlineCallbacks
from twisted.trial.unittest import TestCase

from go_api.cyclone.helpers import AppHelper

from go_auth.bouncer import Bouncer


class TestBouncer(TestCase):
    def setUp(self):
        self.api = self.mk_api()
        self.auth_store = self.api.auth_store
        self.app_helper = AppHelper(app=self.api)

    def mk_config(self, config_dict):
        tempfile = self.mktemp()
        with open(tempfile, 'wb') as fp:
            yaml.safe_dump(config_dict, fp)
        return tempfile

    def mk_api(self):
        configfile = self.mk_config({
            "auth_store": {
                "access-1": {
                    "client_id": "client-1",
                    "scopes": ["scope-a", "scope-b"],
                },
            },
        })
        return Bouncer(configfile)

    def assert_headers(self, resp, headers):
        for key, value in sorted(headers.items()):
            self.assertEqual(resp.headers.getRawHeaders(key), value)

    @inlineCallbacks
    def check_body(self, resp, body):
        self.assertEqual((yield resp.text()), body)

    @inlineCallbacks
    def check_authorized(self, resp):
        self.assertEqual(resp.code, 200)
        self.assert_headers(resp, {
            "X-Owner-ID": ["client-1"],
            "X-Scopes": ["scope-a scope-b"],
        })
        yield self.check_body(resp, (
            "Authenticated as 'client-1' with scopes:"
            " ['scope-a', 'scope-b'].\n"))

    @inlineCallbacks
    def check_denied(self, resp):
        self.assertEqual(resp.code, 403)
        self.assert_headers(resp, {
            "X-Owner-ID": None,
            "X-Scopes": None,
        })
        yield self.check_body(resp, (
            "<html><title>403: Forbidden</title><body>403:"
            " Forbidden</body></html>"))

    @inlineCallbacks
    def test_valid_credentials_in_query(self):
        resp = yield self.app_helper.get('/foo/?access_token=access-1')
        yield self.check_authorized(resp)

    @inlineCallbacks
    def test_invalid_credentials_in_query(self):
        resp = yield self.app_helper.get('/foo/?access_token=unknown-1')
        yield self.check_denied(resp)

    @inlineCallbacks
    def test_valid_credentials_in_headers(self):
        resp = yield self.app_helper.get('/foo/', headers={
            'Authorization': 'Bearer access-1',
        })
        yield self.check_authorized(resp)

    @inlineCallbacks
    def test_invalid_credentials_in_headers(self):
        resp = yield self.app_helper.get('/foo/', headers={
            'Authorization': 'Bearer unknown-1',
        })
        yield self.check_denied(resp)

@@ -1563,22 +1563,382 @@
 f check_
+unauthorized(self, resp):%0A        self.assertEqual(resp.code, 401)%0A        self.assert_headers(resp, %7B%0A            %22X-Owner-ID%22: None,%0A            %22X-Scopes%22: None,%0A        %7D)%0A        yield self.check_body(resp, (%0A            %22%3Chtml%3E%3Ctitle%3E401: Unauthorized%3C/title%3E%3Cbody%3E401:%22%0A            %22 Unauthorized%3C/body%3E%3C/html%3E%22))%0A%0A    @inlineCallbacks%0A    def check_forbid
 den
-ied
 (self, r
@@ -2580,30 +2580,33 @@
  self.check_
+forbid
 den
-ied
 (resp)%0A%0A    
@@ -3054,12 +3054,166 @@
 eck_
-deni
+forbidden(resp)%0A%0A    @inlineCallbacks%0A    def test_no_credentials(self):%0A        resp = yield self.app_helper.get('/foo/')%0A        yield self.check_unauthoriz
 ed(r

Add test for no credentials.