22
33import json
44from ipaddress import ip_address
5+ import os
56
67from http .client import responses
78from tornado import web
89from tornado .log import app_log
10+ from tornado .httpclient import AsyncHTTPClient , HTTPRequest , HTTPError
11+
912from jupyterhub .services .auth import HubOAuthenticated , HubOAuth
1013
1114from . import __version__ as binder_version
@@ -19,6 +22,7 @@ def initialize(self):
1922 super ().initialize ()
2023 if self .settings ['auth_enabled' ]:
2124 self .hub_auth = HubOAuth .instance (config = self .settings ['traitlets_config' ])
25+ self .current_user_model = None
2226
2327 def prepare (self ):
2428 super ().prepare ()
@@ -71,14 +75,46 @@ def get_spec_from_request(self, prefix):
7175 spec = self .request .path [idx + len (prefix ) + 1 :]
7276 return spec
7377
74- def get_provider (self , provider_prefix , spec ):
78+ async def get_provider (self , provider_prefix , spec ):
7579 """Construct a provider object"""
7680 providers = self .settings ['repo_providers' ]
7781 if provider_prefix not in providers :
7882 raise web .HTTPError (404 , "No provider found for prefix %s" % provider_prefix )
7983
84+ async def api_request (url , * args , ** kwargs ):
85+ headers = kwargs .setdefault ('headers' , {})
86+ headers .update ({'Authorization' : 'token %s' % self .hub_auth .api_token })
87+ hub_api_url = os .getenv ('JUPYTERHUB_API_URL' , '' ) or self .hub_auth .api_url
88+ request_url = hub_api_url + url
89+ req = HTTPRequest (request_url , * args , ** kwargs )
90+
91+ try :
92+ return await AsyncHTTPClient ().fetch (req )
93+ except HTTPError as e :
94+ app_log .error ("Error accessing Hub API (using %s): %s" , request_url , e )
95+
96+ async def get_current_user_model ():
97+ """Get the current user model.
98+ The user auth_state is only accessible to admin users.
99+ """
100+ if not self .settings ['auth_enabled' ]:
101+ return None
102+
103+ if self .current_user_model is None :
104+ username = self .get_current_user ()['name' ]
105+ resp = await api_request (
106+ f'/users/{ username } ' ,
107+ method = 'GET' ,
108+ )
109+ self .current_user_model = json .loads (resp .body .decode ('utf-8' ))
110+
111+ return self .current_user_model
112+
80113 return providers [provider_prefix ](
81- config = self .settings ['traitlets_config' ], spec = spec )
114+ config = self .settings ['traitlets_config' ],
115+ spec = spec ,
116+ user_model = await get_current_user_model ()
117+ )
82118
83119 def get_badge_base_url (self ):
84120 badge_base_url = self .settings ['badge_base_url' ]
0 commit comments