Browse Source

Merge pull request #491 from justanr/ISS-452-403-when-visiting-non-anonymous-area

Force login if forum area doesn't allow guest access
Peter Justin 6 years ago
parent
commit
2817349247
4 changed files with 67 additions and 1 deletions
  1. 31 0
      flaskbb/forum/utils.py
  2. 3 0
      flaskbb/forum/views.py
  3. 32 0
      tests/unit/forum/test_forum_utils.py
  4. 1 1
      tox.ini

+ 31 - 0
flaskbb/forum/utils.py

@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+"""
+    flaskbb.forum.utils
+    ~~~~~~~~~~~~~~~~~~~
+
+    Utilities specific to the FlaskBB forums module
+
+    :copyright: (c) 2018 the FlaskBB Team
+    :license: BSD, see LICENSE for more details
+"""
+
+from flask import current_app
+from flask_login import current_user
+
+from .locals import current_forum
+
+
+def force_login_if_needed():
+    """
+    Forces a login if the current user is unauthed and the current forum
+    doesn't allow guest users.
+    """
+
+    if current_forum and should_force_login(current_user, current_forum):
+        return current_app.login_manager.unauthorized()
+
+
+def should_force_login(user, forum):
+    return not user.is_authenticated and not (
+        {g.id for g in forum.groups} & {g.id for g in user.groups}
+    )

+ 3 - 0
flaskbb/forum/views.py

@@ -39,6 +39,7 @@ from flaskbb.utils.requirements import (CanAccessForum,
                                         IsAtleastModeratorInForum)
 from flaskbb.utils.settings import flaskbb_config
 from .locals import current_topic, current_forum, current_category
+from .utils import force_login_if_needed
 
 impl = HookimplMarker("flaskbb")
 
@@ -1246,4 +1247,6 @@ def flaskbb_load_blueprints(app):
         ],
         view_func=MarkdownPreview.as_view("markdown_preview")
     )
+
+    forum.before_request(force_login_if_needed)
     app.register_blueprint(forum, url_prefix=app.config["FORUM_URL_PREFIX"])

+ 32 - 0
tests/unit/forum/test_forum_utils.py

@@ -0,0 +1,32 @@
+from flask import _request_ctx_stack, url_for
+
+from flaskbb.forum import utils
+from flaskbb.forum.models import Forum
+from flaskbb.user.models import Group
+
+
+class TestForceLoginHelpers(object):
+    def test_would_not_force_login_for_authed_user(self, user, forum):
+        assert not utils.should_force_login(user, forum)
+
+    def test_would_not_force_login_for_anon_in_guest_allowed(self, forum, guest):
+        assert not utils.should_force_login(guest, forum)
+
+    def test_would_force_login_for_anon_in_guest_unallowed(self, guest, category):
+        forum = Forum(title="no guest", category=category)
+        forum.groups = Group.query.filter(Group.guest == False).all()
+
+        assert utils.should_force_login(guest, forum)
+
+    def test_redirects_to_login_with_anon(
+        self, guest, category, request_context, application
+    ):
+        forum = Forum(title="no guest", category=category)
+        forum.groups = Group.query.filter(Group.guest == False).all()
+        # sets current_forum
+        _request_ctx_stack.top.forum = forum
+
+        result = utils.force_login_if_needed()
+
+        # use in rather than == because it can contain query params as well
+        assert url_for(application.config["LOGIN_VIEW"]) in result.headers["Location"]

+ 1 - 1
tox.ini

@@ -35,7 +35,7 @@ commands =
 [flake8]
 ignore = E712, E711, C901, W503
 max-complexity = 10
-max-line-length = 80
+max-line-length = 88
 exclude = flaskbb/configs/default.py,flaskbb/_compat.py
 
 [pytest]