Exemple #1
0
class Discussion(db.Document):
    user = db.ReferenceField('User')
    subject = db.GenericReferenceField()
    title = db.StringField(required=True)
    discussion = db.ListField(db.EmbeddedDocumentField(Message))
    created = db.DateTimeField(default=datetime.now, required=True)
    closed = db.DateTimeField()
    closed_by = db.ReferenceField('User')
    extras = db.ExtrasField()

    meta = {
        'indexes': [
            'user',
            'subject',
            '-created'
        ],
        'ordering': ['-created'],
    }

    def person_involved(self, person):
        """Return True if the given person has been involved in the

        discussion, False otherwise.
        """
        return any(message.posted_by == person for message in self.discussion)

    @property
    def external_url(self):
        return self.subject.url_for(
            _anchor='discussion-{id}'.format(id=self.id),
            _external=True)
Exemple #2
0
class Resource(WithMetrics, db.EmbeddedDocument):
    id = db.AutoUUIDField()
    title = db.StringField(verbose_name="Title", required=True)
    description = db.StringField()
    type = db.StringField(choices=RESOURCE_TYPES.keys(),
                          default='file',
                          required=True)
    url = db.StringField()
    urlhash = db.StringField()
    checksum = db.EmbeddedDocumentField(Checksum)
    format = db.StringField()
    mime = db.StringField()
    size = db.IntField()
    owner = db.ReferenceField('User')

    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
    modified = db.DateTimeField(default=datetime.datetime.now, required=True)
    published = db.DateTimeField(default=datetime.datetime.now, required=True)
    deleted = db.DateTimeField()

    on_added = Signal()
    on_deleted = Signal()

    def clean(self):
        super(Resource, self).clean()
        if not self.urlhash or 'url' in self._get_changed_fields():
            self.urlhash = hash_url(self.url)
Exemple #3
0
class HarvestSource(db.Owned, db.Document):
    name = db.StringField(max_length=255)
    slug = db.SlugField(max_length=255,
                        required=True,
                        unique=True,
                        populate_from='name',
                        update=True)
    description = db.StringField()
    url = db.StringField(required=True)
    backend = db.StringField()
    config = db.DictField()
    periodic_task = db.ReferenceField('PeriodicTask',
                                      reverse_delete_rule=db.NULLIFY)
    created_at = db.DateTimeField(default=datetime.now, required=True)
    frequency = db.StringField(choices=HARVEST_FREQUENCIES.keys(),
                               default=DEFAULT_HARVEST_FREQUENCY,
                               required=True)
    active = db.BooleanField(default=True)
    validation = db.EmbeddedDocumentField(HarvestSourceValidation,
                                          default=HarvestSourceValidation)

    deleted = db.DateTimeField()

    @property
    def domain(self):
        parsed = urlparse(self.url)
        return parsed.netloc.split(':')[0]

    @classmethod
    def get(cls, ident):
        return cls.objects(slug=ident).first() or cls.objects.get(pk=ident)

    def get_last_job(self):
        return HarvestJob.objects(source=self).order_by('-created').first()

    @cached_property
    def last_job(self):
        return self.get_last_job()

    @property
    def schedule(self):
        if not self.periodic_task:
            return
        return self.periodic_task.schedule_display

    meta = {
        'indexes': [
            '-created_at',
            'slug',
            ('deleted', '-created_at'),
        ] + db.Owned.meta['indexes'],
        'ordering': ['-created_at'],
        'queryset_class':
        HarvestSourceQuerySet,
    }

    def __unicode__(self):
        return self.name or ''
class HarvestJob(db.Document):
    '''Keep track of harvestings'''
    created = db.DateTimeField(default=datetime.now, required=True)
    started = db.DateTimeField()
    ended = db.DateTimeField()
    status = db.StringField(choices=HARVEST_JOB_STATUS.keys(),
                            default=DEFAULT_HARVEST_JOB_STATUS, required=True)
    errors = db.ListField(db.EmbeddedDocumentField(HarvestError))
    items = db.ListField(db.EmbeddedDocumentField(HarvestItem))
    source = db.ReferenceField(HarvestSource, reverse_delete_rule=db.NULLIFY)
class HarvestItem(db.EmbeddedDocument):
    remote_id = db.StringField()
    dataset = db.ReferenceField(Dataset)
    status = db.StringField(choices=HARVEST_ITEM_STATUS.keys(),
                            default=DEFAULT_HARVEST_ITEM_STATUS, required=True)
    created = db.DateTimeField(default=datetime.now, required=True)
    started = db.DateTimeField()
    ended = db.DateTimeField()
    errors = db.ListField(db.EmbeddedDocumentField(HarvestError))
    args = db.ListField(db.StringField())
    kwargs = db.DictField()
Exemple #6
0
class Issue(db.Document):
    user = db.ReferenceField('User')
    subject = db.GenericReferenceField()
    title = db.StringField(required=True)
    discussion = db.ListField(db.EmbeddedDocumentField(Message))
    created = db.DateTimeField(default=datetime.now, required=True)
    closed = db.DateTimeField()
    closed_by = db.ReferenceField('User')

    meta = {
        'indexes': ['user', 'subject', '-created'],
        'ordering': ['-created'],
    }
Exemple #7
0
class Discussion(db.Document):
    user = db.ReferenceField('User')
    subject = db.ReferenceField(db.DomainModel)
    title = db.StringField(required=True)
    discussion = db.ListField(db.EmbeddedDocumentField(Message))
    created = db.DateTimeField(default=datetime.now, required=True)
    closed = db.DateTimeField()
    closed_by = db.ReferenceField('User')

    meta = {
        'indexes': ['user', 'subject', 'created'],
        'allow_inheritance': True,
        'ordering': ['created'],
    }
Exemple #8
0
class OAuth2Grant(db.Document):
    user = db.ReferenceField('User', required=True)
    client = db.ReferenceField('OAuth2Client', required=True)

    code = db.StringField(required=True)

    redirect_uri = db.StringField()
    expires = db.DateTimeField()

    scopes = db.ListField(db.StringField())

    meta = {
        'collection': 'oauth2_grant'
    }

    def __str__(self):
        return '<OAuth2Grant({0.client.name}, {0.user.fullname})>'.format(self)

    def is_expired(self):
        return self.expires < datetime.utcnow()

    def get_redirect_uri(self):
        return self.redirect_uri

    def get_scope(self):
        return ' '.join(self.scopes)
Exemple #9
0
class Badge(db.EmbeddedDocument):
    kind = db.StringField(choices=[], required=True)
    created = db.DateTimeField(default=datetime.now, required=True)
    created_by = db.ReferenceField('User')
    removed = db.DateTimeField()
    removed_by = db.ReferenceField('User')

    meta = {
        'allow_inheritance': True,
        'ordering': ['created'],
    }

    def __unicode__(self):
        return self.kind

    __str__ = __unicode__
Exemple #10
0
class OAuth2Code(db.Document):
    user = db.ReferenceField('User', required=True)
    client = db.ReferenceField('OAuth2Client', required=True)

    code = db.StringField(required=True)

    redirect_uri = db.StringField()
    expires = db.DateTimeField()

    scope = db.StringField(default='')
    code_challenge = db.StringField()
    code_challenge_method = db.StringField()

    meta = {'collection': 'oauth2_code'}

    def __str__(self):
        return '<OAuth2Code({0.client.name}, {0.user.fullname})>'.format(self)

    def is_expired(self):
        return self.expires < datetime.utcnow()

    def get_redirect_uri(self):
        return self.redirect_uri

    def get_scope(self):
        return self.scope
Exemple #11
0
class HarvestSource(db.Document):
    name = db.StringField(max_length=255)
    slug = db.SlugField(max_length=255,
                        required=True,
                        unique=True,
                        populate_from='name',
                        update=True)
    description = db.StringField()
    url = db.StringField()
    backend = db.StringField()
    config = db.DictField()
    periodic_task = db.ReferenceField('PeriodicTask',
                                      reverse_delete_rule=db.NULLIFY)
    created_at = db.DateTimeField(default=datetime.now, required=True)
    frequency = db.StringField(choices=HARVEST_FREQUENCIES.keys(),
                               default=DEFAULT_HARVEST_FREQUENCY,
                               required=True)
    active = db.BooleanField(default=True)

    owner = db.ReferenceField('User', reverse_delete_rule=db.NULLIFY)
    organization = db.ReferenceField('Organization',
                                     reverse_delete_rule=db.NULLIFY)

    @classmethod
    def get(cls, ident):
        return cls.objects(slug=ident).first() or cls.objects.get(id=ident)

    def get_last_job(self):
        return HarvestJob.objects(source=self).order_by('-created')[0]
Exemple #12
0
class OAuth2Token(db.Document):
    client = db.ReferenceField('OAuth2Client', required=True)
    user = db.ReferenceField('User')

    # currently only bearer is supported
    token_type = db.StringField(choices=TOKEN_TYPES.keys(), default='Bearer')

    access_token = db.StringField(unique=True)
    refresh_token = db.StringField(unique=True, sparse=True)
    created_at = db.DateTimeField(default=datetime.utcnow, required=True)
    expires_in = db.IntField(required=True, default=TOKEN_EXPIRATION)
    scopes = db.ListField(db.StringField())

    meta = {'collection': 'oauth2_token'}

    def __unicode__(self):
        return '<OAuth2Token({0.client.name})>'.format(self)

    def get_scope(self):
        return ' '.join(self.scopes)

    def get_expires_in(self):
        return self.expires_in

    def get_expires_at(self):
        return (self.created_at - EPOCH).total_seconds() + self.expires_in

    def is_refresh_token_expired(self):
        expired_at = datetime.fromtimestamp(self.get_expires_at())
        expired_at += timedelta(days=REFRESH_EXPIRATION)
        return expired_at < datetime.utcnow()
Exemple #13
0
class Follow(db.Document):
    follower = db.ReferenceField('User', required=True)
    following = db.GenericReferenceField()
    since = db.DateTimeField(required=True, default=datetime.now)
    until = db.DateTimeField()

    meta = {
        'indexes': [
            'follower',
            'following',
            ('follower', 'until'),
            ('following', 'until'),
        ],
        'queryset_class':
        FollowQuerySet,
    }
Exemple #14
0
class ResourceMixin(object):
    id = db.AutoUUIDField(primary_key=True)
    title = db.StringField(verbose_name="Title", required=True)
    description = db.StringField()
    filetype = db.StringField(choices=RESOURCE_TYPES.keys(),
                              default='file',
                              required=True)
    url = db.StringField()
    urlhash = db.StringField()
    checksum = db.EmbeddedDocumentField(Checksum)
    format = db.StringField()
    mime = db.StringField()
    filesize = db.IntField()  # `size` is a reserved keyword for mongoengine.

    created_at = db.DateTimeField(default=datetime.now, required=True)
    modified = db.DateTimeField(default=datetime.now, required=True)
    published = db.DateTimeField(default=datetime.now, required=True)
    deleted = db.DateTimeField()

    def clean(self):
        super(ResourceMixin, self).clean()
        if not self.urlhash or 'url' in self._get_changed_fields():
            self.urlhash = hash_url(self.url)

    @property
    def closed_format(self):
        """Return True if the specified format is in CLOSED_FORMATS."""
        return self.format.lower() in CLOSED_FORMATS

    def check_availability(self, group):
        """Check if a resource is reachable against a Croquemort server.

        Return a boolean.
        """
        if self.filetype == 'remote':
            # We perform a quick check for performances matters.
            error, response = check_url_from_cache(self.url, group)
            if error or int(response.get('status', 500)) >= 500:
                return False
            else:
                return True
        else:
            return True  # We consider that API cases (types) are OK.

    @property
    def is_available(self):
        return self.check_availability(group=None)
Exemple #15
0
class HarvestJob(db.Document):
    '''Keep track of harvestings'''
    created = db.DateTimeField(default=datetime.now, required=True)
    started = db.DateTimeField()
    ended = db.DateTimeField()
    status = db.StringField(choices=HARVEST_JOB_STATUS.keys(),
                            default=DEFAULT_HARVEST_JOB_STATUS,
                            required=True)
    errors = db.ListField(db.EmbeddedDocumentField(HarvestError))
    items = db.ListField(db.EmbeddedDocumentField(HarvestItem))
    source = db.ReferenceField(HarvestSource, reverse_delete_rule=db.CASCADE)
    data = db.DictField()

    meta = {
        'indexes': ['-created', 'source', ('source', '-created')],
        'ordering': ['-created'],
    }
Exemple #16
0
class Member(db.EmbeddedDocument):
    user = db.ReferenceField('User')
    role = db.StringField(choices=list(ORG_ROLES), default=DEFAULT_ROLE)
    since = db.DateTimeField(default=datetime.now, required=True)

    @property
    def label(self):
        return ORG_ROLES[self.role]
Exemple #17
0
class HarvestSourceValidation(db.EmbeddedDocument):
    '''Store harvest source validation details'''
    state = db.StringField(choices=VALIDATION_STATES.keys(),
                           default=VALIDATION_PENDING,
                           required=True)
    by = db.ReferenceField('User')
    on = db.DateTimeField()
    comment = db.StringField()
Exemple #18
0
class License(db.Document):
    # We need to declare id explicitly since we do not use the default
    # value set by Mongo.
    id = db.StringField(primary_key=True)
    created_at = db.DateTimeField(default=datetime.now, required=True)
    title = db.StringField(required=True)
    slug = db.SlugField(required=True, populate_from='title')
    url = db.URLField()
    maintainer = db.StringField()
    flags = db.ListField(db.StringField())

    active = db.BooleanField()

    def __unicode__(self):
        return self.title

    @classmethod
    def guess(cls, *strings, **kwargs):
        '''
        Try to guess a license from a list of strings.

        Accept a `default` keyword argument which will be
        the default fallback license.
        '''
        license = None
        for string in strings:
            license = cls.guess_one(string)
            if license:
                break
        return license or kwargs.get('default')

    @classmethod
    def guess_one(cls, text):
        '''
        Try to guess license from a string.

        Try to exact match on identifier then slugified title
        and fallback on edit distance ranking (after slugification)
        '''
        if not text:
            return
        qs = cls.objects
        text = text.strip().lower()  # Stored identifiers are lower case
        slug = cls.slug.slugify(text)  # Use slug as it normalize string
        license = qs(db.Q(id=text) | db.Q(slug=slug) | db.Q(url=text)).first()
        if license is None:
            # Try to single match with a low Damerau-Levenshtein distance
            computed = ((l, rdlevenshtein(l.slug, slug)) for l in cls.objects)
            candidates = [l for l, d in computed if d <= MAX_DISTANCE]
            # If there is more that one match, we cannot determinate
            # which one is closer to safely choose between candidates
            if len(candidates) == 1:
                license = candidates[0]
        return license

    @classmethod
    def default(cls):
        return cls.objects(id=DEFAULT_LICENSE['id']).first()
Exemple #19
0
class PiwikTracking(db.Document):
    url = db.StringField(required=True)
    date = db.DateTimeField(required=True, default=datetime.now)
    kwargs = db.DictField()

    meta = {
        'indexes': ['date'],
        'ordering': ['date'],
    }
Exemple #20
0
class MembershipRequest(db.EmbeddedDocument):
    '''
    Pending organization membership requests
    '''
    id = db.AutoUUIDField()
    user = db.ReferenceField('User')
    status = db.StringField(choices=list(MEMBERSHIP_STATUS), default='pending')

    created = db.DateTimeField(default=datetime.now, required=True)

    handled_on = db.DateTimeField()
    handled_by = db.ReferenceField('User')

    comment = db.StringField()
    refusal_comment = db.StringField()

    @property
    def status_label(self):
        return MEMBERSHIP_STATUS[self.status]
Exemple #21
0
class Post(db.Datetimed, db.Document):
    name = db.StringField(max_length=255, required=True)
    slug = db.SlugField(max_length=255,
                        required=True,
                        populate_from='name',
                        update=True,
                        follow=True)
    headline = db.StringField()
    content = db.StringField(required=True)
    image_url = db.StringField()
    image = db.ImageField(fs=images,
                          basename=default_image_basename,
                          thumbnails=IMAGE_SIZES)

    credit_to = db.StringField()
    credit_url = db.URLField()

    tags = db.ListField(db.StringField())
    datasets = db.ListField(
        db.ReferenceField('Dataset', reverse_delete_rule=db.PULL))
    reuses = db.ListField(
        db.ReferenceField('Reuse', reverse_delete_rule=db.PULL))

    owner = db.ReferenceField('User')
    published = db.DateTimeField()

    meta = {
        'ordering': ['-created_at'],
        'indexes': [
            '-created_at',
            '-published',
        ],
        'queryset_class': PostQuerySet,
    }

    verbose_name = _('post')

    def __str__(self):
        return self.name or ''

    def url_for(self, *args, **kwargs):
        return url_for('posts.show', post=self, *args, **kwargs)

    @property
    def display_url(self):
        return self.url_for()

    @property
    def external_url(self):
        return self.url_for(_external=True)

    def count_discussions(self):
        # There are no metrics on Post to store discussions count
        pass
Exemple #22
0
class Discussion(db.Document):
    user = db.ReferenceField('User')
    subject = db.ReferenceField(db.DomainModel)
    title = db.StringField(required=True)
    discussion = db.ListField(db.EmbeddedDocumentField(Message))
    created = db.DateTimeField(default=datetime.now, required=True)
    closed = db.DateTimeField()
    closed_by = db.ReferenceField('User')

    meta = {
        'indexes': ['user', 'subject', 'created'],
        'allow_inheritance': True,
        'ordering': ['created'],
    }

    def person_involved(self, person):
        """Return True if the given person has been involved in the

        discussion, False otherwise.
        """
        return any(message.posted_by == person for message in self.discussion)
Exemple #23
0
class OAuth2Grant(db.Document):
    user = db.ReferenceField('User', required=True)
    client = db.ReferenceField('OAuth2Client', required=True)

    code = db.StringField(required=True)

    redirect_uri = db.StringField()
    expires = db.DateTimeField()

    scopes = db.ListField(db.StringField())

    meta = {'collection': 'oauth2_grant'}
Exemple #24
0
class Transfer(db.Document):
    owner = db.GenericReferenceField(required=True)
    recipient = db.GenericReferenceField(required=True)
    subject = db.GenericReferenceField(required=True)
    comment = db.StringField()
    status = db.StringField(choices=list(TRANSFER_STATUS), default='pending')

    created = db.DateTimeField(default=datetime.now, required=True)

    responded = db.DateTimeField()
    responder = db.ReferenceField('User')
    response_comment = db.StringField()

    meta = {
        'indexes': [
            'owner',
            'recipient',
            'created',
            'status',
        ]
    }
Exemple #25
0
class License(db.Document):
    id = db.StringField(primary_key=True)
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
    title = db.StringField(required=True)
    slug = db.SlugField(required=True, populate_from='title')
    url = db.URLField()
    maintainer = db.StringField()
    flags = db.ListField(db.StringField())

    active = db.BooleanField()

    def __unicode__(self):
        return self.title
Exemple #26
0
class Badge(db.EmbeddedDocument):
    kind = db.StringField(required=True)
    created = db.DateTimeField(default=datetime.now, required=True)
    created_by = db.ReferenceField('User')

    def __str__(self):
        return self.kind

    def validate(self, clean=True):
        badges = getattr(self._instance, '__badges__', {})
        if self.kind not in badges.keys():
            raise db.ValidationError('Unknown badge type %s' % self.kind)
        return super(Badge, self).validate(clean=clean)
Exemple #27
0
class Issue(db.Document):
    user = db.ReferenceField('User')
    subject = db.ReferenceField(db.DomainModel)
    type = db.StringField(choices=ISSUE_TYPES.keys())

    discussion = db.ListField(db.EmbeddedDocumentField(Message))

    created = db.DateTimeField(default=datetime.now, required=True)
    closed = db.DateTimeField()
    closed_by = db.ReferenceField('User')

    meta = {
        'indexes': ['user', 'subject', 'created'],
        'allow_inheritance': True,
    }

    @property
    def type_label(self):
        return ISSUE_TYPES[self.type]

    @property
    def description(self):
        return self.discussion[0].content
Exemple #28
0
class OAuth2Token(db.Document):
    client = db.ReferenceField('OAuth2Client', required=True)
    user = db.ReferenceField('User')

    # currently only bearer is supported
    token_type = db.StringField(choices=TOKEN_TYPES.keys(), default='Bearer')

    access_token = db.StringField(unique=True)
    refresh_token = db.StringField(unique=True)
    expires = db.DateTimeField(
        default=lambda: datetime.utcnow() + timedelta(hours=TOKEN_EXPIRATION))
    scopes = db.ListField(db.StringField())

    meta = {'collection': 'oauth2_token'}
class License(db.Document):
    # We need to declare id explicitly since we do not use the default
    # value set by Mongo.
    id = db.StringField(primary_key=True)
    created_at = db.DateTimeField(default=datetime.now, required=True)
    title = db.StringField(required=True)
    slug = db.SlugField(required=True, populate_from='title')
    url = db.URLField()
    maintainer = db.StringField()
    flags = db.ListField(db.StringField())

    active = db.BooleanField()

    def __unicode__(self):
        return self.title
Exemple #30
0
class Activity(db.Document):
    '''Store the activity entries for a single related object'''
    actor = db.ReferenceField('User', required=True)
    organization = db.ReferenceField('Organization')
    related_to = db.ReferenceField(db.DomainModel, required=True)
    created_at = db.DateTimeField(default=datetime.now, required=True)

    kwargs = db.DictField()

    on_new = Signal()

    __metaclass__ = EmitNewActivityMetaClass

    meta = {
        'indexes': [
            'actor',
            'organization',
            'related_to',
            '-created_at',
            ('actor', '-created_at'),
            ('organization', '-created_at'),
            ('related_to', '-created_at'),
        ],
        'allow_inheritance': True,
    }

    key = None
    label = None
    badge_type = 'primary'
    icon = 'fa fa-info-circle'
    template = 'activity/base.html'

    @classmethod
    def connect(cls, func):
        return cls.on_new.connect(func, sender=cls)

    @classmethod
    def emit(cls, related_to, organization=None, **kwargs):
        return cls.objects.create(
            actor=current_user._get_current_object(),
            related_to=related_to,
            organization=organization
        )