mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-16 06:22:59 +00:00
support service tokens in /api/authorizations
This commit is contained in:
@@ -18,7 +18,11 @@ class TokenAPIHandler(APIHandler):
|
|||||||
orm_token = orm.APIToken.find(self.db, token)
|
orm_token = orm.APIToken.find(self.db, token)
|
||||||
if orm_token is None:
|
if orm_token is None:
|
||||||
raise web.HTTPError(404)
|
raise web.HTTPError(404)
|
||||||
self.write(json.dumps(self.user_model(self.users[orm_token.user])))
|
if orm_token.user:
|
||||||
|
model = self.user_model(self.users[orm_token.user])
|
||||||
|
elif orm_token.service:
|
||||||
|
model = self.service_model(orm_token.service)
|
||||||
|
self.write(json.dumps(model))
|
||||||
|
|
||||||
@gen.coroutine
|
@gen.coroutine
|
||||||
def post(self):
|
def post(self):
|
||||||
|
@@ -106,7 +106,15 @@ class APIHandler(BaseHandler):
|
|||||||
"""Get the JSON model for a Group object"""
|
"""Get the JSON model for a Group object"""
|
||||||
return {
|
return {
|
||||||
'name': group.name,
|
'name': group.name,
|
||||||
'users': [ u.name for u in group.users ]
|
'users': [ u.name for u in group.users ],
|
||||||
|
}
|
||||||
|
|
||||||
|
def service_model(self, service):
|
||||||
|
"""Get the JSON model for a Service object"""
|
||||||
|
return {
|
||||||
|
'kind': 'service',
|
||||||
|
'name': service.name,
|
||||||
|
'admin': service.admin,
|
||||||
}
|
}
|
||||||
|
|
||||||
_user_model_types = {
|
_user_model_types = {
|
||||||
@@ -152,6 +160,7 @@ class APIHandler(BaseHandler):
|
|||||||
if not isinstance(groupname, str):
|
if not isinstance(groupname, str):
|
||||||
raise web.HTTPError(400, ("group names must be str, not %r", type(groupname)))
|
raise web.HTTPError(400, ("group names must be str, not %r", type(groupname)))
|
||||||
|
|
||||||
|
|
||||||
def options(self, *args, **kwargs):
|
def options(self, *args, **kwargs):
|
||||||
self.set_header('Access-Control-Allow-Headers', 'accept, content-type')
|
self.set_header('Access-Control-Allow-Headers', 'accept, content-type')
|
||||||
self.finish()
|
self.finish()
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
|
from binascii import hexlify
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from queue import Queue
|
from queue import Queue
|
||||||
import sys
|
import sys
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
@@ -217,7 +219,8 @@ def test_hub_authenticated(request):
|
|||||||
assert auth.login_url in r.headers['Location']
|
assert auth.login_url in r.headers['Location']
|
||||||
|
|
||||||
|
|
||||||
def test_service_cookie_auth(app, mockservice_url):
|
def test_hubauth_cookie(app, mockservice_url):
|
||||||
|
"""Test HubAuthenticated service with user cookies"""
|
||||||
cookies = app.login_user('badger')
|
cookies = app.login_user('badger')
|
||||||
r = requests.get(public_url(app, mockservice_url) + '/whoami/', cookies=cookies)
|
r = requests.get(public_url(app, mockservice_url) + '/whoami/', cookies=cookies)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
@@ -230,7 +233,8 @@ def test_service_cookie_auth(app, mockservice_url):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def test_service_token_auth(app, mockservice_url):
|
def test_hubauth_token(app, mockservice_url):
|
||||||
|
"""Test HubAuthenticated service with user API tokens"""
|
||||||
u = add_user(app.db, name='river')
|
u = add_user(app.db, name='river')
|
||||||
token = u.new_api_token()
|
token = u.new_api_token()
|
||||||
app.db.commit()
|
app.db.commit()
|
||||||
@@ -267,3 +271,44 @@ def test_service_token_auth(app, mockservice_url):
|
|||||||
path = urlparse(location).path
|
path = urlparse(location).path
|
||||||
assert path.endswith('/hub/login')
|
assert path.endswith('/hub/login')
|
||||||
|
|
||||||
|
|
||||||
|
def test_hubauth_service_token(app, mockservice_url, io_loop):
|
||||||
|
"""Test HubAuthenticated service with service API tokens"""
|
||||||
|
|
||||||
|
token = hexlify(os.urandom(5)).decode('utf8')
|
||||||
|
name = 'test-api-service'
|
||||||
|
app.service_tokens[token] = name
|
||||||
|
io_loop.run_sync(app.init_api_tokens)
|
||||||
|
|
||||||
|
# token in Authorization header
|
||||||
|
r = requests.get(public_url(app, mockservice_url) + '/whoami/',
|
||||||
|
headers={
|
||||||
|
'Authorization': 'token %s' % token,
|
||||||
|
})
|
||||||
|
r.raise_for_status()
|
||||||
|
reply = r.json()
|
||||||
|
assert reply == {
|
||||||
|
'kind': 'service',
|
||||||
|
'name': name,
|
||||||
|
'admin': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
# token in ?token parameter
|
||||||
|
r = requests.get(public_url(app, mockservice_url) + '/whoami/?token=%s' % token)
|
||||||
|
r.raise_for_status()
|
||||||
|
reply = r.json()
|
||||||
|
assert reply == {
|
||||||
|
'kind': 'service',
|
||||||
|
'name': name,
|
||||||
|
'admin': False,
|
||||||
|
}
|
||||||
|
|
||||||
|
r = requests.get(public_url(app, mockservice_url) + '/whoami/?token=no-such-token',
|
||||||
|
allow_redirects=False,
|
||||||
|
)
|
||||||
|
assert r.status_code == 302
|
||||||
|
assert 'Location' in r.headers
|
||||||
|
location = r.headers['Location']
|
||||||
|
path = urlparse(location).path
|
||||||
|
assert path.endswith('/hub/login')
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user