Skip to content

Commit

Permalink
fix session creation logic
Browse files Browse the repository at this point in the history
  • Loading branch information
SKairinos committed Sep 27, 2023
1 parent ef8b495 commit 217b0b4
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 36 deletions.
2 changes: 1 addition & 1 deletion codeforlife/user/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by Django 3.2.20 on 2023-09-27 14:30
# Generated by Django 3.2.20 on 2023-09-27 15:03

import django.contrib.auth.models
from django.db import migrations, models
Expand Down
66 changes: 32 additions & 34 deletions codeforlife/user/models/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ class Session(AbstractBaseSession):
on_delete=models.CASCADE,
)

@property
def is_expired(self):
return self.expire_date < timezone.now()

@property
def store(self):
return self.get_session_store_class()(self.session_key)
Expand All @@ -58,7 +62,8 @@ class SessionStore(DBStore):
"""
A custom session store interface to support:
1. creating only one session per user;
2. clearing expired sessions per user.
2. setting a session's auth factors;
3. clearing a user's expired sessions.
https://docs.djangoproject.com/en/3.2/topics/http/sessions/#example
"""

Expand All @@ -68,45 +73,38 @@ def get_model_class(cls):

def create_model_instance(self, data):
Session = self.get_model_class()
session: Session = None
session: Session

# Get user ID if not an anon user.
try:
user_id = int(data.get(SESSION_KEY))
except (ValueError, TypeError):
user_id = None

if user_id:
# Clear expired sessions for user.
self.clear_expired(user_id)

try:
# Return user's non-expired session and update its data.
session: Session = Session.objects.get(user_id=user_id)
session.session_data = self.encode(data)
return session
session = Session.objects.get(user_id=user_id)

if session.is_expired:
self.clear_expired(user_id)
session = super().create_model_instance(data)
# Despite having the user's ID, DO NOT set session.user.
else:
session.session_data = self.encode(data)

except Session.DoesNotExist:
# Get and set user's enabled auth factors in the session.
user = User.objects.get(id=user_id)
else:
user = None

# Create session.
session = super().create_model_instance(data)
session.user = user
session.save()

# Create session auth factors.
if user:
session_auth_factor.SessionAuthFactor.objects.bulk_create(
[
session_auth_factor.SessionAuthFactor(
session=session,
auth_factor=auth_factor,
)
for auth_factor in user.auth_factors
]
)
session = Session.objects.get(session_key=self.session_key)
session.user = user.User.objects.get(id=user_id)
session.session_data = self.encode(data)
session_auth_factor.SessionAuthFactor.objects.bulk_create(
[
session_auth_factor.SessionAuthFactor(
session=session,
auth_factor=auth_factor,
)
for auth_factor in session.user.auth_factors.all()
]
)

except (ValueError, TypeError):
# Create an anon session.
session = super().create_model_instance(data)

return session

Expand Down
2 changes: 1 addition & 1 deletion manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"django.contrib.messages",
"django.contrib.staticfiles",
"django.contrib.sites",
"codeforlife.user.apps.UserConfig",
"codeforlife.user",
"aimmo", # TODO: remove this
"game", # TODO: remove this
"common", # TODO: remove this
Expand Down

0 comments on commit 217b0b4

Please sign in to comment.