diff --git a/endpoints/api/__init__.py b/endpoints/api/__init__.py index 2dc28490c..78100f4a7 100644 --- a/endpoints/api/__init__.py +++ b/endpoints/api/__init__.py @@ -24,6 +24,8 @@ from endpoints.decorators import check_anon_protection from util.saas.metricqueue import time_decorator from util.security.crypto import encrypt_string, decrypt_string +# TTL (in seconds) for page tokens. +_PAGE_TOKEN_TTL = datetime.timedelta(days=2).total_seconds() logger = logging.getLogger(__name__) api_bp = Blueprint('api', __name__) @@ -223,7 +225,8 @@ def page_support(func): if query_args['next_page']: # Decrypt the page token. - unencrypted = decrypt_string(query_args['next_page'], app.config['PAGE_TOKEN_KEY']) + unencrypted = decrypt_string(query_args['next_page'], app.config['PAGE_TOKEN_KEY'], + ttl=_PAGE_TOKEN_TTL) if unencrypted is not None: try: page_token = json.loads(unencrypted) @@ -231,7 +234,7 @@ def page_support(func): pass # Note: if page_token is None, we'll receive the first page of results back. - (result, next_page_token) = func(self, query_args, page_token, *args, **kwargs) + (result, next_page_token) = func(self, query_args, page_token=page_token, *args, **kwargs) if next_page_token is not None: result['next_page'] = encrypt_string(json.dumps(next_page_token), app.config['PAGE_TOKEN_KEY']) diff --git a/endpoints/api/logs.py b/endpoints/api/logs.py index 62c397c4d..d2c144c1f 100644 --- a/endpoints/api/logs.py +++ b/endpoints/api/logs.py @@ -118,7 +118,7 @@ class RepositoryLogs(RepositoryParamResource): @query_param('endtime', 'Latest time to which to get logs (%m/%d/%Y %Z)', type=str) @query_param('page', 'The page number for the logs', type=int, default=1) @page_support - def get(self, args, page_token, namespace, repository): + def get(self, args, namespace, repository, page_token): """ List the logs for the specified repository. """ repo = model.repository.get_repository(namespace, repository) if not repo: @@ -164,7 +164,7 @@ class OrgLogs(ApiResource): @query_param('page', 'The page number for the logs', type=int, default=1) @page_support @require_scope(scopes.ORG_ADMIN) - def get(self, args, page_token, orgname): + def get(self, args, orgname, page_token): """ List the logs for the specified organization. """ permission = AdministerOrganizationPermission(orgname) if permission.can(): diff --git a/util/security/crypto.py b/util/security/crypto.py index fe1de2953..1bf46228b 100644 --- a/util/security/crypto.py +++ b/util/security/crypto.py @@ -7,11 +7,11 @@ def encrypt_string(string, key): f = Fernet(base64.urlsafe_b64encode(key)) return f.encrypt(string) -def decrypt_string(string, key): +def decrypt_string(string, key, ttl=None): """ Decrypts an encrypted string with the specified key. The key must be 32 raw bytes. """ f = Fernet(base64.urlsafe_b64encode(key)) try: - return f.decrypt(string) + return f.decrypt(string, ttl=ttl) except InvalidToken: return None except TypeError: