Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

root: allow configuring session cookie age #12389

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft

Conversation

rissson
Copy link
Member

@rissson rissson commented Dec 18, 2024

Details

REPLACE ME


Checklist

  • Local tests pass (ak test authentik/)
  • The code has been formatted (make lint-fix)

If an API change has been made

  • The API schema has been updated (make gen-build)

If changes to the frontend have been made

  • The code has been formatted (make web)

If applicable

  • The documentation has been updated
  • The documentation has been formatted (make website)

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
@rissson rissson self-assigned this Dec 18, 2024
@rissson rissson requested review from a team as code owners December 18, 2024 13:01
Copy link

netlify bot commented Dec 18, 2024

Deploy Preview for authentik-storybook ready!

Name Link
🔨 Latest commit 9ff6de3
🔍 Latest deploy log https://app.netlify.com/sites/authentik-storybook/deploys/6762c7ba6c086d0009c854be
😎 Deploy Preview https://deploy-preview-12389--authentik-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Dec 18, 2024

Deploy Preview for authentik-docs ready!

Name Link
🔨 Latest commit 9ff6de3
🔍 Latest deploy log https://app.netlify.com/sites/authentik-docs/deploys/6762c7bad7ce3000088dd039
😎 Deploy Preview https://deploy-preview-12389--authentik-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

codecov bot commented Dec 18, 2024

❌ 455 Tests Failed:

Tests completed Failed Passed Skipped
1621 455 1166 2
View the top 3 failed tests by shortest run time
authentik.crypto.tests.TestCrypto::test_private_key_download_denied
Stack Traces | 0.006s run time
self = <unittest.case._Outcome object at 0x7f63e4418a70>
test_case = <authentik.crypto.tests.TestCrypto testMethod=test_private_key_download_denied>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_private_key_download_denied>
result = <TestCaseFunction test_private_key_download_denied>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_private_key_download_denied>
method = <bound method TestCrypto.test_private_key_download_denied of <authentik.crypto.tests.TestCrypto testMethod=test_private_key_download_denied>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_private_key_download_denied>

    def test_private_key_download_denied(self):
        """Test private_key export (download)"""
>       self.client.logout()

authentik/crypto/tests.py:250: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7f63e2126360>

    def logout(self):
        self._credentials = {}
    
        # Also clear any `force_authenticate`
        self.handler._force_user = None
        self.handler._force_token = None
    
>       if self.session:

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../site-packages/rest_framework/test.py:341: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7f63e2126360>

    @property
    def session(self):
        """Return the current session variables."""
        engine = import_module(settings.SESSION_ENGINE)
        cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
        if cookie:
            return engine.SessionStore(cookie.value)
        session = engine.SessionStore()
>       session.save()

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django/test/client.py:753: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e441bc80>
must_create = False

    def save(self, must_create=False):
        if self.session_key is None:
>           return self.create()

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:56: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e441bc80>

    def create(self):
        # Because a cache can fail silently (e.g. memcache), we don't know if
        # we are failing to create a new session because of a key collision or
        # because the cache is missing. So we try for a (large) number of times
        # and then raise an exception. That's the risk you shoulder if using
        # cache backing.
        for i in range(10000):
            self._session_key = self._get_new_session_key()
            try:
>               self.save(must_create=True)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:44: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e441bc80>
must_create = True

    def save(self, must_create=False):
        if self.session_key is None:
            return self.create()
        if must_create:
            func = self._cache.add
        elif self._cache.get(self.cache_key) is not None:
            func = self._cache.set
        else:
            raise UpdateError
>       result = func(
            self.cache_key,
            self._get_session(no_load=must_create),
            self.get_expiry_age(),
        )

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.cache.RedisCache object at 0x7f63ea599760>
args = ('django.contrib.sessions.cachejf94mndp1uhxldnlg0sticlg5igz2zws', {}, datetime.timedelta(days=14))
kwargs = {}

    @functools.wraps(method)
    def _decorator(self, *args, **kwargs):
        try:
>           return method(self, *args, **kwargs)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12....../site-packages/django_redis/cache.py:29: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.cache.RedisCache object at 0x7f63ea599760>
args = ('django.contrib.sessions.cachejf94mndp1uhxldnlg0sticlg5igz2zws', {}, datetime.timedelta(days=14))
kwargs = {}

    @omit_exception
    def add(self, *args, **kwargs):
>       return self.client.add(*args, **kwargs)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12....../site-packages/django_redis/cache.py:89: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.client.default.DefaultClient object at 0x7f63ea5be510>
key = 'django.contrib.sessions.cachejf94mndp1uhxldnlg0sticlg5igz2zws'
value = {}, timeout = datetime.timedelta(days=14), version = None, client = None

    def add(
        self,
        key: Any,
        value: Any,
        timeout: Any = DEFAULT_TIMEOUT,
        version: Optional[Any] = None,
        client: Optional[Redis] = None,
    ) -> bool:
        """
        Add a value to the cache, failing if the key already exists.
    
        Returns ``True`` if the object was added, ``False`` if not.
        """
>       return self.set(key, value, timeout, version=version, client=client, nx=True)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django_redis/client/default.py:238: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.client.default.DefaultClient object at 0x7f63ea5be510>
key = 'django.contrib.sessions.cachejf94mndp1uhxldnlg0sticlg5igz2zws'
value = {}, timeout = datetime.timedelta(days=14), version = None
client = Redis<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>
nx = True, xx = False

    def set(
        self,
        key: Any,
        value: Any,
        timeout: Optional[float] = DEFAULT_TIMEOUT,
        version: Optional[int] = None,
        client: Optional[Redis] = None,
        nx: bool = False,
        xx: bool = False,
    ) -> bool:
        """
        Persist a value to the cache, and set an optional expiration time.
    
        Also supports optional nx parameter. If set to True - will use redis
        setnx instead of set.
        """
        nkey = self.make_key(key, version=version)
        nvalue = self.encode(value)
    
        if timeout is DEFAULT_TIMEOUT:
            timeout = self._backend.default_timeout
    
        original_client = client
        tried: List[int] = []
        while True:
            try:
                if client is None:
                    client, index = self.get_client(
                        write=True, tried=tried, show_index=True
                    )
    
                if timeout is not None:
                    # Convert to milliseconds
>                   timeout = int(timeout * 1000)
E                   TypeError: int() argument must be a string, a bytes-like object or a real number, not 'datetime.timedelta'

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django_redis/client/default.py:159: TypeError
authentik.crypto.tests.TestCrypto::test_certificate_download_denied
Stack Traces | 0.007s run time
self = <unittest.case._Outcome object at 0x7f63e235c0b0>
test_case = <authentik.crypto.tests.TestCrypto testMethod=test_certificate_download_denied>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_certificate_download_denied>
result = <TestCaseFunction test_certificate_download_denied>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_certificate_download_denied>
method = <bound method TestCrypto.test_certificate_download_denied of <authentik.crypto.tests.TestCrypto testMethod=test_certificate_download_denied>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_certificate_download_denied>

    def test_certificate_download_denied(self):
        """Test certificate export (download)"""
>       self.client.logout()

authentik/crypto/tests.py:230: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7f63e20d3fe0>

    def logout(self):
        self._credentials = {}
    
        # Also clear any `force_authenticate`
        self.handler._force_user = None
        self.handler._force_token = None
    
>       if self.session:

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../site-packages/rest_framework/test.py:341: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7f63e20d3fe0>

    @property
    def session(self):
        """Return the current session variables."""
        engine = import_module(settings.SESSION_ENGINE)
        cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
        if cookie:
            return engine.SessionStore(cookie.value)
        session = engine.SessionStore()
>       session.save()

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django/test/client.py:753: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e1c5fe30>
must_create = False

    def save(self, must_create=False):
        if self.session_key is None:
>           return self.create()

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:56: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e1c5fe30>

    def create(self):
        # Because a cache can fail silently (e.g. memcache), we don't know if
        # we are failing to create a new session because of a key collision or
        # because the cache is missing. So we try for a (large) number of times
        # and then raise an exception. That's the risk you shoulder if using
        # cache backing.
        for i in range(10000):
            self._session_key = self._get_new_session_key()
            try:
>               self.save(must_create=True)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:44: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e1c5fe30>
must_create = True

    def save(self, must_create=False):
        if self.session_key is None:
            return self.create()
        if must_create:
            func = self._cache.add
        elif self._cache.get(self.cache_key) is not None:
            func = self._cache.set
        else:
            raise UpdateError
>       result = func(
            self.cache_key,
            self._get_session(no_load=must_create),
            self.get_expiry_age(),
        )

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.cache.RedisCache object at 0x7f63ea599760>
args = ('django.contrib.sessions.cache8vdum7dqby1twhwk6r7a118muoxcl4s8', {}, datetime.timedelta(days=14))
kwargs = {}

    @functools.wraps(method)
    def _decorator(self, *args, **kwargs):
        try:
>           return method(self, *args, **kwargs)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12....../site-packages/django_redis/cache.py:29: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.cache.RedisCache object at 0x7f63ea599760>
args = ('django.contrib.sessions.cache8vdum7dqby1twhwk6r7a118muoxcl4s8', {}, datetime.timedelta(days=14))
kwargs = {}

    @omit_exception
    def add(self, *args, **kwargs):
>       return self.client.add(*args, **kwargs)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12....../site-packages/django_redis/cache.py:89: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.client.default.DefaultClient object at 0x7f63ea5be510>
key = 'django.contrib.sessions.cache8vdum7dqby1twhwk6r7a118muoxcl4s8'
value = {}, timeout = datetime.timedelta(days=14), version = None, client = None

    def add(
        self,
        key: Any,
        value: Any,
        timeout: Any = DEFAULT_TIMEOUT,
        version: Optional[Any] = None,
        client: Optional[Redis] = None,
    ) -> bool:
        """
        Add a value to the cache, failing if the key already exists.
    
        Returns ``True`` if the object was added, ``False`` if not.
        """
>       return self.set(key, value, timeout, version=version, client=client, nx=True)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django_redis/client/default.py:238: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.client.default.DefaultClient object at 0x7f63ea5be510>
key = 'django.contrib.sessions.cache8vdum7dqby1twhwk6r7a118muoxcl4s8'
value = {}, timeout = datetime.timedelta(days=14), version = None
client = Redis<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>
nx = True, xx = False

    def set(
        self,
        key: Any,
        value: Any,
        timeout: Optional[float] = DEFAULT_TIMEOUT,
        version: Optional[int] = None,
        client: Optional[Redis] = None,
        nx: bool = False,
        xx: bool = False,
    ) -> bool:
        """
        Persist a value to the cache, and set an optional expiration time.
    
        Also supports optional nx parameter. If set to True - will use redis
        setnx instead of set.
        """
        nkey = self.make_key(key, version=version)
        nvalue = self.encode(value)
    
        if timeout is DEFAULT_TIMEOUT:
            timeout = self._backend.default_timeout
    
        original_client = client
        tried: List[int] = []
        while True:
            try:
                if client is None:
                    client, index = self.get_client(
                        write=True, tried=tried, show_index=True
                    )
    
                if timeout is not None:
                    # Convert to milliseconds
>                   timeout = int(timeout * 1000)
E                   TypeError: int() argument must be a string, a bytes-like object or a real number, not 'datetime.timedelta'

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django_redis/client/default.py:159: TypeError
authentik.crypto.tests.TestCrypto::test_used_by_denied
Stack Traces | 0.007s run time
self = <unittest.case._Outcome object at 0x7f63e21924e0>
test_case = <authentik.crypto.tests.TestCrypto testMethod=test_used_by_denied>
subTest = False

    @contextlib.contextmanager
    def testPartExecutor(self, test_case, subTest=False):
        old_success = self.success
        self.success = True
        try:
>           yield

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:58: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_used_by_denied>
result = <TestCaseFunction test_used_by_denied>

    def run(self, result=None):
        if result is None:
            result = self.defaultTestResult()
            startTestRun = getattr(result, 'startTestRun', None)
            stopTestRun = getattr(result, 'stopTestRun', None)
            if startTestRun is not None:
                startTestRun()
        else:
            stopTestRun = None
    
        result.startTest(self)
        try:
            testMethod = getattr(self, self._testMethodName)
            if (getattr(self.__class__, "__unittest_skip__", False) or
                getattr(testMethod, "__unittest_skip__", False)):
                # If the class or method was skipped.
                skip_why = (getattr(self.__class__, '__unittest_skip_why__', '')
                            or getattr(testMethod, '__unittest_skip_why__', ''))
                _addSkip(result, self, skip_why)
                return result
    
            expecting_failure = (
                getattr(self, "__unittest_expecting_failure__", False) or
                getattr(testMethod, "__unittest_expecting_failure__", False)
            )
            outcome = _Outcome(result)
            start_time = time.perf_counter()
            try:
                self._outcome = outcome
    
                with outcome.testPartExecutor(self):
                    self._callSetUp()
                if outcome.success:
                    outcome.expecting_failure = expecting_failure
                    with outcome.testPartExecutor(self):
>                       self._callTestMethod(testMethod)

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:634: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_used_by_denied>
method = <bound method TestCrypto.test_used_by_denied of <authentik.crypto.tests.TestCrypto testMethod=test_used_by_denied>>

    def _callTestMethod(self, method):
>       if method() is not None:

.../hostedtoolcache/Python/3.12.8........./x64/lib/python3.12/unittest/case.py:589: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <authentik.crypto.tests.TestCrypto testMethod=test_used_by_denied>

    def test_used_by_denied(self):
        """Test used_by endpoint"""
>       self.client.logout()

authentik/crypto/tests.py:302: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7f63e31712b0>

    def logout(self):
        self._credentials = {}
    
        # Also clear any `force_authenticate`
        self.handler._force_user = None
        self.handler._force_token = None
    
>       if self.session:

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../site-packages/rest_framework/test.py:341: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <rest_framework.test.APIClient object at 0x7f63e31712b0>

    @property
    def session(self):
        """Return the current session variables."""
        engine = import_module(settings.SESSION_ENGINE)
        cookie = self.cookies.get(settings.SESSION_COOKIE_NAME)
        if cookie:
            return engine.SessionStore(cookie.value)
        session = engine.SessionStore()
>       session.save()

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django/test/client.py:753: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e2193230>
must_create = False

    def save(self, must_create=False):
        if self.session_key is None:
>           return self.create()

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:56: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e2193230>

    def create(self):
        # Because a cache can fail silently (e.g. memcache), we don't know if
        # we are failing to create a new session because of a key collision or
        # because the cache is missing. So we try for a (large) number of times
        # and then raise an exception. That's the risk you shoulder if using
        # cache backing.
        for i in range(10000):
            self._session_key = self._get_new_session_key()
            try:
>               self.save(must_create=True)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:44: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django.contrib.sessions.backends.cache.SessionStore object at 0x7f63e2193230>
must_create = True

    def save(self, must_create=False):
        if self.session_key is None:
            return self.create()
        if must_create:
            func = self._cache.add
        elif self._cache.get(self.cache_key) is not None:
            func = self._cache.set
        else:
            raise UpdateError
>       result = func(
            self.cache_key,
            self._get_session(no_load=must_create),
            self.get_expiry_age(),
        )

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../sessions/backends/cache.py:63: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.cache.RedisCache object at 0x7f63ea599760>
args = ('django.contrib.sessions.cache1vwmhwnoijzf1d15a6hqyrpj7uoigo8o', {}, datetime.timedelta(days=14))
kwargs = {}

    @functools.wraps(method)
    def _decorator(self, *args, **kwargs):
        try:
>           return method(self, *args, **kwargs)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12....../site-packages/django_redis/cache.py:29: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.cache.RedisCache object at 0x7f63ea599760>
args = ('django.contrib.sessions.cache1vwmhwnoijzf1d15a6hqyrpj7uoigo8o', {}, datetime.timedelta(days=14))
kwargs = {}

    @omit_exception
    def add(self, *args, **kwargs):
>       return self.client.add(*args, **kwargs)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12....../site-packages/django_redis/cache.py:89: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.client.default.DefaultClient object at 0x7f63ea5be510>
key = 'django.contrib.sessions.cache1vwmhwnoijzf1d15a6hqyrpj7uoigo8o'
value = {}, timeout = datetime.timedelta(days=14), version = None, client = None

    def add(
        self,
        key: Any,
        value: Any,
        timeout: Any = DEFAULT_TIMEOUT,
        version: Optional[Any] = None,
        client: Optional[Redis] = None,
    ) -> bool:
        """
        Add a value to the cache, failing if the key already exists.
    
        Returns ``True`` if the object was added, ``False`` if not.
        """
>       return self.set(key, value, timeout, version=version, client=client, nx=True)

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django_redis/client/default.py:238: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <django_redis.client.default.DefaultClient object at 0x7f63ea5be510>
key = 'django.contrib.sessions.cache1vwmhwnoijzf1d15a6hqyrpj7uoigo8o'
value = {}, timeout = datetime.timedelta(days=14), version = None
client = Redis<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>
nx = True, xx = False

    def set(
        self,
        key: Any,
        value: Any,
        timeout: Optional[float] = DEFAULT_TIMEOUT,
        version: Optional[int] = None,
        client: Optional[Redis] = None,
        nx: bool = False,
        xx: bool = False,
    ) -> bool:
        """
        Persist a value to the cache, and set an optional expiration time.
    
        Also supports optional nx parameter. If set to True - will use redis
        setnx instead of set.
        """
        nkey = self.make_key(key, version=version)
        nvalue = self.encode(value)
    
        if timeout is DEFAULT_TIMEOUT:
            timeout = self._backend.default_timeout
    
        original_client = client
        tried: List[int] = []
        while True:
            try:
                if client is None:
                    client, index = self.get_client(
                        write=True, tried=tried, show_index=True
                    )
    
                if timeout is not None:
                    # Convert to milliseconds
>                   timeout = int(timeout * 1000)
E                   TypeError: int() argument must be a string, a bytes-like object or a real number, not 'datetime.timedelta'

../../../..../pypoetry/virtualenvs/authentik-xvtLQ9eE-py3.12/lib/python3.12.../django_redis/client/default.py:159: TypeError

To view more test analytics, go to the Test Analytics Dashboard
📢 Thoughts on this report? Let us know!

@rissson rissson marked this pull request as draft December 18, 2024 15:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant