Beispiel #1
0
def sendXMLResult(response, obj, id=1, opt=None):
    """
    send the result as an xml format
    """
    response.content_type = 'text/xml'
    res = '<?xml version="1.0" encoding="UTF-8"?>\
            <jsonrpc version="%s">\
            <result>\
                <status>True</status>\
                <value>%s</value>\
            </result>\
            <version>%s</version>\
            <id>%s</id>\
            </jsonrpc>' % (get_api_version(), obj, get_version(), id)
    xml_options = ""
    if opt:
        xml_options = "\n<options>" + json2xml(opt) + "</options>"
    xml_object = json2xml(obj)

    res = """<?xml version="1.0" encoding="UTF-8"?>
<jsonrpc version="2.0">
    <result>
        <status>True</status>
        <value>%s</value>
    </result>
    <version>%s</version>
    <id>%s</id>%s
</jsonrpc>""" % (xml_object, get_version(), id, xml_options)
    return res
Beispiel #2
0
def sendResult(response, obj, id=1, opt=None, status=True):
    '''
        sendResult - return an json result document

        :param response: the pylons response object
        :type  response: response object
        :param obj:      simple result object like dict, sting or list
        :type  obj:      dict or list or string/unicode
        :param  id:      id value, for future versions
        :type   id:      int
        :param opt:      optional parameter, which allows to provide more detail
        :type  opt:      None or simple type like dict, list or string/unicode

        :return:     json rendered sting result
        :rtype:      string

    '''

    response.content_type = 'application/json'

    res = {
        "jsonrpc": get_api_version(),
        "result": {
            "status": status,
            "value": obj,
        },
        "version": get_version(),
        "id": id
    }

    if opt is not None and len(opt) > 0:
        res["detail"] = opt

    return json.dumps(res, indent=3)
Beispiel #3
0
def sendXMLResult(response, obj, id=1, opt=None):
    """
    send the result as an xml format
    """
    response.content_type = 'text/xml'
    res = '<?xml version="1.0" encoding="UTF-8"?>\
            <jsonrpc version="%s">\
            <result>\
                <status>True</status>\
                <value>%s</value>\
            </result>\
            <version>%s</version>\
            <id>%s</id>\
            </jsonrpc>' % (get_api_version(), obj, get_version(), id)
    xml_options = ""
    if opt:
        xml_options = "\n<options>" + json2xml(opt) + "</options>"
    xml_object = json2xml(obj)

    res = """<?xml version="1.0" encoding="UTF-8"?>
<jsonrpc version="2.0">
    <result>
        <status>True</status>
        <value>%s</value>
    </result>
    <version>%s</version>
    <id>%s</id>%s
</jsonrpc>""" % (xml_object, get_version(), id, xml_options)
    return res
Beispiel #4
0
def sendResult(response, obj, id=1, opt=None, status=True):
    '''
        sendResult - return an json result document

        :param response: the pylons response object
        :type  response: response object
        :param obj:      simple result object like dict, sting or list
        :type  obj:      dict or list or string/unicode
        :param  id:      id value, for future versions
        :type   id:      int
        :param opt:      optional parameter, which allows to provide more detail
        :type  opt:      None or simple type like dict, list or string/unicode

        :return:     json rendered sting result
        :rtype:      string

    '''

    response.content_type = 'application/json'

    res = { "jsonrpc": get_api_version(),
            "result": { "status": status,
                        "value": obj,
                      },
           "version": get_version(),
           "id": id }

    if opt is not None and len(opt) > 0:
        res["detail"] = opt

    return json.dumps(res, indent=3)
Beispiel #5
0
def sendXMLResult(response, obj, id=1):
    response.content_type = 'text/xml'
    res = '<?xml version="1.0" encoding="UTF-8"?>\
            <jsonrpc version="%s">\
            <result>\
                <status>True</status>\
                <value>%s</value>\
            </result>\
            <version>%s</version>\
            <id>%s</id>\
            </jsonrpc>' % (get_api_version(), obj, get_version(), id)
    return res
Beispiel #6
0
def sendXMLError(response, exception, id=1):
    response.content_type = 'text/xml'
    if not hasattr(exception, "getId"):
        errId = -311
        errDesc = str(exception)
    else:
        errId = exception.getId()
        errDesc = exception.getDescription()
    res = '<?xml version="1.0" encoding="UTF-8"?>\
            <jsonrpc version="%s">\
            <result>\
                <status>False</status>\
                <error>\
                    <code>%s</code>\
                    <message>%s</message>\
                </error>\
            </result>\
            <version>%s</version>\
            <id>%s</id>\
            </jsonrpc>' % (get_api_version(), errId, errDesc, get_version(), id)
    return res
Beispiel #7
0
def sendXMLError(response, exception, id=1):
    response.content_type = 'text/xml'
    if not hasattr(exception, "getId"):
        errId = -311
        errDesc = str(exception)
    else:
        errId = exception.getId()
        errDesc = exception.getDescription()
    res = '<?xml version="1.0" encoding="UTF-8"?>\
            <jsonrpc version="%s">\
            <result>\
                <status>False</status>\
                <error>\
                    <code>%s</code>\
                    <message>%s</message>\
                </error>\
            </result>\
            <version>%s</version>\
            <id>%s</id>\
            </jsonrpc>' % (get_api_version(), errId, errDesc, get_version(),
                           id)
    return res
Beispiel #8
0
def sendResultIterator(obj, id=1, opt=None, rp=None, page=None):
    '''
        sendResultIterator - return an json result document in a streamed mode

        :param obj: iterator of generator object like dict, string or list
        :param  id: id value, for future versions
        :param opt: optional parameter, which allows to provide more detail
        :param rp: results per page
        :param page: number of page

        :return: generator of response data (yield)
    '''
    api_version = get_api_version()
    linotp_version = get_version()

    res = {
        "jsonrpc": api_version,
        "result": {
            "status": True,
            "value": "[DATA]",
        },
        "version": linotp_version,
        "id": id
    }

    err = {
        "jsonrpc": api_version,
        "result": {
            "status": False,
            "error": {},
        },
        "version": linotp_version,
        "id": id
    }

    start_at = 0
    stop_at = 0
    if page:
        if not rp:
            rp = 16
        try:
            start_at = int(page) * int(rp)
            stop_at = start_at + int(rp)
        except ValueError as exx:
            err['result']['error'] = {
                "code": 9876,
                "message": "%r" % exx,
            }
            log.exception("failed to convert paging request parameters: %r" %
                          exx)
            yield json.dumps(err)
            # finally we signal end of error result
            raise StopIteration()

    typ = "%s" % type(obj)
    if 'generator' not in typ and 'iterator' not in typ:
        raise Exception('no iterator method for object %r' % obj)

    res = {
        "jsonrpc": api_version,
        "result": {
            "status": True,
            "value": "[DATA]",
        },
        "version": linotp_version,
        "id": id
    }
    if page:
        res['result']['page'] = int(page)

    if opt is not None and len(opt) > 0:
        res["detail"] = opt

    surrounding = json.dumps(res)
    prefix, postfix = surrounding.split('"[DATA]"')

    # first return the opening
    yield prefix + " ["

    sep = ""
    counter = 0
    for next_one in obj:
        counter = counter + 1
        # are we running in paging mode?
        if page:
            if counter >= start_at and counter < stop_at:
                res = "%s%s\n" % (sep, next_one)
                sep = ','
                yield res
            if counter >= stop_at:
                # stop iterating if we reached the last one of the page
                break
        else:
            # no paging - no limit
            res = "%s%s\n" % (sep, next_one)
            sep = ','
            yield res

    # we add the amount of queried objects
    total = '"queried" : %d' % counter
    postfix = ', %s %s' % (total, postfix)

    # last return the closing
    yield "] " + postfix
Beispiel #9
0
def sendError(response, exception, id=1, context=None):
    '''
    sendError - return a HTML or JSON error result document

    Default LinOTP behaviour in case of error is to try to always send a '200
    OK' HTTP response that contains an error code and description in the body
    (JSON data).  Some clients prefer a different HTTP status code, because
    it allows response filtering without parsing the body. If the client
    sends 'httperror=<INT>' in the request this will be honoured (in case of
    error) and that HTTP status will be set. If 'httperror' is set without a
    value (or an invalid value) status 500 will be used.
    If you would like this to happen only in some error conditions but not
    all you can set 'linotp.errors' in the LinOTP Config. Then the HTTP
    status defined by 'httperror' will ONLY be sent when the error that
    occurs in LinOTP matches one of the errors defined in 'linotp.errors'. In
    other cases '200 OK' with error code and description in the body will be
    returned.
    If 'linotp.errors' is unset all errors will cause responses with HTTP
    status 'httperror'.
    For example:
      Setup 1:
        * The client sends httperror=777 in the request
        * linotp.errors=233,567
        Case 1.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 777.
        Case 1.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 200.
      Setup 2:
        * The client sends httperror (empty) in the request
        * linotp.errors=233,567
        Case 2.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 500.
        Case 2.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 200.
      Setup 3:
        * The client sends httperror (empty) in the request
        * linotp.errors is not set
        Case 3.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 500.
        Case 3.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 500.
      Setup 4:
        * NO httperror in request
        * linotp.errors=233,567 (or is unset, does not matter)
        Case 4.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 200.
        Case 4.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 200.

    remark for 'context' parameter:
     the 'context' is especially required to catch errors from the _before_
     methods. The return of a _before_ must be of type response and
     must have the attribute response._exception set, to stop further
     processing, which otherwise will have ugly results!!

    :param response:  the pylon response object
    :type  response:  response object
    :param exception: should be a linotp exception (s. linotp.lib.error.py)
    :type  exception: exception
    :param id:        id value, for future versions
    :type  id:        int
    :param context:   default is None or 'before'
    :type  context:   string

    :return:     json rendered sting result
    :rtype:      string

    '''
    ret = ''
    errId = -311

    ## handle the different types of exception:
    ## Exception, LinOtpError, str/unicode
    if hasattr(exception, '__class__') is True \
    and isinstance(exception, Exception):
        errDesc = unicode(exception)
        if isinstance(exception, LinotpError):
            errId = exception.getId()

    elif type(exception) in [str, unicode]:
        errDesc = unicode(exception)

    else:
        errDesc = u"%r" % exception

    ## check if we have an additional request parameter 'httperror'
    ## which triggers the error to be delivered as HTTP Error
    httperror = _get_httperror_from_params(request)

    send_custom_http_status = False
    if httperror is not None:
        # Client wants custom HTTP status
        linotp_errors = c.linotpConfig.get('linotp.errors', None)
        if not linotp_errors:
            # Send custom HTTP status in every error case
            send_custom_http_status = True
        else:
            # Only send custom HTTP status in defined error cases
            if unicode(errId) in linotp_errors.split(','):
                send_custom_http_status = True
            else:
                send_custom_http_status = False

    if send_custom_http_status:
        # Send HTML response with HTTP status 'httperror'

        # Always set a reason, when no standard one found (e.g. custom HTTP
        # code like 444) use 'LinOTP Error'
        reason = httpErr.get(httperror, 'LinOTP Error')

        response.content_type = 'text/html'
        response.status = "%s %s" % (httperror, reason)

        code = httperror
        status = "%s %s" % (httperror, reason)
        desc = '[%s] %d: %s' % (get_version(), errId, errDesc)
        ret = resp % (code, status, code, status, desc)

        if context in ['before', 'after']:
            response._exception = exception
            response.text = u'' + ret
            ret = response
    else:
        # Send JSON response with HTTP status 200 OK
        response.content_type = 'application/json'
        res = {
            "jsonrpc": get_api_version(),
            "result": {
                "status": False,
                "error": {
                    "code": errId,
                    "message": errDesc,
                },
            },
            "version": get_version(),
            "id": id
        }

        ret = json.dumps(res, indent=3)

        if context in ['before', 'after']:
            response._exception = exception
            response.body = ret
            ret = response

    return ret
Beispiel #10
0
def sendResultIterator(obj, id=1, opt=None, rp=None, page=None):
    '''
        sendResultIterator - return an json result document in a streamed mode

        :param obj: iterator of generator object like dict, string or list
        :param  id: id value, for future versions
        :param opt: optional parameter, which allows to provide more detail
        :param rp: results per page
        :param page: number of page

        :return: generator of response data (yield)
    '''
    api_version = get_api_version()
    linotp_version = get_version()

    res = {"jsonrpc": api_version,
            "result": {"status": True,
                       "value": "[DATA]",
                      },
           "version": linotp_version,
           "id": id}

    err = {"jsonrpc": api_version,
            "result":
                {"status": False,
                 "error": {},
                },
            "version": linotp_version,
            "id": id
        }

    start_at = 0
    stop_at = 0
    if page:
        if not rp:
            rp = 16
        try:
            start_at = int(page) * int(rp)
            stop_at = start_at + int(rp)
        except ValueError as exx:
            err['result']['error'] = {
                            "code": 9876,
                            "message": "%r" % exx,
                            }
            log.exception("failed to convert paging request parameters: %r"
                          % exx)
            yield json.dumps(err)
            # finally we signal end of error result
            raise StopIteration()

    typ = "%s" % type(obj)
    if 'generator' not in typ and 'iterator' not in typ:
        raise Exception('no iterator method for object %r' % obj)

    res = {"jsonrpc": api_version,
            "result": {"status": True,
                       "value": "[DATA]",
                      },
           "version": linotp_version,
           "id": id}
    if page:
        res['result']['page'] = int(page)

    if opt is not None and len(opt) > 0:
        res["detail"] = opt

    surrounding = json.dumps(res)
    prefix, postfix = surrounding.split('"[DATA]"')

    # first return the opening
    yield prefix + " ["

    sep = ""
    counter = 0
    for next_one in obj:
        counter = counter + 1
        # are we running in paging mode?
        if page:
            if counter >= start_at and counter < stop_at:
                res = "%s%s\n" % (sep, next_one)
                sep = ','
                yield res
            if counter >= stop_at:
                # stop iterating if we reached the last one of the page
                break
        else:
            # no paging - no limit
            res = "%s%s\n" % (sep, next_one)
            sep = ','
            yield res

    log.debug('Result iteration finished!')

    # we add the amount of queried objects
    total = '"queried" : %d' % counter
    postfix = ', %s %s' % (total, postfix)

    # last return the closing
    yield "] " + postfix
Beispiel #11
0
def sendError(response, exception, id=1, context=None):
    '''
    sendError - return a HTML or JSON error result document

    Default LinOTP behaviour in case of error is to try to always send a '200
    OK' HTTP response that contains an error code and description in the body
    (JSON data).  Some clients prefer a different HTTP status code, because
    it allows response filtering without parsing the body. If the client
    sends 'httperror=<INT>' in the request this will be honoured (in case of
    error) and that HTTP status will be set. If 'httperror' is set without a
    value (or an invalid value) status 500 will be used.
    If you would like this to happen only in some error conditions but not
    all you can set 'linotp.errors' in the LinOTP Config. Then the HTTP
    status defined by 'httperror' will ONLY be sent when the error that
    occurs in LinOTP matches one of the errors defined in 'linotp.errors'. In
    other cases '200 OK' with error code and description in the body will be
    returned.
    If 'linotp.errors' is unset all errors will cause responses with HTTP
    status 'httperror'.
    For example:
      Setup 1:
        * The client sends httperror=777 in the request
        * linotp.errors=233,567
        Case 1.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 777.
        Case 1.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 200.
      Setup 2:
        * The client sends httperror (empty) in the request
        * linotp.errors=233,567
        Case 2.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 500.
        Case 2.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 200.
      Setup 3:
        * The client sends httperror (empty) in the request
        * linotp.errors is not set
        Case 3.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 500.
        Case 3.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 500.
      Setup 4:
        * NO httperror in request
        * linotp.errors=233,567 (or is unset, does not matter)
        Case 4.1: An exception is raised in LinOTP that has errId 233.
          - LinOTP will return a response with HTTP status 200.
        Case 4.2: An exception is raised with errId 555
          - LinOTP will return a response with HTTP status 200.

    remark for 'context' parameter:
     the 'context' is especially required to catch errors from the _before_
     methods. The return of a _before_ must be of type response and
     must have the attribute response._exception set, to stop further
     processing, which otherwise will have ugly results!!

    :param response:  the pylon response object
    :type  response:  response object
    :param exception: should be a linotp exception (s. linotp.lib.error.py)
    :type  exception: exception
    :param id:        id value, for future versions
    :type  id:        int
    :param context:   default is None or 'before'
    :type  context:   string

    :return:     json rendered sting result
    :rtype:      string

    '''
    ret = ''
    errId = -311

    ## handle the different types of exception:
    ## Exception, LinOtpError, str/unicode
    if hasattr(exception, '__class__') == True \
    and isinstance(exception, Exception):
        errDesc = unicode(exception)
        if isinstance(exception, LinotpError):
            errId = exception.getId()

    elif type(exception) in [str, unicode]:
        errDesc = unicode(exception)

    else:
        errDesc = u"%r" % exception

    ## check if we have an additional request parameter 'httperror'
    ## which triggers the error to be delivered as HTTP Error
    httperror = _get_httperror_from_params(request)

    send_custom_http_status = False
    if httperror is not None:
        # Client wants custom HTTP status
        linotp_errors = c.linotpConfig.get('linotp.errors', None)
        if not linotp_errors:
            # Send custom HTTP status in every error case
            send_custom_http_status = True
        else:
            # Only send custom HTTP status in defined error cases
            if unicode(errId) in linotp_errors.split(','):
                send_custom_http_status = True
            else:
                send_custom_http_status = False

    if send_custom_http_status:
        # Send HTML response with HTTP status 'httperror'

        # Always set a reason, when no standard one found (e.g. custom HTTP
        # code like 444) use 'LinOTP Error'
        reason = httpErr.get(httperror, 'LinOTP Error')

        response.content_type = 'text/html'
        response.status = "%s %s" % (httperror, reason)

        code = httperror
        status = "%s %s" % (httperror, reason)
        desc = '[%s] %d: %s' % (get_version(), errId, errDesc)
        ret = resp % (code, status, code, status, desc)

        if context in ['before', 'after']:
            response._exception = exception
            response.text = u'' + ret
            ret = response
    else:
        # Send JSON response with HTTP status 200 OK
        response.content_type = 'application/json'
        res = { "jsonrpc": get_api_version(),
                "result" :
                    {"status": False,
                        "error": {
                            "code"    :   errId,
                            "message" :   errDesc,
                            },
                    },
                 "version": get_version(),
                 "id": id
            }

        ret = json.dumps(res, indent=3)

        if context in ['before', 'after']:
            response._exception = exception
            response.body = ret
            ret = response

    return ret