コード例 #1
0
ファイル: contributor.py プロジェクト: h-ci-user01/osf.h-test
class AbstractBaseContributor(models.Model):
    objects = IncludeManager()

    primary_identifier_name = 'user__guids___id'

    read = models.BooleanField(default=False)
    write = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)
    visible = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser', on_delete=models.CASCADE)

    def __repr__(self):
        return ('<{self.__class__.__name__}(user={self.user}, '
                'read={self.read}, write={self.write}, admin={self.admin}, '
                'visible={self.visible}'
                ')>').format(self=self)

    class Meta:
        abstract = True

    @property
    def bibliographic(self):
        return self.visible

    @property
    def permission(self):
        if self.admin:
            return 'admin'
        if self.write:
            return 'write'
        return 'read'
コード例 #2
0
class Email(models.Model):
    email = models.TextField()
    user = models.ForeignKey(User,
                             related_name='emails',
                             on_delete=models.CASCADE)

    objects = IncludeManager()
コード例 #3
0
ファイル: models.py プロジェクト: Johnetordoff/django-include
class Membership(models.Model):
    active = models.BooleanField(default=True)
    joined = models.DateTimeField(auto_now_add=True)

    organization = models.ForeignKey(Organization, related_name='members', on_delete=models.CASCADE)
    member = models.ForeignKey(Cat, related_name='memberships', on_delete=models.CASCADE)

    objects = IncludeManager()
コード例 #4
0
class User(models.Model):
    name = models.TextField()
    date_created = models.DateTimeField(auto_now_add=True)
    col1 = models.TextField(default='col1')
    col2 = models.TextField(default='col2')
    col3 = models.TextField(default='col2')

    objects = IncludeManager()
コード例 #5
0
class Project(models.Model):
    title = models.TextField()
    body = models.TextField()
    date_created = models.DateTimeField(auto_now_add=True)
    col1 = models.TextField(default='col1')
    col2 = models.TextField(default='col2')
    col3 = models.TextField(default='col2')
    tags = models.ManyToManyField(Tag)

    objects = IncludeManager()
コード例 #6
0
ファイル: models.py プロジェクト: cos-forks/django-include
class Cat(models.Model):
    aliases = GenericRelation(Alias)
    archetype = models.ForeignKey(Archetype)
    name = models.CharField(max_length=50)
    parent = models.ForeignKey('Cat', null=True, related_name='children')
    siblings = models.ManyToManyField('Cat', related_name='related_to')
    emergency_contact = models.OneToOneField(
        'Cat', null=True, related_name='emergency_contact_for')

    objects = IncludeManager()
コード例 #7
0
ファイル: models.py プロジェクト: Johnetordoff/django-include
class Cat(models.Model):
    aliases = GenericRelation(Alias)
    archetype = models.ForeignKey(Archetype, on_delete=models.CASCADE)
    name = models.CharField(max_length=50)
    parent = models.ForeignKey('Cat', null=True, related_name='children', on_delete=models.CASCADE)
    siblings = models.ManyToManyField('Cat', related_name='related_to')
    emergency_contact = models.OneToOneField('Cat', null=True, related_name='emergency_contact_for', on_delete=models.CASCADE)
    organizations = models.ManyToManyField('Organization', through='Membership')

    objects = IncludeManager()
コード例 #8
0
class Contributor(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    project = models.ForeignKey(Project,
                                related_name='contributors',
                                on_delete=models.CASCADE)
    col1 = models.TextField(default='col1')
    col2 = models.TextField(default='col2')
    col3 = models.TextField(default='col2')

    objects = IncludeManager()
コード例 #9
0
class AbstractRequest(BaseModel, ObjectIDMixin):
    class Meta:
        abstract = True

    objects = IncludeManager()

    request_type = models.CharField(max_length=31, choices=RequestTypes.choices())
    creator = models.ForeignKey('OSFUser', related_name='submitted_%(class)s')
    comment = models.TextField(null=True, blank=True)

    @property
    def target(self):
        raise NotImplementedError()
コード例 #10
0
class OSFGroupLog(ObjectIDMixin, BaseModel):
    objects = IncludeManager()

    DATE_FORMAT = '%m/%d/%Y %H:%M UTC'

    GROUP_CREATED = 'group_created'

    MEMBER_ADDED = 'member_added'
    MANAGER_ADDED = 'manager_added'
    MEMBER_REMOVED = 'member_removed'
    ROLE_UPDATED = 'role_updated'
    EDITED_NAME = 'edit_name'
    NODE_CONNECTED = 'node_connected'
    NODE_PERMS_UPDATED = 'node_permissions_updated'
    NODE_DISCONNECTED = 'node_disconnected'

    actions = ([GROUP_CREATED, MEMBER_ADDED, MANAGER_ADDED, MEMBER_REMOVED, ROLE_UPDATED,
    EDITED_NAME, NODE_CONNECTED, NODE_PERMS_UPDATED, NODE_DISCONNECTED])

    action_choices = [(action, action.upper()) for action in actions]

    action = models.CharField(max_length=255, db_index=True)
    params = DateTimeAwareJSONField(default=dict)
    should_hide = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser', related_name='group_logs', db_index=True,
                             null=True, blank=True, on_delete=models.CASCADE)
    group = models.ForeignKey('OSFGroup', related_name='logs',
                             db_index=True, null=True, blank=True, on_delete=models.CASCADE)

    def __unicode__(self):
        return ('({self.action!r}, user={self.user!r}, group={self.group!r}, params={self.params!r}) '
                'with id {self.id!r}').format(self=self)

    class Meta:
        ordering = ['-created']
        get_latest_by = 'created'

    @property
    def absolute_api_v2_url(self):
        path = '/logs/{}/'.format(self._id)
        return api_v2_url(path)

    def get_absolute_url(self):
        return self.absolute_api_v2_url

    @property
    def absolute_url(self):
        return self.absolute_api_v2_url
コード例 #11
0
ファイル: filelog.py プロジェクト: yuanyuan-deng/RDM-osf.io
class FileLog(ObjectIDMixin, BaseModel):

    objects = IncludeManager()

    DATE_FORMAT = '%m/%d/%Y %H:%M UTC'

    # Log action constants -- NOTE: templates stored in log_templates.mako
    CREATED_FROM = 'created_from'

    CHECKED_IN = 'checked_in'
    CHECKED_OUT = 'checked_out'

    FILE_TAG_ADDED = 'file_tag_added'
    FILE_TAG_REMOVED = 'file_tag_removed'

    FILE_MOVED = 'addon_file_moved'
    FILE_COPIED = 'addon_file_copied'
    FILE_RENAMED = 'addon_file_renamed'

    FOLDER_CREATED = 'folder_created'

    FILE_ADDED = 'file_added'
    FILE_UPDATED = 'file_updated'
    FILE_REMOVED = 'file_removed'
    FILE_RESTORED = 'file_restored'

    PREPRINT_FILE_UPDATED = 'preprint_file_updated'

    actions = ([CHECKED_IN, CHECKED_OUT, FILE_TAG_REMOVED, FILE_TAG_ADDED,
               FILE_MOVED, FILE_COPIED, FOLDER_CREATED, FILE_ADDED, FILE_UPDATED, FILE_REMOVED,
                FILE_RESTORED, PREPRINT_FILE_UPDATED, ] + list(sum([
                    config.actions for config in apps.get_app_configs() if config.name.startswith('addons.')
                ], tuple())))
    action_choices = [(action, action.upper()) for action in actions]
    project_id = models.CharField(max_length=255, null=True, blank=True, db_index=True)
    date = NonNaiveDateTimeField(db_index=True, null=True, blank=True, default=timezone.now)
    # TODO build action choices on the fly with the addon stuff
    action = models.CharField(max_length=255, db_index=True)  # , choices=action_choices)
    user = models.ForeignKey('OSFUser', related_name='filelogs', db_index=True, null=True, blank=True)
    path = models.CharField(max_length=255, db_index=True, null=True)

    def __unicode__(self):
        return ('({self.action!r}, user={self.user!r},, file={self.file!r}, params={self.params!r}) '
                'with id {self.id!r}').format(self=self)

    class Meta:
        ordering = ['-date']
        get_latest_by = 'date'
コード例 #12
0
class Action(ObjectIDMixin, BaseModel):

    objects = IncludeManager()

    target = models.ForeignKey('PreprintService', related_name='actions')
    creator = models.ForeignKey('OSFUser', related_name='+')

    trigger = models.CharField(max_length=31, choices=Triggers.choices())
    from_state = models.CharField(max_length=31, choices=States.choices())
    to_state = models.CharField(max_length=31, choices=States.choices())

    comment = models.TextField(blank=True)

    is_deleted = models.BooleanField(default=False)
    date_created = NonNaiveDateTimeField(auto_now_add=True)
    date_modified = NonNaiveDateTimeField(auto_now=True)
コード例 #13
0
ファイル: contributor.py プロジェクト: mdicgovbr/osf.io
class PreprintContributor(models.Model):
    objects = IncludeManager()

    primary_identifier_name = 'user__guids___id'
    visible = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser', on_delete=models.CASCADE)
    preprint = models.ForeignKey('Preprint', on_delete=models.CASCADE)

    def __repr__(self):
        return ('<{self.__class__.__name__}(user={self.user}, '
                'visible={self.visible}, '
                'permission={self.permission}, '
                ')>').format(self=self)

    @property
    def _id(self):
        return '{}-{}'.format(self.preprint._id, self.user._id)

    @property
    def bibliographic(self):
        return self.visible

    @property
    def permission(self):
        # Checking group membership instead of permissions since unregistered
        # contributors technically have no permissions
        preprint_id = self.preprint.id
        user = self.user
        read = 'preprint_{}_read'.format(preprint_id)
        write = 'preprint_{}_write'.format(preprint_id)
        admin = 'preprint_{}_admin'.format(preprint_id)
        user_groups = user.groups.filter(
            name__in=[read, write, admin]).values_list('name', flat=True)
        if admin in user_groups:
            return 'admin'
        elif write in user_groups:
            return 'write'
        elif read in user_groups:
            return 'read'
        else:
            return None

    class Meta:
        unique_together = ('user', 'preprint')
        # Make contributors orderable
        # NOTE: Adds an _order column
        order_with_respect_to = 'preprint'
コード例 #14
0
class BaseAction(ObjectIDMixin, BaseModel):
    class Meta:
        abstract = True

    objects = IncludeManager()

    creator = models.ForeignKey('OSFUser', related_name='+', on_delete=models.CASCADE)

    trigger = models.CharField(max_length=31, choices=DefaultTriggers.choices())
    from_state = models.CharField(max_length=31, choices=DefaultStates.choices())
    to_state = models.CharField(max_length=31, choices=DefaultStates.choices())

    comment = models.TextField(blank=True)

    is_deleted = models.BooleanField(default=False)

    @property
    def target(self):
        raise NotImplementedError()
コード例 #15
0
class AbstractBaseContributor(models.Model):
    objects = IncludeManager()

    primary_identifier_name = 'user__guids___id'

    visible = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser', on_delete=models.CASCADE)

    def __repr__(self):
        return ('<{self.__class__.__name__}(user={self.user}, '
                'visible={self.visible}, '
                'permission={self.permission}'
                ')>').format(self=self)

    class Meta:
        abstract = True

    @property
    def bibliographic(self):
        return self.visible

    @property
    def permission(self):
        return get_contributor_permission(self, self.node)
コード例 #16
0
class NodeLog(ObjectIDMixin, BaseModel):
    FIELD_ALIASES = {
        # TODO: Find a better way
        'node': 'node__guids___id',
        'user': '******',
        'original_node': 'original_node__guids___id'
    }

    objects = IncludeManager()

    DATE_FORMAT = '%m/%d/%Y %H:%M UTC'

    # Log action constants -- NOTE: templates stored in log_templates.mako
    CREATED_FROM = 'created_from'

    PROJECT_CREATED = 'project_created'
    # Nodes created as part of the registration process
    PROJECT_CREATED_FROM_DRAFT_REG = 'project_created_from_draft_reg'
    PROJECT_REGISTERED = 'project_registered'
    PROJECT_DELETED = 'project_deleted'

    NODE_CREATED = 'node_created'
    NODE_FORKED = 'node_forked'
    NODE_REMOVED = 'node_removed'
    NODE_ACCESS_REQUESTS_ENABLED = 'node_access_requests_enabled'
    NODE_ACCESS_REQUESTS_DISABLED = 'node_access_requests_disabled'

    POINTER_CREATED = NODE_LINK_CREATED = 'pointer_created'
    POINTER_FORKED = NODE_LINK_FORKED = 'pointer_forked'
    POINTER_REMOVED = NODE_LINK_REMOVED = 'pointer_removed'

    WIKI_UPDATED = 'wiki_updated'
    WIKI_DELETED = 'wiki_deleted'
    WIKI_RENAMED = 'wiki_renamed'

    MADE_WIKI_PUBLIC = 'made_wiki_public'
    MADE_WIKI_PRIVATE = 'made_wiki_private'

    CONTRIB_ADDED = 'contributor_added'
    CONTRIB_REMOVED = 'contributor_removed'
    CONTRIB_REORDERED = 'contributors_reordered'

    CHECKED_IN = 'checked_in'
    CHECKED_OUT = 'checked_out'

    PERMISSIONS_UPDATED = 'permissions_updated'

    MADE_PRIVATE = 'made_private'
    MADE_PUBLIC = 'made_public'

    TAG_ADDED = 'tag_added'
    TAG_REMOVED = 'tag_removed'

    FILE_TAG_ADDED = 'file_tag_added'
    FILE_TAG_REMOVED = 'file_tag_removed'

    FILE_METADATA_UPDATED = 'file_metadata_updated'

    EDITED_TITLE = 'edit_title'
    EDITED_DESCRIPTION = 'edit_description'
    CHANGED_LICENSE = 'license_changed'

    UPDATED_FIELDS = 'updated_fields'

    FILE_MOVED = 'addon_file_moved'
    FILE_COPIED = 'addon_file_copied'
    FILE_RENAMED = 'addon_file_renamed'

    FOLDER_CREATED = 'folder_created'

    FILE_ADDED = 'file_added'
    FILE_UPDATED = 'file_updated'
    FILE_REMOVED = 'file_removed'
    FILE_RESTORED = 'file_restored'

    CATEGORY_UPDATED = 'category_updated'
    ARTICLE_DOI_UPDATED = 'article_doi_updated'

    ADDON_ADDED = 'addon_added'
    ADDON_REMOVED = 'addon_removed'
    COMMENT_ADDED = 'comment_added'
    COMMENT_REMOVED = 'comment_removed'
    COMMENT_UPDATED = 'comment_updated'
    COMMENT_RESTORED = 'comment_restored'

    CUSTOM_CITATION_ADDED = 'custom_citation_added'
    CUSTOM_CITATION_EDITED = 'custom_citation_edited'
    CUSTOM_CITATION_REMOVED = 'custom_citation_removed'

    MADE_CONTRIBUTOR_VISIBLE = 'made_contributor_visible'
    MADE_CONTRIBUTOR_INVISIBLE = 'made_contributor_invisible'

    EXTERNAL_IDS_ADDED = 'external_ids_added'

    EMBARGO_APPROVED = 'embargo_approved'
    EMBARGO_CANCELLED = 'embargo_cancelled'
    EMBARGO_COMPLETED = 'embargo_completed'
    EMBARGO_INITIATED = 'embargo_initiated'
    EMBARGO_TERMINATED = 'embargo_terminated'

    GROUP_ADDED = 'group_added'
    GROUP_UPDATED = 'group_updated'
    GROUP_REMOVED = 'group_removed'

    RETRACTION_APPROVED = 'retraction_approved'
    RETRACTION_CANCELLED = 'retraction_cancelled'
    RETRACTION_INITIATED = 'retraction_initiated'

    EXTERNAL_REGISTRATION_CREATED = 'external_registration_created'
    EXTERNAL_REGISTRATION_IMPORTED = 'external_registration_imported'

    REGISTRATION_APPROVAL_CANCELLED = 'registration_cancelled'
    REGISTRATION_APPROVAL_INITIATED = 'registration_initiated'
    REGISTRATION_APPROVAL_APPROVED = 'registration_approved'
    PREREG_REGISTRATION_INITIATED = 'prereg_registration_initiated'

    AFFILIATED_INSTITUTION_ADDED = 'affiliated_institution_added'
    AFFILIATED_INSTITUTION_REMOVED = 'affiliated_institution_removed'

    PREPRINT_INITIATED = 'preprint_initiated'
    PREPRINT_FILE_UPDATED = 'preprint_file_updated'
    PREPRINT_LICENSE_UPDATED = 'preprint_license_updated'

    SUBJECTS_UPDATED = 'subjects_updated'

    VIEW_ONLY_LINK_ADDED = 'view_only_link_added'
    VIEW_ONLY_LINK_REMOVED = 'view_only_link_removed'

    CONFIRM_HAM = 'confirm_ham'
    FLAG_SPAM = 'flag_spam'
    CONFIRM_SPAM = 'confirm_spam'

    actions = ([
        CHECKED_IN, CHECKED_OUT, FILE_TAG_REMOVED, FILE_TAG_ADDED,
        CREATED_FROM, PROJECT_CREATED, PROJECT_REGISTERED, PROJECT_DELETED,
        NODE_CREATED, NODE_FORKED, NODE_REMOVED, NODE_ACCESS_REQUESTS_ENABLED,
        NODE_ACCESS_REQUESTS_DISABLED, NODE_LINK_CREATED, NODE_LINK_FORKED,
        NODE_LINK_REMOVED, WIKI_UPDATED, WIKI_DELETED, WIKI_RENAMED,
        MADE_WIKI_PUBLIC, MADE_WIKI_PRIVATE, CONTRIB_ADDED, CONTRIB_REMOVED,
        CONTRIB_REORDERED, PERMISSIONS_UPDATED, MADE_PRIVATE, MADE_PUBLIC,
        TAG_ADDED, TAG_REMOVED, EDITED_TITLE, EDITED_DESCRIPTION,
        UPDATED_FIELDS, FILE_MOVED, FILE_COPIED, FILE_METADATA_UPDATED,
        FOLDER_CREATED, FILE_ADDED, FILE_UPDATED, FILE_REMOVED, FILE_RESTORED,
        ADDON_ADDED, ADDON_REMOVED, COMMENT_ADDED, COMMENT_REMOVED,
        COMMENT_UPDATED, COMMENT_RESTORED, MADE_CONTRIBUTOR_VISIBLE,
        CONFIRM_HAM, FLAG_SPAM, CONFIRM_SPAM, MADE_CONTRIBUTOR_INVISIBLE,
        EXTERNAL_IDS_ADDED, EMBARGO_APPROVED, EMBARGO_TERMINATED,
        EMBARGO_CANCELLED, EMBARGO_COMPLETED, EMBARGO_INITIATED,
        RETRACTION_APPROVED, RETRACTION_CANCELLED, RETRACTION_INITIATED,
        EXTERNAL_REGISTRATION_CREATED, EXTERNAL_REGISTRATION_IMPORTED,
        REGISTRATION_APPROVAL_CANCELLED, REGISTRATION_APPROVAL_INITIATED,
        REGISTRATION_APPROVAL_APPROVED, PREREG_REGISTRATION_INITIATED,
        PROJECT_CREATED_FROM_DRAFT_REG, GROUP_ADDED, GROUP_UPDATED,
        GROUP_REMOVED, AFFILIATED_INSTITUTION_ADDED,
        AFFILIATED_INSTITUTION_REMOVED, PREPRINT_INITIATED,
        PREPRINT_FILE_UPDATED, PREPRINT_LICENSE_UPDATED, VIEW_ONLY_LINK_ADDED,
        VIEW_ONLY_LINK_REMOVED
    ] + list(
        sum([
            config.actions for config in apps.get_app_configs()
            if config.name.startswith('addons.')
        ], tuple())))
    action_choices = [(action, action.upper()) for action in actions]
    date = NonNaiveDateTimeField(db_index=True,
                                 null=True,
                                 blank=True,
                                 default=timezone.now)
    # TODO build action choices on the fly with the addon stuff
    action = models.CharField(max_length=255,
                              db_index=True)  # , choices=action_choices)
    params = DateTimeAwareJSONField(default=dict)
    should_hide = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser',
                             related_name='logs',
                             db_index=True,
                             null=True,
                             blank=True,
                             on_delete=models.CASCADE)
    foreign_user = models.CharField(max_length=255, null=True, blank=True)
    node = models.ForeignKey('AbstractNode',
                             related_name='logs',
                             db_index=True,
                             null=True,
                             blank=True,
                             on_delete=models.CASCADE)
    original_node = models.ForeignKey('AbstractNode',
                                      db_index=True,
                                      null=True,
                                      blank=True,
                                      on_delete=models.CASCADE)

    def __repr__(self):
        return (
            '({self.action!r}, user={self.user!r},, node={self.node!r}, params={self.params!r}) '
            'with id {self.id!r}').format(self=self)

    class Meta:
        ordering = ['-date']
        get_latest_by = 'date'

    @property
    def absolute_api_v2_url(self):
        path = '/logs/{}/'.format(self._id)
        return api_v2_url(path)

    def get_absolute_url(self):
        return self.absolute_api_v2_url

    @property
    def absolute_url(self):
        return self.absolute_api_v2_url

    def _natural_key(self):
        return self._id
コード例 #17
0
ファイル: files.py プロジェクト: darshanman40/osf.io
class FileVersion(ObjectIDMixin, BaseModel):
    """A version of an OsfStorageFileNode. contains information
    about where the file is located, hashes and datetimes
    """

    creator = models.ForeignKey('OSFUser', null=True, blank=True)

    identifier = models.CharField(max_length=100, blank=False, null=False)  # max length on staging was 51

    # Date version record was created. This is the date displayed to the user.
    date_created = NonNaiveDateTimeField(auto_now_add=True)

    size = models.BigIntegerField(default=-1, blank=True, null=True)

    content_type = models.CharField(max_length=100, blank=True, null=True)  # was 24 on staging
    # Date file modified on third-party backend. Not displayed to user, since
    # this date may be earlier than the date of upload if the file already
    # exists on the backend
    date_modified = NonNaiveDateTimeField(null=True, blank=True)

    metadata = DateTimeAwareJSONField(blank=True, default=dict)
    location = DateTimeAwareJSONField(default=None, blank=True, null=True, validators=[validate_location])

    includable_objects = IncludeManager()

    @property
    def location_hash(self):
        return self.location['object']

    @property
    def archive(self):
        return self.metadata.get('archive')

    def is_duplicate(self, other):
        return self.location_hash == other.location_hash

    def update_metadata(self, metadata, save=True):
        self.metadata.update(metadata)
        # metadata has no defined structure so only attempt to set attributes
        # If its are not in this callback it'll be in the next
        self.size = self.metadata.get('size', self.size)
        self.content_type = self.metadata.get('contentType', self.content_type)
        if self.metadata.get('modified'):
            self.date_modified = parse_date(self.metadata['modified'], ignoretz=False)

        if save:
            self.save()

    def _find_matching_archive(self, save=True):
        """Find another version with the same sha256 as this file.
        If found copy its vault name and glacier id, no need to create additional backups.
        returns True if found otherwise false
        """

        if 'sha256' not in self.metadata:
            return False  # Dont bother searching for nothing

        if 'vault' in self.metadata and 'archive' in self.metadata:
            # Shouldn't ever happen, but we already have an archive
            return True  # We've found ourself

        qs = self.__class__.find(
            Q('_id', 'ne', self._id) &
            Q('metadata.sha256', 'eq', self.metadata['sha256']) &
            Q('metadata.archive', 'ne', None) &
            Q('metadata.vault', 'ne', None)
        ).limit(1)
        if qs.count() < 1:
            return False
        other = qs[0]
        try:
            self.metadata['vault'] = other.metadata['vault']
            self.metadata['archive'] = other.metadata['archive']
        except KeyError:
            return False
        if save:
            self.save()
        return True

    class Meta:
        ordering = ('date_created',)
コード例 #18
0
class Collection(DirtyFieldsMixin, GuidMixin, BaseModel, GuardianMixin):
    objects = IncludeManager()

    groups = {
        'read': ('read_collection', ),
        'write': (
            'read_collection',
            'write_collection',
        ),
        'admin': (
            'read_collection',
            'write_collection',
            'admin_collection',
        )
    }
    group_format = 'collections_{self.id}_{group}'

    class Meta:
        permissions = (
            ('read_collection', 'Read Collection'),
            ('write_collection', 'Write Collection'),
            ('admin_collection', 'Admin Collection'),
        )

    provider = models.ForeignKey('AbstractProvider',
                                 blank=True,
                                 null=True,
                                 on_delete=models.CASCADE)
    creator = models.ForeignKey('OSFUser', on_delete=models.CASCADE)
    guid_links = models.ManyToManyField('Guid',
                                        through=CollectionSubmission,
                                        related_name='collections')
    collected_types = models.ManyToManyField(
        'contenttypes.ContentType',
        related_name='+',
        limit_choices_to={
            'model__in':
            ['abstractnode', 'basefilenode', 'collection', 'preprint']
        })
    title = models.CharField(max_length=200, validators=[validate_title])
    collected_type_choices = ArrayField(models.CharField(max_length=127),
                                        blank=True,
                                        default=list)
    status_choices = ArrayField(models.CharField(max_length=127),
                                blank=True,
                                default=list)
    volume_choices = ArrayField(models.CharField(max_length=127),
                                blank=True,
                                default=list)
    issue_choices = ArrayField(models.CharField(max_length=127),
                               blank=True,
                               default=list)
    program_area_choices = ArrayField(models.CharField(max_length=127),
                                      blank=True,
                                      default=list)
    is_public = models.BooleanField(default=False, db_index=True)
    is_promoted = models.BooleanField(default=False, db_index=True)
    is_bookmark_collection = models.BooleanField(default=False, db_index=True)
    deleted = NonNaiveDateTimeField(null=True, blank=True)

    def __unicode__(self):
        return '{self.title!r}, with guid {self._id!r}'.format(self=self)

    @property
    def url(self):
        return '/{}/'.format(self._id)

    def get_absolute_url(self):
        return self.absolute_api_v2_url

    @property
    def absolute_api_v2_url(self):
        return api_v2_url('/collections{}'.format(self.url))

    @property
    def linked_nodes_self_url(self):
        return '{}relationships/linked_nodes/'.format(self.absolute_api_v2_url)

    @property
    def linked_registrations_self_url(self):
        return '{}relationships/linked_registrations/'.format(
            self.absolute_api_v2_url)

    @property
    def linked_preprints_self_url(self):
        return '{}relationships/linked_preprints/'.format(
            self.absolute_api_v2_url)

    @property
    def linked_preprints_related_url(self):
        return '{}linked_preprints/'.format(self.absolute_api_v2_url)

    @property
    def linked_nodes_related_url(self):
        return '{}linked_nodes/'.format(self.absolute_api_v2_url)

    @property
    def linked_registrations_related_url(self):
        return '{}linked_registrations/'.format(self.absolute_api_v2_url)

    @classmethod
    def bulk_update_search(cls, cgms, op='update', index=None):
        from website import search
        try:
            search.search.bulk_update_collected_metadata(cgms,
                                                         op=op,
                                                         index=index)
        except search.exceptions.SearchUnavailableError as e:
            logger.exception(e)

    def save(self, *args, **kwargs):
        first_save = self.id is None
        if self.is_bookmark_collection:
            if first_save and self.creator.collection_set.filter(
                    is_bookmark_collection=True,
                    deleted__isnull=True).exists():
                raise IntegrityError(
                    'Each user cannot have more than one Bookmark collection.')
            if self.title != 'Bookmarks':
                # Bookmark collections are always named 'Bookmarks'
                self.title = 'Bookmarks'
        saved_fields = self.get_dirty_fields() or []
        ret = super(Collection, self).save(*args, **kwargs)

        if first_save:
            # Set defaults for M2M
            content_type = ContentType.objects.filter(
                app_label='osf',
                model__in=['abstractnode', 'collection', 'preprint'])

            self.collected_types.add(*content_type)

            # Set up initial permissions
            self.update_group_permissions()
            self.get_group(ADMIN).user_set.add(self.creator)

        elif 'is_public' in saved_fields:
            from website.collections.tasks import on_collection_updated
            enqueue_task(on_collection_updated.s(self._id))

        return ret

    def has_permission(self, user, perm):
        return user.has_perms(self.groups[perm], self)

    def collect_object(self,
                       obj,
                       collector,
                       collected_type=None,
                       status=None,
                       volume=None,
                       issue=None,
                       program_area=None):
        """ Adds object to collection, creates CollectionSubmission reference
            Performs type / metadata validation. User permissions checked in view.

        :param GuidMixin obj: Object to collect. Must be of a ContentType specified in collected_types
        :param OSFUser collector: User doing the collecting
        :param str collected_type: Metadata "type" of submission, validated against collected_type_choices
        :param str status: Metadata "status" of submission, validated against status_choices
        :return: CollectionSubmission object or raise exception
        """
        collected_type = collected_type or ''
        status = status or ''
        volume = volume or ''
        issue = issue or ''
        program_area = program_area or ''

        if not self.collected_type_choices and collected_type:
            raise ValidationError('May not specify "type" for this collection')

        if not self.status_choices and status:
            raise ValidationError(
                'May not specify "status" for this collection')

        if not self.volume_choices and volume:
            raise ValidationError(
                'May not specify "volume" for this collection')

        if not self.issue_choices and issue:
            raise ValidationError(
                'May not specify "issue" for this collection')

        if not self.program_area_choices and program_area:
            raise ValidationError(
                'May not specify "program_area" for this collection')

        if self.collected_type_choices and collected_type not in self.collected_type_choices:
            raise ValidationError(
                '"{}" is not an acceptable "type" for this collection'.format(
                    collected_type))

        if self.status_choices and status not in self.status_choices:
            raise ValidationError(
                '"{}" is not an acceptable "status" for this collection'.
                format(status))

        if self.volume_choices and volume not in self.volume_choices:
            raise ValidationError(
                '"{}" is not an acceptable "volume" for this collection'.
                format(volume))

        if self.issue_choices and issue not in self.issue_choices:
            raise ValidationError(
                '"{}" is not an acceptable "issue" for this collection'.format(
                    issue))

        if self.program_area_choices and program_area not in self.program_area_choices:
            raise ValidationError(
                '"{}" is not an acceptable "program_area" for this collection'.
                format(program_area))

        if not any([
                isinstance(obj, t.model_class())
                for t in self.collected_types.all()
        ]):
            # Not all objects have a content_type_pk, have to look the other way.
            # Ideally, all objects would, and we could do:
            #   self.content_types.filter(id=obj.content_type_pk).exists()
            raise ValidationError(
                '"{}" is not an acceptable "ContentType" for this collection'.
                format(ContentType.objects.get_for_model(obj).model))

        # Unique together -- self and guid
        if self.collectionsubmission_set.filter(
                guid=obj.guids.first()).exists():
            raise ValidationError('Object already exists in collection.')

        cgm = self.collectionsubmission_set.create(guid=obj.guids.first(),
                                                   creator=collector)
        cgm.collected_type = collected_type
        cgm.status = status
        cgm.volume = volume
        cgm.issue = issue
        cgm.program_area = program_area
        cgm.save()

        return cgm

    def remove_object(self, obj):
        """ Removes object from collection

        :param obj: object to remove from collection, if it exists. Acceptable types- CollectionSubmission, GuidMixin
        """
        if isinstance(obj, CollectionSubmission):
            if obj.collection == self:
                obj.remove_from_index()
                self.collectionsubmission_set.filter(id=obj.id).delete()
                return
        else:
            cgm = self.collectionsubmission_set.get(guid=obj.guids.first())
            if cgm:
                cgm.remove_from_index()
                cgm.delete()
                return
        raise ValueError('Node link does not belong to the requested node.')

    def delete(self):
        """ Mark collection as deleted
        """
        if self.is_bookmark_collection:
            # Not really the right exception to raise, but it's for back-compatibility
            # TODO: Use a more correct exception and catch it in the necessary places
            raise NodeStateError('Bookmark collections may not be deleted.')

        self.deleted = timezone.now()

        if self.is_public:
            self.bulk_update_search(list(self.collectionsubmission_set.all()),
                                    op='delete')

        self.save()
コード例 #19
0
ファイル: models.py プロジェクト: Johnetordoff/django-include
class Archetype(models.Model):
    aliases = GenericRelation(Alias)
    color = models.CharField(max_length=75)
    num_toes = models.PositiveIntegerField(default=5)

    objects = IncludeManager()
コード例 #20
0
ファイル: files.py プロジェクト: xlecours/osf.io
class FileVersion(ObjectIDMixin, BaseModel):
    """A version of an OsfStorageFileNode. contains information
    about where the file is located, hashes and datetimes
    """
    # Note on fields:
    # `created`: Date version record was created. This is the date displayed to the user.
    # `modified`: Date this object was last modified. Distinct from the date the file associated
    #       with this object was last modified
    # `external_modified`: Date file modified on third-party backend. Not displayed to user, since
    #       this date may be earlier than the date of upload if the file already
    #       exists on the backend

    creator = models.ForeignKey('OSFUser', null=True, blank=True, on_delete=models.CASCADE)

    identifier = models.CharField(max_length=100, blank=False, null=False)  # max length on staging was 51

    size = models.BigIntegerField(default=-1, blank=True, null=True)

    content_type = models.CharField(max_length=100, blank=True, null=True)  # was 24 on staging
    external_modified = NonNaiveDateTimeField(null=True, blank=True)

    metadata = DateTimeAwareJSONField(blank=True, default=dict)
    location = DateTimeAwareJSONField(default=None, blank=True, null=True, validators=[validate_location])
    seen_by = models.ManyToManyField('OSFUser', through=FileVersionUserMetadata, related_name='versions_seen')
    region = models.ForeignKey('addons_osfstorage.Region', null=True, blank=True, on_delete=models.CASCADE)

    includable_objects = IncludeManager()

    @property
    def location_hash(self):
        return self.location['object']

    @property
    def archive(self):
        return self.metadata.get('archive')

    def is_duplicate(self, other):
        return self.location_hash == other.location_hash

    def get_basefilenode_version(self, file):
        # Returns the throughtable object  - the record that links this version
        # to the given file.
        return self.basefileversionsthrough_set.filter(basefilenode=file).first()

    def update_metadata(self, metadata, save=True):
        self.metadata.update(metadata)
        # metadata has no defined structure so only attempt to set attributes
        # If its are not in this callback it'll be in the next
        self.size = self.metadata.get('size', self.size)
        self.content_type = self.metadata.get('contentType', self.content_type)
        if self.metadata.get('modified'):
            self.external_modified = parse_date(self.metadata['modified'], ignoretz=False)

        if save:
            self.save()

    def _find_matching_archive(self, save=True):
        """Find another version with the same sha256 as this file.
        If found copy its vault name and glacier id, no need to create additional backups.
        returns True if found otherwise false
        """

        if 'sha256' not in self.metadata:
            return False  # Dont bother searching for nothing

        if 'vault' in self.metadata and 'archive' in self.metadata:
            # Shouldn't ever happen, but we already have an archive
            return True  # We've found ourself

        other = self.__class__.objects.filter(
            metadata__sha256=self.metadata['sha256']
        ).exclude(
            _id=self._id, metadata__archive__is_null=True, metadata__vault__is_null=True
        )
        if not other.exists():
            return False
        try:
            other = other.first()
            self.metadata['vault'] = other.metadata['vault']
            self.metadata['archive'] = other.metadata['archive']
        except KeyError:
            return False
        if save:
            self.save()
        return True

    def serialize_waterbutler_settings(self, node_id, root_id):
        return dict(self.region.waterbutler_settings, **{
            'nid': node_id,
            'rootId': root_id,
            'baseUrl': api_url_for(
                'osfstorage_get_metadata',
                guid=node_id,
                _absolute=True,
                _internal=True
            ),
        })

    class Meta:
        ordering = ('-created',)
コード例 #21
0
ファイル: preprintlog.py プロジェクト: xlecours/osf.io
class PreprintLog(ObjectIDMixin, BaseModel):
    FIELD_ALIASES = {
        # TODO: Find a better way
        'preprint': 'preprint__guids___id',
        'user': '******',
    }

    objects = IncludeManager()

    DATE_FORMAT = '%m/%d/%Y %H:%M UTC'

    DELETED = 'deleted'

    CONTRIB_ADDED = 'contributor_added'
    CONTRIB_REMOVED = 'contributor_removed'
    CONTRIB_REORDERED = 'contributors_reordered'
    PERMISSIONS_UPDATED = 'permissions_updated'
    MADE_CONTRIBUTOR_VISIBLE = 'made_contributor_visible'
    MADE_CONTRIBUTOR_INVISIBLE = 'made_contributor_invisible'

    MADE_PRIVATE = 'made_private'
    MADE_PUBLIC = 'made_public'

    TAG_ADDED = 'tag_added'
    TAG_REMOVED = 'tag_removed'

    EDITED_TITLE = 'edit_title'
    EDITED_DESCRIPTION = 'edit_description'
    CHANGED_LICENSE = 'license_changed'

    FILE_UPDATED = 'file_updated'
    FILE_METADATA_UPDATED = 'file_metadata_updated'

    SUBJECTS_UPDATED = 'subjects_updated'

    SUPPLEMENTAL_NODE_ADDED = 'supplement_node_added'
    SUPPLEMENTAL_NODE_REMOVED = 'supplement_node_removed'

    PUBLISHED = 'published'

    actions = ([
        DELETED, CONTRIB_ADDED, CONTRIB_REMOVED, CONTRIB_REORDERED,
        PERMISSIONS_UPDATED, TAG_ADDED, TAG_REMOVED, EDITED_TITLE,
        CHANGED_LICENSE, EDITED_DESCRIPTION, FILE_UPDATED,
        FILE_METADATA_UPDATED, MADE_CONTRIBUTOR_VISIBLE,
        SUPPLEMENTAL_NODE_ADDED, MADE_CONTRIBUTOR_INVISIBLE, SUBJECTS_UPDATED,
        MADE_PRIVATE, MADE_PUBLIC, PUBLISHED
    ] + list(
        sum([
            config.actions for config in apps.get_app_configs()
            if config.name.startswith('addons.')
        ], tuple())))
    action_choices = [(action, action.upper()) for action in actions]
    # TODO build action choices on the fly with the addon stuff
    action = models.CharField(max_length=255,
                              db_index=True)  # , choices=action_choices)
    params = DateTimeAwareJSONField(default=dict)
    should_hide = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser',
                             related_name='preprint_logs',
                             db_index=True,
                             null=True,
                             blank=True,
                             on_delete=models.CASCADE)
    foreign_user = models.CharField(max_length=255, null=True, blank=True)
    preprint = models.ForeignKey('Preprint',
                                 related_name='logs',
                                 db_index=True,
                                 null=True,
                                 blank=True,
                                 on_delete=models.CASCADE)

    def __unicode__(self):
        return (
            '({self.action!r}, user={self.user!r}, preprint={self.preprint!r}, params={self.params!r}) '
            'with id {self.id!r}').format(self=self)

    class Meta:
        ordering = ['-created']
        get_latest_by = 'created'

    @property
    def absolute_api_v2_url(self):
        path = '/logs/{}/'.format(self._id)
        return api_v2_url(path)

    def get_absolute_url(self):
        return self.absolute_api_v2_url

    @property
    def absolute_url(self):
        return self.absolute_api_v2_url

    def _natural_key(self):
        return self._id
コード例 #22
0
ファイル: models.py プロジェクト: Johnetordoff/django-include
class Organization(models.Model):
    title = models.CharField(max_length=75)
    disliked = models.BooleanField(default=True)

    objects = IncludeManager()
コード例 #23
0
ファイル: nodelog.py プロジェクト: nakajimahiroyuki/osf.io
class NodeLog(ObjectIDMixin, BaseModel):
    FIELD_ALIASES = {
        # TODO: Find a better way
        'node': 'node__guids___id',
        'user': '******',
        'original_node': 'original_node__guids___id'
    }

    objects = IncludeManager()

    DATE_FORMAT = '%m/%d/%Y %H:%M UTC'

    # Log action constants -- NOTE: templates stored in log_templates.mako
    CREATED_FROM = 'created_from'

    PROJECT_CREATED = 'project_created'
    PROJECT_REGISTERED = 'project_registered'
    PROJECT_DELETED = 'project_deleted'

    NODE_CREATED = 'node_created'
    NODE_FORKED = 'node_forked'
    NODE_REMOVED = 'node_removed'

    POINTER_CREATED = NODE_LINK_CREATED = 'pointer_created'
    POINTER_FORKED = NODE_LINK_FORKED = 'pointer_forked'
    POINTER_REMOVED = NODE_LINK_REMOVED = 'pointer_removed'

    WIKI_UPDATED = 'wiki_updated'
    WIKI_DELETED = 'wiki_deleted'
    WIKI_RENAMED = 'wiki_renamed'

    MADE_WIKI_PUBLIC = 'made_wiki_public'
    MADE_WIKI_PRIVATE = 'made_wiki_private'

    CONTRIB_ADDED = 'contributor_added'
    CONTRIB_REMOVED = 'contributor_removed'
    CONTRIB_REORDERED = 'contributors_reordered'

    CHECKED_IN = 'checked_in'
    CHECKED_OUT = 'checked_out'

    PERMISSIONS_UPDATED = 'permissions_updated'

    MADE_PRIVATE = 'made_private'
    MADE_PUBLIC = 'made_public'

    TAG_ADDED = 'tag_added'
    TAG_REMOVED = 'tag_removed'

    FILE_TAG_ADDED = 'file_tag_added'
    FILE_TAG_REMOVED = 'file_tag_removed'

    EDITED_TITLE = 'edit_title'
    EDITED_DESCRIPTION = 'edit_description'
    CHANGED_LICENSE = 'license_changed'

    UPDATED_FIELDS = 'updated_fields'

    FILE_MOVED = 'addon_file_moved'
    FILE_COPIED = 'addon_file_copied'
    FILE_RENAMED = 'addon_file_renamed'

    FOLDER_CREATED = 'folder_created'

    FILE_ADDED = 'file_added'
    FILE_UPDATED = 'file_updated'
    FILE_REMOVED = 'file_removed'
    FILE_RESTORED = 'file_restored'

    ADDON_ADDED = 'addon_added'
    ADDON_REMOVED = 'addon_removed'
    COMMENT_ADDED = 'comment_added'
    COMMENT_REMOVED = 'comment_removed'
    COMMENT_UPDATED = 'comment_updated'
    COMMENT_RESTORED = 'comment_restored'

    CITATION_ADDED = 'citation_added'
    CITATION_EDITED = 'citation_edited'
    CITATION_REMOVED = 'citation_removed'

    MADE_CONTRIBUTOR_VISIBLE = 'made_contributor_visible'
    MADE_CONTRIBUTOR_INVISIBLE = 'made_contributor_invisible'

    EXTERNAL_IDS_ADDED = 'external_ids_added'

    EMBARGO_APPROVED = 'embargo_approved'
    EMBARGO_CANCELLED = 'embargo_cancelled'
    EMBARGO_COMPLETED = 'embargo_completed'
    EMBARGO_INITIATED = 'embargo_initiated'
    EMBARGO_TERMINATED = 'embargo_terminated'

    RETRACTION_APPROVED = 'retraction_approved'
    RETRACTION_CANCELLED = 'retraction_cancelled'
    RETRACTION_INITIATED = 'retraction_initiated'

    REGISTRATION_APPROVAL_CANCELLED = 'registration_cancelled'
    REGISTRATION_APPROVAL_INITIATED = 'registration_initiated'
    REGISTRATION_APPROVAL_APPROVED = 'registration_approved'
    PREREG_REGISTRATION_INITIATED = 'prereg_registration_initiated'

    AFFILIATED_INSTITUTION_ADDED = 'affiliated_institution_added'
    AFFILIATED_INSTITUTION_REMOVED = 'affiliated_institution_removed'

    PREPRINT_INITIATED = 'preprint_initiated'
    PREPRINT_FILE_UPDATED = 'preprint_file_updated'
    PREPRINT_LICENSE_UPDATED = 'preprint_license_updated'

    VIEW_ONLY_LINK_ADDED = 'view_only_link_added'
    VIEW_ONLY_LINK_REMOVED = 'view_only_link_removed'

    actions = ([CHECKED_IN, CHECKED_OUT, FILE_TAG_REMOVED, FILE_TAG_ADDED, CREATED_FROM, PROJECT_CREATED,
                PROJECT_REGISTERED, PROJECT_DELETED, NODE_CREATED, NODE_FORKED, NODE_REMOVED,
                NODE_LINK_CREATED, NODE_LINK_FORKED, NODE_LINK_REMOVED, WIKI_UPDATED,
                WIKI_DELETED, WIKI_RENAMED, MADE_WIKI_PUBLIC,
                MADE_WIKI_PRIVATE, CONTRIB_ADDED, CONTRIB_REMOVED, CONTRIB_REORDERED,
                PERMISSIONS_UPDATED, MADE_PRIVATE, MADE_PUBLIC, TAG_ADDED, TAG_REMOVED, EDITED_TITLE,
                EDITED_DESCRIPTION, UPDATED_FIELDS, FILE_MOVED, FILE_COPIED,
                FOLDER_CREATED, FILE_ADDED, FILE_UPDATED, FILE_REMOVED, FILE_RESTORED, ADDON_ADDED,
                ADDON_REMOVED, COMMENT_ADDED, COMMENT_REMOVED, COMMENT_UPDATED, COMMENT_RESTORED,
                MADE_CONTRIBUTOR_VISIBLE,
                MADE_CONTRIBUTOR_INVISIBLE, EXTERNAL_IDS_ADDED, EMBARGO_APPROVED, EMBARGO_TERMINATED,
                EMBARGO_CANCELLED, EMBARGO_COMPLETED, EMBARGO_INITIATED, RETRACTION_APPROVED,
                RETRACTION_CANCELLED, RETRACTION_INITIATED, REGISTRATION_APPROVAL_CANCELLED,
                REGISTRATION_APPROVAL_INITIATED, REGISTRATION_APPROVAL_APPROVED,
                PREREG_REGISTRATION_INITIATED,
                CITATION_ADDED, CITATION_EDITED, CITATION_REMOVED,
                AFFILIATED_INSTITUTION_ADDED, AFFILIATED_INSTITUTION_REMOVED, PREPRINT_INITIATED,
                PREPRINT_FILE_UPDATED, PREPRINT_LICENSE_UPDATED, VIEW_ONLY_LINK_ADDED, VIEW_ONLY_LINK_REMOVED] + list(sum([
                    config.actions for config in apps.get_app_configs() if config.name.startswith('addons.')
                ], tuple())))
    action_choices = [(action, action.upper()) for action in actions]
    date = NonNaiveDateTimeField(db_index=True, null=True, blank=True, default=timezone.now)
    # TODO build action choices on the fly with the addon stuff
    action = models.CharField(max_length=255, db_index=True)  # , choices=action_choices)
    params = DateTimeAwareJSONField(default=dict)
    should_hide = models.BooleanField(default=False)
    user = models.ForeignKey('OSFUser', related_name='logs', db_index=True, null=True, blank=True)
    foreign_user = models.CharField(max_length=255, null=True, blank=True)
    node = models.ForeignKey('AbstractNode', related_name='logs',
                             db_index=True, null=True, blank=True)
    original_node = models.ForeignKey('AbstractNode', db_index=True, null=True, blank=True)

    def __unicode__(self):
        return ('({self.action!r}, user={self.user!r},, node={self.node!r}, params={self.params!r}) '
                'with id {self.id!r}').format(self=self)

    class Meta:
        ordering = ['-date']
        get_latest_by = 'date'

    @property
    def absolute_api_v2_url(self):
        path = '/logs/{}/'.format(self._id)
        return api_v2_url(path)

    def get_absolute_url(self):
        return self.absolute_api_v2_url

    @property
    def absolute_url(self):
        return self.absolute_api_v2_url

    def clone_node_log(self, node_id):
        """
        When a node is forked or registered, all logs on the node need to be
        cloned for the fork or registration.

        :param node_id:
        :return: cloned log
        """
        AbstractNode = apps.get_model('osf.AbstractNode')
        original_log = self.load(self._id)
        node = AbstractNode.load(node_id)
        log_clone = original_log.clone()
        log_clone.node = node
        log_clone.original_node = original_log.original_node
        log_clone.user = original_log.user
        log_clone.save()
        return log_clone

    def _natural_key(self):
        return self._id