class AbstractCard_v6(SQLObject):
    """Table used to upgrade AbstractCard from v6"""
    class sqlmeta:
        """meta class used to set the correct table"""
        table = AbstractCard.sqlmeta.table
        cacheValues = False

    canonicalName = UnicodeCol(alternateID=True, length=MAX_ID_LENGTH)
    name = UnicodeCol()
    text = UnicodeCol()
    search_text = UnicodeCol(default="")
    group = IntCol(default=None, dbName='grp')
    capacity = IntCol(default=None)
    cost = IntCol(default=None)
    life = IntCol(default=None)
    costtype = EnumCol(enumValues=['pool', 'blood', 'conviction', None],
                       default=None)
    level = EnumCol(enumValues=['advanced', None], default=None)

    # Most of these names are singular when they should be plural
    # since they refer to lists. We've decided to live with the
    # inconsistency for old columns but do the right thing for new
    # ones.
    discipline = RelatedJoin('DisciplinePair',
                             intermediateTable='abs_discipline_pair_map',
                             createRelatedTable=False)
    rarity = RelatedJoin('RarityPair',
                         intermediateTable='abs_rarity_pair_map',
                         createRelatedTable=False)
    clan = RelatedJoin('Clan',
                       intermediateTable='abs_clan_map',
                       createRelatedTable=False)
    cardtype = RelatedJoin('CardType',
                           intermediateTable='abs_type_map',
                           createRelatedTable=False)
    sect = RelatedJoin('Sect',
                       intermediateTable='abs_sect_map',
                       createRelatedTable=False)
    title = RelatedJoin('Title',
                        intermediateTable='abs_title_map',
                        createRelatedTable=False)
    creed = RelatedJoin('Creed',
                        intermediateTable='abs_creed_map',
                        createRelatedTable=False)
    virtue = RelatedJoin('Virtue',
                         intermediateTable='abs_virtue_map',
                         createRelatedTable=False)
    rulings = RelatedJoin('Ruling',
                          intermediateTable='abs_ruling_map',
                          createRelatedTable=False)
    artists = RelatedJoin('Artist',
                          intermediateTable='abs_artist_map',
                          createRelatedTable=False)
    keywords = RelatedJoin('Keyword',
                           intermediateTable='abs_keyword_map',
                           createRelatedTable=False)

    physicalCards = MultipleJoin('PhysicalCard')
Exemple #2
0
class Task(SQLObject):
    title = UnicodeCol()
    creationDate = DateTimeCol(notNone=True)
    dueDate = DateTimeCol(default=None)
    doneDate = DateTimeCol(default=None)
    description = UnicodeCol(default="", notNone=True)
    urgency = IntCol(default=0, notNone=True)
    status = EnumCol(enumValues=['new', 'started', 'done'])
    project = ForeignKey("Project")
    keywords = RelatedJoin("Keyword",
                           createRelatedTable=False,
                           intermediateTable="task_keyword",
                           joinColumn="task_id",
                           otherColumn="keyword_id")
    recurrence = ForeignKey("Recurrence", default=None)

    def setKeywordDict(self, dct):
        """
        Defines keywords of a task.
        Dict is of the form: keywordName => value
        """
        for taskKeyword in TaskKeyword.selectBy(task=self):
            taskKeyword.destroySelf()

        for name, value in dct.items():
            keyword = Keyword.selectBy(name=name)[0]
            TaskKeyword(task=self, keyword=keyword, value=value)

    def getKeywordDict(self):
        """
        Returns all keywords of a task as a dict of the form:
        keywordName => value
        """
        dct = {}
        for keyword in TaskKeyword.selectBy(task=self):
            dct[keyword.keyword.name] = keyword.value
        return dct

    def getKeywordsAsString(self):
        """
        Returns all keywords as a string like "key1=value1, key2=value2..."
        """
        return ", ".join(
            list(("%s=%s" % k for k in self.getKeywordDict().items())))

    def getUserKeywordsNameAsString(self):
        """
        Returns all keywords keys as a string like "key1, key2, key3...".
        Internal keywords (starting with _) are ignored.
        """
        keywords = [
            k for k in self.getKeywordDict().keys() if not k.startswith("_")
        ]
        keywords.sort()
        if keywords:
            return ", ".join(keywords)
        else:
            return ""
class DisciplinePair(SQLObject):

    tableversion = 1
    discipline = ForeignKey('Discipline')
    level = EnumCol(enumValues=['inferior', 'superior'])
    disciplineLevelIndex = DatabaseIndex(discipline, level, unique=True)
    cards = RelatedJoin('SutekhAbstractCard',
                        intermediateTable='abs_discipline_pair_map',
                        otherColumn="abstract_card_id",
                        createRelatedTable=False)
class SutekhAbstractCard(AbstractCard):
    """The abstract card specialised to the needs of VtES."""

    _inheritable = False
    tableversion = 1

    search_text = UnicodeCol(default="")
    group = IntCol(default=None, dbName='grp')
    capacity = IntCol(default=None)
    cost = IntCol(default=None)
    life = IntCol(default=None)
    costtype = EnumCol(enumValues=['pool', 'blood', 'conviction', None],
                       default=None)
    level = EnumCol(enumValues=['advanced', None], default=None)

    # Most of these names are singular when they should be plural
    # since they refer to lists. We've decided to live with the
    # inconsistency for old columns but do the right thing for new
    # ones.
    discipline = CachedRelatedJoin('DisciplinePair',
                                   intermediateTable='abs_discipline_pair_map',
                                   joinColumn="abstract_card_id",
                                   createRelatedTable=False)
    clan = CachedRelatedJoin('Clan',
                             joinColumn="abstract_card_id",
                             intermediateTable='abs_clan_map',
                             createRelatedTable=False)
    sect = CachedRelatedJoin('Sect',
                             intermediateTable='abs_sect_map',
                             joinColumn="abstract_card_id",
                             createRelatedTable=False)
    title = CachedRelatedJoin('Title',
                              intermediateTable='abs_title_map',
                              joinColumn="abstract_card_id",
                              createRelatedTable=False)
    creed = CachedRelatedJoin('Creed',
                              intermediateTable='abs_creed_map',
                              joinColumn="abstract_card_id",
                              createRelatedTable=False)
    virtue = CachedRelatedJoin('Virtue',
                               intermediateTable='abs_virtue_map',
                               joinColumn="abstract_card_id",
                               createRelatedTable=False)
Exemple #5
0
class Role(ICTVObject):
    role_id = DatabaseIndex('user', 'channel', unique=True)
    user = ForeignKey('User', cascade=True)
    channel = ForeignKey('PluginChannel', cascade=True)
    permission_level = EnumCol(
        enumValues=['channel_contributor', 'channel_administrator'])

    def _get_permission_level(self):
        """ Magic method to hide enums from SQLObject into a more elegant abstraction. """
        return UserPermissions[self._SO_get_permission_level()]

    def _set_permission_level(self, value):
        """ Magic method to hide enums from SQLObject into a more elegant abstraction. """
        self._SO_set_permission_level(
            UserPermissions.get_permission_string(value))
class Dataset(SQLObject):
    class sqlmeta:
        table = 'wh_dataset'

    whitehall_id = IntCol(alternateID=True)
    stats_type = EnumCol(enumValues=[
        'Official Statistics', 'National Statistics', 'Statistical data set',
        None
    ],
                         default=None)
    title = StringCol()
    url = StringCol(alternateID=True, length=255)
    orgs = RelatedJoin('Organisation')
    publication_date = DateTimeCol()
    government_name = StringCol()
    collections = RelatedJoin('Collection')
Exemple #7
0
class Plugin(ICTVObject):
    name = StringCol(notNone=True, alternateID=True)
    description = StringCol(default=None)
    version = IntCol(notNone=True, default=0)
    activated = EnumCol(notNone=True, enumValues=['yes', 'no', 'notfound'])
    webapp = BoolCol(notNone=True, default=False)
    static = BoolCol(notNone=True, default=False)
    channels_params = JSONCol(
        notNone=True, default={}
    )  # The type and default param's values needed by every plugin instance
    channels = SQLMultipleJoin('PluginChannel')
    params_access_rights = SQLMultipleJoin('PluginParamAccessRights')
    cache_activated_default = BoolCol(default=True)
    cache_validity_default = IntCol(default=60)
    keep_noncomplying_capsules_default = BoolCol(default=False)

    def _get_channels_number(self):
        """ Return the number of channels instantiated with this plugin. """
        return self.channels.count()

    def _get_screens_number(self):
        """ Return the number of screens that are subscribed to channels of this plugin. """
        plugin_channels = PluginChannel.select().filter(
            PluginChannel.q.plugin == self)
        screens = set(plugin_channels.throughTo.subscriptions.throughTo.screen.
                      distinct())
        bundles = set(c for c in ChannelBundle.select()
                      if any(bc.plugin == self for bc in c.flatten()))
        for b in bundles:
            screens |= set(Subscription.select().filter(
                Subscription.q.channel == b).throughTo.screen.distinct())
        return len(screens)

    def _get_package_path(self):
        """ Returns the path to the package of this plugin. """
        try:
            m = importlib.import_module('ictv.plugins.' + self.name)
            return m.__path__[0]
        except ImportError:
            return None

    @classmethod
    def update_plugins(cls, dirs):
        """
        Takes the list of the plugins directories located in ictv/plugins and updates
        the database if they're not in db
        :param dirs: The directory listing of ictv/plugins
        :return: the list of plugins present in updated database
        """
        s = set()
        plugins_list = []
        for p in Plugin.select():
            s.add(p.name)
            if p.name not in dirs:
                # Plugin exists in database but was not found in the plugins directory
                p.activated = 'notfound'
            else:
                path = os.path.join(p.package_path, 'config.yaml')
                if os.path.isfile(path):
                    # Plugin is considered to be found
                    if p.activated == 'notfound':
                        p.activated = 'no'
                    with open(path, 'r') as f:
                        config = yaml.load(f,
                                           Loader=yamlordereddictloader.Loader)
                        p.webapp = config['plugin']['webapp']
                        p.static = config['plugin']['static']
                        p.description = config['plugin'].get(
                            'description', None)
                        if 'channels_params' in config:
                            # The plugin has channel specific parameters that can be changed from channel to channel
                            order = 0
                            for k, v in config['channels_params'].items():
                                p.channels_params[
                                    k] = v  # Sets the parameter to its default value
                                if 'order' not in p.channels_params[k]:
                                    p.channels_params[k]['order'] = order
                                    order += 1
                                if PluginParamAccessRights.selectBy(
                                        plugin=p, name=k).getOne(None) is None:
                                    PluginParamAccessRights(plugin=p, name=k)
                            for k in list(p.channels_params):
                                if k not in config['channels_params'].keys():
                                    p.channels_params.pop(k)
                                    PluginParamAccessRights.deleteBy(plugin=p,
                                                                     name=k)

                            p.channels_params = p.channels_params  # Force SQLObject update
                else:
                    p.activated = 'notfound'

            plugins_list.append(p)
        for p in dirs:
            if p not in s:
                # Plugin was not in database, it should be added but not activated
                plugins_list.append(Plugin(name=p, activated='no'))
        return plugins_list
Exemple #8
0
class Channel(InheritableSQLObject):
    name = StringCol(notNone=True, unique=True)
    description = StringCol(default=None)
    enabled = BoolCol(notNone=True, default=True)
    subscription_right = EnumCol(enumValues=['public', 'restricted', 'private'])
    authorized_subscribers = SQLRelatedJoin('User')
    secret = StringCol(notNone=True, default=lambda: utils.generate_secret())
    subscriptions = SQLMultipleJoin('Subscription')
    bundles = SQLRelatedJoin('ChannelBundle')

    def can_subscribe(self, user):
        """ Return whether this user has sufficient permission to be able to subscribe to this channel or not. """
        return self.subscription_right == 'public' or UserPermissions.administrator in user.highest_permission_level or user in self.authorized_subscribers

    def safe_add_user(self, user):
        """ Avoid user duplication in channel authorized subscribers. """
        if user not in self.authorized_subscribers:
            self.addUser(user)

    @classmethod
    def get_channels_authorized_subscribers_as_json(cls, channels):
        """
            Return the string representation of a dictionary in the form
                {
                    channel.id:
                    [
                        user.id,
                        ...
                    ]
                }
        """
        channels_authorized_subscribers = {}
        for channel in channels:
            channels_authorized_subscribers[channel.id] = [u.id for u in channel.authorized_subscribers]
        return json.dumps(channels_authorized_subscribers)

    @classmethod
    def get_visible_channels_of(cls, user):
        """
            Returns the channels that are accessible for the user (public channels or channels
            with the user specified in authorized_subscribers, or all channels if the user is superadmin)
            :param user: The user to retrieve the accessible channels.
            :return: A iterable with the accessible channels (iterable of sqlobjects)
        """
        if UserPermissions.administrator in user.highest_permission_level:
            return set(Channel.select())
        public_channels = set(Channel.selectBy(subscription_right='public')) if UserPermissions.screen_administrator in \
                                                                                user.highest_permission_level else set()
        return public_channels | set(Role.selectBy(user=user).throughTo.channel) | set(
            User.selectBy(id=user.id).throughTo.authorized_channels)

    @classmethod
    def get_screens_channels_from(cls, user):
        """
            Return the intersection between 3 sets of channels: all the public channels,
            all the channel this user is authorized to subscribe
            and all the channel the screens this user has access are subscribed to.
            The resulting data type is a set of Channel instances.
        """
        if user.super_admin:
            return set(Channel.select())
        return set(c for c in Channel.selectBy(subscription_right='public')) | \
               set(c for c in user.authorized_channels) | \
               set(c for c in user.screens.throughTo.subscriptions.throughTo.channel)

    def get_preview_link(self):
        """ Returns the secret preview link of this channel. """
        return '/preview/channels/' + str(self.id) + '/' + self.secret

    @abstractmethod
    def flatten(self, keep_disabled_channels=False):
        """ Returns all the channels contained in this channel and the channels it contains as an Iterable[Channel]"""

    @abstractmethod
    def get_type_name(self):
        """ Returns a string representing the name of the subtype to be used in the UI for this class. """
Exemple #9
0
class Enum1(SQLObject):

    cl = EnumCol(enumValues=['a', 'bcd', 'e'])
Exemple #10
0
class EnumUnicode(SQLObject):

    n = UnicodeCol()
    cl = EnumCol(enumValues=['a', 'b'])
Exemple #11
0
class EnumWithDefaultOther(SQLObject):

    cl = EnumCol(enumValues=['a', 'bcd', 'e', None], default='a')
Exemple #12
0
class EnumWithNone(SQLObject):

    cl = EnumCol(enumValues=['a', 'bcd', 'e', None])
Exemple #13
0
class EnumWithDefaultNone(SQLObject):

    l = EnumCol(enumValues=['a', 'bcd', 'e', None], default=None)
Exemple #14
0
class Screen(ICTVObject):
    name = StringCol(notNone=True)
    building = ForeignKey('Building', notNone=True, cascade=False)
    location = StringCol(default=None)  # A free text field to precise the screen location
    screen_id = DatabaseIndex('name', 'building', unique=True)
    owners = SQLRelatedJoin('User')
    subscriptions = SQLMultipleJoin('Subscription')
    secret = StringCol(notNone=True, default=utils.generate_secret)
    macs = SQLMultipleJoin('ScreenMac')
    last_ip = StringCol(default=None)
    last_access = DateTimeCol(default=None)
    shuffle = BoolCol(default=False)
    comment = StringCol(default=None)
    show_postit = BoolCol(default=False)
    show_slide_number = BoolCol(default=False)
    orientation = EnumCol(enumValues=['Landscape','Portrait'],default='Landscape')

    @property
    def subscribed_channels(self):
        return self.subscriptions.throughTo.channel

    def subscribe_to(self, user, channel, weight=1):
        """
        Subscribes this screen to the channel. If this screen is already subscribed to the channel by the user, it changes the weight if needed.

        :param user: The user requesting the subscription.
        :param channel: The channel to subscribe this screen to.
        :param weight: The optional positive non null weight to give to the channel by this screen.
        :return: None
        """
        if weight > 0:
            sub = Subscription.selectBy(screen=self, channel=channel).getOne(None)
            if sub is not None:
                if sub.weight != weight:
                    sub.weight = weight
                if sub.created_by != user:
                    sub.created_by = user
            else:
                Subscription(screen=self, channel=channel, weight=weight, created_by=user)

    def unsubscribe_from(self, user, channel):
        """
        Deletes the user's subscription from this screen to the channel if one exists, otherwise do nothing.

        :param user: The user requesting the subscription deletion.
        :param channel: The channel to unsubscribe this screen from.
        :return: None
        """
        sub = Subscription.selectBy(screen=self, channel=channel).getOne(None)
        # TODO: Commit this to user history
        if sub is not None:
            sub.destroySelf()

    def is_subscribed_to(self, channel):
        return channel in self.subscriptions.throughTo.channel

    @classmethod
    def get_visible_screens_of(cls, user):
        """
        Returns the screens that are managed by the user (or all screens for the superadmin)

        :param user: The user to retrieve the managed screens.
        :return: A iterable with the managed screens (iterable of sqlobjects)
        """
        if UserPermissions.administrator in user.highest_permission_level:
            return Screen.select()
        return user.screens

    def safe_add_user(self, user):
        """ Avoid user duplication in screen owners. """
        if user not in self.owners:
            self.addUser(user)

    def get_view_link(self):
        """ Returns a relative URL to the screen rendered view. """
        return '/screens/%d/view/%s' % (self.id, self.secret)

    def get_client_link(self):
        """ Returns a relative URL to web-based client for this screen. """
        return '/screens/%d/client/%s' % (self.id, self.secret)

    def get_macs_string(self):
        return ';'.join(mac.get_pretty_mac() for mac in self.macs)

    def get_channels_content(self, app):
        """ 
            Returns all the capsules provided by the channels of this screen as an Iterable[PluginCapsule] 
            ignoring channel duplicates
        """
        screen_capsules_iterables = []
        already_added_channels = set()
        plugin_manager = app.plugin_manager

        def add_content(channel):
            for c in channel.flatten():
                # do not add duplicates
                if c.id not in already_added_channels:
                    screen_capsules_iterables.append(plugin_manager.get_plugin_content(c))
                    already_added_channels.add(c.id)
        for sub in self.subscriptions:
            add_content(sub.channel)
        screen_capsules = list(itertools.chain.from_iterable(screen_capsules_iterables))
        if self.shuffle:
            random.shuffle(screen_capsules)
        return screen_capsules