Exemple #1
0
    def __routes(self):
        self.__app.route('/', method="GET", callback=self.__render_page)
        self.__app.route('/<template_name:re:[^/]+\.html$>',
                         method="GET",
                         callback=self.__render_page)

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

        self.__app.route('/api/switch/toggle/<switchid:path>',
                         method=['GET'],
                         callback=self.__toggle_switch,
                         apply=auth_basic(
                             self.__authenticate,
                             _('TerrariumPI') + ' ' + _('Authentication'),
                             _('Authenticate to make any changes')))

        self.__app.route(
            '/api/config/<path:re:(system|weather|switches|sensors|webcams|doors|environment)>',
            method=['PUT', 'POST', 'DELETE'],
            callback=self.__update_api_call,
            apply=auth_basic(self.__authenticate,
                             _('TerrariumPI') + ' ' + _('Authentication'),
                             _('Authenticate to make any changes')))

        self.__app.route('/api/<path:path>',
                         method=['GET'],
                         callback=self.__get_api_call)
    def start_server(self, server_adapter=None):
        """
        Sets up all the routes for the server and starts it.

        server_backend: bottle.ServerAdapter (default None)
            The server adapter to use. The default bottle.WSGIRefServer is used if none is given.
            WARNING: If given, this will over-ride the host-ip and port passed as parameters to this
            object.
        """
        application = Bottle()
        application.route(f"/{REGISTER_WORKER_ROUTE}",
                          method='POST', callback=self.add_and_register_worker)
        application.route(f"/{CHALLENGE_PHRASE_ROUTE}/<worker_id>",
                          method='GET', callback=self.worker_manager.get_challenge_phrase)
        application.route(f"/{RETURN_GLOBAL_MODEL_ROUTE}",
                          method='POST', callback=self.return_global_model)
        application.route(f"/{NOTIFY_ME_IF_GM_VERSION_UPDATED_ROUTE}",
                          method='POST', callback=self.notify_me_if_gm_version_updated)
        application.route(f"/{RECEIVE_WORKER_UPDATE_ROUTE}/<worker_id>",
                          method='POST', callback=self.receive_worker_update)

        application.add_hook('after_request', self.enable_cors)

        # Admin routes
        application.get(
            f"/{WORKERS_ROUTE}", callback=auth_basic(self.is_admin)(self.admin_list_workers))
        application.post(
            f"/{WORKERS_ROUTE}", callback=auth_basic(self.is_admin)(self.admin_add_worker))
        application.delete(f"/{WORKERS_ROUTE}/<worker_id>",
                           callback=auth_basic(self.is_admin)(self.admin_delete_worker))
        application.put(f"/{WORKERS_ROUTE}/<worker_id>",
                        callback=auth_basic(self.is_admin)(self.admin_set_worker_status))

        if server_adapter is not None and isinstance(server_adapter, ServerAdapter):
            self.server_host_ip = server_adapter.host
            self.server_port = server_adapter.port
            run(application, server=server_adapter, debug=self.debug, quiet=True)
        elif self.ssl_enabled:
            run(application,
                host=self.server_host_ip,
                port=self.server_port,
                server='gunicorn',
                worker_class='gevent',
                keyfile=self.ssl_keyfile,
                certfile=self.ssl_certfile,
                debug=self.debug,
                timeout=60*60*24,
                quiet=True)
        else:
            run(application,
                host=self.server_host_ip,
                port=self.server_port,
                server='gunicorn',
                worker_class='gevent',
                debug=self.debug,
                timeout=60*60*24,
                quiet=True)
    def __init__(self, config=None, args=None):
        # Init config
        self.config = config

        # Init args
        self.args = args

        # Init stats
        # Will be updated within Bottle route
        self.stats = None

        # cached_time is the minimum time interval between stats updates
        # i.e. HTTP/Restful calls will not retrieve updated info until the time
        # since last update is passed (will retrieve old cached info instead)
        self.timer = Timer(0)

        # Load configuration file
        self.load_config(config)

        # Init Bottle
        self._app = Bottle()
        # Enable CORS (issue #479)
        self._app.install(EnableCors())
        # Password
        if args.password != '':
            self._app.install(auth_basic(self.check_auth))
        # Define routes
        self._route()

        # Path where the statics files are stored
        self.STATIC_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static/public')
 def wrapper (*args, **kwargs):
     if (request.method == "GET"):
         auth_decorator = auth_basic (check)
         auth_wrapper = auth_decorator (func)
         return auth_wrapper (*args, **kwargs)
     else:
         return func (*args, **kwargs)
Exemple #5
0
    def __init__(self, config=None, args=None):
        # Init config
        self.config = config

        # Init args
        self.args = args

        # Init stats
        # Will be updated within Bottle route
        self.stats = None

        # cached_time is the minimum time interval between stats updates
        # i.e. HTTP/Restful calls will not retrieve updated info until the time
        # since last update is passed (will retrieve old cached info instead)
        self.timer = Timer(0)

        # Load configuration file
        self.load_config(config)

        # Init Bottle
        self._app = Bottle()
        # Enable CORS (issue #479)
        self._app.install(EnableCors())
        # Password
        if args.password != '':
            self._app.install(auth_basic(self.check_auth))
        # Define routes
        self._route()

        # Path where the statics files are stored
        self.STATIC_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static/public')

        # Paths for templates
        TEMPLATE_PATH.insert(0, os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static/templates'))
Exemple #6
0
def auth_basic(check):
    """Wrapper around bottle.auth_basic to strip any cache-control header."""
    orig = bottle.auth_basic(check)
    def decorator(func):
        def wrapper(*a, **ka):
            if 'Cache-Control' in bottle.response.headers:
                del bottle.response.headers['Cache-Control']
            return orig(func)(*a, **ka)
        return wrapper
    return decorator
  def __routes(self):
    self.__app.route('/', method="GET", callback=self.__render_page)
    self.__app.route('/<template_name:re:[^/]+\.html$>', method="GET", callback=self.__render_page, apply=[terrariumWebserverHeaders()])

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

    self.__app.route('/api/switch/toggle/<switchid:path>',
                     method=['GET'],
                     callback=self.__toggle_switch,
                     apply=auth_basic(self.__authenticate,'TerrarumPI Authentication','Authenticate to make any changes')
                    )

    self.__app.route('/api/config/<path:re:(system|weather|switches|sensors|webcams|environment)>',
                     method=['PUT','POST','DELETE'],
                     callback=self.__update_api_call,
                     apply=auth_basic(self.__authenticate,'TerrarumPI Authentication','Authenticate to make any changes')
                    )

    self.__app.route('/api/<path:path>', method=['GET'], callback=self.__get_api_call)
Exemple #8
0
def authenticate(function):
    """Function wrapper for basic authenticaion"""
    def check(user, password):
        global AUTHENTICATIONS_LEFT
        if AUTHENTICATIONS_LEFT <= 0:
            return False
        authenticated = password in PASSWORDS
        if not authenticated:
            AUTHENTICATIONS_LEFT -= 1
        return authenticated
    return auth_basic(check, realm=AUTH_REALM,
                      text=Versuche())(function)
Exemple #9
0
def auth_basic(check):
    """Wrapper around bottle.auth_basic to strip any cache-control header."""
    orig = bottle.auth_basic(check)

    def decorator(func):
        def wrapper(*a, **ka):
            if 'Cache-Control' in bottle.response.headers:
                del bottle.response.headers['Cache-Control']
            return orig(func)(*a, **ka)

        return wrapper

    return decorator
Exemple #10
0
    def __init__(self, args=None):
        # Init args
        self.args = args

        # Init stats
        # Will be updated within Bottle route
        self.stats = None

        # Init Bottle
        self._app = Bottle()
        # Enable CORS (issue #479)
        self._app.install(EnableCors())
        # Password
        if args.password != '':
            self._app.install(auth_basic(self.check_auth))
        # Define routes
        self._route()

        # Path where the statics files are stored
        self.STATIC_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'static')
Exemple #11
0
    def __init__(self, args=None):
        # Init args
        self.args = args

        # Init stats
        # Will be updated within Bottle route
        self.stats = None

        # Init Bottle
        self._app = Bottle()
        # Enable CORS (issue #479)
        self._app.install(EnableCors())
        # Password
        if args.password != '':
            self._app.install(auth_basic(self.check_auth))
        # Define routes
        self._route()

        # Path where the statics files are stored
        self.STATIC_PATH = os.path.join(
            os.path.dirname(os.path.realpath(__file__)), 'static')
Exemple #12
0

def check_hardcoded(username, password) -> bool:
    return username == 'admin' and password == 'admin'


def check_ldap(username, password) -> bool:
    logger.debug('Logging in with LDAP')
    connection = ldap3.Connection(ldap_server, username, password)
    if not connection.bind():
        user_dn = config.ldap_dn_template.format(username)
        connection = ldap3.Connection(ldap_server, user_dn, password)
    return connection.bind()


def is_logged_in(request: Request) -> bool:
    return request.auth and auth_function(*request.auth)


auth_function = lambda username, password: False  # If auth is not setup correctly reject all logins

if config.auth_type == 'hardcoded':
    logger.warning("Authentication will be hardcoded")
    auth_function = check_hardcoded
elif config.auth_type == 'ldap':
    logger.info("Authentication will use LDAP")
    # TODO make configurable
    ldap_server = ldap3.Server(config.ldap_server, config.ldap_port, use_ssl=config.ldap_ssl)
    auth_function = check_ldap
needs_login = auth_basic(auth_function)
    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.*>',
                         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/calendar',
                         method=['POST'],
                         callback=self.__create_calender_event,
                         apply=self.__authenticate(True))

        self.__app.route('/api/reboot',
                         method=['POST'],
                         callback=self.__reboot,
                         apply=self.__authenticate(True))

        self.__app.route('/api/shutdown',
                         method=['POST'],
                         callback=self.__shutdown,
                         apply=self.__authenticate(True))

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

        self.__app.route('/api/switch/manual_mode/<switchid:path>',
                         method=['POST'],
                         callback=self.__manual_mode_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/switches/hardware',
                         method=['PUT'],
                         callback=self.__replace_switch_hardware,
                         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')))
Exemple #14
0
    engine, # SQLAlchemy engine created with create_engine function.
    Base.metadata, # SQLAlchemy metadata, required only if create=True.
    keyword='db', # Keyword used to inject session database in a route (default 'db').
    create=True, # If it is true, execute `metadata.create_all(engine)` when plugin is applied (default False).
    commit=True, # If it is true, plugin commit changes after route is executed (default True).
    use_kwargs=False # If it is true and keyword is not defined, plugin uses **kwargs argument to inject session database (default False).
)

app.install(plugin)

BaseTemplate.defaults['get_url'] = app.get_url

statuslookup = {'end': 'Run OK', 'fail': 'Failed', 'latent_run': 'Missing Period'}


@app.route('/jobs', apply=[auth_basic(checkauth)])
def jobsum(db):
    joblogsum=joblogsummary(db)

    output = template('jobsummary', joblist=joblogsum, statuslookup=statuslookup)
    return output


@app.route('/jobs/<name>', apply=[auth_basic(checkauth)])
def jobdetail(db, name):
    starttime = datetime.datetime.now() - datetime.timedelta(days=30)
    endtime = datetime.datetime.now()

    landinglogs = landingtimes(db, name, starttime, endtime)
    jl = joblog(db, last=50, name=name)
Exemple #15
0
    use_kwargs=
    False  # If it is true and keyword is not defined, plugin uses **kwargs argument to inject session database (default False).
)

app.install(plugin)

BaseTemplate.defaults['get_url'] = app.get_url

statuslookup = {
    'end': 'Run OK',
    'fail': 'Failed',
    'latent_run': 'Missing Period'
}


@app.route('/jobs', apply=[auth_basic(checkauth)])
def jobsum(db):
    joblogsum = joblogsummary(db)

    output = template('jobsummary',
                      joblist=joblogsum,
                      statuslookup=statuslookup)
    return output


@app.route('/jobs/<name>', apply=[auth_basic(checkauth)])
def jobdetail(db, name):
    starttime = datetime.datetime.now() - datetime.timedelta(days=30)
    endtime = datetime.datetime.now()

    landinglogs = landingtimes(db, name, starttime, endtime)
Exemple #16
0
    days    = int( seconds / DAY )
    hours   = int( ( seconds % DAY ) / HOUR )
    minutes = int( ( seconds % HOUR ) / MINUTE )
    seconds = int( seconds % MINUTE )

    string = ""
    if days > 0:
        string += str(days) + " " + (days == 1 and "day" or "days" ) + ", "

    string = string + "%d:%02d:%02d" % (hours, minutes, seconds)

    return string


@get('/blurb')
@conditional_decorator('HTTP_USER' in globals() and 'HTTP_PASSWORD' in globals(), auth_basic(check))
def blurb():
    text =  """Homie OTA server running.
    OTA endpoint is: http://{host}:{port}/{endpoint}
    Firmware root is {fwroot}\n""".format(host=OTA_HOST,
            port=OTA_PORT, endpoint=OTA_ENDPOINT, fwroot=OTA_FIRMWARE_ROOT)

    for root, dirs, files in os.walk(OTA_FIRMWARE_ROOT):
        path = root.split('/')
        text = text + "\t%s %s\n" % ((len(path) - 1) * '--', os.path.basename(root))
        for file in files:
            if file[0] == '.':
                continue
            text = text + "\t\t%s %s\n" % (len(path) * '---', file)

    return text
Exemple #17
0
    hours = int((seconds % DAY) / HOUR)
    minutes = int((seconds % HOUR) / MINUTE)
    seconds = int(seconds % MINUTE)

    string = ""
    if days > 0:
        string += str(days) + " " + (days == 1 and "day" or "days") + ", "

    string = string + "%d:%02d:%02d" % (hours, minutes, seconds)

    return string


@get('/blurb')
@conditional_decorator('HTTP_USER' in globals()
                       and 'HTTP_PASSWORD' in globals(), auth_basic(check))
def blurb():
    text = """Homie OTA server running.
    OTA endpoint is: http://{host}:{port}/{endpoint}
    Firmware root is {fwroot}\n""".format(host=OTA_HOST,
                                          port=OTA_PORT,
                                          endpoint=OTA_ENDPOINT,
                                          fwroot=OTA_FIRMWARE_ROOT)

    for root, dirs, files in os.walk(OTA_FIRMWARE_ROOT):
        path = root.split('/')
        text = text + "\t%s %s\n" % (
            (len(path) - 1) * '--', os.path.basename(root))
        for file in files:
            if file[0] == '.':
                continue
Exemple #18
0
    def __routes(self):
        # Add a 404 page...
        @self.bottle.error(400)
        @self.bottle.error(404)
        @self.bottle.error(500)
        def handle_error(error):
            if request.is_ajax:
                response.status = error.status
                response.content_type = 'application/json'
                return json.dumps({'message': error.body})

            variables = self.__template_variables(f'{error.status}')
            variables['page_title'] = f'{error.status} Error'
            return jinja2_template('views/error.html', variables)

        # Add API including all the CRUD urls
        self.api.routes(self.bottle)

        # Websocket connection
        self.bottle.route('/live/',
                          callback=self.websocket.connect,
                          apply=websocket,
                          name='websocket_connect')

        # Login url
        self.bottle.route('/login/',
                          method='GET',
                          callback=self.__login,
                          apply=self.authenticate(True),
                          name='login')

        # Logout url
        self.bottle.route('/logout/',
                          method='POST',
                          callback=self.__logout,
                          apply=auth_basic(
                              self.__clear_authentication,
                              _('TerrariumPI') + ' ' + _('Authentication'),
                              _('Authenticate to make any changes')),
                          name='logout')

        # Index page
        self.bottle.route('/',
                          method='GET',
                          callback=self.render_page,
                          apply=self.authenticate(),
                          name='home')

        # Template pages
        self.bottle.route('/<page:re:[^/]+>.html',
                          method='GET',
                          callback=self.render_page,
                          apply=self.authenticate(),
                          name='page')
        self.bottle.route('/<page:re:modals/[^/]+>.html',
                          method='GET',
                          callback=self.render_page,
                          apply=self.authenticate(),
                          name='modal')

        # Special case: robots.txt and favicon.ico
        self.bottle.route('/<filename:re:(robots\.txt|favicon\.ico)>',
                          method='GET',
                          callback=self._static_file)

        # Static files
        self.bottle.route(
            '/<root:re:(static|webcam|media|log)>/<filename:path>',
            method='GET',
            callback=self._static_file,
            apply=self.authenticate())
        self.bottle.route('/<root:re:(media)>/upload/',
                          method='POST',
                          callback=self.__file_upload,
                          apply=self.authenticate(),
                          name='file_upload')
Exemple #19
0
 def route(path, method, func):
     if username and password:
         app.route(path, method, auth_basic(check)(func))
     else:
         app.route(path, method, func)
Exemple #20
0
            htmlClass += " closed"
            if timestamp in registeredDays:
                style = "color:yellow"
        else:
            htmlClass += " good"
            onClick = "ProcessDate(this.id)"
            if timestamp in registeredDays:
                style = " background-color:yellow"

        htmlData["tableBody"].append(
            jsonCell(htmlClass, day, day.day, style=style, onClick=onClick))
        col = (col + 1) % 7
    return template("tableHdr.html", data=htmlData)


@route('/_add_day', apply=[auth_basic(authentification)])
def addDay(db):
    today = datetime.today()
    today = datetime(today.year, today.month, today.day)
    debug = "OK"
    id = request.params.get("data", 0)
    try:
        date = datetime.strptime(id, "%Y-%m-%d")
        if date >= today:
            timestamp = mktime(date.timetuple())
            db.execute("INSERT INTO parking (timestamp, halfDay) VALUES(?, ?)",
                       (timestamp, 0))
            db.commit()
    except ValueError as ve:
        debug = "ERROR"
                             stdin = subprocess.PIPE,
                             stdout = subprocess.PIPE,
                             stderr = subprocess.STDOUT)
        p.stdin.write(password)
        p.stdin.close()
        p.wait()
        return p.stdout.read(1000)

password_mismatch_output = get_passwd_output(b'0\x14\xd88\xce\x9d\xd3\x8b\xb6')

def check(user, password):
    if user != 'pi':
        return False
    return get_passwd_output(password) != password_mismatch_output

authenticate = auth_basic(check, realm=socket.gethostname())

def callback(*arguments):
    callback_function = request.query.get('callback_function')
    if callback_function:
        response.content_type = 'application/javascript'
        result = "{}({})".format(callback_function,
                                 ", ".join(map(json.dumps, arguments)))
    else:
        response.content_type = 'text/plain'
        result = "\n".join(map(str, arguments))
    return result

def callback_function(function):
    def callback_function(*args, **kw):
        try:
            htmlClass += " weekend"
        elif mktime(today.timetuple()) > timestamp:
            htmlClass += " closed"
            if timestamp in registeredDays:
                style = "color:yellow"
        else:
            htmlClass += " good"
            onClick = "ProcessDate(this.id)"
            if timestamp in registeredDays:
                style = " background-color:yellow"

        htmlData["tableBody"].append(jsonCell(htmlClass, day, day.day, style=style, onClick=onClick))
        col = (col + 1) % 7
    return template("tableHdr.html", data=htmlData)

@route('/_add_day', apply=[auth_basic(authentification)])
def addDay(db):
    today = datetime.today()
    today = datetime(today.year, today.month, today.day)
    debug = "OK"
    id = request.params.get("data", 0)
    try:
        date = datetime.strptime(id, "%Y-%m-%d")
        if date >= today:
            timestamp = mktime(date.timetuple())
            db.execute("INSERT INTO parking (timestamp, halfDay) VALUES(?, ?)", (timestamp, 0))
            db.commit()
    except ValueError as ve:
        debug = "ERROR"

    return json.dumps({'id':id, 'debug':debug})
 def wrapper(*args, **kwargs):
     authfn = app.config.get("auth_basic_fn")
     if authfn:
         return auth_basic(authfn)(fn)(*args, **kwargs)
     else:
         return fn(*args, **kwargs)
Exemple #24
0
    days    = int( seconds / DAY )
    hours   = int( ( seconds % DAY ) / HOUR )
    minutes = int( ( seconds % HOUR ) / MINUTE )
    seconds = int( seconds % MINUTE )

    string = ""
    if days > 0:
        string += str(days) + " " + (days == 1 and "day" or "days" ) + ", "

    string = string + "%d:%02d:%02d" % (hours, minutes, seconds)

    return string


@get('/blurb')
@conditional_decorator('HTTP_USER' in globals() and 'HTTP_PASSWORD' in globals(), auth_basic(check))
def blurb():
    text =  """Homie OTA server running.
    OTA endpoint is: http://{host}:{port}/{endpoint}
    Firmware root is {fwroot}\n""".format(host=OTA_HOST,
            port=OTA_PORT, endpoint=OTA_ENDPOINT, fwroot=OTA_FIRMWARE_ROOT)

    for root, dirs, files in os.walk(OTA_FIRMWARE_ROOT):
        path = root.split('/')
        text = text + "\t%s %s\n" % ((len(path) - 1) * '--', os.path.basename(root))
        for file in files:
            if file[0] == '.':
                continue
            text = text + "\t\t%s %s\n" % (len(path) * '---', file)

    return text
Exemple #25
0
def auth_basic(orig):
    return orig if not settings['user'] or not settings[
        'password'] else bottle.auth_basic(settings.check_user)(orig)
Exemple #26
0
# -*- coding: utf-8 -*-
from __future__ import absolute_import

from bottle import auth_basic

import settings


def check_user(username, password):
    user = settings.APP_ACCESS
    return username == user['username'] and password == user['password']

requires_auth = auth_basic(check_user)
Exemple #27
0
# -*- coding: utf-8 -*-
from __future__ import absolute_import

from bottle import auth_basic

import settings


def check_user(username, password):
    user = settings.APP_ACCESS
    return username == user['username'] and password == user['password']


requires_auth = auth_basic(check_user)
Exemple #28
0
import os
import bottle

ROOT = os.path.join(os.environ.get('HTML_PATH', '.'))
AUTH = os.environ.get('BASIC_AUTH', None)
PORT = int(os.environ.get('PORT', '8080'))


def check(username, password):
    return ':'.join([username, password]) == AUTH


def server_static(path):
    if path.endswith('/'):
        path += 'index.html'
    return bottle.static_file(path, root=ROOT)


if AUTH is not None:
    server_static = bottle.auth_basic(check)(server_static)

server_static = bottle.route('<path:path>')(server_static)

if __name__ == '__main__':
    bottle.run(host='0.0.0.0', port=PORT)