token expiry fixes

typos in token expiry:

- omitted from token model (it's in the spec in docs, but wasn't in the model)
- wrong type when sorting oauth tokens on token page could cause token page to not render
This commit is contained in:
Min RK
2018-09-10 16:01:41 +02:00
parent 3360817cb6
commit 06f646099f
4 changed files with 54 additions and 9 deletions

View File

@@ -2,8 +2,8 @@
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
from datetime import datetime
import json
import datetime
from http.client import responses
@@ -14,7 +14,17 @@ from .. import orm
from ..handlers import BaseHandler
from ..utils import isoformat, url_path_join
class APIHandler(BaseHandler):
"""Base class for API endpoints
Differences from page handlers:
- JSON responses and errors
- strict referer checking for Cookie-authenticated requests
- strict content-security-policy
- methods for REST API models
"""
@property
def content_security_policy(self):
@@ -137,7 +147,7 @@ class APIHandler(BaseHandler):
'oauth_client': token.client.description or token.client.client_id,
}
if token.expires_at:
expires_at = datetime.datetime.fromtimestamp(token.expires_at)
expires_at = datetime.fromtimestamp(token.expires_at)
else:
raise TypeError(
"token must be an APIToken or OAuthAccessToken, not %s"
@@ -157,6 +167,7 @@ class APIHandler(BaseHandler):
'kind': kind,
'created': isoformat(token.created),
'last_activity': isoformat(token.last_activity),
'expires_at': isoformat(expires_at),
}
model.update(extra)
return model

View File

@@ -247,9 +247,11 @@ class TokenPageHandler(BaseHandler):
api_tokens.append(token)
# group oauth client tokens by client id
# AccessTokens have expires_at as an integer timestamp
now_timestamp = now.timestamp()
oauth_tokens = defaultdict(list)
for token in user.oauth_tokens:
if token.expires_at and token.expires_at < now:
if token.expires_at and token.expires_at < now_timestamp:
self.log.warning("Deleting expired token")
self.db.delete(token)
self.db.commit()

View File

@@ -1214,14 +1214,19 @@ def test_token_as_user_deprecated(app, as_user, for_user, status):
@mark.gen_test
@mark.parametrize("headers, status, note", [
({}, 200, 'test note'),
({}, 200, ''),
({'Authorization': 'token bad'}, 403, ''),
@mark.parametrize("headers, status, note, expires_in", [
({}, 200, 'test note', None),
({}, 200, '', 100),
({'Authorization': 'token bad'}, 403, '', None),
])
def test_get_new_token(app, headers, status, note):
def test_get_new_token(app, headers, status, note, expires_in):
options = {}
if note:
body = json.dumps({'note': note})
options['note'] = note
if expires_in:
options['expires_in'] = expires_in
if options:
body = json.dumps(options)
else:
body = ''
# request a new token
@@ -1239,6 +1244,10 @@ def test_get_new_token(app, headers, status, note):
assert reply['user'] == 'admin'
assert reply['created']
assert 'last_activity' in reply
if expires_in:
assert isinstance(reply['expires_at'], str)
else:
assert reply['expires_at'] is None
if note:
assert reply['note'] == note
else:

View File

@@ -598,6 +598,29 @@ def test_announcements(app, announcements):
assert_announcement("logout", r.text)
@pytest.mark.gen_test
def test_token_page(app):
name = "cake"
cookies = yield app.login_user(name)
r = yield get_page("token", app, cookies=cookies)
r.raise_for_status()
assert urlparse(r.url).path.endswith('/hub/token')
assert "Request new API token" in r.text
assert "API Tokens" in r.text
assert "Server at %s" % app.users[name].url in r.text
# no oauth tokens yet, shouldn't have that section
assert "Authorized Applications" not in r.text
# spawn the user to trigger oauth, etc.
r = yield get_page("spawn", app, cookies=cookies)
r.raise_fo_status()
r = yield get_page("token", app, cookies=cookies)
r.raise_for_status()
assert "API Tokens" in r.text
assert "Authorized Applications" not in r.text
@pytest.mark.gen_test
def test_server_not_running_api_request(app):
cookies = yield app.login_user("bees")