示例#1
0
class terrariumWebserver(object):

    app = Bottle()
    app.install(terrariumWebserverHeaders())

    def __init__(self, terrariumEngine):
        self.__terrariumEngine = terrariumEngine
        self.__app = terrariumWebserver.app
        self.__config = self.__terrariumEngine.get_config('system')
        self.__caching_days = 30
        terrariumWebserver.app.terrarium = self.__terrariumEngine
        # Load language
        gettext.translation('terrariumpi',
                            'locales/',
                            languages=[
                                self.__terrariumEngine.config.get_language()
                            ]).install(True)
        self.__translations = terrariumTranslations()

        self.__routes()

    # Custom HTTP authentication routine. This way there is an option to optional secure the hole web interface
    def __auth_basic2(self,
                      check,
                      required,
                      realm="private",
                      text="Access denied"):
        """ Callback decorator to require HTTP auth (basic).
        TODO: Add route(check_auth=...) parameter. """
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*a, **ka):
                user, password = request.auth or (None, None)
                if required or terrariumUtils.is_true(
                        self.__terrariumEngine.config.get_system()
                    ['always_authenticate']):

                    if user is None or not check(user, password):
                        err = HTTPError(401, text)
                        err.add_header('WWW-Authenticate',
                                       'Basic realm="%s"' % realm)
                        return err

                return func(*a, **ka)

            return wrapper

        return decorator

    def __authenticate(self, required):
        return self.__auth_basic2(self.__terrariumEngine.authenticate,
                                  required,
                                  _('TerrariumPI') + ' ' + _('Authentication'),
                                  _('Authenticate to make any changes'))

    def __logout_authenticate(self, user, password):
        return True

    def __routes(self):
        self.__app.route('/',
                         method="GET",
                         callback=self.__render_page,
                         apply=self.__authenticate(False))

        self.__app.route('/<template_name:re:[^/]+\.html$>',
                         method="GET",
                         callback=self.__render_page,
                         apply=self.__authenticate(False))

        self.__app.route('/<filename:re:robots\.txt>',
                         method="GET",
                         callback=self.__static_file)

        self.__app.route('/<root:re:static/extern>/<filename:path>',
                         method="GET",
                         callback=self.__static_file)

        self.__app.route(
            '/<root:re:(static|gentelella|webcam|audio|log)>/<filename:path>',
            method="GET",
            callback=self.__static_file,
            apply=self.__authenticate(False))

        self.__app.route('/api/<path:re:(config/notifications)>',
                         method=['GET'],
                         callback=self.__get_api_call,
                         apply=self.__authenticate(True))

        self.__app.route('/api/<path:path>',
                         method=['GET'],
                         callback=self.__get_api_call,
                         apply=self.__authenticate(False))

        self.__app.route('/api/switch/toggle/<switchid:path>',
                         method=['POST'],
                         callback=self.__toggle_switch,
                         apply=self.__authenticate(True))

        self.__app.route('/api/switch/state/<switchid:path>/<value:int>',
                         method=['POST'],
                         callback=self.__state_switch,
                         apply=self.__authenticate(True))

        self.__app.route(
            '/api/config/<path:re:(system|weather|switches|sensors|webcams|doors|audio|environment|profile|notifications)>',
            method=['PUT', 'POST', 'DELETE'],
            callback=self.__update_api_call,
            apply=self.__authenticate(True))

        self.__app.route(
            '/api/audio/player/<action:re:(start|stop|volumeup|volumedown|mute|unmute)>',
            method=['POST'],
            callback=self.__player_commands,
            apply=self.__authenticate(True))

        self.__app.route('/api/audio/file',
                         method=['POST'],
                         callback=self.__upload_audio_file,
                         apply=self.__authenticate(True))

        self.__app.route('/api/audio/file/<audiofileid:path>',
                         method=['DELETE'],
                         callback=self.__delete_audio_file,
                         apply=self.__authenticate(True))

        self.__app.route('/logout',
                         method=['GET'],
                         callback=self.__logout_url,
                         apply=auth_basic(
                             self.__logout_authenticate,
                             _('TerrariumPI') + ' ' + _('Authentication'),
                             _('Authenticate to make any changes')))

    def __template_variables(self, template):
        variables = {
            'lang':
            self.__terrariumEngine.config.get_language(),
            'title':
            self.__config['title'],
            'version':
            self.__config['version'],
            'page_title':
            _(template.replace('_', ' ').capitalize()),
            'temperature_indicator':
            self.__terrariumEngine.get_temperature_indicator(),
            'distance_indicator':
            self.__terrariumEngine.get_distance_indicator(),
            'volume_indicator':
            self.__terrariumEngine.get_volume_indicator(),
            'horizontal_graph_legend':
            1 if self.__terrariumEngine.get_horizontal_graph_legend() else 0,
            'translations':
            self.__translations,
            'device':
            self.__terrariumEngine.device,
            'notifications':
            self.__terrariumEngine.notification
        }

        if 'index' == template or 'profile' == template:
            variables['person_name'] = self.__terrariumEngine.get_profile_name(
            )
            variables[
                'person_image'] = self.__terrariumEngine.get_profile_image()

        return variables

    def __render_page(self, template_name='index.html'):
        template_name = template_name[:-5]

        if not os.path.isfile('views/' + template_name + '.tpl'):
            template_name = '404'

        return template(template_name,
                        **self.__template_variables(template_name))

    def __static_file(self, filename, root='static'):
        if filename == 'js/terrariumpi.js':
            response.headers[
                'Content-Type'] = 'application/javascript; charset=UTF-8'
            response.headers['Expires'] = (
                datetime.datetime.utcnow() +
                datetime.timedelta(days=self.__caching_days)
            ).strftime('%a, %d %b %Y %H:%M:%S GMT')
            return template(filename, template_lookup=[root])

        staticfile = static_file(filename, root=root)
        if isinstance(staticfile, HTTPError):
            return staticfile

        if 'webcam' == root or 'log' == root:
            staticfile.add_header(
                'Expires',
                datetime.datetime.utcnow().strftime(
                    '%a, %d %b %Y %H:%M:%S GMT'))
            if 'log' == root:
                staticfile.add_header('Content-Type',
                                      'text/text; charset=UTF-8')
                staticfile.add_header('Content-Disposition',
                                      'Attachment;filename=' + filename)
        else:
            staticfile.add_header('Expires',
                                  (datetime.datetime.utcnow() +
                                   datetime.timedelta(days=self.__caching_days)
                                   ).strftime('%a, %d %b %Y %H:%M:%S GMT'))

        if staticfile.get_header('Last-Modified') is not None:
            staticfile.add_header(
                'Etag',
                hashlib.md5(staticfile.get_header(
                    'Last-Modified').encode()).hexdigest())

        return staticfile

    def __player_commands(self, action):
        result = {
            'ok': False,
            'title': _('Error!'),
            'message': _('Player command could ot be executed!')
        }

        if 'start' == action:
            self.__terrariumEngine.audio_player_start()
        elif 'stop' == action:
            self.__terrariumEngine.audio_player_stop()
        elif 'volumeup' == action:
            self.__terrariumEngine.audio_player_volume_up()
            result = {
                'ok': True,
                'title': _('OK!'),
                'message': _('Player command executed!')
            }
        elif 'volumedown' == action:
            self.__terrariumEngine.audio_player_volume_down()
            result = {
                'ok': True,
                'title': _('OK!'),
                'message': _('Player command executed!')
            }
        elif 'mute' == action:
            pass
        elif 'unmute' == action:
            pass

        return result

    def __upload_audio_file(self):
        result = {
            'ok': False,
            'title': _('Error!'),
            'message': _('File is not uploaded!')
        }
        upload = request.files.get('file')
        try:
            upload.save(terrariumAudioPlayer.AUDIO_FOLDER)
            self.__terrariumEngine.reload_audio_files()
            result = {
                'ok': True,
                'title': _('Success!'),
                'message': _('File \'%s\' is uploaded') % (upload.filename, )
            }
        except IOError as message:
            result['message'] = _('Duplicate file \'%s\'') % (
                upload.filename, )

        return result

    def __delete_audio_file(self, audiofileid):
        result = {
            'ok': False,
            'title': _('Error!'),
            'message': _('Action could not be satisfied')
        }

        if self.__terrariumEngine.delete_audio_file(audiofileid):
            result = {
                'ok': True,
                'title': _('Success!'),
                'message': _('Audio file is deleted')
            }

        return result

    def __update_api_call(self, path):
        result = {
            'ok': False,
            'title': _('Error!'),
            'message': _('Data could not be saved')
        }
        postdata = {}

        if request.json is not None:
            postdata = request.json

        result['ok'] = self.__terrariumEngine.set_config(
            path, postdata, request.files)
        if result['ok']:
            result['title'] = _('Data saved')
            result['message'] = _('Your changes are saved')

            # Reload language if needed
            if 'language' in postdata:
                gettext.translation(
                    'terrariumpi',
                    'locales/',
                    languages=[self.__terrariumEngine.config.get_language()
                               ]).install(True)
                self.__translations.reload()

        return result

    def __get_api_call(self, path):
        response.headers['Expires'] = (datetime.datetime.utcnow() +
                                       datetime.timedelta(seconds=10)
                                       ).strftime('%a, %d %b %Y %H:%M:%S GMT')
        response.headers['Access-Control-Allow-Origin'] = '*'

        result = {}
        parameters = path.strip('/').split('/')

        action = parameters[0]
        del (parameters[0])

        if 'switches' == action:
            result = self.__terrariumEngine.get_switches(parameters)

        elif 'doors' == action:
            if len(parameters) > 0 and parameters[0] == 'status':
                result = {'status': self.__terrariumEngine.get_doors_status()}
            else:
                result = self.__terrariumEngine.get_doors()

        elif 'profile' == action:
            result = self.__terrariumEngine.get_profile()

        elif 'sensors' == action:
            result = self.__terrariumEngine.get_sensors(parameters)

        elif 'webcams' == action:
            result = self.__terrariumEngine.get_webcams(parameters)

        elif 'audio' == action:
            if len(parameters) > 0 and parameters[0] == 'files':
                del (parameters[0])
                result = self.__terrariumEngine.get_audio_files(parameters)
            elif len(parameters) > 0 and parameters[0] == 'playing':
                del (parameters[0])
                result = self.__terrariumEngine.get_audio_playing()
            elif len(parameters) > 0 and parameters[0] == 'hardware':
                del (parameters[0])
                result = {
                    'audiohardware': terrariumAudioPlayer.get_sound_cards()
                }
            else:
                result = self.__terrariumEngine.get_audio_playlists(parameters)

        elif 'environment' == action:
            result = self.__terrariumEngine.get_environment(parameters)

        elif 'weather' == action:
            result = self.__terrariumEngine.get_weather(parameters)

        elif 'uptime' == action:
            result = self.__terrariumEngine.get_uptime()

        elif 'power_usage' == action:
            result = self.__terrariumEngine.get_power_usage_water_flow(
            )['power']

        elif 'water_usage' == action:
            result = self.__terrariumEngine.get_power_usage_water_flow(
            )['water']

        elif 'system' == action:
            result = self.__terrariumEngine.get_system_stats()

        elif 'config' == action:
            # TODO: New way of data processing.... fix other config options
            result = self.__terrariumEngine.get_config(
                parameters[0] if len(parameters) == 1 else None)

        elif 'history' == action or 'export' == action:
            response.headers['Expires'] = (
                datetime.datetime.utcnow() + datetime.timedelta(minutes=1)
            ).strftime('%a, %d %b %Y %H:%M:%S GMT')
            if 'export' == action:
                parameters.append('all')
            result = self.__terrariumEngine.get_history(parameters)

            if 'export' == action:
                csv = ''
                export_name = 'error'
                for datatype in result:
                    for dataid in result[datatype]:
                        export_name = datatype + '_' + dataid + '.csv'
                        # Header
                        fields = list(result[datatype][dataid].keys())
                        if 'totals' in fields:
                            fields.remove('totals')
                        csv = '"' + '","'.join(['timestamp'] + fields) + "\"\n"

                        for counter in range(
                                0, len(result[datatype][dataid][fields[0]])):
                            # Timestamp
                            row = [
                                datetime.datetime.fromtimestamp(
                                    int(
                                        str(
                                            int(result[datatype][dataid][
                                                fields[0]][counter][0] /
                                                1000)))).strftime(
                                                    '%Y-%m-%d %H:%M:%S')
                            ]
                            for field in fields:
                                # Row values
                                row.append(
                                    str(result[datatype][dataid][field]
                                        [counter][1]))

                            csv += '"' + '","'.join(row) + "\"\n"

                response.headers['Content-Type'] = 'application/csv'
                response.headers[
                    'Content-Disposition'] = 'attachment; filename=' + export_name
                return csv

        return result

    def __toggle_switch(self, switchid):
        if switchid in self.__terrariumEngine.power_switches:
            self.__terrariumEngine.power_switches[switchid].toggle()
            return {'ok': True}

        return {'ok': False}

    def __state_switch(self, switchid, value):
        if switchid in self.__terrariumEngine.power_switches:
            if value == 1:
                self.__terrariumEngine.power_switches[switchid].set_state(True)
                return {'ok': True}
            elif value == 0:
                self.__terrariumEngine.power_switches[switchid].set_state(
                    False)
                return {'ok': True}
            else:
                self.__terrariumEngine.power_switches[switchid].set_state(
                    value)
                return {'ok': True}

        return {'ok': False}

    def __logout_url(self):
        return {
            'ok': True,
            'title': _('Log out'),
            'message': _('You are now logged out')
        }

    @app.error(404)
    def error404(error):
        config = terrariumWebserver.app.terrarium.get_config('system')
        variables = {
            'lang': terrariumWebserver.app.terrarium.config.get_language(),
            'title': config['title'],
            'page_title': config['title'] + ' | 404'
        }

        return template('404', **variables)

    @app.route('/live', apply=[websocket])
    def handle_websocket(socket):
        messages = Queue()

        def listen_for_messages(messages, socket):
            while True:
                message = messages.get()

                try:
                    socket.send(json.dumps(message))
                except Exception as ex:
                    # Socket connection is lost, stop looping....
                    break

                messages.task_done()

        while True:
            try:

                message = socket.receive()
            except Exception as ex:
                break

            if message is not None:
                message = json.loads(message)

                if message['type'] == 'client_init':
                    _thread.start_new_thread(listen_for_messages,
                                             (messages, socket))
                    terrariumWebserver.app.terrarium.subscribe(messages)

                terrariumWebserver.app.terrarium.get_doors_status(socket=True)
                terrariumWebserver.app.terrarium.get_uptime(socket=True)
                terrariumWebserver.app.terrarium.get_environment(socket=True)
                terrariumWebserver.app.terrarium.get_power_usage_water_flow(
                    socket=True)

    def start(self):
        # Start the webserver
        logger.info('Running webserver at %s:%s' %
                    (self.__config['host'], self.__config['port']))
        print(
            '%s - INFO    - terrariumWebserver   - Running webserver at %s:%s'
            % (datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S,000'),
               self.__config['host'], self.__config['port']))
        self.__app.run(host=self.__config['host'],
                       port=self.__config['port'],
                       server=GeventWebSocketServer,
                       debug=True,
                       reloader=False,
                       quiet=True)
示例#2
0
from bottle import route, run, error, template, request, response, Bottle
from json import dumps

app = application = Bottle()

# class EnableCors(object):
#     name = 'enable_cors'
#     api = 2
#
#     def apply(self, fn, context):
#         def _enable_cors(*args, **kwargs):
#             # set CORS headers
#             response.headers['Access-Control-Allow-Origin'] = '*'
#             response.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, OPTIONS'
#             response.headers['Access-Control-Allow-Headers'] = 'Origin, Accept, Content-Type, X-Requested-With, X-CSRF-Token'
#
#             if request.method != 'OPTIONS':
#                 # actual request; reply with the actual response
#                 return fn(*args, **kwargs)
#
#         return _enable_cors


def temp(file_name,
         *args,
         title="",
         extension=".html",
         template_dir="view/",
         **kwargs):
    file_name = template_dir + file_name + extension
    return template("view/layout/skeleton.html", body_file=file_name)
示例#3
0
from bottle import Bottle, request
import datetime
import pickle
import base64

api = Bottle()


@api.route("/")
def index():
    """Index endpoint"""
    return "token"


@api.route("/token", method="PUT")
def token():
    """Token endpoint

    See https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instancedata-data-retrieval.html
    """
    ttl = request.headers.get("X-aws-ec2-metadata-token-ttl-seconds")
    if ttl is None:
        return
    else:
        try:
            if 1 <= int(ttl) <= 21600:
                now = datetime.datetime.now()
                next = now + datetime.timedelta(seconds=int(ttl))
                payload = {"ttl": ttl, "expires": next.timestamp()}
                return base64.b64encode(pickle.dumps(payload))
            else:
示例#4
0
# _*_ coding: utf-8 _*_
from bottle import Bottle, run, template  # Bottle指定对象分配指定网址,可以不引入route(),引入模板

app = Bottle()  # 给app变量分配一个网址,创建框架


@app.route('/hello')  # 给app创建URL path
def hello():
    return "Hello World!"


if __name__ == '__main__':
    run(app, host='localhost', port=8080, debug=True)  #注意运行要添加app变量
示例#5
0
    from Raspi import System
elif True is CheckWindows():
    from Win import Network
    from Win import VideoInfo
    from Win import HDMI
    from Win import Video
    from Win import System
    pass

path = None  # playing file path
user = None  # playing file user
comment = None  # playing file comment
duration = None  # playing file duration
audioNum = 0  # playing file audio stream
vol = -4500  # current volume
app = Bottle()  # bottle instance
pause = False  # pause
video = None  # video instance
videoInfo = None  # videoInfo instance
network = None  # network Instance
hdmi = None  # hdmi instance
system = None  # system Instance
lock = threading.Lock()  # Lock Object
enter = False  # Enter-Key State


def callback(event):
    global enter
    if event.event_type == keyboard.KEY_DOWN:
        if 28 == event.scan_code or 96 == event.scan_code:
            enter = True
示例#6
0
 def __init__(self, host='', porta=8080):
     self._h = host
     self._p = porta
     self._a = Bottle()
     self._rota()
     self._g = core
示例#7
0
def dummy_xmlrpc_app():
    app = Bottle()
    return app
示例#8
0
    def __init__(self, root):
        self.root = root
        self.app = Bottle()
        self.db = j.sal.bcdbfs

        # Valid token until thousand of years
        # Generated from jwt.iousing
        # {
        #     "user": {
        #         "id": 1,
        #         "locale": "en",
        #         "viewMode": "mosaic",
        #         "perm": {
        #             "admin": true,
        #             "execute": true,
        #             "create": true,
        #             "rename": true,
        #             "modify": true,
        #             "delete": true,
        #             "share": false,
        #             "download": true
        #         },
        #         "commands": [],
        #         "lockPassword": false
        #     },
        #     "exp": 156691277633,
        #     "iat": 1566905576,
        #     "iss": "File Browser"
        # }
        self.TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyIjp7ImlkIjoxLCJsb2NhbGUiOiJlbiIsInZpZXdNb2RlIjoibW9zYWljIiwicGVybSI6eyJhZG1pbiI6dHJ1ZSwiZXhlY3V0ZSI6dHJ1ZSwiY3JlYXRlIjp0cnVlLCJyZW5hbWUiOnRydWUsIm1vZGlmeSI6dHJ1ZSwiZGVsZXRlIjp0cnVlLCJzaGFyZSI6ZmFsc2UsImRvd25sb2FkIjp0cnVlfSwiY29tbWFuZHMiOltdLCJsb2NrUGFzc3dvcmQiOmZhbHNlfSwiZXhwIjoxNTY2OTEyNzc2MzMsImlhdCI6MTU2NjkwNTU3NiwiaXNzIjoiRmlsZSBCcm93c2VyIn0.GaBiL_MeqDev0695MRqE3RhmGatouIT4BtlvpTI4P1A"

        @self.app.route("/fileserver/api/login", method="post")
        def login():
            response.set_header("Content-Type", "cty")
            return self.TOKEN

        @self.app.route("/fileserver/api/renew", method="post")
        def renew():
            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type", "cty")
            return self.TOKEN

        @self.app.route("/static/<path:path>")
        def static(path):
            return static_file(path, root="%s/static" % self.root)

        @self.app.route("/fileserver/api/resources/<dir:path>/", method="post")
        def create_dir(dir):
            dir = j.sal.fs.joinPaths("/", dir).rstrip("/")
            override = request.GET.get("override") == "true"
            if not j.sal.bcdbfs.dir_exists(dir):
                self.db.dir_create(dir)
            elif j.sal.bcdbfs.dir_exists(dir) and override:
                self.db.dir_create(dir)

            obj = self.db._dir_model.get_by_name(name=dir)
            obj.epoch = int(time.time())
            obj.save()

            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type", "text/plain; charset=utf-8")
            return "200 OK"

        @self.app.route("/fileserver/api/resources/<dir:path>/",
                        method="delete")
        def delete_dir(dir):
            dir = j.sal.fs.joinPaths("/", dir).rstrip("/")
            if j.sal.bcdbfs.dir_exists(dir):
                self.db.dir_remove(dir)

                response.set_header("Content-Type",
                                    "text/plain; charset=utf-8")
                response.set_header("X-Content-Type-Options", "nosniff")
                response.set_header("X-Renew-Token", "true")
                return "200 OK"

            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type", "text/plain; charset=utf-8")
            return "409 Conflict"

        @self.app.route("/fileserver/api/resources/<path:re:.*>",
                        method="post")
        def upload_file(path):
            file = j.sal.fs.joinPaths("/", path)
            override = request.GET.get("override") == "true"

            def create(file):
                content_type = "text/plain"
                if request.body.seek(0, 2) == 0:
                    self.db.file_create_empty(file)
                else:
                    request.body.seek(0)
                    buff = request.body.read(1024)
                    request.body.seek(0)
                    mtype = filetype.guess(buff)

                    if mtype:
                        content_type = mtype.mime
                    else:
                        x = mimetypes.MimeTypes()
                        types = {}
                        for l in x.types_map:
                            types.update(l)
                        ct = types.get("." + j.sal.fs.getFileExtension(file))
                        if ct:
                            content_type = ct
                    self.db.file_write(file,
                                       request.body,
                                       append=True,
                                       create=True)

                obj = self.db._file_model.get_by_name(name=file)
                obj.content_type = content_type
                obj.epoch = int(time.time())
                obj.save()

            if not j.sal.bcdbfs.file_exists(file):
                create(file)
            elif j.sal.bcdbfs.file_exists(file) and override:
                create(file)
            else:
                response.set_header("X-Content-Type-Options", "nosniff")
                response.set_header("X-Renew-Token", "true")
                response.set_header("Content-Type",
                                    "text/plain; charset=utf-8")
                return "409 Conflict"

            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            response.set_header("Etag", "15bed3cb4c34f4360")
            response.set_header("Content-Type", "text/plain; charset=utf-8")
            return "200 OK"

        @self.app.route("/fileserver/api/threetransfer/<path:re:.*>",
                        method="post")
        def upload_threetransfer(path):
            file = j.sal.fs.joinPaths("/", path)

            def create(file):
                content_type = "text/plain"
                if request.body.seek(0, 2) == 0:
                    self.db.file_create_empty(file)
                else:
                    request.body.seek(0)
                    buff = request.body.read(1024)
                    request.body.seek(0)
                    mtype = filetype.guess(buff)

                    if mtype:
                        content_type = mtype.mime
                    else:
                        x = mimetypes.MimeTypes()
                        types = {}
                        for l in x.types_map:
                            types.update(l)
                        ct = types.get("." + j.sal.fs.getFileExtension(file))
                        if ct:
                            content_type = ct
                    filename = "{}".format(file)
                    self.db.file_write(filename,
                                       request.body,
                                       append=True,
                                       create=True)

                obj = self.db._file_model.get_by_name(name=filename)
                obj.content_type = content_type
                obj.epoch = int(time.time())
                obj.save()

            # if exists do nothing

            create(file)

            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            response.set_header("Etag", "15bed3cb4c34f4360")
            response.set_header("Content-Type", "text/plain; charset=utf-8")
            return "200 OK"

        @self.app.route(
            "/fileserver/api/threetransferdownload/<identifier:re:.*>")
        def threetransfer_download(identifier):
            """
            single file or single dir
            """
            bcdb = j.data.bcdb.get("threetransfer")
            shortlink_model = bcdb.model_get(url="threetransfer.shortlink.1")

            files = shortlink_model.find(identifier=identifier)

            file = ""
            if files:
                file = files[0].url
            else:
                raise j.exception.Value("The identifier %s does not exist" %
                                        identifier)
            path = j.sal.fs.joinPaths("/", file)
            # download single file
            inline = request.GET.get("inline") == "true"
            obj = self.db._file_model.get_by_name(name=path)

            response.set_header("X-Renew-Token", "true")

            filename = obj.name
            if filename[0] == "/":
                filename = filename[1:]
            response.set_header("filename", filename)

            response.set_header("Content-Type", "application/octet-stream")

            filetype = obj.content_type
            response.set_header("Content-Type", filetype)
            if inline:
                response.set_header("Content-Disposition", "inline")
                response.set_header("Accept-Ranges", "bytes")
            else:
                # response.set_header("Content-Disposition", "attachment; filename=utf-8" "%s" % j.sal.fs.getBaseName(file))
                response.set_header("Content-Disposition",
                                    'attachment; filename="myfile.txt"')
            return self.db.file_read(path)

        @self.app.route("/fileserver/api/resources/<path:re:.*>", method="put")
        def create_file(path):
            def create(file):
                buff = request.body.read(1024)
                request.body.seek(0)
                content_type = "text/plain"
                mtype = filetype.guess(buff)
                if mtype:
                    content_type = mtype.mime
                else:
                    x = mimetypes.MimeTypes()
                    types = {}
                    for l in x.types_map:
                        types.update(l)
                    ct = types.get("." + j.sal.fs.getFileExtension(file))
                    if ct:
                        content_type = ct
                for line in request.body:
                    self.db.file_write(file,
                                       line.decode(),
                                       append=True,
                                       create=True)
                obj = self.db._file_model.get_by_name(name=file)
                obj.content_type = content_type
                obj.epoch = int(time.time())
                obj.save()

            file = j.sal.fs.joinPaths("/", path)
            override = request.GET.get("override") == "true"
            obj = self.db._file_model.get_by_name(name=file)

            if obj.size_bytes == 0:
                override = True

            if j.sal.bcdbfs.file_exists(file) and override:
                self.db.file_delete(file)
                create(file)
            elif not j.sal.bcdbfs.file_exists(file):
                create(file)
            else:
                response.set_header("X-Content-Type-Options", "nosniff")
                response.set_header("X-Renew-Token", "true")
                response.set_header("Content-Type",
                                    "text/plain; charset=utf-8")
                return "409 Conflict"

            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            response.set_header("Etag", "15bed3cb4c34f4360")
            response.set_header("Content-Type", "text/plain; charset=utf-8")
            return "200 OK"

        @self.app.route("/fileserver/api/resources/<path:re:.*>",
                        method="delete")
        def delete_file(path):
            file = j.sal.fs.joinPaths("/", path)

            if j.sal.bcdbfs.file_exists(file):
                self.db.file_delete(file)

                response.set_header("X-Content-Type-Options", "nosniff")
                response.set_header("X-Renew-Token", "true")
                response.set_header("Etag", "15bed3cb4c34f4360")
                response.set_header("Content-Type",
                                    "text/plain; charset=utf-8")
                return "200 OK"

            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type", "text/plain; charset=utf-8")
            return "409 Conflict"

        @self.app.route("/fileserver/api/resources/<dir:path>/",
                        method="patch")
        def dir_copy_rename_move(dir):
            src = j.sal.fs.joinPaths("/", dir)
            action = request.GET.get("action")
            destination = request.GET.get("destination")

            def copy_dir(src, dest):
                self.db.dir_copy_from_bcdbfs(src, dest)

            def move_dir(src, dest):
                self.db.dir_copy_from_bcdbfs(src, dest)
                self.db.dir_remove(src)

            if action == "copy":
                copy_dir(src, destination)
            if action in ["move", "rename"]:
                move_dir(src, destination)

            response.set_header("Content-Type", "text/plain; charset=utf-8")
            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            return "200 OK"

        @self.app.route("/fileserver/api/resources/<path:re:.*>",
                        method="patch")
        def file_copy_rename_move(path):
            file = j.sal.fs.joinPaths("/", path)
            action = request.GET.get("action")
            destination = request.GET.get("destination")

            def copy_file(src, dest):
                self.db.file_copy_form_bcdbfs(src, dest)

            def move_file(src, dest):
                self.db.file_copy_form_bcdbfs(src, dest)
                self.db.file_delete(src)

            if action == "copy":
                copy_file(file, destination)
            if action in ["move", "rename"]:
                move_file(file, destination)

            response.set_header("Content-Type", "text/plain; charset=utf-8")
            response.set_header("X-Content-Type-Options", "nosniff")
            response.set_header("X-Renew-Token", "true")
            return "200 OK"

        @self.app.route("/fileserver/api/resources/<path:re:.*>",
                        method="get",
                        name="list")
        def resources(path=""):
            def get_type(content_type):
                if "text" in content_type:
                    return "text"
                if "image" in content_type:
                    return "image"

                if "video" in content_type:
                    return "video"

                return "blob"

            list = True

            if not path:
                path = "/"  # root

            if not path.endswith("/"):
                list = False

            path = j.sal.fs.joinPaths("/", path).rstrip("/") or "/"

            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type",
                                "application/json; charset=utf-8")
            items = []
            if list:
                dirs = self.db.list_dirs(path)
                files = self.db.list_files(path)
                for file in files:
                    path_ = j.sal.fs.joinPaths(path, file)
                    obj = self.db._file_model.get_by_name(name=path_)
                    item = {
                        "path":
                        path_,
                        "name":
                        j.sal.fs.getBaseName(file),
                        "size":
                        obj.size_bytes,
                        "extension":
                        ".{}".format(
                            j.sal.fs.getFileExtension(path)).rstrip("."),
                        "modified":
                        datetime.datetime.fromtimestamp(
                            obj.epoch).strftime("%Y-%m-%dT%H:%M:%S.%f%Z"),
                        "mode":
                        420,
                        "isDir":
                        False,
                        "type":
                        get_type(obj.content_type),
                    }
                    items.append(item)

                for dir in dirs:
                    path_ = j.sal.fs.joinPaths(path, dir)
                    obj = self.db._dir_model.get_by_name(name=path_)
                    item = {
                        "path":
                        path_,
                        "name":
                        j.sal.fs.getBaseName(dir),
                        "size":
                        4096,
                        "extension":
                        "",
                        "modified":
                        datetime.datetime.fromtimestamp(
                            obj.epoch).strftime("%Y-%m-%dT%H:%M:%S.%f%Z"),
                        "mode":
                        2147484141,
                        "isDir":
                        True,
                        "type":
                        "",
                    }
                    items.append(item)

                response.set_header("X-Renew-Token", "true")
                parent_obj = self.db._dir_model.get_by_name(name=path)
                return json.dumps({
                    "items":
                    items,
                    "numDirs":
                    len(dirs),
                    "numFiles":
                    len(files),
                    "sorting": {
                        "by": "name",
                        "asc": False
                    },
                    "path":
                    path,
                    "name":
                    "filemanager",
                    "size":
                    4096,
                    "extension":
                    "",
                    "modified":
                    datetime.datetime.fromtimestamp(
                        parent_obj.epoch).strftime("%Y-%m-%dT%H:%M:%S.%f%Z"),
                    "mode":
                    2147484141,
                    "isDir":
                    True,
                    "type":
                    "",
                })

            # file info
            modified = time.time()
            size = 0
            content = ""
            if self.db.file_exists(path):
                obj = self.db._file_model.get_by_name(name=path)
                modified = obj.epoch
                size = obj.size_bytes
                content = obj.content
            return json.dumps({
                "content":
                content,
                "checksums": {
                    "md5": "N/A",
                    "sha1": "N/A",
                    "sha256": "N/A",
                    "sha512": "N/A"
                },
                "path":
                path,
                "name":
                j.sal.fs.getBaseName(path),
                "size":
                size,
                "extension":
                ".{}".format(j.sal.fs.getFileExtension(path)).rstrip("."),
                "modified":
                modified,
                "mode":
                420,
                "isDir":
                False,
                "type":
                get_type(obj.content_type),
            })

        @self.app.route("/fileserver/api/users")
        def users():
            return json.dumps([{
                "id": 1,
                "username": "******",
                "password": "",
                "scope": ".",
                "locale": "en",
                "lockPassword": False,
                "viewMode": "mosaic",
                "perm": {
                    "admin": True,
                    "execute": True,
                    "create": True,
                    "rename": True,
                    "modify": True,
                    "delete": True,
                    "share": False,
                    "download": True,
                },
                "commands": [],
                "sorting": {
                    "by": "name",
                    "asc": False
                },
                "rules": [],
            }])

        @self.app.route("/fileserver/api/raw/<file:path>")
        def download_single(file):
            """
            single file or single dir
            """
            path = j.sal.fs.joinPaths("/", file)
            if path.endswith(
                    "/"):  # download_dir (this is a multi file downlad)
                # locate download_many action and call it
                route = [
                    r for r in self.app.routes if r.name == "download_many"
                ][0]
                return route.call(files=path)
            # download single file
            inline = request.GET.get("inline") == "true"
            obj = self.db._file_model.get_by_name(name=path)

            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type", "application/octet-stream")

            if inline:
                response.set_header("Content-Disposition", "inline")
                response.set_header("Accept-Ranges", "bytes")
            else:
                response.set_header(
                    "Content-Disposition", "attachment; filename**=utf-8"
                    "%s" % j.sal.fs.getBaseName(file))
            return self.db.file_read(path)

        @self.app.route("/fileserver/api/raw/", name="download_many")
        def download_many(files=None):
            """
            full directory (recursive) or many files
            """
            def list_files_recursively(dir):
                dir = dir.rstrip("/")
                res = self.db.list_files(dir)
                for d in self.db.list_dirs(dir):
                    res.extend(list_files_recursively(d))
                return res

            def zip(files, archive_name):
                with ZipFile("/tmp/%s" % archive_name, "w", ZIP_DEFLATED) as z:
                    for file in files:
                        c = self.db.file_read(file)
                        z.writestr(file, c)

            def tar(files, archive_name, mode=""):
                tar = tarfile.open("/tmp/%s" % archive_name, "w:%s" % mode)
                for file in files:
                    c = self.db.file_read(file)
                    file_obj = BytesIO(c)
                    info = tarfile.TarInfo(name=file)
                    info.size = len(c)
                    tar.addfile(tarinfo=info, fileobj=file_obj)
                tar.close()

            files = files or request.GET.get("files")
            requested_files = files.split(",")

            algorithm = request.GET.get("algo")
            files = []

            for file in requested_files:
                if self.db.is_file(file):
                    files.append(file)
                else:
                    files.extend(list_files_recursively(file))

            name = str(uuid.uuid4())

            content_type = "application/octet-stream"

            if algorithm == "zip":
                file_name = "filemanager.zip"
                content_type = "application/zip"
                response.set_header("Transfer-Encoding", "chunked")
                zip(files, name)
            elif algorithm == "tar":
                file_name = "filemanager.tar"
                tar(files, name, mode="")
            elif algorithm == "targz":
                file_name = "filemanager.tar.gz"
                tar(files, name, mode="gz")
            elif algorithm == "tarbz2":
                file_name = "filemanager.tar.bz2"
                tar(files, name, mode="bz2")
            elif algorithm == "tarxz":
                file_name = "filemanager.tar.xz"
                tar(files, name, mode="xz")

            response.set_header("Content-Disposition",
                                "attachment; filename**=utf-8''%s" % file_name)
            response.set_header("X-Renew-Token", "true")
            response.set_header("Content-Type", content_type)

            return open("/tmp/%s" % name, "rb")

        @self.app.route("/")
        def home():
            return static_file("index.html", root="%s/static" % self.root)

        @self.app.route("/files/")
        def home():
            return static_file("index.html", root="%s/static" % self.root)

        @self.app.route("/files")
        def home2():
            return static_file("index.html", root="%s/static" % self.root)

        @self.app.route("/files/<path:path>")
        def home3(path):
            return static_file("index.html", root="%s/static" % self.root)

        @self.app.route("/opendocs/file/<path:re:.*>", method="get")
        def onlyoffice(path):
            title = j.sal.fs.getBaseName(path)
            key = hashlib.md5(path.encode("utf-8")).hexdigest()
            extension = j.sal.fs.getFileExtension(path)
            return template("%s/static/onlyoffice.html" % self.root, {
                "title": title,
                "key": key,
                "extension": extension
            })
示例#9
0
文件: run.py 项目: jburke1203/broupy
#!env/bin/python
import builtins
from bottle import Bottle

builtins.app = Bottle()
app = builtins.app

import lists.views
import users.views

if __name__ == "__main__":
    app.run(reloader=True, debug=True)
示例#10
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from bottle import Bottle, request, HTTPResponse
from config.models import Sistema, VWUsuarioSistema
from sqlalchemy.sql import select
from config.middleware import enable_cors, headers, check_csrf
from config.database import engine, session_db
from config.constants import constants

sistema_view = Bottle()


@sistema_view.route('/listar', method='GET')
@enable_cors
@headers
@check_csrf
def listar():
    rpta = None
    status = 200
    try:
        conn = engine.connect()
        stmt = select([Sistema])
        rs = conn.execute(stmt)
        rpta = [dict(r) for r in conn.execute(stmt)]
    except Exception as e:
        rpta = {
            'tipo_mensaje': 'error',
            'mensaje':
            ['Se ha producido un error en listar los sistemas',
             str(e)],
示例#11
0
from bottle import Bottle, run, HTTPResponse

HOST = "0.0.0.0"
PORT = 80
BACK_END_SERVER = "tornado"
HTTP_STATUS_OK = 200

proxy_app = Bottle()


@proxy_app.route("/<url:re:.*>",
                 method=['GET', 'POST'],
                 name='proxy_request_handler')
def proxy_request_handler(url):
    return HTTPResponse(status=HTTP_STATUS_OK)


if __name__ == "__main__":
    run(app=proxy_app, host=HOST, port=int(PORT), server=BACK_END_SERVER)
示例#12
0
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from bottle import Bottle, request
from sqlalchemy.sql import select
from config.models import UnidadMedida
from config.database import engine, session_db

unidad_medida_view = Bottle()


@unidad_medida_view.route('/listar', method='GET')
def listar():
    conn = engine.connect()
    stmt = select([UnidadMedida])
    return json.dumps([dict(r) for r in conn.execute(stmt)])


@unidad_medida_view.route('/listar_select', method='GET')
def listar_select():
    conn = engine.connect()
    stmt = select([UnidadMedida])
    rpta = []
    for r in conn.execute(stmt):
        t = {'id': r[0], 'nombre': r[1] + ', ' + r[2]}
        rpta.append(t)
    return json.dumps(rpta)


@unidad_medida_view.route('/guardar', method='POST')
def guardar():
示例#13
0
#!/usr/bin/env python
# coding:utf-8

# pip install bottle-redis
# pip install bottle-mongo

import bottle
from bottle import Bottle, run, request, response

boy = Bottle()


@boy.hook('before_request')
def before_request():
    request.user = {'name': 'boy'}
    print('boy request={}'.format(request.user))


@boy.get("/hello")
def hello():
    return "boy hello = {}".format(request.user.get('name'))


girl = Bottle()


@girl.hook('before_request')
def before_request():
    request.user = {'name': 'girl'}
    print('girl request={}'.format(request.user))
示例#14
0
from bottle import Bottle, request
import time

httpserver = Bottle()


@httpserver.get('/stuff')
def do_stuff():
    '''
    Method that does stuff.
    '''
    stuff = {'data': 'some data'}
    time.sleep(5)
    # Return the environment info as Json data
    return stuff
示例#15
0
文件: time.py 项目: ilb/pythonproject
import os
import sys
import json
import bottle
import inject
from bottle import route, run, request, Bottle

from webapp.services.timeservice import TimeService

time = Bottle()


@time.get("/")
@inject.autoparams()
def get_time(time_service: TimeService) -> dict:
    return {"time": time_service.get_time()}
示例#16
0
def app(setup_routers='routes.cfg'):
    app = Bottle()
    for build_action in builder_actions(routers(setup_routers)):
        app.route(build_action[0], build_action[1], build_action[2])
    return app
示例#17
0
 def get_bottle_app(self):
     """Returns bottle instance"""
     self.app = Bottle()
     self.dispatch_views()
     self.app.hook('after_request')(self.after_request)
     return self.app
示例#18
0
def serverStart(kwargs={}):
    app = Bottle()
    appConfig = AppConfig()
    bottle.TEMPLATES.clear()

    # register routes
    for appRoute in appConfig.registerRoutes():
        app.route(appRoute[0], appRoute[1], appRoute[2])

    # start system cleaner
    SystemCleaner().startCleaner()

    # init the session
    Session()

    serverOptions = appConfig.serverOptions()
    host = serverOptions.get('host') if not kwargs.get('host') else kwargs.get('host')
    port = serverOptions.get('port') if not kwargs.get('port') else kwargs.get('port')
    reloader = serverOptions.get('reloader') if not kwargs.get('reloader') else kwargs.get('reloader')
    debug = serverOptions.get('debug') if not kwargs.get('debug') else kwargs.get('debug')
    server = serverOptions.get('server') if not kwargs.get('server') else kwargs.get('server')
    interval = serverOptions.get('interval') if not kwargs.get('interval') else kwargs.get('interval')
    certfile = serverOptions.get('ssl').get('certfile') if not kwargs.get('certfile') else kwargs.get('certfile')
    keyfile = serverOptions.get('ssl').get('keyfile') if not kwargs.get('keyfile') else kwargs.get('keyfile')
    
    if os.access(os.getcwd(), os.W_OK) or (os.is_file(appserverPIDFile) and os.access(appserverPIDFile, os.W_OK)):
        # try to check the address already bind or not
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        alreadyRun = False
        try:
            s.bind((host, port))
            writePID(str(os.getpid()))

        except Exception as ex:
            alreadyRun = True
            print('server already running or address already in used {}:{} -> {}'.format(host, port, ex))

            # if in debug mode try kill the server and force alradyRun to false
            if reloader and debug:
                if serverStop(kwargs) == 0:
                    alreadyRun = False

        finally:
            s.close()

        if not alreadyRun:
            overrideBuiltinPrint()

            if certfile is None or keyfile is None:
                run(app=app, host=host, port=port, reloader=reloader, debug=debug, server=server, interval=interval)

            else:
                run(app=app, host=host, port=port, reloader=reloader, debug=debug, server=server, interval=interval, certfile=certfile, keyfile=keyfile)

        else:
            print('----------')
            print('| server already running or address already in used {}:{} |'.format(host, port))
            print('----------')


    else:
        print('''You don't have write access to {}, need read write access!'''.format(os.getcwd()))
示例#19
0
        http_range = env['HTTP_RANGE'].replace('bytes=', '').split('-', 1)
        start_at = int(http_range[0])
        #end_at = http_range[1] and int(http_range[1]) or None
        if start_at > 0:
            response.status = 416
            return response.status_line
    
    length = size_mb*1024**2

    response.set_header('Content-Disposition', 'filename="{}mb.bin"'.format(size_mb))
    response.set_header('Content-Length', length)

    return func()


http = Bottle(catchall=False)

@http.route("/{}mb.bin".format(size_mb))
def route_default():
    return _default()

@http.route("/resume/{}mb.bin".format(size_mb))
def route_resume():
    return _resume()

@http.route("/resume_fake/{}mb.bin".format(size_mb))
def route_resume_fake():
    return _resume_fake()

@http.route("/noresume/{}mb.bin".format(size_mb))
def route_noresume():
示例#20
0
def make_wsgi_app(dbcontext, imgserver, dbapi, paymentapi, jinja_env,
                  auth_decorator, imagefiles, invapi):
    w = Bottle()

    @w.get('/app/resumen_form')
    @dbcontext
    @auth_decorator
    def resume_form():
        temp = jinja_env.get_template('invoice/resumen_form.html')
        stores = dbapi.search(Store)
        users = dbapi.search(User)
        return temp.render(almacenes=stores, users=users)

    @w.get('/app/resumen')
    @dbcontext
    @auth_decorator
    def get_resumen():
        user = request.query.get('user')
        store = request.query.get('almacen_id')
        start, end = parse_start_end_date(request.query)

        if user is None or store is None:
            abort(400, 'Escoje usuario y almacen')
        if start is None or end is None:
            abort(400, 'Hay que ingresar las fechas')

        store = int(store)
        report = payment_report(dbapi, end, start, store)

        temp = jinja_env.get_template('invoice/resumen_nuevo.html')
        return temp.render(start=start,
                           end=end,
                           user=user,
                           store=dbapi.search(Store),
                           report=report)

    @w.get('/app/resumen_viejo')
    @dbcontext
    @auth_decorator
    def get_resumen_viejo():
        user = request.query.get('user')
        store = request.query.get('almacen_id')
        start, end = parse_start_end_date(request.query)

        if user is None or store is None:
            abort(400, 'Escoje usuario y almacen')
        if start is None or end is None:
            abort(400, 'Hay que ingresar las fechas')

        store = int(store)
        result = get_notas_with_clients(dbapi.session, end, start, store)

        by_status = split_records(result, lambda x: x.status)
        deleted = by_status[Status.DELETED]
        committed = by_status[Status.COMITTED]
        ventas = split_records(committed, lambda x: x.payment_format)

        gtotal = sum((x.total for x in committed))
        temp = jinja_env.get_template('invoice/resumen.html')
        return temp.render(start=start,
                           end=end,
                           user=user,
                           store=dbapi.search(Store),
                           ventas=ventas,
                           gtotal=gtotal,
                           eliminados=deleted)

    @w.get('/app/entregar_cuenta_form')
    @dbcontext
    @auth_decorator
    def entrega_de_cuenta():
        temp = jinja_env.get_template('invoice/entregar_cuenta_form.html')
        return temp.render()

    @w.get('/app/crear_entrega_de_cuenta')
    @dbcontext
    @auth_decorator
    def crear_entrega_de_cuenta():
        date = request.query.get('fecha')
        if date:
            date = parse_iso(date).date()
        else:
            date = datetime.date.today()
        report = generate_daily_report(dbapi, date)
        total_spent = sum((x.paid_from_cashier for x in report.spent))
        checkimgs = {
            check.payment_id: os.path.split(check.imgcheck)[1]
            for check in report.checks if check.imgcheck
        }
        existing = dbapi.get(date, AccountStat)
        all_img = list(
            imgserver.getimg(objtype='entrega_cuenta', objid=date.isoformat()))
        temp = jinja_env.get_template(
            'invoice/crear_entregar_cuenta_form.html')
        total_cash = sum(report.cash.values()) + report.other_cash
        return temp.render(cash=report.cash,
                           others=report.other_by_client,
                           total_cash=total_cash,
                           deleted=report.deleted,
                           date=date.isoformat(),
                           pagos=report.payments,
                           all_spent=report.spent,
                           total_spent=total_spent,
                           retension=report.retension,
                           other_cash=report.other_cash,
                           imgs=all_img,
                           checkimgs=checkimgs,
                           existing=existing)

    def get_cents_with_default(number, default=0):
        try:
            return int(float(number) * 100)
        except ValueError:
            return default

    @w.post('/app/crear_entrega_de_cuenta')
    @dbcontext
    @auth_decorator
    def post_crear_entrega_de_cuenta():
        cash = request.forms.get('cash', 0)
        gastos = request.forms.get('gastos', 0)
        deposito = request.forms.get('deposito', 0)
        turned_cash = request.forms.get('valor', 0)
        diff = request.forms.get('diff', 0)
        date = request.forms.get('date')

        cash = get_cents_with_default(cash)
        gastos = get_cents_with_default(gastos)
        deposito = get_cents_with_default(deposito)
        turned_cash = get_cents_with_default(turned_cash)
        diff = get_cents_with_default(diff)
        date = parse_iso(date).date()

        userid = get_user(request)['username']
        if request.forms.get('submit') == 'Crear':
            stat = AccountStat(date=date,
                               total_spend=gastos,
                               turned_cash=turned_cash,
                               deposit=deposito,
                               created_by=userid)
            dbapi.create(stat)
            dbapi.db_session.flush()
        else:
            dbapi.update(
                AccountStat(date=date), {
                    'revised_by': userid,
                    'turned_cash': turned_cash,
                    'deposit': deposito,
                    'diff': diff
                })
            now = datetime.datetime.now()
            todo1 = Todo(objtype=ObjType.ACCOUNT,
                         objid=date,
                         status='PENDING',
                         msg='Papeleta de deposito de {}: ${}'.format(
                             date,
                             Decimal(deposito) / 100),
                         creation_date=now,
                         due_date=now)
            todo2 = Todo(objtype=ObjType.ACCOUNT,
                         objid=date,
                         status='PENDING',
                         msg='Papeleta de deposito de {}: ${}'.format(
                             date,
                             Decimal(turned_cash) / 100),
                         creation_date=now,
                         due_date=now)
            dbapi.create(todo1)
            dbapi.create(todo2)

        redirect('/app/crear_entrega_de_cuenta?fecha={}'.format(
            date.isoformat()))

    @w.get('/app/entrega_de_cuenta_list')
    @dbcontext
    @auth_decorator
    def ver_entrega_de_cuenta_list():
        start, end = parse_start_end_date(request.query)
        if end is None:
            end = datetime.date.today()
        if start is None:
            start = datetime.date.today() - datetime.timedelta(days=7)

        accts = dbapi.db_session.query(NAccountStat).filter(
            NAccountStat.date >= start, NAccountStat.date <= end)
        temp = jinja_env.get_template('invoice/entrega_de_cuenta_list.html')
        return temp.render(accts=accts, start=start, end=end)

    def render_form_with_msg(path, title):
        msg = request.query.msg
        temp = jinja_env.get_template(path)
        return temp.render(msg=msg, title=title)

    @w.get('/app/crear_cuenta_form')
    @dbcontext
    @auth_decorator
    def create_cuenta():
        return render_form_with_msg('invoice/crear_banco_form.html',
                                    title='Crear Cuenta')

    @w.get('/app/crear_banco_form')
    @dbcontext
    @auth_decorator
    def create_bank():
        return render_form_with_msg('invoice/crear_banco_form.html',
                                    title='Crear Banco')

    @w.post('/app/crear_banco_form')
    @dbcontext
    @auth_decorator
    def post_create_bank():
        name = request.forms.name
        bank = Bank(nombre=name)
        dbapi.create(bank)
        redirect('/app/crear_banco_form?msg=Cuenta+Creada')

    @w.post('/app/crear_cuenta_form')
    @dbcontext
    @auth_decorator
    def post_create_cuenta():
        name = request.forms.name
        acc = DepositAccount(nombre=name)
        dbapi.create(acc)
        redirect('/app/crear_banco_form?msg=Cuenta+Creada')

    @w.post('/app/guardar_cheque_deposito')
    @dbcontext
    @auth_decorator
    def post_guardar_cheque_deposito():
        nexturl = request.forms.get('next', '/app')
        for key, value in request.forms.items():
            print key, value
            if key.startswith('acct-'):
                key = key.replace('acct-', '')
                print key, value
                dbapi.db_session.query(NCheck).filter_by(uid=key).update(
                    {NCheck.deposit_account: value})
                dbapi.db_session.flush()
        redirect(nexturl)

    @w.get('/app/ver_cheque/<cid>')
    @dbcontext
    @auth_decorator
    def ver_cheque(cid):
        check = paymentapi.get_check(cid)
        if check.imgcheck:
            _, check.imgcheck = os.path.split(check.imgcheck)
        if check.imgdeposit:
            _, check.imgdeposit = os.path.split(check.imgdeposit)
        temp = jinja_env.get_template('invoice/ver_cheque.html')
        comments = list(
            dbapi.db_session.query(NComment).filter_by(objtype=ObjType.CHECK,
                                                       objid=str(cid)))
        return temp.render(check=check, comments=comments)

    @w.post('/app/postregar_cheque')
    @dbcontext
    @auth_decorator
    def postregar_cheque():
        checkid = request.forms.checkid
        new_date = parse_iso(request.forms.new_date).date()
        session = dbapi.db_session
        check = session.query(NCheck).filter_by(uid=checkid).first()
        comment = NComment(
            timestamp=datetime.datetime.now(),
            user_id=get_user(request)['username'],
            comment='Cheque postponer desde {} hasta {}'.format(
                check.checkdate.isoformat(), new_date.isoformat()),
            objtype=ObjType.CHECK,
            objid=str(checkid),
        )
        session.add(comment)
        check.checkdate = new_date
        session.flush()
        redirect('/app/ver_cheque/{}'.format(checkid))

    @w.post('/app/save_check_img/<imgtype>/<cid>')
    @dbcontext
    @auth_decorator
    def save_check_image(cid, imgtype):
        upload = request.files.get('imgcheck')
        _, ext = os.path.splitext(upload.raw_filename)
        filename = uuid.uuid1().hex + ext
        filename = imagefiles.make_fullpath(filename)
        if save_check_image.image is None:
            try:
                from PIL import Image

                save_check_image.image = Image
            except ImportError:
                return 'Image module not installed'
        im = save_check_image.image.open(upload.file)
        if im.size[0] > 1024:
            im.resize((1024, 768))
        im.save(filename)

        if imgtype == 'deposit':
            row = NCheck.imgdeposit
            newstatus = 'DEPOSITADO'
        else:
            row = NCheck.imgcheck
            newstatus = 'RECIBIDO'
        dbapi.db_session.query(NCheck).filter_by(uid=cid).update({
            row:
            filename,
            NCheck.status:
            newstatus
        })
        redirect('/app/ver_cheque/{}'.format(cid))

    save_check_image.image = None

    @w.get('/app/imgcheck/<cid>')
    @dbcontext
    @auth_decorator
    def check_image_get(cid):
        check = paymentapi.get(cid)
        return static_file(check.imgcheck, root='.')

    @w.get('/app/guardar_deposito')
    @dbcontext
    @auth_decorator
    def guardar_deposito():
        msg = request.query.msg
        temp = jinja_env.get_template('invoice/save_deposito_form.html')
        return temp.render(cuentas=dbapi.search(DepositAccount),
                           stores=dbapi.search(Store),
                           msg=msg)

    @w.get('/app/guardar_cheque')
    @dbcontext
    @auth_decorator
    def save_check_form():
        msg = request.query.msg
        temp = jinja_env.get_template('invoice/save_check_form.html')
        return temp.render(banks=dbapi.search(Bank),
                           stores=dbapi.search(Store),
                           msg=msg)

    def parse_payment_from_request(form, clazz, url):
        date = datetime.date.today()
        if request.forms.ingresado == 'ayer':
            date = date - datetime.timedelta(days=1)
        payment = clazz.deserialize(request.forms)
        payment.note_id, payment.client_id = extract_nota_and_client(
            dbapi, form, url)
        payment.value = int(Decimal(payment.value) * 100)
        payment.date = date
        return payment

    @w.post('/app/guardar_cheque')
    @dbcontext
    @auth_decorator
    def save_check():
        check = parse_payment_from_request(request.forms, Check,
                                           '/app/guardar_cheque')
        check.checkdate = parse_iso(check.checkdate)
        paymentapi.save_check(check)
        redirect('/app/guardar_cheque?msg=Cheque+Guardado')

    @w.get('/app/ver_cheques_guardados')
    @dbcontext
    @auth_decorator
    def list_checks():
        today = datetime.date.today()
        start, end = parse_start_end_date_with_default(
            request.query, today, today - datetime.timedelta(hours=12))
        result = paymentapi.list_checks(paymentdate=(start, end))
        temp = jinja_env.get_template('invoice/list_cheque.html')
        return temp.render(start=start,
                           end=end,
                           checks=result,
                           title='Cheques Guardados',
                           accounts=dbapi.search(DepositAccount),
                           thisurl=request.url)

    @w.get('/app/ver_cheques_para_depositar')
    @dbcontext
    @auth_decorator
    def list_checks_deposit():
        today = datetime.date.today()
        start, end = parse_start_end_date_with_default(request.query, today,
                                                       today)
        if start.isoweekday() == 1:
            start = start - datetime.timedelta(days=2)
        result = paymentapi.list_checks(checkdate=(start, end))
        temp = jinja_env.get_template('invoice/list_cheque.html')
        return temp.render(start=start,
                           end=end,
                           checks=result,
                           title='Cheques para depositar',
                           accounts=dbapi.search(Store),
                           thisurl=request.url)

    @w.get('/app/ver_cheques_por_titular')
    @dbcontext
    @auth_decorator
    def ver_cheques_por_titular():
        start, end = parse_start_end_date_with_default(request.query, None,
                                                       None)
        titular = request.query.titular
        if titular:
            result = dbapi.db_session.query(NCheck).filter(
                NCheck.holder.contains(titular))
            if start is not None:
                result = result.filter(NCheck.checkdate >= start)
            if end is not None:
                result = result.filter(NCheck.checkdate <= end)
            result = map(Check.from_db_instance, result)
        else:
            result = []
        temp = jinja_env.get_template('invoice/list_cheque.html')
        return temp.render(start=start,
                           end=end,
                           checks=result,
                           title='Cheques para depositar',
                           accounts=dbapi.search(DepositAccount),
                           thisurl=request.url,
                           show_titular=True,
                           titular=titular)

    @w.post('/app/guardar_deposito')
    @dbcontext
    @auth_decorator
    def post_guardar_deposito():
        deposit = parse_payment_from_request(request.forms, Deposit,
                                             '/app/guardar_deposito')
        paymentapi.save_payment(deposit, PaymentFormat.DEPOSIT)
        redirect('/app/guardar_deposito?msg=Deposito+Guardado')

    @w.get('/app/guardar_abono')
    @dbcontext
    @auth_decorator
    def guardar_abono():
        msg = request.query.msg
        temp = jinja_env.get_template('invoice/save_abono_form.html')
        return temp.render(stores=dbapi.search(Store),
                           action='/app/guardar_abono',
                           msg=msg,
                           payment_type=PaymentFormat.CASH)

    @w.get('/app/guardar_retension')
    @dbcontext
    @auth_decorator
    def guardar_retension():
        msg = request.query.msg
        temp = jinja_env.get_template('invoice/save_abono_form.html')
        return temp.render(stores=dbapi.search(Store),
                           action='/app/guardar_abono',
                           msg=msg,
                           payment_type='retension')

    @w.post('/app/guardar_abono')
    @dbcontext
    @auth_decorator
    def post_guardar_abono():
        payment = Payment()
        url = '/app/guardar_abono'
        payment_type = request.forms.payment_type
        if payment_type != PaymentFormat.CASH:
            url = '/app/guardar_retension'
        payment.note_id, payment.client_id = extract_nota_and_client(
            dbapi, request.forms, url)
        payment.value = int(Decimal(request.forms.value) * 100)
        payment.date = datetime.date.today()
        paymentapi.save_payment(payment, payment_type)
        url = '/app/guardar_abono?msg=Abono+Guardado'
        if payment_type != PaymentFormat.CASH:
            url = '/app/guardar_retension?msg=Retension+Guardado'
        redirect(url)

    @w.get('/app/guardar_gastos')
    @w.get('/app/guardar_gastos/<uid>')
    @dbcontext
    @auth_decorator
    def save_spent(msg='', uid=-1):
        spent = None
        if uid >= 0:
            spent = dbapi.db_session.query(NSpent).filter_by(uid=uid).first()
            if spent is None:
                msg = 'Gasto no encontrado'
        temp = jinja_env.get_template('invoice/guardar_gastos.html')
        return temp.render(msg=msg, spent=spent)

    @w.post('/app/guardar_gastos')
    @dbcontext
    @auth_decorator
    def post_save_spent():
        uid = request.forms.get('uid')
        spent = None
        create = True
        if uid is not None:
            spent = dbapi.db_session.query(NSpent).filter_by(uid=uid).first()
            create = False
            if spent is None:
                redirect('/app/guardar_gastos/{}'.format(uid))
        if spent is None:
            spent = NSpent()
        for x in ('seller', 'seller_ruc', 'invnumber', 'invdate', 'desc',
                  'total', 'tax', 'retension', 'paid_from_cashier',
                  'inputdate'):
            setattr(spent, x, request.forms.get(x))
        spent.total = int(Decimal(spent.total) * 100)
        spent.tax = int(Decimal(spent.tax) * 100)
        spent.retension = int(Decimal(spent.retension) * 100)
        spent.paid_from_cashier = int(Decimal(spent.paid_from_cashier) * 100)

        spent.invdate = parse_iso(spent.invdate)
        spent.inputdate = parse_iso(spent.inputdate)

        if create:
            dbapi.db_session.add(spent)
        dbapi.db_session.commit()
        return save_spent('Gasto Guardado')

    @w.get('/app/ver_gastos')
    @dbcontext
    @auth_decorator
    def ver_gastos():
        today = datetime.datetime.today()
        start, end = parse_start_end_date_with_default(request.query, today,
                                                       today)

        all_spent = dbapi.db_session.query(NSpent).filter(
            NSpent.inputdate >= start,
            NSpent.inputdate <= end + datetime.timedelta(days=1))

        temp = jinja_env.get_template('invoice/ver_gastos.html')
        return temp.render(start=start, end=end, all_spent=all_spent)

    class CustomerSell(object):
        def __init__(self):
            self.subtotal = 0
            self.iva = 0
            self.count = 0
            self.total = 0

    def group_by_customer(inv):
        result = defaultdict(CustomerSell)
        for i in inv:
            if i.client.codigo is None:
                i.client.codigo = 'NA'
            cliente_id = fix_id(i.client.codigo)
            if not i.discount:
                i.discount = 0
            result[cliente_id].subtotal += (i.subtotal - i.discount)
            result[cliente_id].iva += i.tax
            result[cliente_id].total += i.total
            result[cliente_id].count += 1
        return result

    @w.get('/app/accounting_form')
    @dbcontext
    def get_sells_xml_form():
        temp = jinja_env.get_template('accounting/ats_form.html')
        stores = filter(lambda x: x.ruc, dbapi.search(Store))
        return temp.render(stores=stores, title='ATS')

    class Meta(object):
        pass

    @w.get('/app/accounting.xml')
    @dbcontext
    def get_sells_xml():
        start_date, end_date = parse_start_end_date(request.query)
        end_date = end_date + datetime.timedelta(days=1) - datetime.timedelta(
            seconds=1)
        form_type = request.query.get('form_type')

        ruc = request.query.get('alm')
        invs = invapi.search_metadata_by_date_range(
            start_date, end_date, other_filters={'almacen_ruc': ruc})

        deleted, sold = split_records_binary(
            invs, lambda x: x.status == Status.DELETED)
        grouped = group_by_customer(sold)

        meta = Meta()
        meta.date = start_date
        meta.total = reduce(lambda acc, x: acc + x.subtotal, grouped.values(),
                            0)
        meta.almacen_ruc = ruc
        meta.almacen_name = [
            x.nombre for x in dbapi.search(Store) if x.ruc == ruc
        ][0]
        temp = jinja_env.get_template('accounting/resumen_agrupado.html')
        if form_type == 'ats':
            temp = jinja_env.get_template('accounting/ats.xml')
            response.set_header('Content-disposition', 'attachment')
            response.set_header('Content-type', 'application/xml')
        return temp.render(vendidos=grouped, eliminados=deleted, meta=meta)

    @w.get('/app/img/<rest:path>')
    @dbcontext
    @auth_decorator
    def img(rest):
        if constants.ENV == 'test':
            return static_file(rest, root=constants.IMAGE_PATH)
        else:
            response.set_header('X-Accel-Redirect', '/image/{}'.format(rest))
            response.set_header('Content-Type', '')

    def save_img_from_request(therequest):
        imgdata = therequest.files.get('img')
        objtype = therequest.forms.get('objtype')
        objid = therequest.forms.get('objid')
        do_replace = therequest.forms.get('replace')
        return imgserver.saveimg(objtype, objid, imgdata, do_replace)

    @w.post('/app/attachimg')
    @dbcontext
    @auth_decorator
    def post_img():
        redirect_url = request.forms.get('redirect_url')
        save_img_from_request(request)
        redirect(redirect_url)

    @w.post('/app/api/attachimg')
    @dbcontext
    @auth_decorator
    def post_img():
        img = save_img_from_request(request)
        url = imgserver.get_url_path(img.path)
        return {'url': url}

    return w
示例#21
0
class terrariumWebserver():

    app = Bottle()
    app.install(terrariumWebserverHeaders())

    def __init__(self, terrariumEngine):
        self.__terrariumEngine = terrariumEngine
        self.__app = terrariumWebserver.app
        self.__config = self.__terrariumEngine.get_config('system')
        self.__caching_days = 30
        terrariumWebserver.app.terrarium = self.__terrariumEngine
        # Load language
        gettext.translation('terrariumpi',
                            'locales/',
                            languages=[
                                self.__terrariumEngine.config.get_language()
                            ]).install(True)
        self.__translations = terrariumTranslations()

        self.__routes()

    # Custom HTTP authentication routine. This way there is an option to optional secure the hole web interface
    def __auth_basic2(self,
                      check,
                      required,
                      realm="private",
                      text="Access denied"):
        """ Callback decorator to require HTTP auth (basic).
        TODO: Add route(check_auth=...) parameter. """
        def decorator(func):
            @functools.wraps(func)
            def wrapper(*a, **ka):
                user, password = request.auth or (None, None)
                if required or terrariumUtils.is_true(
                        self.__terrariumEngine.config.get_system()
                    ['always_authenticate']):

                    if user is None or not check(user, password):
                        err = HTTPError(401, text)
                        err.add_header('WWW-Authenticate',
                                       'Basic realm="%s"' % realm)
                        return err

                return func(*a, **ka)

            return wrapper

        return decorator

    def __authenticate(self, required):
        return self.__auth_basic2(self.__terrariumEngine.authenticate,
                                  required,
                                  _('TerrariumPI') + ' ' + _('Authentication'),
                                  _('Authenticate to make any changes'))

    def __logout_authenticate(self, user, password):
        return True

    def __routes(self):
        self.__app.route('/',
                         method="GET",
                         callback=self.__render_page,
                         apply=self.__authenticate(False))

        self.__app.route('/<template_name:re:[^/]+\.html$>',
                         method="GET",
                         callback=self.__render_page,
                         apply=self.__authenticate(False))

        self.__app.route('/<filename:re:robots\.txt>',
                         method="GET",
                         callback=self.__static_file,
                         apply=self.__authenticate(False))

        self.__app.route(
            '/<root:re:(static|gentelella|webcam|audio|log)>/<filename:path>',
            method="GET",
            callback=self.__static_file,
            apply=self.__authenticate(False))

        self.__app.route('/api/<path:path>',
                         method=['GET'],
                         callback=self.__get_api_call,
                         apply=self.__authenticate(False))

        self.__app.route('/api/switch/toggle/<switchid:path>',
                         method=['POST'],
                         callback=self.__toggle_switch,
                         apply=self.__authenticate(True))

        self.__app.route('/api/switch/state/<switchid:path>/<value:int>',
                         method=['POST'],
                         callback=self.__state_switch,
                         apply=self.__authenticate(True))

        self.__app.route(
            '/api/config/<path:re:(system|weather|switches|sensors|webcams|doors|audio|environment|profile)>',
            method=['PUT', 'POST', 'DELETE'],
            callback=self.__update_api_call,
            apply=self.__authenticate(True))

        self.__app.route(
            '/api/audio/player/<action:re:(start|stop|volumeup|volumedown|mute|unmute)>',
            method=['POST'],
            callback=self.__player_commands,
            apply=self.__authenticate(True))

        self.__app.route('/api/audio/file',
                         method=['POST'],
                         callback=self.__upload_audio_file,
                         apply=self.__authenticate(True))

        self.__app.route('/api/audio/file/<audiofileid:path>',
                         method=['DELETE'],
                         callback=self.__delete_audio_file,
                         apply=self.__authenticate(True))

        self.__app.route('/logout',
                         method=['GET'],
                         callback=self.__logout_url,
                         apply=auth_basic(
                             self.__logout_authenticate,
                             _('TerrariumPI') + ' ' + _('Authentication'),
                             _('Authenticate to make any changes')))

    def __template_variables(self, template):
        variables = {
            'lang':
            self.__terrariumEngine.config.get_language(),
            'title':
            self.__config['title'],
            'version':
            self.__config['version'],
            'page_title':
            _(template.replace('_', ' ').capitalize()),
            'temperature_indicator':
            self.__terrariumEngine.get_temperature_indicator(),
            'distance_indicator':
            self.__terrariumEngine.get_distance_indicator(),
            'translations':
            self.__translations,
            'device':
            self.__terrariumEngine.device
        }

        if 'index' == template or 'profile' == template:
            variables['person_name'] = self.__terrariumEngine.get_profile_name(
            )
            variables[
                'person_image'] = self.__terrariumEngine.get_profile_image()

        return variables

    def __render_page(self, template_name='index.html'):
        template_name = template_name[:-5]

        if not os.path.isfile('views/' + template_name + '.tpl'):
            template_name = '404'

        return template(template_name,
                        **self.__template_variables(template_name))

    def __static_file(self, filename, root='static'):
        if filename == 'js/terrariumpi.js':
            response.headers[
                'Content-Type'] = 'application/javascript; charset=UTF-8'
            response.headers['Expires'] = (
                datetime.datetime.utcnow() +
                datetime.timedelta(days=self.__caching_days)
            ).strftime('%a, %d %b %Y %H:%M:%S GMT')
            return template(filename, template_lookup=[root])

        staticfile = static_file(filename, root=root)
        if isinstance(staticfile, HTTPError):
            return staticfile

        if 'webcam' == root or 'log' == root:
            staticfile.add_header(
                'Expires',
                datetime.datetime.utcnow().strftime(
                    '%a, %d %b %Y %H:%M:%S GMT'))
            if 'log' == root:
                staticfile.add_header('Content-Type',
                                      'text/text; charset=UTF-8')
                staticfile.add_header('Content-Disposition',
                                      'Attachment;filename=' + filename)
        else:
            staticfile.add_header('Expires',
                                  (datetime.datetime.utcnow() +
                                   datetime.timedelta(days=self.__caching_days)
                                   ).strftime('%a, %d %b %Y %H:%M:%S GMT'))

        if staticfile.get_header('Last-Modified') is not None:
            staticfile.add_header(
                'Etag',
                hashlib.md5(
                    staticfile.get_header('Last-Modified')).hexdigest())

        return staticfile

    def __player_commands(self, action):
        result = {
            'ok': False,
            'title': _('Error!'),
            'message': _('Player command could ot be executed!')
        }

        if 'start' == action:
            self.__terrariumEngine.audio_player_start()
        elif 'stop' == action:
            self.__terrariumEngine.audio_player_stop()
        elif 'volumeup' == action:
            self.__terrariumEngine.audio_player_volume_up()
            result = {
                'ok': True,
                'title': _('OK!'),
                'message': _('Player command executed!')
            }
        elif 'volumedown' == action:
            self.__terrariumEngine.audio_player_volume_down()
            result = {
                'ok': True,
                'title': _('OK!'),
                'message': _('Player command executed!')
            }
        elif 'mute' == action:
            pass
        elif 'unmute' == action:
            pass

        return result

    def __upload_audio_file(self):
        result = {
            'ok': False,
            'title': _('Error!'),
            'message': _('File is not uploaded!')
        }
        upload = request.files.get('file')
        try:
            upload.save(terrariumAudioPlayer.AUDIO_FOLDER)
            self.__terrariumEngine.reload_audio_files()
            result = {
                'ok': True,
                'title': _('Success!'),
                'message': _('File \'%s\' is uploaded' % (upload.filename, ))
            }
        except IOError, message:
            result['message'] = _('Duplicate file \'%s\'' %
                                  (upload.filename, ))

        return result
示例#22
0
def make_wsgi_api(dbapi, invapi, dbcontext, auth_decorator, paymentapi,
                  imgserver):
    w = Bottle()

    @w.get('/app/api/sales')
    @dbcontext
    def get_sales():
        """ start=<start>&end=<end>
        """
        start_date, end_date = parse_start_end_date(request.query)
        if not end_date:
            end_date = datetime.date.today()
        end_date = end_date + datetime.timedelta(hours=23)
        query = dbapi.db_session.query(NNota.almacen_id, func.sum(
            NNota.total)).filter(NNota.timestamp >= start_date).filter(
                NNota.timestamp <= end_date).filter(
                    NNota.status != Status.DELETED).group_by(NNota.almacen_id)
        result = []
        for aid, total in query:
            result.append((aid, Decimal(total) / 100))
        return json_dumps({'result': result})

    @w.get('/app/api/payment')
    @dbcontext
    def get_all_payments():
        start, end = parse_start_end_date(request.query)
        result = list(paymentapi.list_payments(start, end))
        return json_dumps({'result': result})

    @w.get('/app/api/gasto')
    @dbcontext
    def get_all_gastos():
        day = parse_iso(request.query.get('date'))
        result = dbapi.search(Spent, inputdate=day)
        return json_dumps(result)

    @w.get('/app/api/account_transaction')
    @dbcontext
    def get_account_transactions_mult_days():
        start, end = parse_start_end_date(request.query)
        result = get_transactions(dbapi, paymentapi, invapi, imgserver, start,
                                  end)
        return json_dumps(result)

    @w.get('/app/api/check')
    @dbcontext
    def get_checks():
        save_date = request.query.get('save_date')
        save_date_end = request.query.get('save_date_end')
        deposit_date = request.query.get('deposit_date')
        deposit_date_end = request.query.get('deposit_date_end')
        if save_date:
            save_date = (save_date, save_date_end)
        if deposit_date:
            deposit_date = (deposit_date, deposit_date_end)
        checks = paymentapi.list_checks(save_date, deposit_date)
        for x in checks:
            x.imgdeposit = imgserver.get_url_path(x.imgdeposit)
            x.imgcheck = imgserver.get_url_path(x.imgcheck)
            x.value = Decimal(x.value) / 100
        return json_dumps({'result': checks})

    @w.post('/app/api/acct_transaction')
    @dbcontext
    def post_acct_transaction():
        data = request.body.read()
        acct = AccountTransaction.deserialize(json.loads(data))
        acct.input_timestamp = datetime.datetime.now()
        acct.deleted = False
        pkey = dbapi.create(acct)
        return {'pkey': pkey}

    @w.put('/app/api/acct_transaction/<uid>')
    @dbcontext
    def put_acct_transaction(uid):
        data = json.loads(request.body.read())
        acct = AccountTransaction(uid=uid)
        count = dbapi.update(acct, data)
        return {'updated': count}

    @w.get('/app/api/noncash_sales_with_payments')
    @dbcontext
    @auth_decorator
    def ver_ventas_no_efectivos():
        start, end = parse_start_end_date(request.query)
        end += datetime.timedelta(hours=23)
        sales = dbapi.db_session.query(NNota).filter(
            NNota.timestamp >= start).filter(NNota.timestamp <= end).filter(
                NNota.payment_format != PaymentFormat.CASH)

        sales = map(InvMetadata.from_db_instance, sales)
        payments = list(paymentapi.list_payments(start, end))

        result = {}
        for x in sales:
            if x.client.codigo not in result:
                result[x.client.codigo] = {}
                result[x.client.codigo]['sales'] = []
                result[x.client.codigo]['payments'] = []
            result[x.client.codigo]['sales'].append(x)

        unused_payments = []
        for x in payments:
            if x.client_id in result:
                result[x.client_id]['payments'].append(x)
            else:
                unused_payments.append(x)

        result['unused_payments'] = unused_payments
        return json_dumps({
            'unused_payments': unused_payments,
            'sales': result.items()
        })

    @w.get('/app/api/account_deposit_with_img')
    @dbcontext
    @auth_decorator
    def get_account_deposit_with_img():
        today = datetime.datetime.today()
        thisyear = today - datetime.timedelta(days=365)
        turned_in = sorted(get_turned_in_cash(dbapi, thisyear, today,
                                              imgserver),
                           key=lambda x: x.date,
                           reverse=True)
        result = defaultdict(list)
        for x in turned_in:
            if getattr(x, 'img', None):
                if len(result['with_deposit']) < 10:
                    result['with_deposit'].append(x)
            else:
                result['without_deposit'].append(x)
        return json_dumps(result)

    # account stat
    bind_dbapi_rest('/app/api/account_stat', dbapi, AccountStat, w)
    bind_dbapi_rest('/app/api/bank_account', dbapi, DepositAccount, w)
    bind_dbapi_rest('/app/api/account_deposit', dbapi, AccountTransaction, w)

    bind_dbapi_rest('/app/api/spent',
                    dbapi,
                    Spent,
                    w,
                    skips_method=('DELETE', ))

    @w.get('/app/api/pago/<uid>')
    @dbcontext
    def get_pago_with_id(uid):
        elm = dbapi.db_session.query(NPayment).filter_by(uid=uid).first()
        if elm is None:
            response.status = 404
            return ''
        return json_dumps(Payment().merge_from(elm).serialize())

    @w.delete('/app/api/pago/<uid>')
    @dbcontext
    def mark_pago_deleted(uid):
        success = dbapi.db_session.query(NPayment).filter_by(uid=uid).update(
            {'deleted': True})
        dbapi.db_session.commit()
        return {'success': success > 0}

    @w.put('/app/api/pago/<uid>')
    @dbcontext
    def modify_payment(uid):
        data = json.loads(request.body.read())
        success = dbapi.db_session.query(NPayment).filter_by(
            uid=uid).update(data)
        dbapi.db_session.commit()
        return {'success': success > 0}

    @w.delete('/app/api/spent/<uid>')
    @dbcontext
    def mark_pago_deleted(uid):
        spent = Spent(uid=uid)
        sucess = dbapi.update(spent, {'deleted': True})
        dbapi.db_session.commit()
        return {'success': sucess > 0}

    return w
示例#23
0
import api.controllers.notes as noteController
from bottle import request, Bottle
from api.middleware.cheack_auth import requiresAuth, jwt_token_from_header
from api.middleware.corsUtil import enable_cors

noteApp = Bottle()


@noteApp.route('/', method=['OPTIONS', 'GET'])
@enable_cors
@requiresAuth
def getAllNotes(*args):
    """ Route for getting all notes of a specific user.
        Require authentication
    """
    userID = args[0]["userID"]
    notes = noteController.allNotes(userID)
    return notes


@noteApp.route('/<noteID>', method=['OPTIONS', 'GET'])
@enable_cors
@requiresAuth
def getNoteByID(*args, noteID):
    """ Route for getting a single note of a specific user.
        Require authentication
    """

    userID = args[0]["userID"]
    note = noteController.singleNote(noteID, userID)
    return note
示例#24
0
import doreah
# technical
import os
import datetime
import sys
import unicodedata
from collections import namedtuple
from threading import Lock
# url handling
from importlib.machinery import SourceFileLoader
import urllib




dbserver = Bottle()

dblock = Lock() #global database lock

SCROBBLES = []	# Format: tuple(track_ref,timestamp,saved)
ARTISTS = []	# Format: artist
TRACKS = []	# Format: namedtuple(artists=frozenset(artist_ref,...),title=title)


Track = namedtuple("Track",["artists","title"])
Scrobble = namedtuple("Scrobble",["track","timestamp","saved"])

### OPTIMIZATION
SCROBBLESDICT = {}	# timestamps to scrobble mapping
STAMPS = []		# sorted
#STAMPS_SET = set()	# as set for easier check if exists # we use the scrobbles dict for that now
示例#25
0
    def __init__(self, data_dir):
        self.data_dir = data_dir.rstrip("/")

        self.app = Bottle()
        self.setup_routes()
示例#26
0
            f"[{request_time}] {request.remote_addr} - {request.method} {request.fullpath}?{request.query_string} {response.status_code} - {duration * 1000:0.2f}ms")
        return actual_response

    return _timing_and_logger


def record_request_stats():
    """ Records stats for an http request in Redis
    """
    try:
        app.config['translateapp.redis'].hincrby("requests_by_ip", request.remote_addr, 1)
    except redis.RedisError as redis_err:
        print(f"Error sending stats to Redis: {redis_err}")


app: Bottle = Bottle()
app.install(timing_and_logger)


@app.route('/api/v1/translate')
def translate() -> Dict[str, Union[str, List[str]]]:
    """ Translate a phrase from Orcish to English
    """
    phrase: str = request.query.phrase or None
    response_body: Dict[str, Union[str, List[str]]] = {"phrase": phrase, "translation": None, "errors": []}

    if app.config.get('translateapp.redis'):
        record_request_stats()

    if not phrase:
        response.status = 400
示例#27
0
from bottle import Bottle
from app.api.return_api_messages import ReturnMessages
from app.service.summoner_service import SummonerService

summoner_api = Bottle()
summoner_service = SummonerService()


@summoner_api.get('/<summoner_name>')
def get_summoner_info_by_name(summoner_name):
    result = summoner_service.get_summoner_by_name(summoner_name)
    return result if result.status_code == 200 else ReturnMessages.error_get_response(
    )
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import json
from bottle import Bottle, request
from config.models import criadores
from config.middleware import response_headers, enable_cors
import time
from tinydb import Query

criador_view = Bottle()


@criador_view.route('/traer/<criador_id>', method=['GET'])
@response_headers
@enable_cors
def traer(criador_id):
    rpta = None
    try:
        Criador = Query()
        tmp = criadores.search(Criador.criador_id == int(criador_id))
        return tmp[0]
    except TypeError:
        rpta = {
            'tipo_mensaje':
            'error',
            'mensaje': [
                'Se ha producido un error en crear los comentarios del criador',
                str(e)
            ]
        }
    return json.dumps(rpta)
示例#29
0
    time = time.strftime("%d/%m/%Y %H:%M:%S" + "\n")
    # 设置id是为了方便后面提取,顺序或逆序也在其中
    id = 'id' + str(count)
    record = {'time': time, 'record': newline}
    kv.set(id, record)


# 读取数据库中的信息
def printhistory():
    notelist = []
    for item in kv.get_by_prefix('id'):
        notelist.append(item[1])
    return notelist


app = Bottle()


@app.route('/')
def home():
    return '''
    <form action="/index" method="POST">
    <br/>    
    Please input a new line: 
    <br/>
    <input name="newline" type="text"/>
    <br/>
    <input value="save" type="submit" />
    </form>'''

示例#30
0
from bottle import Bottle, request, abort

from models.movie import Movie, Base

recommendation_app = Bottle()


@recommendation_app.post('/recommendation')
def recommendation():
    cursor_about = request.json.get("cursorAbout")
    user_matrix = request.json.get("userMatrix", {})
    selection = request.json.get('selection', [])

    clean_selection = [int(uid) for uid in selection]

    results = Movie.related_base(cursor_about, clean_selection)

    scoring = {}
    for index, row in enumerate(results):
        movie = Movie.inflate(row[0])
        bases = [Base.inflate(b).name for b in row[1]]

        content = {
            'title': movie.title,
            'score': 0,
            'relations': [],
            'data': movie.serialize
        }

        for key, value in user_matrix.items():
            if key in bases: