Move the session into requests.session for universal access.

This commit is contained in:
voussoir 2023-02-01 22:04:44 -08:00
parent d16fcd7c48
commit e78a667ee3
15 changed files with 68 additions and 64 deletions

View file

@ -78,11 +78,14 @@ def before_request():
# In NGINX: proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # In NGINX: proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
request.is_localhost = (request.remote_addr == '127.0.0.1') request.is_localhost = (request.remote_addr == '127.0.0.1')
if site.localhost_only and not request.is_localhost: if site.localhost_only and not request.is_localhost:
flask.abort(403) return flask.abort(403)
session_manager._before_request(request)
@site.after_request @site.after_request
def after_request(response): def after_request(response):
response = flasktools.gzip_response(request, response) response = flasktools.gzip_response(request, response)
response = session_manager._after_request(response)
return response return response
site.route = flasktools.decorate_and_route( site.route = flasktools.decorate_and_route(
@ -95,7 +98,6 @@ site.route = flasktools.decorate_and_route(
default_theme='slate', default_theme='slate',
), ),
catch_etiquette_exception, catch_etiquette_exception,
session_manager.give_token
], ],
) )
@ -173,13 +175,11 @@ def back_url():
return request.args.get('goto') or request.referrer or '/' return request.args.get('goto') or request.referrer or '/'
def render_template(request, template_name, **kwargs): def render_template(request, template_name, **kwargs):
session = session_manager.get(request)
theme = request.cookies.get('etiquette_theme', None) theme = request.cookies.get('etiquette_theme', None)
response = flask.render_template( response = flask.render_template(
template_name, template_name,
request=request, request=request,
session=session,
theme=theme, theme=theme,
**kwargs, **kwargs,
) )

View file

@ -37,12 +37,10 @@ def get_user_id_redirect(user_id):
@site.route('/user/<username>/edit', methods=['POST']) @site.route('/user/<username>/edit', methods=['POST'])
def post_user_edit(username): def post_user_edit(username):
session = session_manager.get(request) if not request.session:
if not session:
return flasktools.json_response(etiquette.exceptions.Unauthorized().jsonify(), status=403) return flasktools.json_response(etiquette.exceptions.Unauthorized().jsonify(), status=403)
user = common.P_user(username, response_type='json') user = common.P_user(username, response_type='json')
if session.user != user: if request.session.user != user:
return flasktools.json_response(etiquette.exceptions.Unauthorized().jsonify(), status=403) return flasktools.json_response(etiquette.exceptions.Unauthorized().jsonify(), status=403)
display_name = request.form.get('display_name') display_name = request.form.get('display_name')
@ -68,8 +66,7 @@ def get_login():
@site.route('/login', methods=['POST']) @site.route('/login', methods=['POST'])
@flasktools.required_fields(['username', 'password']) @flasktools.required_fields(['username', 'password'])
def post_login(): def post_login():
session = session_manager.get(request) if request.session.user:
if session.user:
exc = etiquette.exceptions.AlreadySignedIn() exc = etiquette.exceptions.AlreadySignedIn()
response = exc.jsonify() response = exc.jsonify()
return flasktools.json_response(response, status=403) return flasktools.json_response(response, status=403)
@ -93,8 +90,8 @@ def post_login():
response = exc.jsonify() response = exc.jsonify()
return flasktools.json_response(response, status=400) return flasktools.json_response(response, status=400)
session = sessions.Session(request, user) request.session = sessions.Session(request, user)
session_manager.add(session) session_manager.add(request.session)
return flasktools.json_response({}) return flasktools.json_response({})
@site.route('/logout', methods=['POST']) @site.route('/logout', methods=['POST'])
@ -112,8 +109,7 @@ def get_register():
@site.route('/register', methods=['POST']) @site.route('/register', methods=['POST'])
@flasktools.required_fields(['username', 'password_1', 'password_2']) @flasktools.required_fields(['username', 'password_1', 'password_2'])
def post_register(): def post_register():
session = session_manager.get(request) if request.session.user:
if session.user:
exc = etiquette.exceptions.AlreadySignedIn() exc = etiquette.exceptions.AlreadySignedIn()
response = exc.jsonify() response = exc.jsonify()
return flasktools.json_response(response, status=403) return flasktools.json_response(response, status=403)
@ -133,6 +129,6 @@ def post_register():
with common.P.transaction: with common.P.transaction:
user = common.P.new_user(username, password_1, display_name=display_name) user = common.P.new_user(username, password_1, display_name=display_name)
session = sessions.Session(request, user) request.session = sessions.Session(request, user)
session_manager.add(session) session_manager.add(request.session)
return flasktools.json_response({}) return flasktools.json_response({})

View file

@ -34,6 +34,45 @@ class SessionManager:
def __init__(self, maxlen=None): def __init__(self, maxlen=None):
self.sessions = cacheclass.Cache(maxlen=maxlen) self.sessions = cacheclass.Cache(maxlen=maxlen)
def _before_request(self, request):
# Inject new token so the function doesn't know the difference
token = request.cookies.get('etiquette_session', None)
if not token or token not in self.sessions:
token = _generate_token()
# cookies is currently an ImmutableMultiDict, but in order to
# trick the wrapped function I'm gonna have to mutate it.
# It is important to use a werkzeug MultiDict and not a plain
# Python dict, because werkzeug puts cookies into lists like
# {name: [value]} and then cookies.get pulls the first item out
# of that list. A plain dict wouldn't have this .get behavior.
request.cookies = werkzeug.datastructures.MultiDict(request.cookies)
request.cookies['etiquette_session'] = token
try:
session = self.get(request)
except KeyError:
session = Session(request, user=None)
self.add(session)
else:
session.maintain()
request.session = session
return session
def _after_request(self, response):
# Send the token back to the client
# but only if the endpoint didn't manually set the cookie.
function_cookies = response.headers.get_all('Set-Cookie')
if not any('etiquette_session=' in cookie for cookie in function_cookies):
response.set_cookie(
'etiquette_session',
value=request.session.token,
max_age=SESSION_MAX_AGE,
httponly=True,
)
return response
def add(self, session): def add(self, session):
self.sessions[session.token] = session self.sessions[session.token] = session
@ -61,41 +100,10 @@ class SessionManager:
''' '''
@functools.wraps(function) @functools.wraps(function)
def wrapped(*args, **kwargs): def wrapped(*args, **kwargs):
# Inject new token so the function doesn't know the difference self._before_request(request)
token = request.cookies.get('etiquette_session', None)
if not token or token not in self.sessions:
token = _generate_token()
# cookies is currently an ImmutableMultiDict, but in order to
# trick the wrapped function I'm gonna have to mutate it.
# It is important to use a werkzeug MultiDict and not a plain
# Python dict, because werkzeug puts cookies into lists like
# {name: [value]} and then cookies.get pulls the first item out
# of that list. A plain dict wouldn't have this .get behavior.
request.cookies = werkzeug.datastructures.MultiDict(request.cookies)
request.cookies['etiquette_session'] = token
try:
session = self.get(request)
except KeyError:
session = Session(request, user=None)
self.add(session)
else:
session.maintain()
response = function(*args, **kwargs) response = function(*args, **kwargs)
return self._after_request(response)
# Send the token back to the client
# but only if the endpoint didn't manually set the cookie.
function_cookies = response.headers.get_all('Set-Cookie')
if not any('etiquette_session=' in cookie for cookie in function_cookies):
response.set_cookie(
'etiquette_session',
value=session.token,
max_age=SESSION_MAX_AGE,
httponly=True,
)
return response
return wrapped return wrapped
def remove(self, token): def remove(self, token):

View file

@ -28,7 +28,7 @@ th, td
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<div class="panel"> <div class="panel">
<h1>Admin tools</h1> <h1>Admin tools</h1>

View file

@ -99,7 +99,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right"> <div id="content_body" class="sticky_side_right sticky_bottom_right">
<div id="left"> <div id="left">
<div id="album_list" class="panel"> <div id="album_list" class="panel">
@ -162,7 +162,7 @@ const ALBUM_ID = undefined;
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right"> <div id="content_body" class="sticky_side_right sticky_bottom_right">
<div id="right" class="panel"> <div id="right" class="panel">
{% if view != "list" %} {% if view != "list" %}

View file

@ -34,7 +34,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<div id="bookmark_list" class="panel"> <div id="bookmark_list" class="panel">
<h1>{{bookmarks|length}} Bookmarks</h1> <h1>{{bookmarks|length}} Bookmarks</h1>

View file

@ -96,7 +96,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right"> <div id="content_body" class="sticky_side_right sticky_bottom_right">
<div id="left"> <div id="left">

View file

@ -72,7 +72,7 @@ form h2
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<form id="login_form" class="panel" action="/login" method="post"> <form id="login_form" class="panel" action="/login" method="post">
<h2>Log in</h2> <h2>Log in</h2>

View file

@ -158,7 +158,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<div id="left" class="panel"> <div id="left" class="panel">
<div id="editor_area"> <div id="editor_area">

View file

@ -71,8 +71,8 @@ body > .nice_link
<a class="nice_link navigation_link" href="/tags">Browse tags</a> <a class="nice_link navigation_link" href="/tags">Browse tags</a>
<a class="nice_link navigation_link" href="/albums">Browse albums</a> <a class="nice_link navigation_link" href="/albums">Browse albums</a>
<a class="nice_link navigation_link" href="/bookmarks">Bookmarks</a> <a class="nice_link navigation_link" href="/bookmarks">Bookmarks</a>
{% if session.user %} {% if request.session.user %}
<a class="nice_link navigation_link" href="/userid/{{session.user.id}}">{{session.user.display_name}}</a> <a class="nice_link navigation_link" href="/userid/{{request.session.user.id}}">{{request.session.user.display_name}}</a>
{% else %} {% else %}
<a class="nice_link navigation_link" href="/login">Log in</a> <a class="nice_link navigation_link" href="/login">Log in</a>
{% endif %} {% endif %}

View file

@ -186,7 +186,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<div id="left" class="panel"> <div id="left" class="panel">
{% for tagtype in ["musts", "mays", "forbids"] %} {% for tagtype in ["musts", "mays", "forbids"] %}

View file

@ -92,7 +92,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<div id="right" class="panel"> <div id="right" class="panel">
<a id="name_tag" target="_blank">Swipe!</a> <a id="name_tag" target="_blank">Swipe!</a>

View file

@ -87,7 +87,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body" class="sticky_side_right sticky_bottom_right"> <div id="content_body" class="sticky_side_right sticky_bottom_right">
<div id="right" class="panel"> <div id="right" class="panel">
<div id="editor_area"> <div id="editor_area">

View file

@ -18,7 +18,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<p>test</p> <p>test</p>
</div> </div>

View file

@ -27,7 +27,7 @@
</head> </head>
<body> <body>
{{header.make_header(session=session)}} {{header.make_header(session=request.session)}}
<div id="content_body"> <div id="content_body">
<div id="hierarchy_self" class="panel"> <div id="hierarchy_self" class="panel">
<h1 id="display_name">{{user.display_name}}</h1> <h1 id="display_name">{{user.display_name}}</h1>
@ -82,7 +82,7 @@
</body> </body>
<script type="text/javascript"> <script type="text/javascript">
{% if user.id == session.user.id %} {% if user.id == request.session.user.id %}
const USERNAME = "{{user.username}}"; const USERNAME = "{{user.username}}";
profile_ed_on_open = undefined; profile_ed_on_open = undefined;