Пример #1
0
def _merge_users(target, source, **kwargs):
    from indico.modules.attachments.models.attachments import Attachment, AttachmentFile
    from indico.modules.attachments.models.principals import AttachmentPrincipal, AttachmentFolderPrincipal
    Attachment.find(user_id=source.id).update({Attachment.user_id: target.id})
    AttachmentFile.find(user_id=source.id).update({AttachmentFile.user_id: target.id})
    AttachmentPrincipal.merge_users(target, source, 'attachment')
    AttachmentFolderPrincipal.merge_users(target, source, 'folder')
Пример #2
0
def _merge_users(target, source, **kwargs):
    from indico.modules.attachments.models.attachments import Attachment, AttachmentFile
    from indico.modules.attachments.models.principals import AttachmentPrincipal, AttachmentFolderPrincipal
    Attachment.find(user_id=source.id).update({Attachment.user_id: target.id})
    AttachmentFile.find(user_id=source.id).update({AttachmentFile.user_id: target.id})
    AttachmentPrincipal.merge_users(target, source, 'attachment')
    AttachmentFolderPrincipal.merge_users(target, source, 'folder')
Пример #3
0
 def update_merged_ids(self):
     self.print_step('updating merged users in attachment acls')
     for p in AttachmentPrincipal.find(User.merged_into_id != None, _join=AttachmentPrincipal.user):  # noqa
         user = p.user
         while p.user.merged_into_user:
             p.user = p.user.merged_into_user
         self.print_success(cformat('%{cyan}{}%{reset} -> %{cyan}{}%{reset}').format(user, p.user), always=True)
     self.print_step('updating merged users in folder acls')
     for p in AttachmentFolderPrincipal.find(User.merged_into_id != None,
                                             _join=AttachmentFolderPrincipal.user):  # noqa
         while p.user.merged_into_user:
             p.user = p.user.merged_into_user
         self.print_success(cformat('%{cyan}{}%{reset} -> %{cyan}{}%{reset}').format(user, p.user), always=True)
     db.session.commit()
Пример #4
0
 def update_merged_ids(self):
     self.print_step('updating merged users in attachment acls')
     for p in AttachmentPrincipal.find(User.merged_into_id != None, _join=AttachmentPrincipal.user):  # noqa
         user = p.user
         while p.user.merged_into_user:
             p.user = p.user.merged_into_user
         self.print_success(cformat('%{cyan}{}%{reset} -> %{cyan}{}%{reset}').format(user, p.user), always=True)
     self.print_step('updating merged users in folder acls')
     for p in AttachmentFolderPrincipal.find(User.merged_into_id != None,
                                             _join=AttachmentFolderPrincipal.user):  # noqa
         while p.user.merged_into_user:
             p.user = p.user.merged_into_user
         self.print_success(cformat('%{cyan}{}%{reset} -> %{cyan}{}%{reset}').format(user, p.user), always=True)
     db.session.commit()
Пример #5
0
class Attachment(ProtectionMixin, VersionedResourceMixin, db.Model):
    __tablename__ = 'attachments'
    __table_args__ = (
        # links: url but no file
        db.CheckConstraint(
            f'type != {AttachmentType.link.value} OR (link_url IS NOT NULL AND file_id IS NULL)',
            'valid_link'),
        # we can't require the file_id to be NOT NULL for files because of the circular relationship...
        # but we can ensure that we never have both a file_id AND a link_url...for
        db.CheckConstraint('link_url IS NULL OR file_id IS NULL',
                           'link_or_file'),
        {
            'schema': 'attachments'
        })

    stored_file_table = 'attachments.files'
    stored_file_class = AttachmentFile
    stored_file_fkey = 'attachment_id'

    #: The ID of the attachment
    id = db.Column(db.Integer, primary_key=True)
    #: The ID of the folder the attachment belongs to
    folder_id = db.Column(db.Integer,
                          db.ForeignKey('attachments.folders.id'),
                          nullable=False,
                          index=True)
    #: The ID of the user who created the attachment
    user_id = db.Column(db.Integer,
                        db.ForeignKey('users.users.id'),
                        index=True,
                        nullable=False)
    #: If the attachment has been deleted
    is_deleted = db.Column(db.Boolean, nullable=False, default=False)
    #: The name of the attachment
    title = db.Column(db.String, nullable=False)
    #: The description of the attachment
    description = db.Column(db.Text, nullable=False, default='')
    #: The date/time when the attachment was created/modified
    modified_dt = db.Column(UTCDateTime,
                            nullable=False,
                            default=now_utc,
                            onupdate=now_utc)
    #: The type of the attachment (file or link)
    type = db.Column(PyIntEnum(AttachmentType), nullable=False)
    #: The target URL for a link attachment
    link_url = db.Column(db.String, nullable=True)

    #: The user who created the attachment
    user = db.relationship('User',
                           lazy=True,
                           backref=db.backref('attachments', lazy='dynamic'))
    #: The folder containing the attachment
    folder = db.relationship('AttachmentFolder',
                             lazy=True,
                             backref=db.backref('all_attachments', lazy=True))
    acl_entries = db.relationship('AttachmentPrincipal',
                                  backref='attachment',
                                  cascade='all, delete-orphan',
                                  collection_class=set)
    #: The ACL of the folder (used for ProtectionMode.protected)
    acl = association_proxy('acl_entries',
                            'principal',
                            creator=lambda v: AttachmentPrincipal(principal=v))

    # relationship backrefs:
    # - legacy_mapping (LegacyAttachmentMapping.attachment)

    @property
    def protection_parent(self):
        return self.folder

    @property
    def locator(self):
        return dict(self.folder.locator, attachment_id=self.id)

    def get_download_url(self, absolute=False):
        """Return the download url for the attachment.

        During static site generation this returns a local URL for the
        file or the target URL for the link.

        :param absolute: If the returned URL should be absolute.
        """
        if g.get('static_site'):
            return _offline_download_url(self)
        else:
            filename = self.file.filename if self.type == AttachmentType.file else 'go'
            return url_for('attachments.download',
                           self,
                           filename=filename,
                           _external=absolute)

    @property
    def download_url(self):
        """The download url for the attachment."""
        return self.get_download_url()

    @property
    def absolute_download_url(self):
        """The absolute download url for the attachment."""
        return self.get_download_url(absolute=True)

    def can_access(self, user, *args, **kwargs):
        """Check if the user is allowed to access the attachment.

        This is the case if the user has access to see the attachment
        or if the user can manage attachments for the linked object.
        """
        return (super().can_access(user, *args, **kwargs)
                or can_manage_attachments(self.folder.object, user))

    def __repr__(self):
        return '<Attachment({}, {}, {}{}, {}, {})>'.format(
            self.id, self.title,
            self.file if self.type == AttachmentType.file else self.link_url,
            ', is_deleted=True' if self.is_deleted else '',
            self.protection_repr, self.folder_id)