<commit_before># -*- coding: utf-8 -*-

# FOGLAMP_BEGIN
# See: http://foglamp.readthedocs.io/
# FOGLAMP_END

""" auth routes """

import re
from collections import OrderedDict

from aiohttp import web
from foglamp.services.core.user_model import User
from foglamp.common.web.middleware import has_permission
from foglamp.common import logger


__author__ = "<NAME>"
__copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
__license__ = "Apache 2.0"
__version__ = "${VERSION}"

_logger = logger.setup(__name__)

_help = """
    ------------------------------------------------------------------------------------
    | GET POST                   | /foglamp/user                                       |
    | PUT DELETE                 | /foglamp/user/{id}                                  |

    | GET                        | /foglamp/user/role                                  |
    
    | POST                       | /foglamp/login                                      |
    | PUT                        | /foglamp/{user_id}/logout                                |
    ------------------------------------------------------------------------------------
"""

JWT_SECRET = 'f0gl@mp'
JWT_ALGORITHM = 'HS256'
JWT_EXP_DELTA_SECONDS = 30*60  # 30 minutes

PASSWORD_REGEX_PATTERN = '((?=.*\d)(?=.*[A-Z])(?=.*\W).{6,}$)'
PASSWORD_ERROR_MSG = 'Password must contain at least one digit, one lowercase, one uppercase & one special character ' \
                     'and length of minimum 6 characters'

# TODO: remove me, use from roles table
ADMIN_ROLE_ID = 1
DEFAULT_ROLE_ID = 2


async def login(request):
    """ Validate user with its username and password

    :Example:
        curl -X POST -d '{"username": "user", "password": "<PASSWORD>"}' http://localhost:8081/foglamp/login
    """

    data = await request.json()

    username = data.get('username')
    password = data.get('password')

    if not username or not password:
        _logger.warning("Username and password are required to login")
        raise web.HTTPBadRequest(reason="Username or password is missing")

    peername = request.transport.get_extra_info('peername')
    host = '0.0.0.0'
    if peername is not None:
        host, port = peername
    try:
        uid, token, is_admin = User.Objects.login(username, password, host)
    except (User.DoesNotExist, User.PasswordDoesNotMatch, ValueError) as ex:
        _logger.warning(str(ex))
        return web.HTTPBadRequest(reason=str(ex))

    _logger.info("User with username:<{}> has been logged in successfully".format(username))

    return web.json_response({"message": "Logged in successfully", "uid": uid, "token": token, "admin": is_admin})


async def logout_me(request):
    """ log out user

    :Example:
        curl -H "authorization: <token>" -X PUT http://localhost:8081/foglamp/logout

    """

    if not request.token:
        raise web.HTTPUnauthorized()

    result = User.Objects.delete_token(request.token)

    if not result['rows_affected']:
        _logger.warning("Logout requested with bad user token")
        raise web.HTTPNotFound()

    _logger.info("User has been logged out successfully")
    return web.json_response({"logout": True})


async def logout(request):
    """ log out user's all active sessions

    :Example:
        curl -H "authorization: <token>" -X PUT http://localhost:8081/foglamp/{user_id}/logout

    """
<commit_msg>fixed attribute error check; no action needed on token if auth optional<commit_after># -*- coding: utf-8 -*-

# FOGLAMP_BEGIN
# See: http://foglamp.readthedocs.io/
# FOGLAMP_END

""" auth routes """

import re
from collections import OrderedDict

from aiohttp import web
from foglamp.services.core.user_model import User
from foglamp.common.web.middleware import has_permission
from foglamp.common import logger


__author__ = "<NAME>"
__copyright__ = "Copyright (c) 2017 OSIsoft, LLC"
__license__ = "Apache 2.0"
__version__ = "${VERSION}"

_logger = logger.setup(__name__)

_help = """
    ------------------------------------------------------------------------------------
    | GET POST                   | /foglamp/user                                       |
    | PUT DELETE                 | /foglamp/user/{id}                                  |

    | GET                        | /foglamp/user/role                                  |
    
    | POST                       | /foglamp/login                                      |
    | PUT                        | /foglamp/{user_id}/logout                                |
    ------------------------------------------------------------------------------------
"""

JWT_SECRET = 'f0gl@mp'
JWT_ALGORITHM = 'HS256'
JWT_EXP_DELTA_SECONDS = 30*60  # 30 minutes

PASSWORD_REGEX_PATTERN = '((?=.*\d)(?=.*[A-Z])(?=.*\W).{6,}$)'
PASSWORD_ERROR_MSG = 'Password must contain at least one digit, one lowercase, one uppercase & one special character ' \
                     'and length of minimum 6 characters'

# TODO: remove me, use from roles table
ADMIN_ROLE_ID = 1
DEFAULT_ROLE_ID = 2


async def login(request):
    """ Validate user with its username and password

    :Example:
        curl -X POST -d '{"username": "user", "password": "<PASSWORD>"}' http://localhost:8081/foglamp/login
    """

    data = await request.json()

    username = data.get('username')
    password = data.get('password')

    if not username or not password:
        _logger.warning("Username and password are required to login")
        raise web.HTTPBadRequest(reason="Username or password is missing")

    peername = request.transport.get_extra_info('peername')
    host = '0.0.0.0'
    if peername is not None:
        host, port = peername
    try:
        uid, token, is_admin = User.Objects.login(username, password, host)
    except (User.DoesNotExist, User.PasswordDoesNotMatch, ValueError) as ex:
        _logger.warning(str(ex))
        return web.HTTPBadRequest(reason=str(ex))

    _logger.info("User with username:<{}> has been logged in successfully".format(username))

    return web.json_response({"message": "Logged in successfully", "uid": uid, "token": token, "admin": is_admin})


async def logout_me(request):
    """ log out user

    :Example:
        curl -H "authorization: <token>" -X PUT http://localhost:8081/foglamp/logout

    """

    if request.is_auth_optional:
        # no action need
        return web.json_response({"logout": True})

    result = User.Objects.delete_token(request.token)

    if not result['rows_affected']:
        _logger.warning("Logout requested with bad user token")
        raise web.HTTPNotFound()

    _logger.info("User has been logged out successfully")
    return web.json_response({"logout": True})


async def logout(request):
    """ log out user's all active sessions

    :Example:
        curl -H "authorization: <token>" -X PUT http://localhost:8081/foglamp/{user_id}/logout

    """

{'fraction_non_alphanumeric': 0.16245644599303136, 'fraction_numerical': 0.010743321718931475, 'mean_word_length': 2.0348017621145376, 'pattern_counts': {'":': 15, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 2, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1547082', 'n_tokens_mistral': 2088, 'n_tokens_neox': 1953, 'n_words': 518}