some cleanup

This commit is contained in:
ziirish 2018-06-04 14:27:55 +02:00
parent 94e832b56b
commit c116626e2a
No known key found for this signature in database
GPG key ID: 72DB229A64B54E46
13 changed files with 36 additions and 101 deletions

1
.gitignore vendored
View file

@ -8,6 +8,7 @@ devel.sh
.tox
.coverage
.coveragerc
.ropeproject
.pylintrc
dist
_build

View file

@ -27,8 +27,6 @@ def to_unicode(input_bytes, encoding='utf-8'):
"""Decodes input_bytes to text if needed."""
if not isinstance(input_bytes, string_types):
input_bytes = input_bytes.decode(encoding)
elif re.match(r'\\u[0-9a-f]{4}', input_bytes):
input_bytes = input_bytes.decode('unicode-escape')
return input_bytes or ''

View file

@ -20,7 +20,6 @@ from flask_login import current_user
from importlib import import_module
from functools import wraps
from .custom.namespace import Namespace
from .._compat import to_bytes
from ..desc import __version__, __release__, __url__, __doc__
from ..server import BUIServer # noqa
@ -189,15 +188,6 @@ class Api(ApiPlus):
return decorated
return decorator
def namespace(self, *args, **kwargs):
"""A namespace factory
:returns Namespace: a new namespace instance
"""
ns = Namespace(*args, **kwargs)
self.add_namespace(ns)
return ns
apibp = Blueprint('api', __name__, url_prefix='/api')
api = Api(
@ -217,4 +207,5 @@ def handle_bui_server_exception(error):
:param error: Custom exception
:type error: :class:`burpui.exceptions.BUIserverException`
"""
bui.logger.error(error)
return {'message': error.description}, error.code

View file

@ -478,7 +478,6 @@ class AsyncRunningBackup(RunningBackup):
RunningBackup.running_fields,
code=200,
description='Success',
strict=False
)
def get(self, server=None):
"""Tells if a backup is running right now
@ -570,7 +569,6 @@ class AsyncHistory(History):
History.history_fields,
code=200,
description='Success',
strict=False,
as_list=True
)
@ns.expect(History.parser)
@ -650,7 +648,6 @@ class AsyncClientsReport(ClientsReport):
ClientsReport.report_fields,
code=200,
description='Success',
strict=False
)
@ns.expect(ClientsReport.parser)
@ns.doc(

View file

@ -12,8 +12,7 @@ import re
from . import api, cache_key, force_refresh
from ..server import BUIServer # noqa
from .custom import fields, Resource
from .custom.inputs import boolean
from .custom import fields, Resource, inputs
from ..decorators import browser_cache
from ..ext.cache import cache
from ..exceptions import BUIserverException
@ -141,7 +140,7 @@ class ClientTree(Resource):
)
parser.add_argument(
'recursive',
type=boolean,
type=inputs.boolean,
help='Returns the whole tree instead of just the sub-tree',
nullable=True,
required=False,
@ -149,7 +148,7 @@ class ClientTree(Resource):
)
parser.add_argument(
'selected',
type=boolean,
type=inputs.boolean,
help='Make the returned path selected at load time. Only works' +
' if \'recursive\' is True',
nullable=True,
@ -158,7 +157,7 @@ class ClientTree(Resource):
)
parser.add_argument(
'init',
type=boolean,
type=inputs.boolean,
help='First call to load the root of the tree',
nullable=True,
required=False,

View file

@ -8,6 +8,11 @@
"""
import flask_restplus.fields
from flask_restplus.fields import * # noqa # pylint: disable=locally-disabled, wildcard-import, unused-wildcard-import
from .my_fields import DateTime, DateTimeHuman, BackupNumber, SafeString, LocalizedString, Wildcard # noqa
from .my_fields2 import Nested # noqa
__all__ = flask_restplus.fields.__all__ + \
(DateTime, DateTimeHuman, BackupNumber, SafeString, LocalizedString, Wildcard)

View file

@ -8,5 +8,10 @@
"""
import inspect
import flask_restplus.inputs
from flask_restplus.inputs import * # noqa # pylint: disable=locally-disabled, wildcard-import, unused-wildcard-import
from .my_inputs import boolean # noqa
ALL = inspect.getmembers(flask_restplus.inputs, inspect.isfunction)
__all__ = [x for x, _ in ALL if not x.startswith('_')] + ['boolean']

View file

@ -8,12 +8,14 @@
"""
# Monkey patching flask-restplus to handle our own marshalling/wildcard implementation
from flask_restplus import fields
from .my_marshalling import marshal
class Nested(fields.Nested):
def output(self, key, obj, ordered=False):
def output(self, key, obj, ordered=False, **kwargs):
value = fields.get_value(key if self.attribute is None else self.attribute, obj)
if value is None:
if self.allow_null:
@ -21,4 +23,4 @@ class Nested(fields.Nested):
elif self.default is not None:
return self.default
return marshal(value, self.nested, ordered=ordered)
return marshal(value, self.nested, skip_none=self.skip_none, ordered=ordered)

View file

@ -29,9 +29,9 @@ def boolean(value):
"""
try:
return boolean_ori(value)
except ValueError as e:
except ValueError as exp:
if not value:
return False
if value.lower() == 'on':
if isinstance(value, str) and value.lower() == 'on':
return True
raise e
raise exp

View file

@ -1,64 +0,0 @@
# -*- coding: utf8 -*-
"""
.. module:: burpui.api.custom.namespace
:platform: Unix
:synopsis: Burp-UI api custom namespace module.
.. moduleauthor:: Ziirish <hi+burpui@ziirish.me>
"""
# All of this is creepy hacky since Flask-Resplus seem dead...
from functools import wraps
from werkzeug.wrappers import Response
from flask import Response as FlaskResponse, request, current_app, \
has_app_context
from flask_restplus import Namespace as NamespacePlus
from flask_restplus.utils import unpack, merge
from flask_restplus.marshalling import marshal_with as marshal_with_plus
from .my_marshalling import marshal
class marshal_with(marshal_with_plus):
"""Subclass default marshal_with to manage custom API responses"""
def __init__(self, fields, envelope=None, mask=None, strict=True):
super(marshal_with, self).__init__(fields, envelope, mask)
self.strict = strict
def __call__(self, f):
@wraps(f)
def wrapper(*args, **kwargs):
resp = f(*args, **kwargs)
if not self.strict and (isinstance(resp, Response) or
isinstance(resp, FlaskResponse)):
return resp
mask = self.mask
if has_app_context():
mask_header = current_app.config['RESTPLUS_MASK_HEADER']
mask = request.headers.get(mask_header) or mask
if isinstance(resp, tuple):
data, code, headers = unpack(resp)
return marshal(data, self.fields, self.envelope, mask), code, headers
else:
return marshal(resp, self.fields, self.envelope, mask)
return wrapper
class Namespace(NamespacePlus):
"""Subclass default Namespace to manage custom API responses"""
def marshal_with(self, fields, as_list=False, code=200, description=None, strict=True, **kwargs):
"""If the decorated function returns a :class:`Flask.Response` object,
we don't marshal it
"""
def wrapper(func):
doc = {
'responses': {
code: (description, [fields]) if as_list else (description, fields)
},
'__mask__': kwargs.get('mask', True), # Mask values can't be determined outside app context
}
func.__apidoc__ = merge(getattr(func, '__apidoc__', {}), doc)
kwargs['strict'] = strict
return marshal_with(fields, **kwargs)(func)
return wrapper

View file

@ -12,8 +12,7 @@ import struct
from . import api
from ..server import BUIServer # noqa
from .custom import fields, Resource
from .custom.inputs import boolean
from .custom import fields, Resource, inputs
from ..exceptions import BUIserverException
from zlib import adler32
@ -372,7 +371,7 @@ class DoServerRestore(Resource):
parser.add_argument('list-sc', required=True, help='List of files/directories to restore', nullable=False)
parser.add_argument('strip-sc', type=int, help='Number of elements to strip in the path', default=0, nullable=True)
parser.add_argument('prefix-sc', help='Prefix to the restore path', nullable=True)
parser.add_argument('force-sc', type=boolean, help='Whether to overwrite existing files', default=False, nullable=True)
parser.add_argument('force-sc', type=inputs.boolean, help='Whether to overwrite existing files', default=False, nullable=True)
parser.add_argument('restoreto-sc', help='Restore files on an other client', nullable=True)
@api.disabled_on_demo()

View file

@ -10,8 +10,7 @@
from . import api
from ..server import BUIServer # noqa
from ..ext.cache import cache
from .custom import Resource
from .custom.inputs import boolean
from .custom import Resource, inputs
from .._compat import unquote
from ..utils import NOTIF_INFO
@ -476,14 +475,14 @@ class NewClientSettings(Resource):
)
class ClientSettings(Resource):
parser_delete = ns.parser()
parser_delete.add_argument('revoke', type=boolean, help='Whether to revoke the certificate or not', default=False, nullable=True)
parser_delete.add_argument('delcert', type=boolean, help='Whether to delete the certificate or not', default=False, nullable=True)
parser_delete.add_argument('keepconf', type=boolean, help='Whether to keep the conf or not', default=False, nullable=True)
parser_delete.add_argument('template', type=boolean, help='Whether we work on a template or not', default=False, nullable=True)
parser_delete.add_argument('revoke', type=inputs.boolean, help='Whether to revoke the certificate or not', default=False, nullable=True)
parser_delete.add_argument('delcert', type=inputs.boolean, help='Whether to delete the certificate or not', default=False, nullable=True)
parser_delete.add_argument('keepconf', type=inputs.boolean, help='Whether to keep the conf or not', default=False, nullable=True)
parser_delete.add_argument('template', type=inputs.boolean, help='Whether we work on a template or not', default=False, nullable=True)
parser_post = ns.parser()
parser_post.add_argument('template', type=boolean, help='Whether we work on a template or not', default=False, nullable=True)
parser_post.add_argument('template', type=inputs.boolean, help='Whether we work on a template or not', default=False, nullable=True)
parser_get = ns.parser()
parser_get.add_argument('template', type=boolean, help='Whether we work on a template or not', default=False, nullable=True)
parser_get.add_argument('template', type=inputs.boolean, help='Whether we work on a template or not', default=False, nullable=True)
@api.disabled_on_demo()
@api.acl_admin_or_moderator_required(message=_('Sorry, you don\'t have rights to access the setting panel'))

View file

@ -213,7 +213,10 @@ class BUIServer(Flask):
)
self.format_labels = []
for format_label in format_labels:
search = re.search(r'^s(?P<separator>.)(?P<regex>.*?)(?P=separator)(?P<replace>.*?)(?P=separator)$', format_label)
search = re.search(
r'^s(?P<separator>.)(?P<regex>.*?)(?P=separator)(?P<replace>.*?)(?P=separator)$',
format_label
)
if search:
self.format_labels.append((search.group('regex'), search.group('replace')))