#!/usr/bin/env python

# Contributors Listed Below - COPYRIGHT 2016
# [+] International Business Machines Corp.
#
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied. See the License for the specific language governing
# permissions and limitations under the License.

import os
import sys
import dbus
import dbus.exceptions
import json
import logging
from xml.etree import ElementTree
from rocket import Rocket
from bottle import Bottle, abort, request, response, JSONPlugin, HTTPError
import obmc.utils.misc
import obmc.utils.pathtree
from obmc.dbuslib.introspection import IntrospectionNodeParser
import obmc.mapper
import spwd
import grp
import crypt

DBUS_UNKNOWN_INTERFACE = 'org.freedesktop.UnknownInterface'
DBUS_UNKNOWN_INTERFACE_ERROR = 'org.freedesktop.DBus.Error.UnknownInterface'
DBUS_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
DBUS_INVALID_ARGS = 'org.freedesktop.DBus.Error.InvalidArgs'
DBUS_TYPE_ERROR = 'org.freedesktop.DBus.Python.TypeError'
DELETE_IFACE = 'org.openbmc.Object.Delete'

_4034_msg = "The specified %s cannot be %s: '%s'"


def valid_user(session, *a, **kw):
    ''' Authorization plugin callback that checks
    that the user is logged in. '''
    if session is None:
        abort(403, 'Login required')


class UserInGroup:
    ''' Authorization plugin callback that checks that the user is logged in
    and a member of a group. '''
    def __init__(self, group):
        self.group = group

    def __call__(self, session, *a, **kw):
        valid_user(session, *a, **kw)
        res = False

        try:
            res = session['user'] in grp.getgrnam(self.group)[3]
        except KeyError:
            pass

        if not res:
            abort(403, 'Insufficient access')


class RouteHandler(object):
    _require_auth = obmc.utils.misc.makelist(valid_user)

    def __init__(self, app, bus, verbs, rules):
        self.app = app
        self.bus = bus
        self.mapper = obmc.mapper.Mapper(bus)
        self._verbs = obmc.utils.misc.makelist(verbs)
        self._rules = rules
        self.intf_match = obmc.utils.misc.org_dot_openbmc_match

    def _setup(self, **kw):
        request.route_data = {}
        if request.method in self._verbs:
            return self.setup(**kw)
        else:
            self.find(**kw)
            raise HTTPError(
                405, "Method not allowed.", Allow=','.join(self._verbs))

    def __call__(self, **kw):
        return getattr(self, 'do_' + request.method.lower())(**kw)

    def install(self):
        self.app.route(
            self._rules, callback=self,
            method=['GET', 'PUT', 'PATCH', 'POST', 'DELETE'])

    @staticmethod
    def try_mapper_call(f, callback=None, **kw):
        try:
            return f(**kw)
        except dbus.exceptions.DBusException, e:
            if e.get_dbus_name() != obmc.mapper.MAPPER_NOT_FOUND:
                raise
            if callback is None:
                def callback(e, **kw):
                    abort(404, str(e))

            callback(e, **kw)

    @staticmethod
    def try_properties_interface(f, *a):
        try:
            return f(*a)
        except dbus.exceptions.DBusException, e:
            if DBUS_UNKNOWN_INTERFACE in e.get_dbus_message():
                # interface doesn't have any properties
                return None
            if DBUS_UNKNOWN_INTERFACE_ERROR in e.get_dbus_name():
                # interface doesn't have any properties
                return None
            if DBUS_UNKNOWN_METHOD == e.get_dbus_name():
                # properties interface not implemented at all
                return None
            raise


class DirectoryHandler(RouteHandler):
    verbs = 'GET'
    rules = '<path:path>/'

    def __init__(self, app, bus):
        super(DirectoryHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path='/'):
        return self.try_mapper_call(
            self.mapper.get_subtree_paths, path=path, depth=1)

    def setup(self, path='/'):
        request.route_data['map'] = self.find(path)

    def do_get(self, path='/'):
        return request.route_data['map']


class ListNamesHandler(RouteHandler):
    verbs = 'GET'
    rules = ['/list', '<path:path>/list']

    def __init__(self, app, bus):
        super(ListNamesHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path='/'):
        return self.try_mapper_call(
            self.mapper.get_subtree, path=path).keys()

    def setup(self, path='/'):
        request.route_data['map'] = self.find(path)

    def do_get(self, path='/'):
        return request.route_data['map']


class ListHandler(RouteHandler):
    verbs = 'GET'
    rules = ['/enumerate', '<path:path>/enumerate']

    def __init__(self, app, bus):
        super(ListHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path='/'):
        return self.try_mapper_call(
            self.mapper.get_subtree, path=path)

    def setup(self, path='/'):
        request.route_data['map'] = self.find(path)

    def do_get(self, path='/'):
        return {x: y for x, y in self.mapper.enumerate_subtree(
                path,
                mapper_data=request.route_data['map']).dataitems()}


class MethodHandler(RouteHandler):
    verbs = 'POST'
    rules = '<path:path>/action/<method>'
    request_type = list

    def __init__(self, app, bus):
        super(MethodHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path, method):
        busses = self.try_mapper_call(
            self.mapper.get_object, path=path)
        for items in busses.iteritems():
            m = self.find_method_on_bus(path, method, *items)
            if m:
                return m

        abort(404, _4034_msg % ('method', 'found', method))

    def setup(self, path, method):
        request.route_data['method'] = self.find(path, method)

    def do_post(self, path, method):
        try:
            if request.parameter_list:
                return request.route_data['method'](*request.parameter_list)
            else:
                return request.route_data['method']()

        except dbus.exceptions.DBusException, e:
            if e.get_dbus_name() == DBUS_INVALID_ARGS:
                abort(400, str(e))
            if e.get_dbus_name() == DBUS_TYPE_ERROR:
                abort(400, str(e))
            raise

    @staticmethod
    def find_method_in_interface(method, obj, interface, methods):
        if methods is None:
            return None

        method = obmc.utils.misc.find_case_insensitive(method, methods.keys())
        if method is not None:
            iface = dbus.Interface(obj, interface)
            return iface.get_dbus_method(method)

    def find_method_on_bus(self, path, method, bus, interfaces):
        obj = self.bus.get_object(bus, path, introspect=False)
        iface = dbus.Interface(obj, dbus.INTROSPECTABLE_IFACE)
        data = iface.Introspect()
        parser = IntrospectionNodeParser(
            ElementTree.fromstring(data),
            intf_match=obmc.utils.misc.ListMatch(interfaces))
        for x, y in parser.get_interfaces().iteritems():
            m = self.find_method_in_interface(
                method, obj, x, y.get('method'))
            if m:
                return m


class PropertyHandler(RouteHandler):
    verbs = ['PUT', 'GET']
    rules = '<path:path>/attr/<prop>'

    def __init__(self, app, bus):
        super(PropertyHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path, prop):
        self.app.instance_handler.setup(path)
        obj = self.app.instance_handler.do_get(path)
        try:
            obj[prop]
        except KeyError, e:
            if request.method == 'PUT':
                abort(403, _4034_msg % ('property', 'created', str(e)))
            else:
                abort(404, _4034_msg % ('property', 'found', str(e)))

        return {path: obj}

    def setup(self, path, prop):
        request.route_data['obj'] = self.find(path, prop)

    def do_get(self, path, prop):
        return request.route_data['obj'][path][prop]

    def do_put(self, path, prop, value=None):
        if value is None:
            value = request.parameter_list

        prop, iface, properties_iface = self.get_host_interface(
            path, prop, request.route_data['map'][path])
        try:
            properties_iface.Set(iface, prop, value)
        except ValueError, e:
            abort(400, str(e))
        except dbus.exceptions.DBusException, e:
            if e.get_dbus_name() == DBUS_INVALID_ARGS:
                abort(403, str(e))
            raise

    def get_host_interface(self, path, prop, bus_info):
        for bus, interfaces in bus_info.iteritems():
            obj = self.bus.get_object(bus, path, introspect=True)
            properties_iface = dbus.Interface(
                obj, dbus_interface=dbus.PROPERTIES_IFACE)

            info = self.get_host_interface_on_bus(
                path, prop, properties_iface, bus, interfaces)
            if info is not None:
                prop, iface = info
                return prop, iface, properties_iface

    def get_host_interface_on_bus(self, path, prop, iface, bus, interfaces):
        for i in interfaces:
            properties = self.try_properties_interface(iface.GetAll, i)
            if properties is None:
                continue
            prop = obmc.utils.misc.find_case_insensitive(prop, properties.keys())
            if prop is None:
                continue
            return prop, i


class SchemaHandler(RouteHandler):
    verbs = ['GET']
    rules = '<path:path>/schema'

    def __init__(self, app, bus):
        super(SchemaHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path):
        return self.try_mapper_call(
            self.mapper.get_object,
            path=path)

    def setup(self, path):
        request.route_data['map'] = self.find(path)

    def do_get(self, path):
        schema = {}
        for x in request.route_data['map'].iterkeys():
            obj = self.bus.get_object(x, path, introspect=False)
            iface = dbus.Interface(obj, dbus.INTROSPECTABLE_IFACE)
            data = iface.Introspect()
            parser = IntrospectionNodeParser(
                ElementTree.fromstring(data))
            for x, y in parser.get_interfaces().iteritems():
                schema[x] = y

        return schema


class InstanceHandler(RouteHandler):
    verbs = ['GET', 'PUT', 'DELETE']
    rules = '<path:path>'
    request_type = dict

    def __init__(self, app, bus):
        super(InstanceHandler, self).__init__(
            app, bus, self.verbs, self.rules)

    def find(self, path, callback=None):
        return {path: self.try_mapper_call(
            self.mapper.get_object,
            callback,
            path=path)}

    def setup(self, path):
        callback = None
        if request.method == 'PUT':
            def callback(e, **kw):
                abort(403, _4034_msg % ('resource', 'created', path))

        if request.route_data.get('map') is None:
            request.route_data['map'] = self.find(path, callback)

    def do_get(self, path):
        return self.mapper.enumerate_object(
            path,
            mapper_data=request.route_data['map'])

    def do_put(self, path):
        # make sure all properties exist in the request
        obj = set(self.do_get(path).keys())
        req = set(request.parameter_list.keys())

        diff = list(obj.difference(req))
        if diff:
            abort(403, _4034_msg % (
                'resource', 'removed', '%s/attr/%s' % (path, diff[0])))

        diff = list(req.difference(obj))
        if diff:
            abort(403, _4034_msg % (
                'resource', 'created', '%s/attr/%s' % (path, diff[0])))

        for p, v in request.parameter_list.iteritems():
            self.app.property_handler.do_put(
                path, p, v)

    def do_delete(self, path):
        for bus_info in request.route_data['map'][path].iteritems():
            if self.bus_missing_delete(path, *bus_info):
                abort(403, _4034_msg % ('resource', 'removed', path))

        for bus in request.route_data['map'][path].iterkeys():
            self.delete_on_bus(path, bus)

    def bus_missing_delete(self, path, bus, interfaces):
        return DELETE_IFACE not in interfaces

    def delete_on_bus(self, path, bus):
        obj = self.bus.get_object(bus, path, introspect=False)
        delete_iface = dbus.Interface(
            obj, dbus_interface=DELETE_IFACE)
        delete_iface.Delete()


class SessionHandler(MethodHandler):
    ''' Handles the /login and /logout routes, manages
    server side session store and session cookies.  '''

    rules = ['/login', '/logout']
    login_str = "User '%s' logged %s"
    bad_passwd_str = "Invalid username or password"
    no_user_str = "No user logged in"
    bad_json_str = "Expecting request format { 'data': " \
        "[<username>, <password>] }, got '%s'"
    _require_auth = None
    MAX_SESSIONS = 16

    def __init__(self, app, bus):
        super(SessionHandler, self).__init__(
            app, bus)
        self.hmac_key = os.urandom(128)
        self.session_store = []

    @staticmethod
    def authenticate(username, clear):
        try:
            encoded = spwd.getspnam(username)[1]
            return encoded == crypt.crypt(clear, encoded)
        except KeyError:
            return False

    def invalidate_session(self, session):
        try:
            self.session_store.remove(session)
        except ValueError:
            pass

    def new_session(self):
        sid = os.urandom(32)
        if self.MAX_SESSIONS <= len(self.session_store):
            self.session_store.pop()
        self.session_store.insert(0, {'sid': sid})

        return self.session_store[0]

    def get_session(self, sid):
        sids = [x['sid'] for x in self.session_store]
        try:
            return self.session_store[sids.index(sid)]
        except ValueError:
            return None

    def get_session_from_cookie(self):
        return self.get_session(
            request.get_cookie(
                'sid', secret=self.hmac_key))

    def do_post(self, **kw):
        if request.path == '/login':
            return self.do_login(**kw)
        else:
            return self.do_logout(**kw)

    def do_logout(self, **kw):
        session = self.get_session_from_cookie()
        if session is not None:
            user = session['user']
            self.invalidate_session(session)
            response.delete_cookie('sid')
            return self.login_str % (user, 'out')

        return self.no_user_str

    def do_login(self, **kw):
        session = self.get_session_from_cookie()
        if session is not None:
            return self.login_str % (session['user'], 'in')

        if len(request.parameter_list) != 2:
            abort(400, self.bad_json_str % (request.json))

        if not self.authenticate(*request.parameter_list):
            return self.bad_passwd_str

        user = request.parameter_list[0]
        session = self.new_session()
        session['user'] = user
        response.set_cookie(
            'sid', session['sid'], secret=self.hmac_key,
            secure=True,
            httponly=True)
        return self.login_str % (user, 'in')

    def find(self, **kw):
        pass

    def setup(self, **kw):
        pass


class AuthorizationPlugin(object):
    ''' Invokes an optional list of authorization callbacks. '''

    name = 'authorization'
    api = 2

    class Compose:
        def __init__(self, validators, callback, session_mgr):
            self.validators = validators
            self.callback = callback
            self.session_mgr = session_mgr

        def __call__(self, *a, **kw):
            sid = request.get_cookie('sid', secret=self.session_mgr.hmac_key)
            session = self.session_mgr.get_session(sid)
            for x in self.validators:
                x(session, *a, **kw)

            return self.callback(*a, **kw)

    def apply(self, callback, route):
        undecorated = route.get_undecorated_callback()
        if not isinstance(undecorated, RouteHandler):
            return callback

        auth_types = getattr(
            undecorated, '_require_auth', None)
        if not auth_types:
            return callback

        return self.Compose(
            auth_types, callback, undecorated.app.session_handler)


class JsonApiRequestPlugin(object):
    ''' Ensures request content satisfies the OpenBMC json api format. '''
    name = 'json_api_request'
    api = 2

    error_str = "Expecting request format { 'data': <value> }, got '%s'"
    type_error_str = "Unsupported Content-Type: '%s'"
    json_type = "application/json"
    request_methods = ['PUT', 'POST', 'PATCH']

    @staticmethod
    def content_expected():
        return request.method in JsonApiRequestPlugin.request_methods

    def validate_request(self):
        if request.content_length > 0 and \
                request.content_type != self.json_type:
            abort(415, self.type_error_str % request.content_type)

        try:
            request.parameter_list = request.json.get('data')
        except ValueError, e:
            abort(400, str(e))
        except (AttributeError, KeyError, TypeError):
            abort(400, self.error_str % request.json)

    def apply(self, callback, route):
        verbs = getattr(
            route.get_undecorated_callback(), '_verbs', None)
        if verbs is None:
            return callback

        if not set(self.request_methods).intersection(verbs):
            return callback

        def wrap(*a, **kw):
            if self.content_expected():
                self.validate_request()
            return callback(*a, **kw)

        return wrap


class JsonApiRequestTypePlugin(object):
    ''' Ensures request content type satisfies the OpenBMC json api format. '''
    name = 'json_api_method_request'
    api = 2

    error_str = "Expecting request format { 'data': %s }, got '%s'"

    def apply(self, callback, route):
        request_type = getattr(
            route.get_undecorated_callback(), 'request_type', None)
        if request_type is None:
            return callback

        def validate_request():
            if not isinstance(request.parameter_list, request_type):
                abort(400, self.error_str % (str(request_type), request.json))

        def wrap(*a, **kw):
            if JsonApiRequestPlugin.content_expected():
                validate_request()
            return callback(*a, **kw)

        return wrap


class JsonApiResponsePlugin(object):
    ''' Emits normal responses in the OpenBMC json api format. '''
    name = 'json_api_response'
    api = 2

    def apply(self, callback, route):
        def wrap(*a, **kw):
            resp = {'data': callback(*a, **kw)}
            resp['status'] = 'ok'
            resp['message'] = response.status_line
            return resp
        return wrap


class JsonApiErrorsPlugin(object):
    ''' Emits error responses in the OpenBMC json api format. '''
    name = 'json_api_errors'
    api = 2

    def __init__(self, **kw):
        self.app = None
        self.function_type = None
        self.original = None
        self.json_opts = {
            x: y for x, y in kw.iteritems()
            if x in ['indent', 'sort_keys']}

    def setup(self, app):
        self.app = app
        self.function_type = type(app.default_error_handler)
        self.original = app.default_error_handler
        self.app.default_error_handler = self.function_type(
            self.json_errors, app, Bottle)

    def apply(self, callback, route):
        return callback

    def close(self):
        self.app.default_error_handler = self.function_type(
            self.original, self.app, Bottle)

    def json_errors(self, res, error):
        response_object = {'status': 'error', 'data': {}}
        response_object['message'] = error.status_line
        response_object['data']['description'] = str(error.body)
        if error.status_code == 500:
            response_object['data']['exception'] = repr(error.exception)
            response_object['data']['traceback'] = error.traceback.splitlines()

        json_response = json.dumps(response_object, **self.json_opts)
        response.content_type = 'application/json'
        return json_response


class JsonpPlugin(JsonApiErrorsPlugin):
    ''' Json javascript wrapper. '''
    name = 'jsonp'
    api = 2

    def __init__(self, **kw):
        super(JsonpPlugin, self).__init__(**kw)

    @staticmethod
    def to_jsonp(json):
        jwrapper = request.query.callback or None
        if(jwrapper):
            response.set_header('Content-Type', 'application/javascript')
            json = jwrapper + '(' + json + ');'
        return json

    def apply(self, callback, route):
        def wrap(*a, **kw):
            return self.to_jsonp(callback(*a, **kw))
        return wrap

    def json_errors(self, res, error):
        json = super(JsonpPlugin, self).json_errors(res, error)
        return self.to_jsonp(json)


class RestApp(Bottle):
    def __init__(self, bus):
        super(RestApp, self).__init__(autojson=False)
        self.bus = bus
        self.mapper = obmc.mapper.Mapper(bus)

        self.install_hooks()
        self.install_plugins()
        self.create_handlers()
        self.install_handlers()

    def install_plugins(self):
        # install json api plugins
        json_kw = {'indent': 2, 'sort_keys': True}
        self.install(AuthorizationPlugin())
        self.install(JsonpPlugin(**json_kw))
        self.install(JSONPlugin(**json_kw))
        self.install(JsonApiResponsePlugin())
        self.install(JsonApiRequestPlugin())
        self.install(JsonApiRequestTypePlugin())

    def install_hooks(self):
        self.real_router_match = self.router.match
        self.router.match = self.custom_router_match
        self.add_hook('before_request', self.strip_extra_slashes)

    def create_handlers(self):
        # create route handlers
        self.session_handler = SessionHandler(self, self.bus)
        self.directory_handler = DirectoryHandler(self, self.bus)
        self.list_names_handler = ListNamesHandler(self, self.bus)
        self.list_handler = ListHandler(self, self.bus)
        self.method_handler = MethodHandler(self, self.bus)
        self.property_handler = PropertyHandler(self, self.bus)
        self.schema_handler = SchemaHandler(self, self.bus)
        self.instance_handler = InstanceHandler(self, self.bus)

    def install_handlers(self):
        self.session_handler.install()
        self.directory_handler.install()
        self.list_names_handler.install()
        self.list_handler.install()
        self.method_handler.install()
        self.property_handler.install()
        self.schema_handler.install()
        # this has to come last, since it matches everything
        self.instance_handler.install()

    def custom_router_match(self, environ):
        ''' The built-in Bottle algorithm for figuring out if a 404 or 405 is
            needed doesn't work for us since the instance rules match
            everything. This monkey-patch lets the route handler figure
            out which response is needed.  This could be accomplished
            with a hook but that would require calling the router match
            function twice.
        '''
        route, args = self.real_router_match(environ)
        if isinstance(route.callback, RouteHandler):
            route.callback._setup(**args)

        return route, args

    @staticmethod
    def strip_extra_slashes():
        path = request.environ['PATH_INFO']
        trailing = ("", "/")[path[-1] == '/']
        parts = filter(bool, path.split('/'))
        request.environ['PATH_INFO'] = '/' + '/'.join(parts) + trailing

if __name__ == '__main__':
    log = logging.getLogger('Rocket.Errors')
    log.setLevel(logging.INFO)
    log.addHandler(logging.StreamHandler(sys.stdout))

    bus = dbus.SystemBus()
    app = RestApp(bus)
    default_cert = os.path.join(
        sys.prefix, 'share', os.path.basename(__file__), 'cert.pem')

    server = Rocket(
        ('0.0.0.0', 443, default_cert, default_cert),
        'wsgi', {'wsgi_app': app},
        min_threads=1,
        max_threads=1)
    server.start()
