Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/205.canada.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added functionality for `no-cache, no-store` cache control with `nocache_store` blueprint decorator.
24 changes: 23 additions & 1 deletion ckan/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@

import six

# (canada fork only): nocache decorator
# TODO: upstream contrib??
from functools import wraps

from urllib.parse import quote
from flask.wrappers import Response

Expand All @@ -18,6 +22,16 @@
log = logging.getLogger(__name__)


# (canada fork only): nocache decorator
# TODO: upstream contrib??
def nocache_store(f):
@wraps(f)
def decorated_function(*args, **kwargs):
request.environ['__no_cache_store__'] = True
return f(*args, **kwargs)
return decorated_function


def set_cors_headers_for_response(response: Response) -> Response:
u'''
Set up Access Control Allow headers if either origin_allow_all is True, or
Expand Down Expand Up @@ -49,6 +63,9 @@ def set_cache_control_headers_for_response(response: Response) -> Response:

# __no_cache__ should not be present when caching is allowed
allow_cache = u'__no_cache__' not in request.environ
# (canada fork only): nocache decorator
# TODO: upstream contrib??
allow_store = '__no_cache_store__' not in request.environ
limit_cache_by_cookie = u'__limit_cache_by_cookie__' in request.environ

if u'Pragma' in response.headers:
Expand All @@ -62,10 +79,15 @@ def set_cache_control_headers_for_response(response: Response) -> Response:
response.cache_control.must_revalidate = True
except ValueError:
pass
else:
# (canada fork only): nocache decorator
# TODO: upstream contrib??
elif allow_store:
# (canada fork only): set NOCACHE for logged in sessions
response.cache_control.no_cache = True
response.cache_control.private = True
else:
response.cache_control.no_cache = True
response.cache_control.no_store = True

# Invalidate cached pages upon login/logout
if limit_cache_by_cookie:
Expand Down
31 changes: 31 additions & 0 deletions ckan/views/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
from ckan.types import Context, Schema, Response
from ckan.lib import signals

# (canada fork only): nocache decorator
# TODO: upstream contrib??
from . import nocache_store

log = logging.getLogger(__name__)

# hooks for subclasses
Expand Down Expand Up @@ -476,6 +480,9 @@ def _prepare(self):
base.abort(403, _(u'Unauthorized to register as a user.'))
return context

# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def post(self) -> Union[Response, str]:
context = self._prepare()
try:
Expand Down Expand Up @@ -534,6 +541,9 @@ def post(self) -> Union[Response, str]:
resp = h.redirect_to(u'user.me')
return resp

# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def get(self,
data: Optional[dict[str, Any]] = None,
errors: Optional[dict[str, Any]] = None,
Expand Down Expand Up @@ -577,6 +587,9 @@ def rotate_token():
generate_csrf()


# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def login() -> Union[Response, str]:
for item in plugins.PluginImplementations(plugins.IAuthenticator):
response = item.login()
Expand Down Expand Up @@ -622,6 +635,9 @@ def login() -> Union[Response, str]:
return base.render("user/login.html", extra_vars)


# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def logout() -> Response:
for item in plugins.PluginImplementations(plugins.IAuthenticator):
response = item.logout()
Expand All @@ -644,6 +660,9 @@ def logout() -> Response:
return h.redirect_to('user.logged_out_page')


# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def logged_out_page() -> str:
return base.render(u'user/logout.html', {})

Expand Down Expand Up @@ -710,6 +729,9 @@ def _prepare(self):
except logic.NotAuthorized:
base.abort(403, _(u'Unauthorized to request reset password.'))

# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def post(self) -> Response:
self._prepare()
id = request.form.get(u'user', '')
Expand Down Expand Up @@ -796,6 +818,9 @@ def post(self) -> Response:
return h.redirect_to(config.get(
u'ckan.user_reset_landing_page'))

# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def get(self) -> str:
self._prepare()
return base.render(u'user/request_reset.html', {})
Expand Down Expand Up @@ -829,6 +854,9 @@ def _prepare(self, id: str) -> tuple[Context, dict[str, Any]]:
base.abort(403, msg)
return context, user_dict

# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def post(self, id: str) -> Union[Response, str]:
context, user_dict = self._prepare(id)
context[u'reset_password'] = True
Expand Down Expand Up @@ -876,6 +904,9 @@ def post(self, id: str) -> Union[Response, str]:
u'user_dict': user_dict
})

# (canada fork only): nocache decorator
# TODO: upstream contrib??
@nocache_store
def get(self, id: str,
errors: Optional[dict[str, Any]] = None,
error_summary: Optional[dict[str, Any]] = None) -> str:
Expand Down