diff --git a/CTFd/api/v1/users.py b/CTFd/api/v1/users.py index 895c9ea..20e3998 100644 --- a/CTFd/api/v1/users.py +++ b/CTFd/api/v1/users.py @@ -1,7 +1,7 @@ from flask import abort, request from flask_restx import Namespace, Resource -from CTFd.cache import clear_standings +from CTFd.cache import clear_standings, clear_user_session from CTFd.models import ( Awards, Notifications, @@ -107,6 +107,7 @@ class UserPublic(Resource): db.session.close() + clear_user_session(user_id=user_id) clear_standings() return {"success": True, "data": response} @@ -123,6 +124,7 @@ class UserPublic(Resource): db.session.commit() db.session.close() + clear_user_session(user_id=user_id) clear_standings() return {"success": True} @@ -149,6 +151,7 @@ class UserPrivate(Resource): db.session.commit() + clear_user_session(user_id=user.id) response = schema.dump(response.data) db.session.close() diff --git a/CTFd/cache/__init__.py b/CTFd/cache/__init__.py index 200e207..ba31a2b 100644 --- a/CTFd/cache/__init__.py +++ b/CTFd/cache/__init__.py @@ -48,4 +48,5 @@ def clear_pages(): def clear_user_session(user_id): from CTFd.utils.user import get_user_type + cache.delete_memoized(get_user_type, user_id=user_id) diff --git a/tests/cache/__init__.py b/tests/cache/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/cache/test_cache.py b/tests/cache/test_cache.py new file mode 100644 index 0000000..0d01133 --- /dev/null +++ b/tests/cache/test_cache.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from CTFd.models import Users +from CTFd.utils.user import is_admin, get_current_user +from CTFd.utils.security.auth import login_user +from tests.helpers import create_ctfd, destroy_ctfd, register_user + +from CTFd.cache import clear_user_session + + +def test_clear_user_session(): + app = create_ctfd() + with app.app_context(): + register_user(app) + + # Users by default should have a non-admin type + user = Users.query.filter_by(id=2).first() + with app.test_request_context("/"): + login_user(user) + user = get_current_user() + assert user.id == 2 + assert user.type == "user" + assert is_admin() is False + + # Set the user's updated type + user = Users.query.filter_by(id=2).first() + user.type = "admin" + app.db.session.commit() + + # The user shouldn't be considered admin because their type is still cached + user = Users.query.filter_by(id=2).first() + with app.test_request_context("/"): + login_user(user) + user = get_current_user() + assert user.id == 2 + assert user.type == "admin" + assert is_admin() is False + + # Clear the user's cached session (for now just the type) + clear_user_session(user_id=2) + + # The user's type should now be admin + user = Users.query.filter_by(id=2).first() + with app.test_request_context("/"): + login_user(user) + user = get_current_user() + assert user.id == 2 + assert user.type == "admin" + assert is_admin() is True + destroy_ctfd(app)