Skip to content
Snippets Groups Projects
views.py 5.62 KiB
from pyramid.view import view_config
import uuid

import json

from webob import Response, exc
from cornice import Service

import logging

from pytsprf.distance_getter_factory import DistanceGetterFactory
from pytsprf.route_solver_factory import RouteSolverFactory

from pytsprf.models import get_db_user_token, get_db_user
from pytsprf.models import create_db_user, delete_db_user, get_db_users


# ==================================================
#  Service : Users authentication and autorization
# ==================================================

users = Service(name='users', path='/users', description="Users management")

_USERS = {}


def _create_token():
    return uuid.uuid4().hex


class _401(exc.HTTPError):
    def __init__(self, msg='Unauthorized'):
        body = {'status': 401, 'message': msg}
        Response.__init__(self, json.dumps(body))
        self.status = 401
        self.content_type = 'application/json'


def valid_token(request):
    header = 'X-Messaging-Token'
    htoken = request.headers.get(header)

    if htoken is None:
        raise _401()
    try:
        user, token = htoken.split('-', 1)

    except ValueError:
        raise _401()

    dbtoken = get_db_user_token(user)
    valid = (dbtoken is not None) and (dbtoken == token)

    if not valid:
        raise _401()

    request.validated['user'] = user


def is_valid_username(request):
    body_unicode = request.body.decode('utf-8')
    username = json.loads(body_unicode)
    request.validated['username'] = username


def is_new_user(request):
    is_valid_username(request)
    username = request.validated['username']
    is_new_user = False
    if (username is not None):
        isfound, user = get_db_user(username)
        is_new_user = not(isfound)
        if isfound:
            request.errors.add(
                '/users',
                'POST', 'Le Client possede deja une cle d''API active'
            )

    request.validated['is_new_user'] = is_new_user


def is_authorized(request):
    request.validated['is_authorized'] = True


# Services - User Management
@users.get(validators=is_authorized)
def get_users(request):
    """Returns a list of all users."""
    is_authorized = request.validated['is_authorized']
    if (is_authorized):
        success, users = get_db_users()
        if success:
            names = list()
            for user in users:
                names.append(user.name)

    return {'authorized': is_authorized, 'users': names}


@users.post(validators=is_new_user)
def create_user(request):
    """Adds a new user."""
    username = request.validated['username']
    success = False
    is_new_user = request.validated['is_new_user']
    if is_new_user:
        success, user = create_db_user(username)
        if success:
            user = {'name': username, 'token': get_db_user_token(username)}
            request.validated['created'] = True
        else:
            request.errors.add(
                '/users',
                username,
                'Request aborted due to a Database Access error'
            )

    if success:
        response = {
            'created': success,
            'token': '%s-%s' % (
                user.get('name'),
                user.get('token')
            )
        }

    else:
        response = {'created': success}

    return response


@users.delete(validators=valid_token)
def delete_user(request):
    """Removes the user."""
    username = request.validated['user']
    success = delete_db_user(username)
    return {'deleted': success}


# ==================================================
#  Service : Home
# ==================================================
@view_config(route_name='access', renderer='templates/service.pt')
def access_page(request):
    return {'project': 'access'}


@view_config(route_name='credentials', renderer='templates/index.pt')
def home_page(request):
    return {'project': 'pytsprf'}


# ==================================================
#  Service : Route
# ==================================================
tsp = Service(
    name='tsp',
    path='/tsp',
    description="Route in response to the requested TSP"
)


def activate_logging():
    logname = "log.txt"
    logging.basicConfig(
        filename=logname,
        filemode='a',
        format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
        level=logging.DEBUG
    )


def get_response(points, route, cost, distance_getter_name, solver_name):

    return {
        'waypoints': points,
        'route': route,
        'api-description': u'XCG Consulting API : TSP solution',
        'distance-solver': distance_getter_name,
        'route-solver': solver_name,
        'origin': points[0],
        'destination': points[0],
        'cost': cost
    }


def convert_to_points(pointsDict):

    points = []

    for pointDict in pointsDict:
        points.append([pointDict.get('lat'), pointDict.get('lng')])

    print(points)
    return points


def get_route(points, is_test_mode=False):

    dgetterFactory = DistanceGetterFactory(is_test_mode)
    distance_getter = dgetterFactory.get_instance()
    solverFactory = RouteSolverFactory(points, distance_getter)
    solver = solverFactory.get_instance()
    route = solver.get_route()
    cost = solver.get_cost(route)

    return route, cost, distance_getter.name, solver.name


@tsp.post(validators=valid_token)
def calc_route(request):

    requestDataDict = request.json
    points = convert_to_points(requestDataDict)

    route, cost, distance_getter_name, solver_name = get_route(
        points, is_test_mode=False
    )
    response = get_response(
        requestDataDict, route, cost, distance_getter_name, solver_name
    )

    return json.dumps(response)