Create sessions for anons as well, instead of just logged in.

It makes sense that anon sessions are still sessions. So @give_token
will ensure that every request has a session. Logged in conditionals
move from 'if session' to 'if session.user'.
This commit is contained in:
voussoir 2018-01-15 18:41:21 -08:00
parent 8a1f2c65f9
commit be0fca729f
4 changed files with 28 additions and 12 deletions

View file

@ -51,7 +51,8 @@ def get_login():
@session_manager.give_token @session_manager.give_token
@decorators.required_fields(['username', 'password']) @decorators.required_fields(['username', 'password'])
def post_login(): def post_login():
if session_manager.get(request): session = session_manager.get(request)
if session.user:
exc = etiquette.exceptions.AlreadySignedIn() exc = etiquette.exceptions.AlreadySignedIn()
response = etiquette.jsonify.exception(exc) response = etiquette.jsonify.exception(exc)
return jsonify.make_json_response(response, status=403) return jsonify.make_json_response(response, status=403)
@ -94,7 +95,8 @@ def get_register():
@decorators.catch_etiquette_exception @decorators.catch_etiquette_exception
@decorators.required_fields(['username', 'password_1', 'password_2']) @decorators.required_fields(['username', 'password_1', 'password_2'])
def post_register(): def post_register():
if session_manager.get(request): session = session_manager.get(request)
if session.user:
exc = etiquette.exceptions.AlreadySignedIn() exc = etiquette.exceptions.AlreadySignedIn()
response = etiquette.jsonify.exception(exc) response = etiquette.jsonify.exception(exc)
return jsonify.make_json_response(response, status=403) return jsonify.make_json_response(response, status=403)

View file

@ -6,6 +6,8 @@ import werkzeug.wrappers
import etiquette import etiquette
SESSION_MAX_AGE = 86400
def _generate_token(length=32): def _generate_token(length=32):
randbytes = os.urandom(math.ceil(length / 2)) randbytes = os.urandom(math.ceil(length / 2))
token = ''.join('{:02x}'.format(x) for x in randbytes) token = ''.join('{:02x}'.format(x) for x in randbytes)
@ -35,7 +37,7 @@ class SessionManager:
def get(self, token): def get(self, token):
token = _normalize_token(token) token = _normalize_token(token)
session = self.sessions.get(token, None) session = self.sessions[token]
return session return session
def give_token(self, function): def give_token(self, function):
@ -54,6 +56,14 @@ class SessionManager:
request.cookies = dict(request.cookies) request.cookies = dict(request.cookies)
request.cookies['etiquette_session'] = token request.cookies['etiquette_session'] = token
try:
session = self.get(token)
except KeyError:
session = Session(request, user=None)
self.add(session)
else:
session.maintain()
response = function(*args, **kwargs) response = function(*args, **kwargs)
if not isinstance(response, (flask.Response, werkzeug.wrappers.Response)): if not isinstance(response, (flask.Response, werkzeug.wrappers.Response)):
response = flask.Response(response) response = flask.Response(response)
@ -64,17 +74,15 @@ class SessionManager:
if headerkey == 'Set-Cookie' and value.startswith('etiquette_session='): if headerkey == 'Set-Cookie' and value.startswith('etiquette_session='):
break break
else: else:
response.set_cookie('etiquette_session', value=token, max_age=86400) response.set_cookie(
self.maintain(token) 'etiquette_session',
value=session.token,
max_age=SESSION_MAX_AGE,
)
return response return response
return wrapped return wrapped
def maintain(self, token):
session = self.get(token)
if session:
session.maintain()
def remove(self, token): def remove(self, token):
token = _normalize_token(token) token = _normalize_token(token)
if token in self.sessions: if token in self.sessions:
@ -88,5 +96,11 @@ class Session:
self.user_agent = request.headers.get('User-Agent', '') self.user_agent = request.headers.get('User-Agent', '')
self.last_activity = int(etiquette.helpers.now()) self.last_activity = int(etiquette.helpers.now())
def __repr__(self):
if self.user:
return 'Session %s for user %s' % (self.token, self.user)
else:
return 'Session %s for anonymous' % self.token
def maintain(self): def maintain(self):
self.last_activity = int(etiquette.helpers.now()) self.last_activity = int(etiquette.helpers.now())

View file

@ -3,7 +3,7 @@
<a class="header_element" href="/">Etiquette</a> <a class="header_element" href="/">Etiquette</a>
<a class="header_element" href="/search">Search</a> <a class="header_element" href="/search">Search</a>
<a class="header_element" href="/tags">Tags</a> <a class="header_element" href="/tags">Tags</a>
{% if session %} {% if session.user %}
<a class="header_element" href="/user/{{session.user.username}}">{{session.user.username}}</a> <a class="header_element" href="/user/{{session.user.username}}">{{session.user.username}}</a>
<a class="header_element" href="/logout" style="flex:0">Logout</a> <a class="header_element" href="/logout" style="flex:0">Logout</a>
{% else %} {% else %}

View file

@ -38,7 +38,7 @@ body, .nice_link
<a class="nice_link" href="/tags">Browse tags</a> <a class="nice_link" href="/tags">Browse tags</a>
<a class="nice_link" href="/albums">Browse albums</a> <a class="nice_link" href="/albums">Browse albums</a>
<a class="nice_link" href="/bookmarks">Bookmarks</a> <a class="nice_link" href="/bookmarks">Bookmarks</a>
{% if session %} {% if session.user %}
<a class="nice_link" href="/user/{{session.user.username}}">{{session.user.username}}</a> <a class="nice_link" href="/user/{{session.user.username}}">{{session.user.username}}</a>
{% else %} {% else %}
<a class="nice_link" href="/login">Log in</a> <a class="nice_link" href="/login">Log in</a>