コード例 #1
0
 def __auto_table_args(cls):
     uniques = ()
     if cls.unique_columns:
         uniques = [db.Index('ix_uq_{}_user'.format(cls.__tablename__), 'user_id', *cls.unique_columns, unique=True,
                             postgresql_where=db.text('type = {}'.format(PrincipalType.user))),
                    db.Index('ix_uq_{}_local_group'.format(cls.__tablename__), 'local_group_id', *cls.unique_columns,
                             unique=True, postgresql_where=db.text('type = {}'.format(PrincipalType.local_group))),
                    db.Index('ix_uq_{}_mp_group'.format(cls.__tablename__), 'mp_group_provider', 'mp_group_name',
                             *cls.unique_columns, unique=True,
                             postgresql_where=db.text('type = {}'.format(PrincipalType.multipass_group)))]
         if cls.allow_emails:
             uniques.append(db.Index('ix_uq_{}_email'.format(cls.__tablename__), 'email', *cls.unique_columns,
                                     unique=True, postgresql_where=db.text('type = {}'.format(PrincipalType.email))))
     indexes = [db.Index(None, 'mp_group_provider', 'mp_group_name')]
     checks = [_make_check(PrincipalType.user, cls.allow_emails, cls.allow_networks, cls.allow_event_roles,
                           'user_id'),
               _make_check(PrincipalType.local_group, cls.allow_emails, cls.allow_networks, cls.allow_event_roles,
                           'local_group_id'),
               _make_check(PrincipalType.multipass_group, cls.allow_emails, cls.allow_networks,
                           cls.allow_event_roles, 'mp_group_provider', 'mp_group_name')]
     if cls.allow_emails:
         checks.append(_make_check(PrincipalType.email, cls.allow_emails, cls.allow_networks, cls.allow_event_roles,
                                   'email'))
         checks.append(db.CheckConstraint('email IS NULL OR email = lower(email)', 'lowercase_email'))
     if cls.allow_networks:
         checks.append(_make_check(PrincipalType.network, cls.allow_emails, cls.allow_networks,
                                   cls.allow_event_roles, 'ip_network_group_id'))
     if cls.allow_event_roles:
         checks.append(_make_check(PrincipalType.event_role, cls.allow_emails, cls.allow_networks,
                                   cls.allow_event_roles, 'event_role_id'))
     return tuple(uniques + indexes + checks)
コード例 #2
0
ファイル: principals.py プロジェクト: bkolobara/indico
 def __auto_table_args(cls):
     uniques = ()
     if cls.unique_columns:
         uniques = [db.Index('ix_uq_{}_user'.format(cls.__tablename__), 'user_id', *cls.unique_columns, unique=True,
                             postgresql_where=db.text('type = {}'.format(PrincipalType.user))),
                    db.Index('ix_uq_{}_local_group'.format(cls.__tablename__), 'local_group_id', *cls.unique_columns,
                             unique=True, postgresql_where=db.text('type = {}'.format(PrincipalType.local_group))),
                    db.Index('ix_uq_{}_mp_group'.format(cls.__tablename__), 'mp_group_provider', 'mp_group_name',
                             *cls.unique_columns, unique=True,
                             postgresql_where=db.text('type = {}'.format(PrincipalType.multipass_group)))]
         if cls.allow_emails:
             uniques.append(db.Index('ix_uq_{}_email'.format(cls.__tablename__), 'email', *cls.unique_columns,
                                     unique=True, postgresql_where=db.text('type = {}'.format(PrincipalType.email))))
     indexes = [db.Index(None, 'mp_group_provider', 'mp_group_name')]
     checks = [_make_check(PrincipalType.user, cls.allow_emails, cls.allow_networks, cls.allow_event_roles,
                           'user_id'),
               _make_check(PrincipalType.local_group, cls.allow_emails, cls.allow_networks, cls.allow_event_roles,
                           'local_group_id'),
               _make_check(PrincipalType.multipass_group, cls.allow_emails, cls.allow_networks,
                           cls.allow_event_roles, 'mp_group_provider', 'mp_group_name')]
     if cls.allow_emails:
         checks.append(_make_check(PrincipalType.email, cls.allow_emails, cls.allow_networks, cls.allow_event_roles,
                                   'email'))
         checks.append(db.CheckConstraint('email IS NULL OR email = lower(email)', 'lowercase_email'))
     if cls.allow_networks:
         checks.append(_make_check(PrincipalType.network, cls.allow_emails, cls.allow_networks,
                                   cls.allow_event_roles, 'ip_network_group_id'))
     if cls.allow_event_roles:
         checks.append(_make_check(PrincipalType.event_role, cls.allow_emails, cls.allow_networks,
                                   cls.allow_event_roles, 'event_role_id'))
     return tuple(uniques + indexes + checks)
コード例 #3
0
ファイル: events.py プロジェクト: harshdchandel/indico
 def __auto_table_args(cls):
     return (
         db.Index('ix_events_start_dt_desc', cls.start_dt.desc()),
         db.Index('ix_events_end_dt_desc', cls.end_dt.desc()),
         db.Index('ix_events_not_deleted_category', cls.is_deleted,
                  cls.category_id),
         db.Index('ix_events_not_deleted_category_dates', cls.is_deleted,
                  cls.category_id, cls.start_dt, cls.end_dt),
         db.Index('ix_uq_events_url_shortcut',
                  db.func.lower(cls.url_shortcut),
                  unique=True,
                  postgresql_where=db.text('NOT is_deleted')),
         db.CheckConstraint("category_id IS NOT NULL OR is_deleted",
                            'category_data_set'),
         db.CheckConstraint(
             "(logo IS NULL) = (logo_metadata::text = 'null')",
             'valid_logo'),
         db.CheckConstraint(
             "(stylesheet IS NULL) = (stylesheet_metadata::text = 'null')",
             'valid_stylesheet'),
         db.CheckConstraint("end_dt >= start_dt", 'valid_dates'),
         db.CheckConstraint("url_shortcut != ''", 'url_shortcut_not_empty'),
         db.CheckConstraint("cloned_from_id != id", 'not_cloned_from_self'),
         db.CheckConstraint('visibility IS NULL OR visibility >= 0',
                            'valid_visibility'), {
                                'schema': 'events'
                            })
コード例 #4
0
ファイル: cli.py プロジェクト: marcosmolla/indico
    def check_plugin_schema(self, name):
        """Checks if a plugin schema exists in the database.

        :param name: Name of the plugin
        """
        sql = 'SELECT COUNT(*) FROM "information_schema"."schemata" WHERE "schema_name" = :name'
        count = db.engine.execute(db.text(sql), name='plugin_{}'.format(name)).scalar()
        if not count:
            print cformat('%{red!}Plugin schema does not exist%{reset}')
            print cformat('Run %{yellow!}indico plugindb upgrade --plugin {}%{reset} to create it').format(name)
            return False
        return True
コード例 #5
0
ファイル: cli.py プロジェクト: marcosmolla/indico
    def check_plugin_schema(self, name):
        """Checks if a plugin schema exists in the database.

        :param name: Name of the plugin
        """
        sql = 'SELECT COUNT(*) FROM "information_schema"."schemata" WHERE "schema_name" = :name'
        count = db.engine.execute(db.text(sql),
                                  name='plugin_{}'.format(name)).scalar()
        if not count:
            print cformat('%{red!}Plugin schema does not exist%{reset}')
            print cformat(
                'Run %{yellow!}indico plugindb upgrade --plugin {}%{reset} to create it'
            ).format(name)
            return False
        return True
コード例 #6
0
ファイル: events.py プロジェクト: indico/indico
 def __auto_table_args(cls):
     return (db.Index('ix_events_start_dt_desc', cls.start_dt.desc()),
             db.Index('ix_events_end_dt_desc', cls.end_dt.desc()),
             db.Index('ix_events_not_deleted_category', cls.is_deleted, cls.category_id),
             db.Index('ix_events_not_deleted_category_dates',
                      cls.is_deleted, cls.category_id, cls.start_dt, cls.end_dt),
             db.Index('ix_uq_events_url_shortcut', db.func.lower(cls.url_shortcut), unique=True,
                      postgresql_where=db.text('NOT is_deleted')),
             db.CheckConstraint("category_id IS NOT NULL OR is_deleted", 'category_data_set'),
             db.CheckConstraint("(logo IS NULL) = (logo_metadata::text = 'null')", 'valid_logo'),
             db.CheckConstraint("(stylesheet IS NULL) = (stylesheet_metadata::text = 'null')",
                                'valid_stylesheet'),
             db.CheckConstraint("end_dt >= start_dt", 'valid_dates'),
             db.CheckConstraint("url_shortcut != ''", 'url_shortcut_not_empty'),
             db.CheckConstraint("cloned_from_id != id", 'not_cloned_from_self'),
             db.CheckConstraint('visibility IS NULL OR visibility >= 0', 'valid_visibility'),
             {'schema': 'events'})
コード例 #7
0
ファイル: persons.py プロジェクト: wasm-network/indico
class EventPerson(PersonMixin, db.Model):
    """A person inside an event, e.g. a speaker/author etc."""

    __tablename__ = 'persons'
    __table_args__ = (db.UniqueConstraint('event_id', 'user_id'),
                      db.CheckConstraint('email = lower(email)',
                                         'lowercase_email'),
                      db.Index(None,
                               'event_id',
                               'email',
                               unique=True,
                               postgresql_where=db.text("email != ''")), {
                                   'schema': 'events'
                               })

    id = db.Column(db.Integer, primary_key=True)
    event_id = db.Column(db.Integer,
                         db.ForeignKey('events.events.id'),
                         nullable=False,
                         index=True)
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.users.id'),
                        nullable=True,
                        index=True)
    first_name = db.Column(db.String, nullable=False, default='')
    last_name = db.Column(db.String, nullable=False)
    email = db.Column(db.String, nullable=False, index=True, default='')
    # the title of the user - you usually want the `title` property!
    _title = db.Column('title',
                       PyIntEnum(UserTitle),
                       nullable=False,
                       default=UserTitle.none)
    affiliation = db.Column(db.String, nullable=False, default='')
    address = db.Column(db.Text, nullable=False, default='')
    phone = db.Column(db.String, nullable=False, default='')
    invited_dt = db.Column(UTCDateTime, nullable=True)
    is_untrusted = db.Column(db.Boolean, nullable=False, default=False)

    event = db.relationship('Event',
                            lazy=True,
                            backref=db.backref('persons',
                                               cascade='all, delete-orphan',
                                               cascade_backrefs=False,
                                               lazy='dynamic'))
    user = db.relationship('User',
                           lazy=True,
                           backref=db.backref('event_persons',
                                              cascade_backrefs=False,
                                              lazy='dynamic'))

    # relationship backrefs:
    # - abstract_links (AbstractPersonLink.person)
    # - contribution_links (ContributionPersonLink.person)
    # - event_links (EventPersonLink.person)
    # - session_block_links (SessionBlockPersonLink.person)
    # - subcontribution_links (SubContributionPersonLink.person)

    @locator_property
    def locator(self):
        return dict(self.event.locator, person_id=self.id)

    @return_ascii
    def __repr__(self):
        return format_repr(self,
                           'id',
                           is_untrusted=False,
                           _text=self.full_name)

    @property
    def principal(self):
        if self.user is not None:
            return self.user
        elif self.email:
            return EmailPrincipal(self.email)
        return None

    @classmethod
    def create_from_user(cls, user, event=None, is_untrusted=False):
        return EventPerson(user=user,
                           event=event,
                           first_name=user.first_name,
                           last_name=user.last_name,
                           email=user.email,
                           affiliation=user.affiliation,
                           address=user.address,
                           phone=user.phone,
                           is_untrusted=is_untrusted)

    @classmethod
    def for_user(cls, user, event=None, is_untrusted=False):
        """Return EventPerson for a matching User in Event creating if needed"""
        person = event.persons.filter_by(user=user).first() if event else None
        return person or cls.create_from_user(
            user, event, is_untrusted=is_untrusted)

    @classmethod
    def merge_users(cls, target, source):
        """Merge the EventPersons of two users.

        :param target: The target user of the merge
        :param source: The user that is being merged into `target`
        """
        existing_persons = {ep.event_id: ep for ep in target.event_persons}
        for event_person in source.event_persons:
            existing = existing_persons.get(event_person.event_id)
            if existing is None:
                event_person.user = target
            else:
                existing.merge_person_info(event_person)
                db.session.delete(event_person)
        db.session.flush()

    @classmethod
    def link_user_by_email(cls, user):
        """
        Links all email-based persons matching the user's
        email addresses with the user.

        :param user: A User object.
        """
        from indico.modules.events.models.events import Event
        query = (cls.query.join(EventPerson.event).filter(
            ~Event.is_deleted, cls.email.in_(user.all_emails),
            cls.user_id.is_(None)))
        for event_person in query:
            existing = (cls.query.filter_by(
                user_id=user.id, event_id=event_person.event_id).one_or_none())
            if existing is None:
                event_person.user = user
            else:
                existing.merge_person_info(event_person)
                db.session.delete(event_person)
        db.session.flush()

    @no_autoflush
    def merge_person_info(self, other):
        from indico.modules.events.contributions.models.persons import AuthorType
        for column_name in {
                '_title', 'affiliation', 'address', 'phone', 'first_name',
                'last_name'
        }:
            value = getattr(self, column_name) or getattr(other, column_name)
            setattr(self, column_name, value)

        for event_link in other.event_links:
            existing_event_link = next(
                (link for link in self.event_links
                 if link.event_id == event_link.event_id), None)
            if existing_event_link is None:
                event_link.person = self
            else:
                other.event_links.remove(event_link)

        for abstract_link in other.abstract_links:
            existing_abstract_link = next(
                (link for link in self.abstract_links
                 if link.abstract_id == abstract_link.abstract_id), None)

            if existing_abstract_link is None:
                abstract_link.person = self
            else:
                existing_abstract_link.is_speaker |= abstract_link.is_speaker
                existing_abstract_link.author_type = AuthorType.get_highest(
                    existing_abstract_link.author_type,
                    abstract_link.author_type)
                other.abstract_links.remove(abstract_link)

        for contribution_link in other.contribution_links:
            existing_contribution_link = next(
                (link for link in self.contribution_links
                 if link.contribution_id == contribution_link.contribution_id),
                None)

            if existing_contribution_link is None:
                contribution_link.person = self
            else:
                existing_contribution_link.is_speaker |= contribution_link.is_speaker
                existing_contribution_link.author_type = AuthorType.get_highest(
                    existing_contribution_link.author_type,
                    contribution_link.author_type)
                other.contribution_links.remove(contribution_link)

        for subcontribution_link in other.subcontribution_links:
            existing_subcontribution_link = next(
                (link for link in self.subcontribution_links
                 if link.subcontribution_id ==
                 subcontribution_link.subcontribution_id), None)
            if existing_subcontribution_link is None:
                subcontribution_link.person = self
            else:
                other.subcontribution_links.remove(subcontribution_link)

        for session_block_link in other.session_block_links:
            existing_session_block_link = next(
                (link
                 for link in self.session_block_links if link.session_block_id
                 == session_block_link.session_block_id), None)
            if existing_session_block_link is None:
                session_block_link.person = self
            else:
                other.session_block_links.remove(session_block_link)

        db.session.flush()

    def has_role(self, role, obj):
        """Whether the person has a role in the ACL list of a given object"""
        principals = [
            x for x in obj.acl_entries
            if x.has_management_permission(role, explicit=True)
        ]
        return any(
            x for x in principals
            if ((self.user_id is not None and self.user_id == x.user_id) or (
                self.email is not None and self.email == x.email)))