track activity of individual tokens

This commit is contained in:
Min RK
2017-12-19 11:23:11 +01:00
parent 9640364713
commit d16461052b
3 changed files with 21 additions and 4 deletions

View File

@@ -3,6 +3,7 @@
# Copyright (c) Jupyter Development Team. # Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License. # Distributed under the terms of the Modified BSD License.
from datetime import datetime
import json import json
from urllib.parse import quote from urllib.parse import quote
@@ -31,6 +32,9 @@ class TokenAPIHandler(APIHandler):
self.db.delete(orm_token) self.db.delete(orm_token)
self.db.commit() self.db.commit()
raise web.HTTPError(404) raise web.HTTPError(404)
# record activity whenever we see a token
orm_token.last_activity = datetime.utcnow()
self.db.commit()
self.write(json.dumps(model)) self.write(json.dumps(model))
@gen.coroutine @gen.coroutine
@@ -49,7 +53,7 @@ class TokenAPIHandler(APIHandler):
raise web.HTTPError(403) raise web.HTTPError(403)
else: else:
data = self.get_json_body() data = self.get_json_body()
# admin users can request # admin users can request tokens for other usrs
if data and data.get('username') != user.name: if data and data.get('username') != user.name:
if user.admin: if user.admin:
user = self.find_user(data['username']) user = self.find_user(data['username'])

View File

@@ -6,7 +6,7 @@
import copy import copy
import re import re
import time import time
from datetime import timedelta from datetime import datetime, timedelta
from http.client import responses from http.client import responses
from urllib.parse import urlparse, urlunparse, parse_qs, urlencode from urllib.parse import urlparse, urlunparse, parse_qs, urlencode
import uuid import uuid
@@ -179,7 +179,7 @@ class BaseHandler(RequestHandler):
def get_current_user_oauth_token(self): def get_current_user_oauth_token(self):
"""Get the current user identified by OAuth access token """Get the current user identified by OAuth access token
Separate from API token because OAuth access tokens Separate from API token because OAuth access tokens
can only be used for identifying users, can only be used for identifying users,
not using the API. not using the API.
@@ -191,8 +191,10 @@ class BaseHandler(RequestHandler):
if orm_token is None: if orm_token is None:
return None return None
else: else:
orm_token.last_activity = datetime.utcnow()
self.db.commit()
return self._user_from_orm(orm_token.user) return self._user_from_orm(orm_token.user)
def get_current_user_token(self): def get_current_user_token(self):
"""get_current_user from Authorization header token""" """get_current_user from Authorization header token"""
token = self.get_auth_token() token = self.get_auth_token()
@@ -202,6 +204,9 @@ class BaseHandler(RequestHandler):
if orm_token is None: if orm_token is None:
return None return None
else: else:
# record token activity
orm_token.last_activity = datetime.utcnow()
self.db.commit()
return orm_token.service or self._user_from_orm(orm_token.user) return orm_token.service or self._user_from_orm(orm_token.user)
def _user_for_cookie(self, cookie_name, cookie_value=None): def _user_for_cookie(self, cookie_name, cookie_value=None):

View File

@@ -319,6 +319,11 @@ class APIToken(Hashed, Base):
hashed = Column(Unicode(255), unique=True) hashed = Column(Unicode(255), unique=True)
prefix = Column(Unicode(16), index=True) prefix = Column(Unicode(16), index=True)
# token metadata for bookkeeping
created = Column(DateTime, default=datetime.utcnow)
last_activity = Column(DateTime)
note = Column(Unicode(1023))
def __repr__(self): def __repr__(self):
if self.user is not None: if self.user is not None:
kind = 'user' kind = 'user'
@@ -419,6 +424,9 @@ class OAuthAccessToken(Hashed, Base):
hashed = Column(Unicode(255), unique=True) hashed = Column(Unicode(255), unique=True)
prefix = Column(Unicode(16), index=True) prefix = Column(Unicode(16), index=True)
created = Column(DateTime, default=datetime.utcnow)
last_activity = Column(DateTime, nullable=True)
def __repr__(self): def __repr__(self):
return "<{cls}('{prefix}...', user='{user}'>".format( return "<{cls}('{prefix}...', user='{user}'>".format(
cls=self.__class__.__name__, cls=self.__class__.__name__,