Beispiel #1
0
def main():
    setup()

    if is_balena_app():
        load_browser()
    else:
        setup_hotspot()

    url = 'http://{0}:{1}/splash-page'.format(
        LISTEN, PORT) if settings['show_splash'] else 'file://' + BLACK_PAGE
    browser_url(url=url)

    if settings['show_splash']:
        sleep(SPLASH_DELAY)

    global scheduler
    scheduler = Scheduler()

    subscriber = ZmqSubscriber()
    subscriber.daemon = True
    subscriber.start()

    # We don't want to show splash-page if there are active assets but all of them are not available
    view_image(HOME + LOAD_SCREEN)

    logging.debug('Entering infinite loop.')
    while True:
        asset_loop(scheduler)
Beispiel #2
0
def main():
    global db_conn, scheduler
    setup()

    subscriber = ZmqSubscriber()
    subscriber.daemon = True
    subscriber.start()

    scheduler = Scheduler()

    wait_for_server(5)

    if not is_balena_app():
        setup_hotspot()

    if settings['show_splash']:
        url = 'http://{0}:{1}/splash-page'.format(LISTEN, PORT)
        view_webpage(url)
        sleep(SPLASH_DELAY)

    # We don't want to show splash-page if there are active assets but all of them are not available
    view_image(LOAD_SCREEN)

    logging.debug('Entering infinite loop.')
    while True:
        if loop_is_stopped:
            sleep(0.1)
            continue
        if not db_conn:
            load_settings()
            db_conn = db.conn(settings['database'])

        asset_loop(scheduler)
Beispiel #3
0
def main():
    setup()

    if is_balena_app():
        load_browser()
    else:
        setup_hotspot()

    wait_for_node_ip(5)

    url = 'http://{0}:{1}/splash_page'.format(LISTEN, PORT) if settings['show_splash'] else 'file://' + BLACK_PAGE
    browser_url(url=url)

    if settings['show_splash']:
        sleep(SPLASH_DELAY)

    global scheduler
    scheduler = Scheduler()

    subscriber = ZmqSubscriber()
    subscriber.daemon = True
    subscriber.start()

    # We don't want to show splash_page if there are active assets but all of them are not available
    view_image(HOME + LOAD_SCREEN)

    logging.debug('Entering infinite loop.')
    while True:
        asset_loop(scheduler)
Beispiel #4
0
def is_up_to_date():
    """
    Primitive update check. Checks local hash against GitHub hash for branch.
    Returns True if the player is up to date.
    """

    latest_sha, retrieved_update = fetch_remote_hash()
    git_branch = get_git_branch()
    git_hash = get_git_hash()
    git_short_hash = get_git_short_hash()
    get_device_id = r.get('device_id')

    if not latest_sha:
        logging.error('Unable to get latest version from GitHub')
        return True

    if not get_device_id:
        device_id = ''.join(
            random.choice(string.ascii_lowercase + string.digits)
            for _ in range(15))
        r.set('device_id', device_id)
    else:
        device_id = get_device_id

    if retrieved_update:
        if not settings['analytics_opt_out'] and not is_ci():
            mp = Mixpanel('d18d9143e39ffdb2a4ee9dcc5ed16c56')
            try:
                mp.track(
                    device_id, 'Version', {
                        'Branch':
                        str(git_branch),
                        'Hash':
                        str(git_short_hash),
                        'NOOBS':
                        os.path.isfile('/boot/os_config.json'),
                        'Balena':
                        is_balena_app(),
                        'Docker':
                        is_docker(),
                        'Pi_Version':
                        lookup_raspberry_pi_revision(
                            parse_cpu_info()['revision'])['model']
                    })
            except MixpanelException:
                pass
            except AttributeError:
                pass

    return latest_sha == git_hash
Beispiel #5
0
def integrations():

    context = {
        'is_balena': is_balena_app(),
    }

    if context['is_balena']:
        context['balena_device_id'] = getenv('BALENA_DEVICE_UUID')
        context['balena_app_id'] = getenv('BALENA_APP_ID')
        context['balena_app_name'] = getenv('BALENA_APP_NAME')
        context['balena_supervisor_version'] = getenv('BALENA_SUPERVISOR_VERSION')
        context['balena_host_os_version'] = getenv('BALENA_HOST_OS_VERSION')
        context['balena_device_name_at_init'] = getenv('BALENA_DEVICE_NAME_AT_INIT')

    return template('integrations.html', **context)
Beispiel #6
0
def main():
    global db_conn, scheduler
    setup()

    subscriber = ZmqSubscriber()
    subscriber.daemon = True
    subscriber.start()

    scheduler = Scheduler()

    wait_for_server(5)

    if is_balena_app():
        load_browser()
    else:
        setup_hotspot()

    url = ("http://{0}:{1}/splash-page".format(LISTEN, PORT)
           if settings["show_splash"] else "file://" + BLACK_PAGE)
    browser_url(url=url)

    if settings["show_splash"]:
        sleep(SPLASH_DELAY)

    # We don't want to show splash-page if there are active assets but all of them are not available
    view_image(HOME + LOAD_SCREEN)

    logging.debug("Entering infinite loop.")
    while True:
        if loop_is_stopped:
            sleep(0.1)
            continue
        if not db_conn:
            load_settings()
            db_conn = db.conn(settings["database"])

        asset_loop(scheduler)
Beispiel #7
0
def check_update():
    """
    Check if there is a later version of Screenly OSE
    available. Only do this update once per day.
    Return True if up to date was written to disk,
    False if no update needed and None if unable to check.
    """

    sha_file = path.join(settings.get_configdir(), 'latest_screenly_sha')
    device_id_file = path.join(settings.get_configdir(), 'device_id')

    if path.isfile(sha_file):
        sha_file_mtime = path.getmtime(sha_file)
        last_update = datetime.fromtimestamp(sha_file_mtime)
    else:
        last_update = None

    if not path.isfile(device_id_file):
        device_id = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(15))
        with open(device_id_file, 'w') as f:
            f.write(device_id)
    else:
        with open(device_id_file, 'r') as f:
            device_id = f.read()

    logging.debug('Last update: %s' % str(last_update))

    git_branch = get_git_branch()
    git_hash = get_git_short_hash()

    if last_update is None or last_update < (datetime.now() - timedelta(days=1)):

        if not settings['analytics_opt_out'] and not is_ci():
            mp = Mixpanel('d18d9143e39ffdb2a4ee9dcc5ed16c56')
            try:
                mp.track(device_id, 'Version', {
                    'Branch': str(git_branch),
                    'Hash': str(git_hash),
                    'NOOBS': path.isfile('/boot/os_config.json'),
                    'Balena': is_balena_app()
                })
            except MixpanelException:
                pass
            except AttributeError:
                pass

        if remote_branch_available(git_branch):
            latest_sha = fetch_remote_hash(git_branch)

            if latest_sha:
                with open(sha_file, 'w') as f:
                    f.write(latest_sha)
                return True
            else:
                logging.debug('Unable to fetch latest hash.')
                return
        else:
            touch(sha_file)
            logging.debug('Unable to check if branch exist. Checking again tomorrow.')
            return
    else:
        return False
Beispiel #8
0
def settings_page():
    context = {'flash': None}

    if request.method == "POST":
        try:
            # put some request variables in local variables to make easier to read
            current_pass = request.form.get('current-password', '')
            auth_backend = request.form.get('auth_backend', '')

            if auth_backend != settings['auth_backend'] and settings[
                    'auth_backend']:
                if not current_pass:
                    raise ValueError(
                        "Must supply current password to change authentication method"
                    )
                if not settings.auth.check_password(current_pass):
                    raise ValueError("Incorrect current password.")

            prev_auth_backend = settings['auth_backend']
            if not current_pass and prev_auth_backend:
                current_pass_correct = None
            else:
                current_pass_correct = settings.auth_backends[
                    prev_auth_backend].check_password(current_pass)
            next_auth_backend = settings.auth_backends[auth_backend]
            next_auth_backend.update_settings(current_pass_correct)
            settings['auth_backend'] = auth_backend

            for field, default in CONFIGURABLE_SETTINGS.items():
                value = request.form.get(field, default)

                if not value and field in [
                        'default_duration', 'default_streaming_duration'
                ]:
                    value = str(0)

                if isinstance(default, bool):
                    value = value == 'on'
                settings[field] = value

            settings.save()
            publisher = ZmqPublisher.get_instance()
            publisher.send_to_viewer('reload')
            context['flash'] = {
                'class': "success",
                'message': "Settings were successfully saved."
            }
        except ValueError as e:
            context['flash'] = {'class': "danger", 'message': e}
        except IOError as e:
            context['flash'] = {'class': "danger", 'message': e}
        except OSError as e:
            context['flash'] = {'class': "danger", 'message': e}
    else:
        settings.load()
    for field, default in DEFAULTS['viewer'].items():
        context[field] = settings[field]

    auth_backends = []
    for backend in settings.auth_backends_list:
        if backend.template:
            html, ctx = backend.template
            context.update(ctx)
        else:
            html = None
        auth_backends.append({
            'name':
            backend.name,
            'text':
            backend.display_name,
            'template':
            html,
            'selected':
            'selected' if settings['auth_backend'] == backend.name else ''
        })

    context.update({
        'user': settings['user'],
        'need_current_password': bool(settings['auth_backend']),
        'is_balena': is_balena_app(),
        'auth_backend': settings['auth_backend'],
        'auth_backends': auth_backends
    })

    return template('settings.html', **context)
Beispiel #9
0
def settings_page():
    context = {'flash': None}

    if request.method == "POST":
        try:
            # put some request variables in local variables to make easier to read
            current_pass = request.form.get('curpassword', '')
            new_pass = request.form.get('password', '')
            new_pass2 = request.form.get('password2', '')
            current_pass = '' if current_pass == '' else hashlib.sha256(current_pass).hexdigest()
            new_pass = '' if new_pass == '' else hashlib.sha256(new_pass).hexdigest()
            new_pass2 = '' if new_pass2 == '' else hashlib.sha256(new_pass2).hexdigest()

            new_user = request.form.get('user', '')
            use_auth = request.form.get('use_auth', '') == 'on'

            # Handle auth components
            if settings['password'] != '':  # if password currently set,
                if new_user != settings['user']:  # trying to change user
                    # should have current password set. Optionally may change password.
                    if current_pass == '':
                        if not use_auth:
                            raise ValueError("Must supply current password to disable authentication")
                        raise ValueError("Must supply current password to change username")
                    if current_pass != settings['password']:
                        raise ValueError("Incorrect current password.")

                    settings['user'] = new_user

                if new_pass != '' and use_auth:
                    if current_pass == '':
                        raise ValueError("Must supply current password to change password")
                    if current_pass != settings['password']:
                        raise ValueError("Incorrect current password.")

                    if new_pass2 != new_pass:  # changing password
                        raise ValueError("New passwords do not match!")

                    settings['password'] = new_pass

                if new_pass == '' and not use_auth and new_pass2 == '':
                    # trying to disable authentication
                    if current_pass == '':
                        raise ValueError("Must supply current password to disable authentication")
                    settings['password'] = ''

            else:  # no current password
                if new_user != '':  # setting username and password
                    if new_pass != '' and new_pass != new_pass2:
                        raise ValueError("New passwords do not match!")
                    if new_pass == '':
                        raise ValueError("Must provide password")
                    settings['user'] = new_user
                    settings['password'] = new_pass

            for field, default in CONFIGURABLE_SETTINGS.items():
                value = request.form.get(field, default)

                # skip user and password as they should be handled already.
                if field == "user" or field == "password":
                    continue

                if not value and field in ['default_duration', 'default_streaming_duration']:
                    value = str(0)

                if isinstance(default, bool):
                    value = value == 'on'
                settings[field] = value

            settings.save()
            publisher = ZmqPublisher.get_instance()
            publisher.send_to_viewer('reload')
            context['flash'] = {'class': "success", 'message': "Settings were successfully saved."}
        except ValueError as e:
            context['flash'] = {'class': "danger", 'message': e}
        except IOError as e:
            context['flash'] = {'class': "danger", 'message': e}
        except OSError as e:
            context['flash'] = {'class': "danger", 'message': e}
    else:
        settings.load()
    for field, default in DEFAULTS['viewer'].items():
        context[field] = settings[field]

    context['user'] = settings['user']
    context['password'] = "******" if settings['password'] != "" else ""

    context['is_balena_app'] = is_balena_app()

    if not settings['user'] or not settings['password']:
        context['use_auth'] = False
    else:
        context['use_auth'] = True

    return template('settings.html', **context)
Beispiel #10
0
def settings_page():
    context = {'flash': None}

    if request.method == "POST":
        try:
            # put some request variables in local variables to make easier to read
            current_pass = request.form.get('curpassword', '')
            new_pass = request.form.get('password', '')
            new_pass2 = request.form.get('password2', '')
            current_pass = '' if current_pass == '' else hashlib.sha256(
                current_pass).hexdigest()
            new_pass = '' if new_pass == '' else hashlib.sha256(
                new_pass).hexdigest()
            new_pass2 = '' if new_pass2 == '' else hashlib.sha256(
                new_pass2).hexdigest()

            new_user = request.form.get('user', '')
            use_auth = request.form.get('use_auth', '') == 'on'

            # Handle auth components
            if settings['password'] != '':  # if password currently set,
                if new_user != settings['user']:  # trying to change user
                    # should have current password set. Optionally may change password.
                    if current_pass == '':
                        if not use_auth:
                            raise ValueError(
                                "Must supply current password to disable authentication"
                            )
                        raise ValueError(
                            "Must supply current password to change username")
                    if current_pass != settings['password']:
                        raise ValueError("Incorrect current password.")

                    settings['user'] = new_user

                if new_pass != '' and use_auth:
                    if current_pass == '':
                        raise ValueError(
                            "Must supply current password to change password")
                    if current_pass != settings['password']:
                        raise ValueError("Incorrect current password.")

                    if new_pass2 != new_pass:  # changing password
                        raise ValueError("New passwords do not match!")

                    settings['password'] = new_pass

                if new_pass == '' and not use_auth and new_pass2 == '':
                    # trying to disable authentication
                    if current_pass == '':
                        raise ValueError(
                            "Must supply current password to disable authentication"
                        )
                    settings['password'] = ''

            else:  # no current password
                if new_user != '':  # setting username and password
                    if new_pass != '' and new_pass != new_pass2:
                        raise ValueError("New passwords do not match!")
                    if new_pass == '':
                        raise ValueError("Must provide password")
                    settings['user'] = new_user
                    settings['password'] = new_pass

            for field, default in CONFIGURABLE_SETTINGS.items():
                value = request.form.get(field, default)

                # skip user and password as they should be handled already.
                if field == "user" or field == "password":
                    continue

                if not value and field in [
                        'default_duration', 'default_streaming_duration'
                ]:
                    value = str(0)

                if isinstance(default, bool):
                    value = value == 'on'
                settings[field] = value

            settings.save()
            publisher = ZmqPublisher.get_instance()
            publisher.send_to_viewer('reload')
            context['flash'] = {
                'class': "success",
                'message': "Settings were successfully saved."
            }
        except ValueError as e:
            context['flash'] = {'class': "danger", 'message': e}
        except IOError as e:
            context['flash'] = {'class': "danger", 'message': e}
        except OSError as e:
            context['flash'] = {'class': "danger", 'message': e}
    else:
        settings.load()
    for field, default in DEFAULTS['viewer'].items():
        context[field] = settings[field]

    context['user'] = settings['user']
    context['password'] = "******" if settings['password'] != "" else ""

    context['is_balena_app'] = is_balena_app()

    if not settings['user'] or not settings['password']:
        context['use_auth'] = False
    else:
        context['use_auth'] = True

    return template('settings.html', **context)
Beispiel #11
0
def check_update():
    """
    Check if there is a later version of Screenly OSE
    available. Only do this update once per day.
    Return True if up to date was written to disk,
    False if no update needed and None if unable to check.
    """

    sha_file = path.join(settings.get_configdir(), 'latest_screenly_sha')
    device_id_file = path.join(settings.get_configdir(), 'device_id')

    if path.isfile(sha_file):
        sha_file_mtime = path.getmtime(sha_file)
        last_update = datetime.fromtimestamp(sha_file_mtime)
    else:
        last_update = None

    if not path.isfile(device_id_file):
        device_id = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(15))
        with open(device_id_file, 'w') as f:
            f.write(device_id)
    else:
        with open(device_id_file, 'r') as f:
            device_id = f.read()

    logging.debug('Last update: %s' % str(last_update))

    git_branch = sh.git('rev-parse', '--abbrev-ref', 'HEAD').strip()
    git_hash = sh.git('rev-parse', '--short', 'HEAD').strip()

    if last_update is None or last_update < (datetime.now() - timedelta(days=1)):

        if not settings['analytics_opt_out'] and not is_ci():
            mp = Mixpanel('d18d9143e39ffdb2a4ee9dcc5ed16c56')
            try:
                mp.track(device_id, 'Version', {
                    'Branch': str(git_branch),
                    'Hash': str(git_hash),
                    'NOOBS': path.isfile('/boot/os_config.json'),
                    'Balena': is_balena_app()
                })
            except MixpanelException:
                pass
            except AttributeError:
                pass

        if remote_branch_available(git_branch):
            latest_sha = fetch_remote_hash(git_branch)

            if latest_sha:
                with open(sha_file, 'w') as f:
                    f.write(latest_sha)
                return True
            else:
                logging.debug('Unable to fetch latest hash.')
                return
        else:
            touch(sha_file)
            logging.debug('Unable to check if branch exist. Checking again tomorrow.')
            return
    else:
        return False