Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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]
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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)
Ejemplo n.º 5
0
    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
        ]
Ejemplo n.º 6
0
    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()
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
 def POST(self, status):
     User.get(self.session['user']['id']).has_toured = status == 'ended'
     raise web.seeother(web.ctx.env.get('HTTP_REFERER', '/'))
Ejemplo n.º 9
0
 def render_page(self):
     current_user = User.get(self.session['user']['id'])
     return self.renderer.buildings(buildings=Building.select(), current_user=current_user)
Ejemplo n.º 10
0
    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()
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
    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()
Ejemplo n.º 13
0
    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')
Ejemplo n.º 14
0
 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'])
Ejemplo n.º 15
0
    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
Ejemplo n.º 16
0
 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()
Ejemplo n.º 17
0
 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))
Ejemplo n.º 18
0
 def get(self):
     u = User.get(self.session['user']['id'])
     channels = Channel.select()
     return self.renderer.emails(user=u, channels=channels)
Ejemplo n.º 19
0
 def post_auth():
     if 'user' in app.session:
         User.get(id=app.session['user']['id'])
         app.session.pop('sidebar', None)
Ejemplo n.º 20
0
    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)
Ejemplo n.º 21
0
 def get(self):
     return self.renderer.home(
         homepage_description=self.config['homepage_description'],
         user_disabled=User.get(self.session['user']['id']).disabled)
Ejemplo n.º 22
0
    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
Ejemplo n.º 23
0
 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)
Ejemplo n.º 24
0
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