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)
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)
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)
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
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)
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)
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
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)
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)
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)
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