def runTest(self): """ Tests the User SQLObject """ user = User(username='******', fullname='fullname', email='email') fake_plugin = Plugin(name='fake_plugin', activated='notfound') plugin_channel = PluginChannel(plugin=fake_plugin, name='Channel', subscription_right='public') building = Building(name='building') screen = Screen(name='Screen', building=building) screen.subscribe_to(user, plugin_channel) # Miscellaneous test assert user.log_name == 'fullname (%d)' % user.id user.fullname = None assert user.log_name == 'email (%d)' % user.id user.fullname = 'fullname' assert user.log_name == 'fullname (%d)' % user.id assert user.readable_name == 'fullname' user.fullname = None assert user.readable_name == 'username' user.username = None assert user.readable_name == 'email' # Test permissions assert user.highest_permission_level == UserPermissions.no_permission assert list(user.get_subscriptions_of_owned_screens()) == [] assert list( user.get_channels_with_permission_level( UserPermissions.channel_contributor)) == [] assert list( user.get_channels_with_permission_level( UserPermissions.channel_administrator)) == [] plugin_channel.give_permission_to_user( user, UserPermissions.channel_contributor) assert user.highest_permission_level == UserPermissions.channel_contributor assert list( user.get_channels_with_permission_level( UserPermissions.channel_contributor)) == [plugin_channel] assert list( user.get_channels_with_permission_level( UserPermissions.channel_administrator)) == [] plugin_channel.give_permission_to_user( user, UserPermissions.channel_administrator) assert user.highest_permission_level == UserPermissions.channel_administrator assert list( user.get_channels_with_permission_level( UserPermissions.channel_contributor)) == [] assert list( user.get_channels_with_permission_level( UserPermissions.channel_administrator)) == [plugin_channel] plugin_channel.remove_permission_to_user(user) assert user.highest_permission_level == UserPermissions.no_permission assert list(user.get_subscriptions_of_owned_screens()) == [] user.admin = True assert user.highest_permission_level == UserPermissions.administrator assert list(user.get_subscriptions_of_owned_screens()) == list( screen.subscriptions) user.admin = False assert user.highest_permission_level == UserPermissions.no_permission assert list(user.get_subscriptions_of_owned_screens()) == [] user.super_admin = True assert user.highest_permission_level == UserPermissions.super_administrator assert list(user.get_subscriptions_of_owned_screens()) == list( screen.subscriptions) user.super_admin = False assert user.highest_permission_level == UserPermissions.no_permission assert list(user.get_subscriptions_of_owned_screens()) == [] screen.safe_add_user(user) assert user.highest_permission_level == UserPermissions.screen_administrator assert list(user.get_subscriptions_of_owned_screens()) == list( screen.subscriptions) screen.removeUser(user) assert list(user.get_subscriptions_of_owned_screens()) == [] assert user.highest_permission_level == UserPermissions.no_permission
def runTest(self): """ Tests the PluginChannel SQLObject """ Channel.deleteMany(None) fake_plugin = Plugin.selectBy(name='fake_plugin').getOne() plugin_channel = PluginChannel(name='MyPluginChannel', plugin=fake_plugin, subscription_right='public') user = User(fullname='User', email='test@localhost') user2 = User(fullname='User2', email='test2@localhost') assert plugin_channel.get_type_name() == 'Plugin fake_plugin' # Test user permissions def assert_no_permission(c, u): assert c.get_channel_permissions_of( u) == UserPermissions.no_permission assert u not in c.get_admins() and u not in c.get_contribs() def has_contrib(u, check_inlist=True): return plugin_channel.has_contrib(u) and ( not check_inlist or u in plugin_channel.get_contribs()) def has_admin(u): return plugin_channel.has_admin( u) and u in plugin_channel.get_admins() assert_no_permission(plugin_channel, user) assert_no_permission(plugin_channel, user2) plugin_channel.give_permission_to_user( user, UserPermissions.channel_contributor) role = Role.selectBy(user=user, channel=plugin_channel).getOne() assert has_contrib(user) assert not has_admin(user) assert not has_contrib(user2) assert not has_admin(user2) assert role.permission_level == UserPermissions.channel_contributor == plugin_channel.get_channel_permissions_of( user) assert json.loads(plugin_channel.get_users_as_json()) == { str(user.id): UserPermissions.channel_contributor.value } plugin_channel.give_permission_to_user( user, UserPermissions.channel_administrator) assert has_contrib(user, check_inlist=False) assert has_admin(user) assert not has_contrib(user2) assert not has_admin(user2) assert role.permission_level == UserPermissions.channel_administrator == plugin_channel.get_channel_permissions_of( user) assert json.loads(plugin_channel.get_users_as_json()) == { str(user.id): UserPermissions.channel_administrator.value } assert json.loads(PluginChannel.get_channels_users_as_json([plugin_channel])) == \ {str(plugin_channel.id): {str(user.id): UserPermissions.channel_administrator.value}} plugin_channel.remove_permission_to_user(user) plugin_channel.give_permission_to_user( user2, UserPermissions.channel_administrator) assert not has_contrib(user) assert not has_admin(user) assert has_contrib(user2, check_inlist=False) assert has_admin(user2) plugin_channel.remove_permission_to_user(user2) assert not has_contrib(user2) assert not has_admin(user2) # Test plugin config parameters assert plugin_channel.get_config_param( 'string_param') == 'default string' assert plugin_channel.get_config_param('int_param') == 1 assert plugin_channel.get_config_param('float_param') == float('-inf') assert plugin_channel.get_config_param('boolean_param') is True assert plugin_channel.get_config_param('template_param') is None with pytest.raises(KeyError): assert plugin_channel.get_config_param( 'this_param_does_not_exists') def assert_value_is_set(param, value): plugin_channel.plugin_config[param] = value plugin_channel.plugin_config = plugin_channel.plugin_config # Force SQLObject update assert plugin_channel.get_config_param(param) == value assert_value_is_set('string_param', 'Hello, world!') assert_value_is_set('int_param', 42) assert_value_is_set('float_param', 42.0) assert_value_is_set('boolean_param', False) assert_value_is_set('template_param', 'fake-template') # Test parameters access rights ppar = PluginParamAccessRights.selectBy(plugin=fake_plugin, name='int_param').getOne() ppar.channel_contributor_read = False ppar.channel_contributor_write = False ppar.channel_administrator_read = True ppar.channel_administrator_write = False ppar.administrator_read = True ppar.administrator_write = True user.super_admin = True assert plugin_channel.has_visible_params_for(user) for param in [ 'string_param', 'int_param', 'float_param', 'boolean_param', 'template_param' ]: assert plugin_channel.get_access_rights_for(param, user) == (True, True) user.super_admin = False assert not plugin_channel.has_visible_params_for(user) plugin_channel.give_permission_to_user( user, UserPermissions.channel_contributor) assert not plugin_channel.has_visible_params_for(user) assert plugin_channel.get_access_rights_for('int_param', user) == (False, False) plugin_channel.give_permission_to_user( user, UserPermissions.channel_administrator) assert plugin_channel.has_visible_params_for(user) assert plugin_channel.get_access_rights_for('int_param', user) == (True, False) user.admin = True assert plugin_channel.has_visible_params_for(user) assert plugin_channel.get_access_rights_for('int_param', user) == (True, True) plugin_channel.remove_permission_to_user(user) user.admin = False assert not plugin_channel.has_visible_params_for(user) assert plugin_channel.get_access_rights_for('int_param', user) == (False, False) # Test miscellaneous parameters assert plugin_channel.cache_activated is True plugin_channel.plugin.cache_activated_default = False assert plugin_channel.cache_activated is False plugin_channel.cache_activated = True assert plugin_channel.cache_activated is True assert plugin_channel.cache_validity is 60 plugin_channel.plugin.cache_validity_default = 120 assert plugin_channel.cache_validity is 120 plugin_channel.cache_validity = 42 assert plugin_channel.cache_validity is 42 assert plugin_channel.keep_noncomplying_capsules is False plugin_channel.plugin.keep_noncomplying_capsules_default = True assert plugin_channel.keep_noncomplying_capsules is True plugin_channel.keep_noncomplying_capsules = False assert plugin_channel.keep_noncomplying_capsules is False # Test flatten() plugin_channel.enabled = False assert plugin_channel.flatten() == [] assert plugin_channel.flatten(keep_disabled_channels=True) == [ plugin_channel ] plugin_channel.enabled = True assert plugin_channel.flatten() == [plugin_channel]
def runTest(self): """ Tests the Screen SQLObject """ Channel.deleteMany(None) Screen.deleteMany(None) channel = Channel(name='Channel', subscription_right='public', secret='abcdef') plugin_channel = PluginChannel(name='Channel2', plugin=Plugin.byName('fake_plugin'), subscription_right='public') plugin_channel2 = PluginChannel(name='Channel3', plugin=Plugin.byName('fake_plugin'), subscription_right='public') bundle_channel = ChannelBundle(name='Channel4', subscription_right='public') bundle_channel.add_channel(plugin_channel2) building = Building(name='building') screen = Screen(name='Screen', building=building, secret='abcdef') screen2 = Screen(name='Screen2', building=building) user = User(fullname='User', email='test@localhost') user2 = User(fullname='User2', email='test2@localhost') # Miscellaneous test assert screen.get_view_link() == '/screens/%d/view/abcdef' % screen.id assert screen.get_client_link( ) == '/screens/%d/client/abcdef' % screen.id assert screen.get_macs_string() == '' assert screen not in user.screens screen.safe_add_user(user) assert screen in user.screens assert screen not in user2.screens screen.removeUser(user) assert screen not in user2.screens # Test subscription assert not screen.is_subscribed_to(channel) screen.subscribe_to(user, channel) assert screen.is_subscribed_to(channel) sub = screen.subscriptions[0] screen.subscribe_to(user2, channel, weight=42) assert sub.created_by == user2 assert sub.weight == 42 assert screen.is_subscribed_to(channel) assert list(screen.subscribed_channels) == [channel] screen.unsubscribe_from(user2, channel) assert not screen.is_subscribed_to(channel) # Test macs ScreenMac(screen=screen, mac='00b16b00b500') ScreenMac(screen=screen, mac='00b16b00b501') assert screen.get_macs_string( ) == '00:b1:6b:00:b5:00;00:b1:6b:00:b5:01' # Test get_visible_screens_of() assert list(Screen.get_visible_screens_of(user)) == list( Screen.get_visible_screens_of(user2)) == [] user.admin = True assert list(Screen.get_visible_screens_of(user)) == [screen, screen2] assert list(Screen.get_visible_screens_of(user2)) == [] user.admin = False user2.super_admin = True assert list(Screen.get_visible_screens_of(user2)) == [screen, screen2] assert list(Screen.get_visible_screens_of(user)) == [] user2.super_admin = False screen.safe_add_user(user) screen2.safe_add_user(user2) assert list(Screen.get_visible_screens_of(user)) == [screen] assert list(Screen.get_visible_screens_of(user2)) == [screen2] # Test channel content screen.subscribe_to(user, plugin_channel) screen.subscribe_to(user, bundle_channel) screen_content = screen.get_channels_content(self.ictv_app) assert len(screen_content) == 2 assert len(screen_content[0].get_slides()) == 1 assert screen_content[0].get_slides()[0].get_content() == { 'background-1': { 'size': 'contain', 'src': '' }, 'title-1': { 'text': 'Channel2' }, 'text-1': { 'text': '' } } assert len(screen_content[1].get_slides()) == 1 assert screen_content[1].get_slides()[0].get_content() == { 'background-1': { 'size': 'contain', 'src': '' }, 'title-1': { 'text': 'Channel3' }, 'text-1': { 'text': '' } } screen.shuffle = True assert len(screen.get_channels_content(self.ictv_app)) == 2
def POST(self, bundle_id): def wrong_channel(channel, bundle, add): """ returns True if the channel to add is the bundle itself or if the channel is a PluginChannel with disabled plugin """ return bundle.id == channel.id or add and type( channel) is PluginChannel and channel.plugin.activated != "yes" form = web.input() try: bundle = ChannelBundle.get(bundle_id) u = User.get(self.session['user']['id']) diff = json.loads(form.diff) if diff == {}: logger.info( 'user %s submitted empty diff for bundle management %s', u.log_name, bundle.name) raise ImmediateFeedback("manage_channels", 'nothing_changed') # Do the subscription/unsubscription for every channel in the diff contained = [] not_contained = [] try: changes = [(Channel.get(channel_id), add) for channel_id, add in diff.items()] except SQLObjectNotFound: logger.warning( 'user %s tried to add a channel which does not exist to bundle %d', u.log_name, bundle.id) raise web.forbidden() # if somebody tries to add a channel with a disabled plugin or to add a bundle to itself wrong_channels = [(channel, add) for channel, add in changes if wrong_channel(channel, bundle, add)] if wrong_channels: channel, add = wrong_channels[0] if channel.id == bundle.id: logger.warning('user %s tried to %s bundle %d to itself', u.log_name, 'add' if add else "remove", bundle.id) raise ImmediateFeedback("manage_channels", "added_to_itself") else: logger.warning( 'user %s tried to %s channel %d with disabled plugin to bundle %d', u.log_name, 'add' if add else "remove", channel.id, bundle.id) raise ImmediateFeedback("manage_channels", "disabled_plugin") for channel, add in changes: if add: try: bundle.add_channel(channel) except ValueError: logger.warning( "user %s has made changes in channels management of bundle %d that created a " "cycle of bundles by adding channel %d (%s)", u.log_name, bundle.id, channel.id, channel.name) form.channel_name = channel.name raise ImmediateFeedback("manage_channels", "bundle_cycle") contained.append(str(channel.id)) else: bundle.remove_channel(channel) not_contained.append(str(channel.id)) if contained and not_contained: message = "user %s has added to channel(s) %s and removed channel(s) %s to bundle %d" % \ (u.log_name, ', '.join(contained), ', '.join(not_contained), bundle.id) else: message = "user %s has %s channel(s) %s to bundle %d" % \ (u.log_name, "added" if contained else "removed", ', '.join(contained if contained else not_contained), bundle.id) logger.info(message) add_feedback("manage_channels", 'ok') except SQLObjectNotFound: raise web.notfound() except ImmediateFeedback: pass store_form(form) raise web.seeother("/channels/%s/manage_bundle" % bundle.id)
def setUp(self, fake_plugin_middleware=lambda: None, ictv_middleware=lambda: None): super().setUp(fake_plugin_middleware, ictv_middleware) building = Building(name="mytestbuilding") self.screen = Screen(name="mytestscreen", building=building, secret="secret") self.other_screen = Screen(name="myothertestscreen", building=building, secret="secret") self.plugins = [ Plugin(name="%s%d" % (self.plugin_name, i), activated="yes") for i in range(self.n_elements - 1) ] self.plugins.append(Plugin.selectBy(name="fake_plugin").getOne()) self.plugin_channels = [ PluginChannel(name="%s%d" % (self.plugin_channel_name, i), plugin=self.plugins[i], subscription_right="public") for i in range(self.n_elements) ] self.bundle_channels = [ ChannelBundle(name="%s%d" % (self.bundle_channel_name, i), subscription_right="public") for i in range(self.n_elements) ] other_channel = PluginChannel(name="other_channel", plugin=self.plugins[0], subscription_right="public") User(email=self.user_nothing_email, username=self.user_nothing_username, disabled=False) User(email=self.user_administrator_email, disabled=False, admin=True) User(email=self.user_super_administrator_email, disabled=False, admin=True, super_admin=True) screen_owner = User(email=self.user_screen_owner_email, disabled=False) self.screen.safe_add_user(screen_owner) other_screen_owner = User(email=self.user_other_screen_owner_email, disabled=False) self.other_screen.safe_add_user(other_screen_owner) contributor = User(email=self.user_contributor_email, disabled=False) [ plugin_channel.give_permission_to_user(contributor) for plugin_channel in self.plugin_channels ] contributor_other_channel = User( email=self.user_contributor_of_other_channel_email, disabled=False) other_channel.give_permission_to_user(contributor_other_channel) administrator_other_channel = User( email=self.user_administrator_of_other_channel_email, disabled=False) other_channel.give_permission_to_user( administrator_other_channel, UserPermissions.channel_administrator) channel_admin = User(email=self.user_channel_admin_email, disabled=False) [ plugin_channel.give_permission_to_user( channel_admin, UserPermissions.channel_administrator) for plugin_channel in self.plugin_channels ]
def post(self): """ Handles screen creation, editing, deletion, channel subscriptions. """ form = self.form u = User.get(self.session['user']['id']) try: if form.action == 'delete': if not u.super_admin: resp.forbidden() try: screenid = int(form.screenid) except ValueError: raise ImmediateFeedback(form.action, 'invalid_id') try: Screen.delete(screenid) raise ImmediateFeedback(form.action, 'ok') except SQLObjectNotFound as e: raise ImmediateFeedback(form.action, 'no_id_matching') elif form.action == 'subscribe': if form.diff == 'diff': raise ImmediateFeedback(form.action, 'nothing_changed') try: diff = json.loads(form.diff) except (json.JSONDecodeError, ValueError): raise ImmediateFeedback(form.action, 'inconsistent_diff') try: screenid = int(form.screenid) except ValueError: raise ImmediateFeedback(form.action, 'invalid_channel/screen_id') for k, v in diff.items(): try: sub = bool(v) except ValueError: raise ImmediateFeedback(form.action, 'invalid_channel/screen_id') try: channelid = int(k) except ValueError: raise ImmediateFeedback(form.action, 'invalid_channel/screen_id') try: channel = Channel.get(channelid) screen = Screen.get(screenid) if UserPermissions.administrator not in u.highest_permission_level and not ( channel.can_subscribe(u) and u in screen.owners): resp.forbidden() if sub: if hasattr(channel, "plugin" ) and channel.plugin.activated != 'yes': resp.forbidden() screen.subscribe_to(user=u, channel=channel) else: screen.unsubscribe_from(user=u, channel=channel) except SQLObjectNotFound: raise ImmediateFeedback(form.action, 'invalid_channel/screen_id') except DuplicateEntryError: # if the user has checked + unchecked the same checkbox, it will appear on the diff, # we just need to do nothing. pass except SQLObjectIntegrityError: # when there id more than one subscription matching the pair channel/screen # TODO: log something pass elif form.action == 'chown': if form.diff == 'diff': raise ImmediateFeedback(form.action, 'nothing_changed') try: diff = json.loads(form.diff) except (json.JSONDecodeError, ValueError): raise ImmediateFeedback(form.action, 'inconsistent_diff') try: screenid = int(form.screenid) except ValueError: raise ImmediateFeedback(form.action, 'screenid') for k, v in diff.items(): try: own = bool(v) except ValueError: raise ImmediateFeedback(form.action, 'invalid_screen/user_id') try: userid = int(k) except ValueError: raise ImmediateFeedback(form.action, 'invalid_screen/user_id') try: screen = Screen.get(screenid) if UserPermissions.administrator not in u.highest_permission_level and u not in screen.owners: resp.forbidden() user = User.get(userid) if own: screen.safe_add_user(user) else: screen.removeUser(user) except SQLObjectNotFound: raise ImmediateFeedback(form.action, 'invalid_screen/user_id') except DuplicateEntryError: # if the user has checked + unchecked the same checkbox, it will appear on the diff, # we just need to do nothing. pass except SQLObjectIntegrityError: # when there is more than one subscription mathing the pair channel/screen # TODO: log something pass elif form.action == 'configure': screen = Screen.get(int(form.id)) screen.shuffle = form.get('shuffle') == 'on' screen.show_postit = form.get('postit') == 'on' screen.show_slide_number = form.get( 'show_slide_number') == 'on' else: building = Building.get(form.building.strip()) name = form.name.strip() form.building_name = None if not building: raise ImmediateFeedback(form.action, 'empty_building') form.building_name = building.name if not name: raise ImmediateFeedback(form.action, 'empty_name') if len(name) > Screen.sqlmeta.columns['name'].length: raise ImmediateFeedback(form.action, 'too_long_name') try: macs = { self.check_mac_address(mac) for mac in form.mac.strip().lower().split(';') if mac } except ValueError: raise ImmediateFeedback(form.action, 'invalid_mac_address') if form.action == 'create': if UserPermissions.administrator not in u.highest_permission_level: resp.forbidden() try: screen = Screen(name=form.name.strip(), building=form.building, location=form.location.strip(), comment=form.comment.strip(), orientation=form.orientation) except DuplicateEntryError: raise ImmediateFeedback(form.action, 'name_already_exists') elif form.action == 'edit': if UserPermissions.administrator not in u.highest_permission_level: resp.forbidden() try: screenid = int(form.screenid) except ValueError: raise ImmediateFeedback(form.action, 'invalid_id') screen = Screen.get(screenid) if screen is None: raise ImmediateFeedback(form.action, 'no_id_matching') try: screen.name = form.name.strip() screen.building = form.building screen.orientation = form.orientation except DuplicateEntryError: raise ImmediateFeedback(form.action, 'name_already_exists') screen.location = form.location.strip() screen.comment = form.comment.strip() else: raise NotImplementedError try: screen_macs = [ screen_mac.mac for screen_mac in screen.macs ] for mac in screen_macs: if mac not in macs: ScreenMac.selectBy(mac=mac).getOne().destroySelf() for mac in macs: if mac not in screen_macs: ScreenMac(screen=screen, mac=mac) except DuplicateEntryError: raise ImmediateFeedback(form.action, 'mac_already_exists') add_feedback(form.action, 'ok') except ImmediateFeedback: pass store_form(form) return self.render_page()
def get_app(config_path): """ Returns the flask main application of ICTV. Currently, only one application can be run a time due to how data such as assets, database, config files or plugins is stored. """ config = get_config(config_path) if database.database_path is None: database.database_path = config['database_uri'] # Create a base flask application app = FrankenFlask(__name__) # The following line might be used to speedup queries app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 300 app.config.update(**config) init_flask_url_mapping(app) app.version = ictv.common.__version__ with open(os.path.join(get_root_path(), 'info' + os.extsep + 'yaml')) as f: # Loads ICTV user info texts info_texts = yaml.unsafe_load(f) # Load the SMTP config into web.py smtp_conf = app.config.get('smtp', None) if smtp_conf: app.config['MAIL_DEFAULT_SENDER'] = smtp_conf['sender_name'] app.config['MAIL_SERVER'] = smtp_conf['host'] app.config['MAIL_PORT'] = smtp_conf['port'] app.config['MAIL_USERNAME'] = smtp_conf.get('username', '') app.config['MAIL_PASSWORD'] = smtp_conf.get('password', '') app.config['MAIL_USE_TLS'] = smtp_conf.get('starttls', False) # Create a persistent HTTP session storage for the app app.secret_key = app.config['session_secret_key'] # Populate the jinja templates globals template_globals = { 'session': app.session, 'get_feedbacks': get_feedbacks, 'get_next_feedbacks': get_next_feedbacks, 'pop_previous_form': pop_previous_form, 'UserPermissions': UserPermissions, 'json': json, 'str': str, 'sorted': sorted, 'hasattr': hasattr, 'sidebar_collapse': False, 'show_header': True, 'show_footer': True, 're': re, 'info': info_texts, 'make_tooltip': make_tooltip, 'make_alert': make_alert, 'escape': html.escape, 'show_reset_password': '******' in app.config['authentication'], 'homedomain': lambda: flask.request.url_root[:-1], 'generate_secret': generate_secret, 'version': lambda: app.version, 'pretty_print_size': pretty_print_size, 'timesince': timesince, 'User': User, 'get_user': lambda: User.get(app.session['user']['id']) } ### Jinja2 renderer ### app.renderer = render_jinja(os.path.join(get_root_path(), 'templates/')) app.renderer._lookup.globals.update(base='base.html', **template_globals) app.standalone_renderer = render_jinja( os.path.join(get_root_path(), 'templates/')) app.standalone_renderer._lookup.globals.update(**template_globals) # Init loggers load_loggers_stats() # Determine logging level and user feedback when an internal error occurs based on ICTV core config level = logging.INFO loggers_to_init = [ 'app', 'pages', 'screens', 'plugin_manager', 'storage_manager', 'local_login', 'database', 'transcoding_queue' ] for logger_name in loggers_to_init: init_logger(logger_name, level, rotation_interval=app.config['logs']['rotation_interval'], backup_count=app.config['logs']['backup_count']) # Init the renderer used for slide, capsule, channel and screen rendering app.ictv_renderer = ICTVRenderer(app) # Init the plugin manager, used as a gateway between ICTV core and its plugins. app.plugin_manager = PluginManager(app) # Init the download manager, a download queue which asynchronously downloads assets from the network app.download_manager = DownloadManager() # Init the cleanup manager which will regularly cleanup unused cached assets app.cleanup_scheduler = CleanupScheduler() app.cleanup_scheduler.start() # Init the video transcoding queue which will convert videos to WebM format using FFmpeg app.transcoding_queue = TranscodingQueue() # Add an general authentication processor to handle user authentication app.register_before_request(get_authentication_processor, cascade=True, needs_app=True) # Add a preprocessor to populate flask.g and mimic the old web.ctx app.register_before_request(get_web_ctx_processor, cascade=True) # Add a preprocessor to encapsulate every SQL requests in a transaction on a per HTTP request basis app.register_before_request(get_db_thread_preprocessor, cascade=True) app.prepare_error_handler(DatabaseError, lambda: database_error_handler) app.prepare_error_handler(werkzeug.exceptions.InternalServerError, lambda: internal_error_handler) # Add a hook to clean feedbacks from the previous request and prepare next feedbacks to be shown to the user app.register_after_request(lambda: rotate_feedbacks, cascade=True, needs_app=False) # Instantiate plugins through the plugin manager app.plugin_manager.instantiate_plugins(app) # Load themes and templates into database sqlhub.doInTransaction(load_templates_and_themes) return app
def POST(self, status): User.get(self.session['user']['id']).has_toured = status == 'ended' raise web.seeother(web.ctx.env.get('HTTP_REFERER', '/'))
def render_page(self): current_user = User.get(self.session['user']['id']) return self.renderer.buildings(buildings=Building.select(), current_user=current_user)
def POST(self): """ Handles building creation, editing and deletion. """ current_user = User.get(self.session['user']['id']) form = web.input() try: if form.action == 'delete': if not current_user.super_admin: raise web.forbidden() try: id = int(form.id) except ValueError: logger.warning( 'user %s tries to delete a building with invalid id (id = %s)', current_user.log_name, str(form.id)) raise ImmediateFeedback(form.action, 'invalid_id') try: screens = Screen.selectBy(building=id) if screens.count() > 0: logger.warning( 'user %s tries to delete a building with screens still present in this building (id = %s)', current_user.log_name, str(id)) raise ImmediateFeedback( form.action, 'delete_building_but_screens_present', [(s.id, s.name) for s in screens]) Building.delete(id) logger.info("building %s has been deleted by user %s", str(id), current_user.log_name) except SQLObjectNotFound as e: logger.warning( "user %s tries to delete a building with an id that doesn't exist (id = %s)", current_user.log_name, str(form.id)) raise ImmediateFeedback(form.action, 'no_id_matching') else: name = form.name.strip() if name == "": raise ImmediateFeedback(form.action, 'empty_name') if form.action == 'create': try: Building(name=form.name, city=form.city) logger.info("building %s has been created by user %s", form.name, current_user.log_name) except DuplicateEntryError: logger.warning( "user %s tries to create a building with a name that already exists (name = %s)", current_user.log_name, form.name) raise ImmediateFeedback(form.action, 'name_already_exists') elif form.action == 'edit': try: id = int(form.id) except ValueError: logger.warning( 'user %s tries to edit a building with invalid id (id = %s)', current_user.log_name, str(form.id)) raise ImmediateFeedback(form.action, 'invalid_building_id') try: building = Building.get(id) except SQLObjectNotFound as e: logger.warning( "user %s tries to edit a building with an id that doesn't exist (id = %s)", current_user.log_name, str(form.id)) raise ImmediateFeedback(form.action, 'no_id_matching') try: building.name = form.name building.city = form.city except DuplicateEntryError: logger.warning( "user %s tries to edit the building %s with a name already present (name = %d)", current_user.log_name, str(form.id), form.name) raise ImmediateFeedback(form.action, 'name_already_exists') logger.info( "building %s has been edited by user %s (new name = %s)", str(id), current_user.log_name, form.name) add_feedback(form.action, 'ok') except ImmediateFeedback: store_form(form) return self.render_page()
def POST(self): """ Handles channel creation, editing, deletion, configuration and user permissions. """ form = web.input() current_user = User.get(self.session['user']['id']) channel = None try: if form.action.startswith('create') or form.action.startswith( 'edit'): # Prepare creation or edition of channels/bundles name = form.name.strip() description = form.description if form.description and form.description.strip( ) else None enabled = form.get('enabled') == 'on' if form.subscription_right not in [ 'public', 'restricted', 'private' ]: raise ImmediateFeedback(form.action, 'invalid_subscription_right') if len(name) < 3: raise ImmediateFeedback(form.action, 'invalid_name') if form.action.startswith('create'): if UserPermissions.administrator not in current_user.highest_permission_level: logger.warning( 'user %s tried to create a channel without being admin', current_user.log_name) raise web.forbidden() try: if form.action == 'create-channel': try: plugin_id = int(form.plugin) except ValueError: raise ImmediateFeedback(form.action, 'invalid_plugin') p = Plugin.get(plugin_id) channel = PluginChannel( name=name, plugin=p, subscription_right=form.subscription_right, description=description, enabled=enabled) if p.webapp: self.plugin_manager.add_mapping(self.app, channel) elif form.action == 'create-bundle': channel = ChannelBundle( name=name, description=description, subscription_right=form.subscription_right, enabled=enabled) else: raise web.badrequest() except SQLObjectNotFound: raise ImmediateFeedback(form.action, 'invalid_plugin') except DuplicateEntryError: raise ImmediateFeedback(form.action, 'name_already_exists') logger.info('channel ' + channel.name + ' created by ' + current_user.log_name) elif form.action.startswith('edit'): if UserPermissions.administrator not in current_user.highest_permission_level: raise web.forbidden() try: form.id = int(form.id) channel = (PluginChannel if form.action == 'edit-channel' else Channel).get(form.id) except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') previous_state = { 'name': channel.name, 'description': channel.description, 'subscription_right': channel.subscription_right, 'enabled': channel.enabled } new_state = { 'name': name, 'description': description, 'subscription_right': form.subscription_right, 'enabled': enabled } state_diff = dict( set(new_state.items()) - set(previous_state.items())) if form.action == 'edit-channel': try: plugin_id = int(form.plugin) p = Plugin.get(plugin_id) add_mapping = p.webapp and channel.plugin != p previous_state['plugin'] = channel.plugin new_state['plugin'] = p except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_plugin') elif form.action == 'edit-bundle': pass # There is nothing more to edit for a bundle than a channel else: raise web.badrequest() try: channel.set(**new_state) except DuplicateEntryError: channel.set(**previous_state) # Rollback raise ImmediateFeedback(form.action, 'name_already_exists') logger.info( '[Channel %s (%d)] ' % (channel.name, channel.id) + current_user.log_name + ' edited the channel.\n' 'Previous state: %s\n' % str({ k: v for k, v in previous_state.items() if k in state_diff }) + 'New state: %s' % str(state_diff)) if form.action == 'edit-channel' and add_mapping: self.plugin_manager.add_mapping(self.app, channel) elif form.action.startswith('delete'): if not current_user.super_admin: logger.warning( 'the user %s tried to delete a channel without having the rights to do it', current_user.log_name) raise web.forbidden() try: form.id = int(form.id) channel = Channel.get(form.id) if channel.subscriptions.count( ) > 0 and 'confirm-delete' not in form: raise ImmediateFeedback( form.action, 'channel_has_subscriptions', { 'channel': { 'name': channel.name, 'id': channel.id, 'description': channel.description, 'subscription_right': channel.subscription_right }, 'plugin_id': channel.plugin.id if form.action == 'delete-channel' else None, 'subscriptions': [(s.screen.id, s.screen.name, s.screen.building.name) for s in channel.subscriptions] }) form.name = channel.name channel_name = channel.name channel.destroySelf() logger.info('the channel %s has been deleted by user %s', channel_name, current_user.log_name) except (SQLObjectNotFound, ValueError) as e: print(e) raise ImmediateFeedback(form.action, 'invalid_id') elif form.action == 'add-users-channel': try: if 'users' not in form: raise web.badrequest() form.users = json.loads(form.users) form.id = int(form.id) channel = PluginChannel.get(form.id) if not channel.has_admin( current_user ) and UserPermissions.administrator not in current_user.highest_permission_level: raise web.forbidden() form.name = channel.name for user_id, diff in form.users.items(): user_id = int(user_id) user = User.get(user_id) if 'permission' in diff: permission_level = diff['permission'] new_permission_level = UserPermissions( permission_level) old_permission_level = channel.get_channel_permissions_of( user) if new_permission_level == UserPermissions.no_permission \ and (UserPermissions.administrator in current_user.highest_permission_level or old_permission_level == UserPermissions.channel_contributor): channel.remove_permission_to_user(user) logger.info( 'permissions of user %s concerning channel %s have been removed by user %s', user.log_name, channel.name, current_user.log_name) elif (new_permission_level == UserPermissions.channel_contributor and channel.has_admin( current_user) and old_permission_level == UserPermissions.no_permission) \ or (new_permission_level in UserPermissions.channel_administrator and UserPermissions.administrator in current_user.highest_permission_level): channel.give_permission_to_user( user, new_permission_level) logger.info( 'permissions of user %s concerning channel %s have been set to %s by user %s', user.log_name, channel.name, UserPermissions.get_permission_string( new_permission_level), current_user.log_name) if 'authorized_subscriber' in diff: authorized_subscriber = diff[ 'authorized_subscriber'] if authorized_subscriber and ( user not in channel.authorized_subscribers): channel.addUser(user) logger.info( 'the user %s has been added to channel %s as authorized subscriber by user %s', user.log_name, channel.name, current_user.log_name) elif not authorized_subscriber and ( user in channel.authorized_subscribers): channel.removeUser(user) logger.info( 'the user %s has been removed from channel %s as authorized subscriber by user %s', user.log_name, channel.name, current_user.log_name) except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') except (KeyError, json.JSONDecodeError): raise ImmediateFeedback(form.action, 'invalid_users') elif form.action == 'configure': try: form.id = int(form.id) channel = PluginChannel.get(form.id) pattern = re.compile(r'list\[.*\]') if UserPermissions.administrator in current_user.highest_permission_level or UserPermissions.channel_administrator in channel.get_channel_permissions_of( current_user) or channel.has_contrib(current_user): for k, v in [(k, v) for k, v in channel.plugin.channels_params.items() if channel.get_access_rights_for( k, current_user)[1]]: # Iterates on the parameters the current user can write to if v['type'] == 'bool': value = k in form and form[k] == 'on' elif v['type'] == 'int': value = int(form[k]) if not (v.get('min', float('-inf')) <= value <= v.get('max', float('inf'))): continue elif pattern.match(v['type']): inner_type = v['type'][5:-1] if inner_type == 'string': value = web.input(**{k: ['']})[k] elif pattern.match(inner_type): inner_type = inner_type[5:-1] if inner_type == 'string': delimiter = form[k + '-delimiter'] values = web.input(**{k: ['']})[k] lists = [] l = [] for v in values: if v == delimiter: lists.append(l) l = [] else: l.append(v) value = lists elif k in form: if v['type'] == 'template' and form[k] == '~': value = None else: value = form[k] else: continue if channel.get_config_param(k) != value: channel.plugin_config[k] = value logger.info( 'the %s parameter of channel %s has been changed to %s by user %s', k, channel.name, value, current_user.log_name) if current_user.super_admin: channel.cache_activated = 'cache-activated' in form and form[ 'cache-activated'] == 'on' channel.cache_validity = int( form['cache-validity'] ) if 'cache-validity' in form and form[ 'cache-validity'] else channel.cache_validity channel.keep_noncomplying_capsules = 'keep-capsules' in form and form[ 'keep-capsules'] == 'on' channel.plugin_config = channel.plugin_config # Force SQLObject update try: self.plugin_manager.invalidate_cache( channel.plugin.name, channel.id) self.plugin_manager.get_plugin( channel.plugin.name).get_content(channel.id) except MisconfiguredParameters as e: for faulty_param in e: add_feedback(form.action, faulty_param[0], faulty_param) raise web.seeother('/channels/%d' % channel.id) except Exception as e: add_feedback(form.action, 'general_error', str(e)) raise web.seeother('/channels/%d' % channel.id) else: raise web.forbidden() form.name = channel.name except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') if channel: form.name = channel.name add_feedback(form.action, 'ok') except ImmediateFeedback: if channel is not None and channel.enabled: form.enabled = 'on' store_form(form) return self.render_page(current_user)
def POST(self): """ Handles plugin editing and activation. """ form = web.input() try: if form.action == 'check_dependencies': self.plugin_manager.check_all_plugins_dependencies() else: plugin_id = int(form.id) p = Plugin.get(plugin_id) current_user = User.get(self.session['user']['id']) if form.action == 'edit': state = 'yes' if 'state' in form and form.state == 'on' else 'no' try: form.name = p.name if p.activated == 'notfound': raise ImmediateFeedback( 'general', 'plugin_activate_not_found') p.set(activated=state) if p.activated == 'yes': if self.plugin_manager.instantiate_plugin( self.app, p): add_feedback('general', 'plugin_activated') else: raise ImmediateFeedback( 'general', 'plugin_activation_error') else: add_feedback('general', 'plugin_disabled') except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') elif form.action == 'configure': try: for param in p.params_access_rights: param.channel_contributor_read = form.get( param.name + '-cc-r') == 'on' param.channel_contributor_write = form.get( param.name + '-cc-w') == 'on' param.channel_administrator_read = form.get( param.name + '-ca-r') == 'on' param.channel_administrator_write = form.get( param.name + '-ca-w') == 'on' param.administrator_write = form.get( param.name + '-a-r') == 'on' param.administrator_write = form.get( param.name + '-a-w') == 'on' p.cache_activated_default = form.get( 'cache-activated') == 'on' if 'cache-validity' in form: p.cache_validity_default = int( form['cache-validity']) p.keep_noncomplying_capsules_default = form.get( 'keep-capsules') == 'on' form.name = p.name add_feedback('general', 'plugin_configured') except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') elif form.action == 'delete': if p.channels.count() > 0 and 'confirm-delete' not in form: raise ImmediateFeedback( form.action, 'plugin_has_channels', { 'plugin': p.to_dictionary([ 'id', 'name', 'channels_number', 'screens_number' ]), 'channels': [(c.id, c.name, c.enabled) for c in p.channels] }) plugin_name = p.name form.name = plugin_name p.destroySelf() logger.info('The plugin %s has been deleted by %s', plugin_name, current_user.log_name) add_feedback('general', 'plugin_deleted') except ImmediateFeedback: pass store_form(form) return self.render_page()
def post(self): """ Handles user creation, editing and deletion. """ form = self.form super_admin = form.get('super_admin', False) == 'on' admin = form.get('admin', False) == 'on' if super_admin: admin = False current_user = User.get(self.session['user']['id']) try: if form.action == 'create': username = form.username.strip() fullname = form.fullname.strip() form.email = form.email.strip() email = None if len(form.email) == 0 or not self.pattern.match( form.email) else form.email if email is None and len(form.email) != 0: raise ImmediateFeedback(form.action, 'invalid_email') if len(email) > User.sqlmeta.columns['email'].length: raise ImmediateFeedback(form.action, 'too_long_email') if len(username) > User.sqlmeta.columns['username'].length: raise ImmediateFeedback(form.action, 'too_long_username') if not username: username = None elif len(username) < 3: raise ImmediateFeedback(form.action, 'invalid_username') try: User(username=username, fullname=fullname, email=email, super_admin=super_admin, disabled=False) except DuplicateEntryError: u = User.selectBy(email=form.email).getOne(None) if u is not None: raise ImmediateFeedback(form.action, 'email_already_exists') u = User.selectBy(username=username).getOne(None) if u is not None: raise ImmediateFeedback(form.action, 'username_already_exists') elif form.action == 'edit': try: form.id = int(form.id) u = User.get(form.id) form.email = form.email.strip() email = None if len( form.email) == 0 or not self.pattern.match( form.email) else form.email form.username = u.username form.fullname = u.fullname if email is None and len(form.email) != 0: raise ImmediateFeedback(form.action, 'invalid_email') if email: try: u.email = email except DuplicateEntryError: raise ImmediateFeedback(form.action, 'email_already_exists') form.email = u.email if len(email) > User.sqlmeta.columns['email'].length: raise ImmediateFeedback(form.action, 'too_long_email') if not current_user.super_admin: if u.super_admin: resp.forbidden() else: if self.session['user']['id'] != form.id: u.set(super_admin=super_admin, admin=admin) except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') elif form.action == 'toggle-activation': if not current_user.super_admin: resp.forbidden() try: form.id = int(form.id) u = User.get(form.id) form.email = u.email u.disabled = not u.disabled add_feedback( form.action, 'activated' if not u.disabled else 'deactivated') except (SQLObjectNotFound, ValueError): raise ImmediateFeedback(form.action, 'invalid_id') add_feedback(form.action, 'ok') except ImmediateFeedback: pass store_form(form) resp.seeother('/users')
def render_page(self): current_user = User.get(self.session['user']['id']) return self.renderer.users(users=User.select(), current_user=current_user, show_reset_button='local' in self.config['authentication'])
def runTest(self): """ Tests the Channel SQLObject """ Channel.deleteMany(None) fake_plugin = Plugin(name='fake_plugin', activated='notfound') channel = Channel(name='Channel', subscription_right='public', secret='abcdef') plugin_channel = PluginChannel(name='Channel2', plugin=fake_plugin, subscription_right='public') bundle_channel = ChannelBundle(name='Channel3', subscription_right='public') building = Building(name='building') screen = Screen(name='Screen', building=building) user = User(fullname='User', email='test@localhost') user2 = User(fullname='User2', email='test2@localhost') # Test can_subscribe() def test_channel_subscription(c, u): def assert_subscription_no_perm(): assert c.can_subscribe(u) c.subscription_right = 'restricted' assert not c.can_subscribe(u) c.subscription_right = 'private' assert not c.can_subscribe(u) c.subscription_right = 'public' assert c.can_subscribe(u) def assert_subscription_admin(): assert c.can_subscribe(u) c.subscription_right = 'restricted' assert c.can_subscribe(u) c.subscription_right = 'private' assert c.can_subscribe(u) c.subscription_right = 'public' assert c.can_subscribe(u) def assert_subscription_super_admin(): assert c.can_subscribe(u) c.subscription_right = 'restricted' assert c.can_subscribe(u) c.subscription_right = 'private' assert c.can_subscribe(u) c.subscription_right = 'public' assert c.can_subscribe(u) assert_subscription_no_perm() user.admin = True assert_subscription_admin() user.admin = False user.super_admin = True assert_subscription_super_admin() user.super_admin = False test_channel_subscription(channel, user) test_channel_subscription(plugin_channel, user) test_channel_subscription(bundle_channel, user) # Test get_channels_authorized_subscribers_as_json() def test_channel_subscribers(c): def assert_no_users(): assert Channel.get_channels_authorized_subscribers_as_json( [c]) == '{"%d": []}' % c.id def assert_only_user(u): assert Channel.get_channels_authorized_subscribers_as_json( [c]) == '{"%d": [%d]}' % (c.id, u.id) def assert_users(*users): for u in json.loads( Channel.get_channels_authorized_subscribers_as_json( [c]))[str(c.id)]: assert u in [u.id for u in users] assert_no_users() c.safe_add_user(user) assert_only_user(user) # check that there is no duplicate c.safe_add_user(user) assert_only_user(user) c.removeUser(user) c.safe_add_user(user) assert_only_user(user) c.safe_add_user(user2) assert_users(user, user2) c.removeUser(user) assert_only_user(user2) c.removeUser(user2) assert_no_users() test_channel_subscribers(channel) test_channel_subscribers(plugin_channel) test_channel_subscribers(bundle_channel) # Test get_visible_channels_of() def test_visible_channels(u): def assert_no_channels(): assert Channel.get_visible_channels_of(u) == set() def assert_channel(c): assert Channel.get_visible_channels_of(u) == {c} def assert_all_channels(): assert Channel.get_visible_channels_of(u) == { channel, plugin_channel, bundle_channel } def assert_public_channels(): channel.subscription_right = 'restricted' assert Channel.get_visible_channels_of(u) == { plugin_channel, bundle_channel } channel.subscription_right = 'private' assert Channel.get_visible_channels_of(u) == { plugin_channel, bundle_channel } channel.subscription_right = 'public' assert_no_channels() u.admin = True assert_all_channels() u.admin = False assert_no_channels() u.super_admin = True assert_all_channels() u.super_admin = False assert_no_channels() screen.addUser(u) assert_public_channels() screen.removeUser(u) assert_no_channels() channel.subscription_right = 'restricted' assert_no_channels() channel.addUser(u) assert_channel(channel) screen.addUser(u) assert_all_channels() channel.removeUser(u) screen.removeUser(u) assert_no_channels() channel.subscription_right = 'public' plugin_channel.give_permission_to_user( u, UserPermissions.channel_contributor) assert_channel(plugin_channel) plugin_channel.give_permission_to_user( u, UserPermissions.channel_administrator) assert_channel(plugin_channel) plugin_channel.remove_permission_to_user(u) assert_no_channels() test_visible_channels(user) test_visible_channels(user2) # Test get_screens_channels_from() def test_screens_channels(u): def assert_no_channels(): assert set(Channel.get_screens_channels_from(u)) == set() def assert_channel(c): assert set(Channel.get_screens_channels_from(u)) == {c} def assert_channels(*channels): assert set( Channel.get_screens_channels_from(u)) == set(channels) def assert_all_channels(): assert set(Channel.get_screens_channels_from(u)) == { channel, plugin_channel, bundle_channel } assert_all_channels() channel.subscription_right = 'restricted' plugin_channel.subscription_right = 'restricted' bundle_channel.subscription_right = 'restricted' assert_no_channels() u.super_admin = True assert_all_channels() u.super_admin = False assert_no_channels() channel.addUser(u) assert_channel(channel) channel.removeUser(u) assert_no_channels() screen.addUser(user) screen.subscribe_to(user, channel) assert_channel(channel) screen.subscribe_to(user, bundle_channel) assert_channels(channel, bundle_channel) channel.subscription_right = 'public' plugin_channel.subscription_right = 'public' bundle_channel.subscription_right = 'public' test_screens_channels(user) # Test get_preview_link() assert channel.get_preview_link( ) == '/preview/channels/%d/abcdef' % channel.id
def GET(self, channel_id): channel = Channel.get(int(channel_id)) current_user = User.get(self.session['user']['id']) if channel in Channel.get_visible_channels_of(current_user): return self.render_page(channel) raise web.forbidden()
def GET(self): # TODO: Redirect if not using local authentication user = User.get(self.session['user']['id']) user.reset_secret = utils.generate_secret() logger.info('User %s requested a new password reset link', user.log_name) raise web.seeother(self.url_for(ResetPage, user.reset_secret))
def get(self): u = User.get(self.session['user']['id']) channels = Channel.select() return self.renderer.emails(user=u, channels=channels)
def post_auth(): if 'user' in app.session: User.get(id=app.session['user']['id']) app.session.pop('sidebar', None)
def runTest(self): """ Tests the User object """ try: User(username='******', fullname='test test', email='*****@*****.**', super_admin=True, disabled=False) except DuplicateEntryError: assert_true(False) b = User.selectBy(username="******").getOne() assert_not_equal(b, None) assert_equal(b.username, "test") try: b.set(username="******") except DuplicateEntryError: assert_true(False) assert_equal(b.username, "newName") b.set(username="******") l = b.get_subscriptions_of_owned_screens() assert_true(l.count() >= 0) una = User(username='******', fullname='testnoadmin test', email='*****@*****.**', super_admin=False, disabled=False) l = una.get_subscriptions_of_owned_screens() assert_true(l.count() >= 0) User.delete(una.id) b.set(disabled=True) assert_equal(b.disabled, True) t = b.owns_screen() assert_equal(t, False) b = User.selectBy(username="******").getOne() b.addScreen(Screen(name='A', building=Building(name='A'))) t = b.owns_screen() assert_equal(t, True) b = User.selectBy(username="******").getOne() t = User.delete(b.id) assert_equal(t, None) b = User.selectBy(username="******").getOne(None) assert_true(None == b)
def get(self): return self.renderer.home( homepage_description=self.config['homepage_description'], user_disabled=User.get(self.session['user']['id']).disabled)
def runTest(self): """ Tests the Channel object. """ try: PluginChannel(name='test', plugin=Plugin(name='channel_plugin', activated='no'), subscription_right='restricted') PluginChannel( name='test2', plugin=Plugin.selectBy(name='channel_plugin').getOne(), subscription_right='restricted') c = PluginChannel.selectBy(name="test").getOne() assert_not_equal(None, c) c.set(name="testNew") assert_equal(c.name, "testNew") u = User(username='******', fullname='test test', email='*****@*****.**', super_admin=True, disabled=False) up = UserPermissions.channel_contributor c.give_permission_to_user(u, up) role = Role.selectBy(user=u, channel=c).getOne(None) assert_true(role != None) c.give_permission_to_user(u, up) role = Role.selectBy(user=u, channel=c).getOne(None) assert_true(role != None) getup = c.get_channel_permissions_of(u) assert_equal(getup, up) getupnoperm = c.get_channel_permissions_of(User.get(1)) assert_equal(getupnoperm, UserPermissions.no_permission) c.remove_permission_to_user(u) role = Role.selectBy(user=u, channel=c).getOne(None) assert_true(role == None) assert_false(c.has_admin(u)) up = UserPermissions.channel_administrator c.give_permission_to_user(u, up) assert_true(c.has_admin(u)) assert_true(c.has_contrib(u)) assert_is_not_none(c.get_admins()) assert_is_not_none(c.get_contribs()) assert_in(str(u.id), c.get_users_as_json()) c.remove_permission_to_user(u) role = Role.selectBy(user=u, channel=c).getOne(None) assert_true(role == None) c.give_permission_to_user(None, up) role = Role.selectBy(user=u).getOne(None) assert_true(role == None) tru = c.has_visible_params_for(u) assert_true(tru) u3 = User(username='******', fullname='test3 test2', email='*****@*****.**', super_admin=False, disabled=False) tru = c.has_visible_params_for(u3) assert_false(tru) t = PluginChannel.delete(c.id) assert_equal(t, None) # try to delete a channel used by a screen - Seems to work... sc = Screen(name='A', building=Building(name='A')) sc.subscribe_to(u, PluginChannel.get(2)) # t2 = PluginChannel.delete(2) c4 = PluginChannel.get(2) nbSub = c4.subscriptions.count() c4.set(enabled=False) assert_equal(nbSub, c4.subscriptions.count()) c4.set(enabled=True) c4.set(subscription_right="private") assert_equal(nbSub, c4.subscriptions.count()) c4.set(subscription_right="public") # todo seems working by bypassing the webinterface c4.set(cache_validity=-10) assert_true(c4.cache_validity < 0) sc.unsubscribe_from(u, PluginChannel.get(2)) u2 = User(username='******', fullname='test2 test2', email='*****@*****.**', super_admin=False, disabled=False) l = PluginChannel.get_screens_channels_from(u2) assert_is_not_none(l) temp = PluginChannel.get_visible_channels_of(u2) assert_is_not_none(temp) User.delete(u.id) User.delete(u2.id) User.delete(u3.id) except DuplicateEntryError: assert_true(False) return
def local_login(self): self.testApp.get('/login') self.testApp.get('/reset', status=303) u = User.get(1) r = self.testApp.get('/reset/' + u.reset_secret, status=200) assert_not_equal(r.body, None)
def get_app(config_path, sessions_path=""): """ Returns the web.py main application of ICTV. Currently, only one application can be run a time due to how data such as assets, database, config files or plugins is stored. """ # Loads ICTV core config file config_file = get_config(config_path) if database.database_path is None: database.database_path = config_file['database_uri'] app_urls = urls if config_file['debug']['dummy_login']: app_urls += ('/login/(.+)', 'ictv.pages.utils.DummyLogin') if config_file['debug']['debug_env']: app_urls += ('/debug_env', 'DebugEnv') if 'local' in config_file['authentication']: app_urls += ( '/login', 'ictv.pages.local_login.LoginPage', '/reset', 'ictv.pages.local_login.GetResetLink', '/reset/(.+)', 'ictv.pages.local_login.ResetPage', '/logout', 'ictv.pages.utils.LogoutPage', ) if 'saml2' in config_file['authentication']: app_urls += ( '/shibboleth', 'ictv.pages.shibboleth.Shibboleth', '/shibboleth_metadata', 'ictv.pages.shibboleth.MetadataPage', ) # Create a base web.py application app = web.application(app_urls, globals()) app.config = config_file app.version = ictv.common.__version__ with open(os.path.join(get_root_path(), 'info' + os.extsep + 'yaml')) as f: # Loads ICTV user info texts info_texts = yaml.load(f) # Load the SMTP config into web.py smtp_conf = app.config.get('smtp', None) if smtp_conf: web.config.smtp_sendername = smtp_conf['sender_name'] web.config.smtp_server = smtp_conf['host'] web.config.smtp_port = smtp_conf['port'] web.config.smtp_username = smtp_conf.get('username', '') web.config.smtp_password = smtp_conf.get('password', '') web.config.smtp_starttls = smtp_conf.get('starttls', False) # Create a persistent HTTP session storage for the app app.session = web.session.Session( app, OptimisticThreadSafeDisktore(os.path.join(sessions_path, 'sessions'))) # Populate the web.py templates globals template_globals = { 'session': app.session, 'get_feedbacks': get_feedbacks, 'get_next_feedbacks': get_next_feedbacks, 'pop_previous_form': pop_previous_form, 'UserPermissions': UserPermissions, 'json': json, 'str': str, 'sorted': sorted, 'hasattr': hasattr, 'sidebar_collapse': False, 'show_header': True, 'show_footer': True, 're': re, 'info': info_texts, 'make_tooltip': make_tooltip, 'make_alert': make_alert, 'escape': html.escape, 'show_reset_password': '******' in app.config['authentication'], 'homedomain': lambda: web.ctx.homedomain, 'generate_secret': generate_secret, 'version': lambda: app.version, 'pretty_print_size': pretty_print_size, 'timesince': timesince, 'User': User, 'get_user': lambda: User.get(app.session['user']['id']) } # Init the web.py renderer used for the admin interface template_kwargs = { 'loc': os.path.join(get_root_path(), 'templates/'), 'cache': not app.config['debug']['debug_on_error'], 'globals': template_globals } app.renderer = web.template.render(base='base', **template_kwargs) # Init a second web.py renderer without any base template app.standalone_renderer = web.template.render(**template_kwargs) # Init loggers load_loggers_stats() # Determine logging level and user feedback when an internal error occurs based on ICTV core config level = logging.INFO if app.config['debug']['debug_on_error']: level = logging.DEBUG app.internalerror = web.debugerror loggers_to_init = [ 'app', 'pages', 'screens', 'plugin_manager', 'storage_manager', 'local_login', 'database', 'transcoding_queue' ] for logger_name in loggers_to_init: init_logger(logger_name, level, rotation_interval=app.config['logs']['rotation_interval'], backup_count=app.config['logs']['backup_count']) # Init the renderer used for slide, capsule, channel and screen rendering app.ictv_renderer = ICTVRenderer(app) # Init the plugin manager, used as a gateway between ICTV core and its plugins. app.plugin_manager = PluginManager(app) # Init the download manager, a download queue which asynchronously downloads assets from the network app.download_manager = DownloadManager() # Init the cleanup manager which will regularly cleanup unused cached assets app.cleanup_scheduler = CleanupScheduler() app.cleanup_scheduler.start() # Init the video transcoding queue which will convert videos to WebM format using FFmpeg app.transcoding_queue = TranscodingQueue() # Add an hook to make session available through web.ctx for plugin webapps def session_hook(): web.ctx.session = app.session web.template.Template.globals['session'] = app.session app.add_processor(web.loadhook(session_hook)) # Add a preprocessor to populate web.ctx with meaningful values when app is run behind a proxy app.add_processor(proxy_web_ctx_processor) # Add a preprocessor to encapsulate every SQL requests in a transaction on a per HTTP request basis app.add_processor( get_request_errors_preprocessor(logging.getLogger('database'), logging.getLogger('pages'))) # Add an general authentication processor to handle user authentication app.add_processor(get_authentication_processor(app)) # Add a hook to clean feedbacks from the previous request and prepare next feedbacks to be shown to the user app.add_processor(web.unloadhook(rotate_feedbacks)) # Instantiate plugins through the plugin manager app.plugin_manager.instantiate_plugins(app) # Load themes and templates into database sqlhub.doInTransaction(load_templates_and_themes) return app