"""
byceps.blueprints.authentication.session
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

:Copyright: 2006-2017 Jochen Kupperschmidt
:License: Modified BSD, see LICENSE for details.
"""

from flask import session

from ...services.authentication.exceptions import AuthenticationFailed
from ...services.authentication.session import service as session_service
from ...services.user import service as user_service


KEY_USER_ID = 'user_id'
KEY_USER_AUTH_TOKEN = 'user_auth_token'


def start(user_id, auth_token, *, permanent=False):
    """Initialize the user's session by putting the relevant data
    into the session cookie.
    """
    session[KEY_USER_ID] = str(user_id)
    session[KEY_USER_AUTH_TOKEN] = str(auth_token)
    session.permanent = permanent


def end():
    """End the user's session by deleting the session cookie."""
    session.pop(KEY_USER_ID, None)
    session.pop(KEY_USER_AUTH_TOKEN, None)
    session.permanent = False


def get_user():
    """Return the current user, falling back to the anonymous user."""
    return _load_user(_get_user_id(), _get_auth_token())


def _get_user_id():
    """Return the current user's ID, or `None` if not available."""
    return session.get(KEY_USER_ID)


def _get_auth_token():
    """Return the current user's auth token, or `None` if not available."""
    return session.get(KEY_USER_AUTH_TOKEN)


def _load_user(user_id, auth_token):
    """Load the user with that ID.

    Fall back to the anonymous user if the ID is unknown, the account is
    not enabled, or the auth token is invalid.
    """
    if user_id is None:
        return user_service.get_anonymous_user()

    user = user_service.find_user(user_id, with_orga_teams=True)

    if (user is None) or not user.enabled:
        return user_service.get_anonymous_user()

    # Validate auth token.
    try:
        session_service.authenticate_session(user.id, auth_token)
    except AuthenticationFailed:
        # Bad auth token, not logging in.
        return user_service.get_anonymous_user()

    return user

@@ -177,16 +177,52 @@
 s.%0A%22%22%22%0A%0A
+from typing import Optional, Union%0A%0A
 from fla
@@ -235,24 +235,24 @@
 ort session%0A
-
 %0Afrom ...ser
@@ -385,16 +385,77 @@
 service%0A
+from ...services.user.models.user import AnonymousUser, User%0A
 from ...
@@ -499,16 +499,45 @@
 service%0A
+from ...typing import UserID%0A
 %0A%0AKEY_US
@@ -605,32 +605,40 @@
 ef start(user_id
+: UserID
 , auth_token, *,
@@ -633,16 +633,21 @@
 th_token
+: str
 , *, per
@@ -656,15 +656,29 @@
 nent
+: bool
 =False)
+ -%3E None
 :%0A  
@@ -914,16 +914,24 @@
 ef end()
+ -%3E None
 :%0A    %22%22
@@ -1113,16 +1113,46 @@
 t_user()
+ -%3E Union%5BAnonymousUser, User%5D
 :%0A    %22%22
@@ -1293,16 +1293,33 @@
 ser_id()
+ -%3E Optional%5Bstr%5D
 :%0A    %22%22
@@ -1439,16 +1439,33 @@
 _token()
+ -%3E Optional%5Bstr%5D
 :%0A    %22%22
@@ -1602,16 +1602,21 @@
 (user_id
+: str
 , auth_t
@@ -1619,17 +1619,52 @@
 th_token
-)
+: str) -%3E Union%5BAnonymousUser, User%5D
 :%0A    %22%22

Add missing type hints