Skip to content

Commit 807a300

Browse files
authored
Merge pull request #1 from adriendelsalle/user-credentials
Pass user model to RepoProvider
2 parents 2c09d72 + 44ef87f commit 807a300

File tree

3 files changed

+41
-6
lines changed

3 files changed

+41
-6
lines changed

binderhub/base.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
"""Base classes for request handlers"""
22

33
import json
4+
import os
45

56
from http.client import responses
67
from tornado import web
8+
from tornado.log import app_log
9+
from tornado.httpclient import AsyncHTTPClient, HTTPRequest, HTTPError
10+
711
from jupyterhub.services.auth import HubOAuthenticated, HubOAuth
812

913
from . import __version__ as binder_version
@@ -16,6 +20,7 @@ def initialize(self):
1620
super().initialize()
1721
if self.settings['auth_enabled']:
1822
self.hub_auth = HubOAuth.instance(config=self.settings['traitlets_config'])
23+
self.current_user_model = None
1924

2025
def get_current_user(self):
2126
if not self.settings['auth_enabled']:
@@ -43,16 +48,46 @@ def get_spec_from_request(self, prefix):
4348
spec = self.request.path[idx + len(prefix) + 1:]
4449
return spec
4550

46-
def get_provider(self, provider_prefix, spec):
51+
async def get_provider(self, provider_prefix, spec):
4752
"""Construct a provider object"""
4853
providers = self.settings['repo_providers']
4954
if provider_prefix not in providers:
5055
raise web.HTTPError(404, "No provider found for prefix %s" % provider_prefix)
5156

57+
async def api_request(url, *args, **kwargs):
58+
headers = kwargs.setdefault('headers', {})
59+
headers.update({'Authorization': 'token %s' % self.hub_auth.api_token})
60+
hub_api_url = os.getenv('JUPYTERHUB_API_URL', '') or self.hub_auth.api_url
61+
request_url = hub_api_url + url
62+
req = HTTPRequest(request_url, *args, **kwargs)
63+
64+
try:
65+
return await AsyncHTTPClient().fetch(req)
66+
except HTTPError as e:
67+
app_log.error("Error accessing Hub API (using %s): %s", request_url, e)
68+
69+
async def get_current_user_model():
70+
"""Get the current user model.
71+
The user auth_state is only accessible to admin users.
72+
"""
73+
if not self.settings['auth_enabled']:
74+
return None
75+
76+
if self.current_user_model is None:
77+
username = self.get_current_user()['name']
78+
resp = await api_request(
79+
f'/users/{username}',
80+
method='GET',
81+
)
82+
self.current_user_model = json.loads(resp.body.decode('utf-8'))
83+
84+
return self.current_user_model
85+
5286
return providers[provider_prefix](
53-
config=self.settings['traitlets_config'],
54-
spec=spec,
55-
handler=self)
87+
config=self.settings['traitlets_config'],
88+
spec=spec,
89+
user_model=await get_current_user_model()
90+
)
5691

5792
def get_badge_base_url(self):
5893
badge_base_url = self.settings['badge_base_url']

binderhub/builder.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ async def get(self, provider_prefix, _unescaped_spec):
224224

225225
# get a provider object that encapsulates the provider and the spec
226226
try:
227-
provider = self.get_provider(provider_prefix, spec=spec)
227+
provider = await self.get_provider(provider_prefix, spec=spec)
228228
except Exception as e:
229229
app_log.exception("Failed to get provider for %s", key)
230230
await self.fail(str(e))

binderhub/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ async def get(self, provider_prefix, _unescaped_spec):
4747
spec = self.get_spec_from_request(prefix)
4848
spec = spec.rstrip("/")
4949
try:
50-
self.get_provider(provider_prefix, spec=spec)
50+
await self.get_provider(provider_prefix, spec=spec)
5151
except HTTPError:
5252
raise
5353
except Exception as e:

0 commit comments

Comments
 (0)