Repository: Kinto/kinto

Issue:
Expose a dedicated capability when basicauth is enabled
Refs https://github.com/Kinto/kinto-admin/issues/331

We need to know if the basicauth authentication method is available on a given server. We could detect if the server is configured with basicauth enabled and expose a dedicated capability in the hello endpoint; wdyt?


Discussion:
As @Natim said somewhere: everything that can be (un)plugged from settings should be mentionned as a capability

Resolving patch:
diff --git a/kinto/core/authentication.py b/kinto/core/authentication.py
--- a/kinto/core/authentication.py
+++ b/kinto/core/authentication.py
@@ -50,3 +50,11 @@ def unauthenticated_userid(self, request):
             credentials = '%s:%s' % credentials
             userid = utils.hmac_digest(hmac_secret, credentials)
             return userid
+
+
+def includeme(config):
+    config.add_api_capability(
+        "basicauth",
+        description="Very basic authentication sessions. Not for production use.",
+        url="http://kinto.readthedocs.io/en/stable/api/1.x/authentication.html",
+    )
diff --git a/kinto/core/initialization.py b/kinto/core/initialization.py
--- a/kinto/core/initialization.py
+++ b/kinto/core/initialization.py
@@ -101,6 +101,11 @@ def setup_authentication(config):
     from configuration.
     """
     config.include('pyramid_multiauth')
+    settings = config.get_settings()
+
+    policies = aslist(settings['multiauth.policies'])
+    if 'basicauth' in policies:
+        config.include('kinto.core.authentication')
 
     # Track policy used, for prefixing user_id and for logging.
     def on_policy_selected(event):


Test patch:
diff --git a/tests/core/test_authentication.py b/tests/core/test_authentication.py
--- a/tests/core/test_authentication.py
+++ b/tests/core/test_authentication.py
@@ -12,10 +12,16 @@ class AuthenticationPoliciesTest(BaseWebTest, unittest.TestCase):
 
     def test_basic_auth_is_accepted_by_default(self):
         self.app.get(self.collection_url, headers=self.headers, status=200)
+        # Check that the capability is exposed on the homepage.
+        resp = self.app.get('/')
+        assert 'basicauth' in resp.json['capabilities']
 
     def test_basic_auth_is_accepted_if_enabled_in_settings(self):
         app = self.make_app({'multiauth.policies': 'basicauth'})
         app.get(self.collection_url, headers=self.headers, status=200)
+        # Check that the capability is exposed on the homepage.
+        resp = app.get('/')
+        assert 'basicauth' in resp.json['capabilities']
 
     def test_basic_auth_is_declined_if_disabled_in_settings(self):
         app = self.make_app({
@@ -23,6 +29,9 @@ def test_basic_auth_is_declined_if_disabled_in_settings(self):
             'multiauth.policy.dummy.use': ('pyramid.authentication.'
                                            'RepozeWho1AuthenticationPolicy')})
         app.get(self.collection_url, headers=self.headers, status=401)
+        # Check that the capability is exposed on the homepage.
+        resp = app.get('/')
+        assert 'basicauth' not in resp.json['capabilities']
 
     def test_views_are_forbidden_if_unknown_auth_method(self):
         app = self.make_app({'multiauth.policies': 'basicauth'})
diff --git a/tests/core/test_views_hello.py b/tests/core/test_views_hello.py
--- a/tests/core/test_views_hello.py
+++ b/tests/core/test_views_hello.py
@@ -64,21 +64,28 @@ def test_return_http_api_version_when_set(self):
 
 
 class APICapabilitiesTest(BaseWebTest, unittest.TestCase):
-    def test_list_of_capabilities_is_empty_by_default(self):
+    def test_list_of_capabilities_contains_basicauth_by_default(self):
         app = self.make_app()
         response = app.get('/')
         capabilities = response.json['capabilities']
-        self.assertEqual(capabilities, {})
+        self.assertEqual(capabilities, {"basicauth": {
+            'description': 'Very basic authentication sessions. Not for production use.',
+            'url': 'http://kinto.readthedocs.io/en/stable/api/1.x/authentication.html'
+        }})
 
     def test_capabilities_can_be_specified_via_config(self):
-        config = testing.setUp(settings=self.get_app_settings())
+        settings = self.get_app_settings()
+        settings['multiauth.policies'] = ""
+        config = testing.setUp(settings=settings)
         app = self.make_app(config=config)
 
         config.add_api_capability("cook-coffee")
 
         response = app.get('/')
         capabilities = response.json['capabilities']
-        expected = {"cook-coffee": {"description": "", "url": ""}}
+        expected = {
+            "cook-coffee": {"description": "", "url": ""}
+        }
         self.assertEqual(capabilities, expected)
 
     def test_capabilities_can_have_arbitrary_attributes(self):