diff --git a/test/actionsmap/moulitest.yml b/test/actionsmap/moulitest.yml index 88ddeae0..9802037d 100644 --- a/test/actionsmap/moulitest.yml +++ b/test/actionsmap/moulitest.yml @@ -4,7 +4,6 @@ ############################# _global: namespace: moulitest - cookie_name: moulitest authentication: api: dummy cli: dummy diff --git a/test/src/authenticators/dummy.py b/test/src/authenticators/dummy.py index 904d6ed4..7590500d 100644 --- a/test/src/authenticators/dummy.py +++ b/test/src/authenticators/dummy.py @@ -1,13 +1,16 @@ # -*- coding: utf-8 -*- import logging -from moulinette.core import MoulinetteError +from moulinette.utils.text import random_ascii +from moulinette.core import MoulinetteError, MoulinetteAuthenticationError from moulinette.authentication import BaseAuthenticator -logger = logging.getLogger("moulinette.authenticator.dummy") +logger = logging.getLogger("moulinette.authenticator.yoloswag") # Dummy authenticator implementation +session_secret = random_ascii() + class Authenticator(BaseAuthenticator): @@ -24,3 +27,50 @@ class Authenticator(BaseAuthenticator): raise MoulinetteError("invalid_password", raw_msg=True) return + + def set_session_cookie(self, infos): + + from bottle import response + + assert isinstance(infos, dict) + + # This allows to generate a new session id or keep the existing one + current_infos = self.get_session_cookie(raise_if_no_session_exists=False) + new_infos = {"id": current_infos["id"]} + new_infos.update(infos) + + response.set_cookie( + "moulitest", + new_infos, + secure=True, + secret=session_secret, + httponly=True, + # samesite="strict", # Bottle 0.12 doesn't support samesite, to be added in next versions + ) + + def get_session_cookie(self, raise_if_no_session_exists=True): + + from bottle import request + + try: + infos = request.get_cookie( + "moulitest", secret=session_secret, default={} + ) + except Exception: + if not raise_if_no_session_exists: + return {"id": random_ascii()} + raise MoulinetteAuthenticationError("unable_authenticate") + + if "id" not in infos: + infos["id"] = random_ascii() + + return infos + + @staticmethod + def delete_session_cookie(self): + + from bottle import response + + response.set_cookie("moulitest", "", max_age=-1) + response.delete_cookie("moulitest") + diff --git a/test/src/authenticators/yoloswag.py b/test/src/authenticators/yoloswag.py index d199f121..8607be40 100644 --- a/test/src/authenticators/yoloswag.py +++ b/test/src/authenticators/yoloswag.py @@ -1,13 +1,16 @@ # -*- coding: utf-8 -*- import logging -from moulinette.core import MoulinetteError +from moulinette.utils.text import random_ascii +from moulinette.core import MoulinetteError, MoulinetteAuthenticationError from moulinette.authentication import BaseAuthenticator logger = logging.getLogger("moulinette.authenticator.yoloswag") # Dummy authenticator implementation +session_secret = random_ascii() + class Authenticator(BaseAuthenticator): @@ -24,3 +27,50 @@ class Authenticator(BaseAuthenticator): raise MoulinetteError("invalid_password", raw_msg=True) return + + def set_session_cookie(self, infos): + + from bottle import response + + assert isinstance(infos, dict) + + # This allows to generate a new session id or keep the existing one + current_infos = self.get_session_cookie(raise_if_no_session_exists=False) + new_infos = {"id": current_infos["id"]} + new_infos.update(infos) + + response.set_cookie( + "moulitest", + new_infos, + secure=True, + secret=session_secret, + httponly=True, + # samesite="strict", # Bottle 0.12 doesn't support samesite, to be added in next versions + ) + + def get_session_cookie(self, raise_if_no_session_exists=True): + + from bottle import request + + try: + infos = request.get_cookie( + "moulitest", secret=session_secret, default={} + ) + except Exception: + if not raise_if_no_session_exists: + return {"id": random_ascii()} + raise MoulinetteAuthenticationError("unable_authenticate") + + if "id" not in infos: + infos["id"] = random_ascii() + + return infos + + @staticmethod + def delete_session_cookie(self): + + from bottle import response + + response.set_cookie("moulitest", "", max_age=-1) + response.delete_cookie("moulitest") + diff --git a/test/test_auth.py b/test/test_auth.py index a245cc58..5563a92e 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -66,7 +66,7 @@ class TestAuthAPI: def test_login(self, moulinette_webapi): assert self.login(moulinette_webapi).text == "Logged in" - assert "session.moulitest" in moulinette_webapi.cookies + assert "moulitest" in moulinette_webapi.cookies def test_login_bad_password(self, moulinette_webapi): assert ( @@ -74,7 +74,7 @@ class TestAuthAPI: == "invalid_password" ) - assert "session.moulitest" not in moulinette_webapi.cookies + assert "moulitest" not in moulinette_webapi.cookies def test_login_csrf_attempt(self, moulinette_webapi): # C.f. @@ -86,7 +86,7 @@ class TestAuthAPI: in self.login(moulinette_webapi, csrf=True, status=403).text ) assert not any( - c.name == "session.moulitest" for c in moulinette_webapi.cookiejar + c.name == "moulitest" for c in moulinette_webapi.cookiejar ) def test_login_then_legit_request_without_cookies(self, moulinette_webapi): @@ -99,7 +99,7 @@ class TestAuthAPI: def test_login_then_legit_request(self, moulinette_webapi): self.login(moulinette_webapi) - assert "session.moulitest" in moulinette_webapi.cookies + assert "moulitest" in moulinette_webapi.cookies assert ( moulinette_webapi.get("/test-auth/default", status=200).text @@ -124,7 +124,7 @@ class TestAuthAPI: def test_login_other_profile(self, moulinette_webapi): self.login(moulinette_webapi, profile="yoloswag", password="yoloswag") - assert "session.moulitest" in moulinette_webapi.cookies + assert "moulitest" in moulinette_webapi.cookies def test_login_wrong_profile(self, moulinette_webapi): self.login(moulinette_webapi)