Exemplo n.º 1
0
class OAuth2Client(db.Model, MyOAuth2ClientMixin):
    __tablename__ = 'oauth2_client'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(
        db.Integer, db.ForeignKey('user.id', ondelete='CASCADE'))
    class ClientTypes(str, enum.Enum):
        public = 'public'
        confidential = 'confidential'

    client_type = db.Column(db.Enum(ClientTypes), default=ClientTypes.public, nullable=False)
    default_scopes = db.Column(ScalarListType(separator=' '), nullable=False)
    scope = db.Column(ScalarListType(separator=' '), nullable=False)

    user = db.relationship('User')

    @property
    def default_redirect_uri(self):
        return self.get_default_redirect_uri()

    @classmethod
    def find(cls, client_id):
        if not client_id:
            return
        return cls.query.get(client_id)
class OAuth2Client(db.Model):
    """
    Model that binds OAuth2 Client ID and Secret to a specific User.
    """

    __tablename__ = 'oauth2_client'

    client_id = db.Column(db.String(length=40), primary_key=True)
    client_secret = db.Column(db.String(length=55), nullable=False)

    user_id = db.Column(db.ForeignKey('user.id', ondelete='CASCADE'), index=True, nullable=False)
    user = db.relationship(User)

    class ClientTypes(str, enum.Enum):
        public = 'public'
        confidential = 'confidential'

    client_type = db.Column(db.Enum(ClientTypes), default=ClientTypes.public, nullable=False)
    redirect_uris = db.Column(ScalarListType(separator=' '), default=[], nullable=False)
    default_scopes = db.Column(ScalarListType(separator=' '), nullable=False)

    @property
    def default_redirect_uri(self):
        redirect_uris = self.redirect_uris
        if redirect_uris:
            return redirect_uris[0]
        return None

    @classmethod
    def find(cls, client_id):
        if not client_id:
            return
        return cls.query.get(client_id)
Exemplo n.º 3
0
class OAuth2Client(db.Model):
    """
    Model that binds OAuth2 Client ID and Secret to a specific User.
    """

    __tablename__ = 'oauth2_client'

    guid = db.Column(db.GUID, default=uuid.uuid4, primary_key=True)
    secret = db.Column(db.String(length=64),
                       default=_generate_salt_64,
                       nullable=False)

    user_guid = db.Column(db.ForeignKey('user.guid', ondelete='CASCADE'),
                          index=True,
                          nullable=False)
    user = db.relationship(User)

    class ClientLevels(str, enum.Enum):
        public = 'public'
        session = 'session'
        confidential = 'confidential'

    level = db.Column(db.Enum(ClientLevels),
                      default=ClientLevels.public,
                      nullable=False)
    redirect_uris = db.Column(ScalarListType(separator=' '),
                              default=[],
                              nullable=False)
    default_scopes = db.Column(ScalarListType(separator=' '), nullable=False)

    @property
    def default_redirect_uri(self):
        redirect_uris = self.redirect_uris
        if redirect_uris:
            return redirect_uris[0]
        return None

    @property
    def client_id(self):
        return self.guid

    @property
    def client_secret(self):
        return self.secret

    @classmethod
    def find(cls, guid):
        if not guid:
            return None
        return cls.query.get(guid)

    def validate_scopes(self, scopes):
        # The only reason for this override is that Swagger UI has a bug which leads to that
        # `scope` parameter contains extra spaces between scopes:
        # https://github.com/frol/flask-restplus-server-example/issues/131
        return set(self.default_scopes).issuperset(set(scopes) - {''})

    def delete(self):
        with db.session.begin():
            db.session.delete(self)
class OAuth2Grant(db.Model):
    """
    Intermediate temporary helper for OAuth2 Grants.
    """

    __tablename__ = 'oauth2_grant'

    id = db.Column(db.Integer, primary_key=True)  # pylint: disable=invalid-name

    user_id = db.Column(db.ForeignKey('user.id', ondelete='CASCADE'), index=True, nullable=False)
    user = db.relationship('User')

    client_id = db.Column(
        db.String(length=40),
        db.ForeignKey('oauth2_client.client_id'),
        index=True,
        nullable=False,
    )
    client = db.relationship('OAuth2Client')

    code = db.Column(db.String(length=255), index=True, nullable=False)

    redirect_uri = db.Column(db.String(length=255), nullable=False)
    expires = db.Column(db.DateTime, nullable=False)

    scopes = db.Column(ScalarListType(separator=' '), nullable=False)

    def delete(self):
        db.session.delete(self)
        db.session.commit()
        return self

    @classmethod
    def find(cls, client_id, code):
        return cls.query.filter_by(client_id=client_id, code=code).first()
Exemplo n.º 5
0
class Voting(db.Model):
    __tablename__ = 'voting'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(128), nullable=False)
    description = db.Column(db.String(512), nullable=False)
    start_at = db.Column(db.DateTime, default=timezone.now)
    finish_at = db.Column(db.DateTime, nullable=False)
    items = db.Column(ScalarListType(), nullable=False)
    users = db.Column(ScalarListType(), default=[])
    enabled = db.Column(db.Boolean, default=True)
    anonymous = db.Column(db.Boolean, default=True)
    can_discard = db.Column(db.Boolean, default=True)
    select_count = db.Column(db.Integer, default=1)

    members = db.relationship('VotingMember', backref='voting', lazy='dynamic')

    @validates('finish_at')
    def validate_finish_at(self, key, value):
        if value <= self.start_at:
            raise ValueError('`finish_at` must be more then `start_at`')
        return value

    @hybrid_property
    def active(self) -> bool:
        return self.finish_at > timezone.now() >= self.start_at and self.enabled

    @active.expression
    def active(cls) -> bool:
        return db.and_(
            cls.finish_at > timezone.now(),
            cls.start_at <= timezone.now(),
            cls.enabled
        )

    def result(self) -> list:
        if timezone.now() < self.start_at:
            raise VotingError('Voting not started')
        if self.anonymous:
            return [m.result for m in self.memderships]
        else:
            return [(m.result, m.user_id) for m in self.memderships]
Exemplo n.º 6
0
class OAuth2Grant(db.Model):
    """
    Intermediate temporary helper for OAuth2 Grants.
    """

    __tablename__ = 'oauth2_grant'

    guid = db.Column(
        db.GUID, default=uuid.uuid4, primary_key=True
    )  # pylint: disable=invalid-name

    user_guid = db.Column(
        db.ForeignKey('user.guid', ondelete='CASCADE'), index=True, nullable=False
    )
    user = db.relationship('User')

    client_guid = db.Column(
        db.GUID,
        db.ForeignKey('oauth2_client.guid'),
        index=True,
        nullable=False,
    )
    client = db.relationship('OAuth2Client')

    code = db.Column(db.String(length=255), index=True, nullable=False)

    redirect_uri = db.Column(db.String(length=255), nullable=False)
    expires = db.Column(db.DateTime, nullable=False)

    scopes = db.Column(ScalarListType(separator=' '), nullable=False)

    def delete(self):
        with db.session.begin():
            db.session.delete(self)

    @property
    def client_id(self):
        return self.client_guid

    @classmethod
    def find(cls, client_guid, code):
        return cls.query.filter_by(client_guid=client_guid, code=code).first()

    @property
    def is_expired(self):
        now_utc = datetime.datetime.now(tz=pytz.utc)
        expired = now_utc > self.expires.replace(tzinfo=pytz.utc)
        return expired
Exemplo n.º 7
0
class OAuth2Token(db.Model):
    """
    OAuth2 Access Tokens storage model.
    """

    __tablename__ = 'oauth2_token'

    id = db.Column(db.Integer, primary_key=True)  # pylint: disable=invalid-name
    client_id = db.Column(
        db.String(length=40),
        db.ForeignKey('oauth2_client.client_id'),
        index=True,
        nullable=False,
    )
    client = db.relationship('OAuth2Client')

    user_id = db.Column(db.ForeignKey('user.id', ondelete='CASCADE'),
                        index=True,
                        nullable=False)
    user = db.relationship('User')

    class TokenTypes(str, enum.Enum):
        # currently only bearer is supported
        Bearer = 'Bearer'

    token_type = db.Column(db.Enum(TokenTypes), nullable=False)

    access_token = db.Column(db.String(length=255),
                             unique=True,
                             nullable=False)
    refresh_token = db.Column(db.String(length=255),
                              unique=True,
                              nullable=True)
    expires = db.Column(db.DateTime, nullable=False)
    scopes = db.Column(ScalarListType(separator=' '), nullable=False)

    @classmethod
    def find(cls, access_token=None, refresh_token=None):
        if access_token:
            return cls.query.filter_by(access_token=access_token).first()
        if refresh_token:
            return cls.query.filter_by(refresh_token=refresh_token).first()
        return None

    def delete(self):
        with db.session.begin():
            db.session.delete(self)
Exemplo n.º 8
0
class VotingMember(InternalAPIMixin, db.Model):
    __tablename__ = 'voting_members'
    __table_args__ = (
        db.UniqueConstraint('user_id', 'voting_id'),
    )

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    voting_id = db.Column(db.Integer, db.ForeignKey('voting.id'), nullable=False)
    result = db.Column(ScalarListType(), nullable=False)
    created = db.Column(db.DateTime, default=timezone.now)
    updated = db.Column(db.DateTime, onupdate=timezone.now)
    voted = db.Column(db.Boolean, default=False)
    enabled = db.Column(db.Boolean, default=True)

    async def get_user(self) -> RemoteUser:
        data = await self.internal_request('login', 'get_user', user_id=self.user_id)
        return RemoteUser(**data)

    @as_future
    def vote(self, items: Optional[list] = None) -> None:
        items = self.result or items
        if not items:
            raise VotingError('No items to vote')
        if not self.voting.active:
            raise VotingError('Voting not active')
        if not self.enabled:
            raise VotingError('Voting member disabled')
        if self.voted:
            raise VotingError('Already voted')
        if len(items) != self.voting.select_count:
            raise VotingError('Voting items count: %s/%s' % (len(items), self.voting.select_count))
        if not set(items).issubset(self.voting.items):
            raise VotingError('Voting items is %s. Must be a subset '
                              'of %s' % (','.join(items), ','.join(self.voting.items)))

        self.result = items
        self.voted = True
        self.save()

    @as_future
    def discard(self) -> None:
        if self.voting.can_discard:
            self.delete()
        else:
            raise VotingError('Cannot discard')
Exemplo n.º 9
0
class OAuth2Token(db.Model):
    """
    OAuth2 Access Tokens storage model.
    """

    __tablename__ = 'oauth2_token'

    guid = db.Column(
        db.GUID, default=uuid.uuid4, primary_key=True
    )  # pylint: disable=invalid-name

    client_guid = db.Column(
        db.GUID,
        db.ForeignKey('oauth2_client.guid'),
        index=True,
        nullable=False,
    )
    client = db.relationship('OAuth2Client')

    user_guid = db.Column(
        db.ForeignKey('user.guid', ondelete='CASCADE'), index=True, nullable=False
    )
    user = db.relationship('User')

    class TokenTypes(str, enum.Enum):
        # currently only bearer is supported
        Bearer = 'Bearer'

    token_type = db.Column(db.Enum(TokenTypes), nullable=False)

    access_token = db.Column(
        db.String(length=128),
        default=security.generate_random_128,
        unique=True,
        nullable=False,
    )
    refresh_token = db.Column(
        db.String(length=128),
        default=security.generate_random_128,
        unique=True,
        nullable=True,
    )
    expires = db.Column(db.DateTime, nullable=False)
    scopes = db.Column(ScalarListType(separator=' '), nullable=False)

    @property
    def client_id(self):
        return self.client_guid

    @classmethod
    def find(cls, access_token=None, refresh_token=None):
        response = None

        if access_token:
            response = cls.query.filter_by(access_token=access_token).first()

        if refresh_token:
            response = cls.query.filter_by(refresh_token=refresh_token).first()

        return response

    def delete(self):
        with db.session.begin():
            db.session.delete(self)

    @property
    def is_expired(self):
        now_utc = datetime.datetime.now(tz=pytz.utc)
        expired = now_utc > self.expires.replace(tzinfo=pytz.utc)
        return expired
Exemplo n.º 10
0
class Dataset(db.Model):
    """
    Database of datasets
    """
    __tablename__ = 'dataset'
    type = 'table'

    id = db.Column(db.String(128), primary_key=True)
    name = db.Column(db.String(128), unique=True, nullable=False)
    title = db.Column(db.String(256), nullable=False)
    description = db.Column(db.Text, nullable=False)
    homepage = db.Column(db.String(1024), nullable=False)
    version = db.Column(db.String(24))
    keywords = db.Column(ScalarListType(separator=' '), nullable=False)
    image = db.Column(db.String(1024))
    temporal = db.Column(db.String(64))
    spatial = db.Column(db.String(64))
    access_level = db.Column(db.String(32), nullable=False)
    copyrights = db.Column(db.String(256))
    accrual_periodicity = db.Column(db.String(32))
    specification = db.Column(db.Text)
    data_quality = db.Column(db.Boolean, nullable=False)
    data_dictionary = db.Column(db.String(1024))
    category = db.Column(db.String(128), nullable=False)
    issued_time = db.Column(db.String(64))
    language = db.Column(db.String(64))
    stars = db.Column(db.Integer, default=0)

    license_id = db.Column(db.Integer, db.ForeignKey('license.id'))
    license = db.relationship('License', backref='datasets')

    organization_id = db.Column(db.Integer, db.ForeignKey('organization.id'))
    organization = db.relationship('Organization', backref='datasets')

    # Original publisher of dataset
    publisher_id = db.Column(db.String(128), db.ForeignKey('publisher.id'))
    publisher = db.relationship('Publisher', backref='datasets')

    # Owner
    contributor_id = db.Column(db.Integer,
                               db.ForeignKey('user.id'),
                               nullable=True)
    contributor = db.relationship('User', backref='datasets')

    created = db.Column(db.DateTime(), default=func.now())
    updated = db.Column(db.DateTime(), onupdate=func.now())
    deleted = db.Column(db.Boolean, default=False)

    # relationships
    sources = db.relationship('Source', backref='dataset', lazy='dynamic')
    references = db.relationship('Reference',
                                 backref='dataset',
                                 lazy='dynamic')

    @classmethod
    def dataset_id(cls):
        return uuid.uuid4().hex

    @classmethod
    def get(cls, id=None, deleted=False, **kwargs):
        """
        DAO: query dataset by ID or arguments.
        :return: Dataset object or None
        """
        if id is not None:
            dataset = cls.query.filter_by(id=id, deleted=deleted,
                                          **kwargs).first()
            if dataset is None:
                raise ObjectDoesNotExist('Dataset "%s" does not exists' % id)
            return dataset

        if len(kwargs) > 0:
            return Dataset.query.filter_by(**kwargs).all()
        return None

    @classmethod
    def create(cls, **params):
        new_dataset = Dataset(
            id=cls.dataset_id(),
            name=params.get('name'),
            title=params.get('title'),
            license_id=params.get('license_id'),
            organization_id=params.get('organization_id'),
            publisher_id=params.get('publisher_id'),
            contributor_id=params.get('contributor_id'),
            description=params.get('description'),
            homepage=params.get('homepage'),
            version=params.get('version'),
            keywords=params.get('keywords'),
            image=params.get('image'),
            temporal=params.get('temporal'),
            spatial=params.get('spatial'),
            access_level=params.get('access_level'),
            copyrights=params.get('copyrights'),
            accrual_periodicity=params.get('accrual_periodicity'),
            specification=params.get('specification'),
            data_quality=params.get('data_quality'),
            data_dictionary=params.get('data_dictionary'),
            category=params.get('category'),
            issued_time=params.get('issued_time'),
            language=params.get('language'),
            stars=params.get('stars', 0))
        db.session.add(new_dataset)
        return new_dataset

    @classmethod
    def update(cls, id, **kwargs):
        cls.query.filter_by(id=id, deleted=False).update(dict(kwargs))
        return cls.get(id=id)

    @classmethod
    def delete(cls, id=None, dataset=None, hard=True):
        if id is not None:
            dataset = cls.get(id=id)

        if hard:
            db.session.delete(dataset)
        else:
            dataset.deleted = True

    @classmethod
    def delete_all(cls, hard=True):
        try:
            if not hard:
                db.session.get(Dataset).update(deleted=True)
            else:
                db.session.get(Dataset).delete()
        except Exception as e:
            logger.error(
                'Problems occur for deleting datastes, rollback: {}'.format(e))
            db.session.rollback()

    @classmethod
    def update_contributor(cls, dataset_id, contributor):
        dataset = cls.get(id=dataset_id)
        dataset.contributor = contributor

    @classmethod
    def update_license(cls, dataset_id, license):
        dataset = cls.get(id=dataset_id)
        dataset.license = license

    @classmethod
    def update_organization(cls, dataset_id, organization):
        dataset = cls.get(id=dataset_id)
        dataset.organization = organization

    @classmethod
    def update_publisher(cls, dataset_id, publisher):
        dataset = cls.get(id=dataset_id)
        dataset.publisher = publisher

    @classmethod
    def add_reference(cls, dataset_id, **params):
        """Add a new Reference
        """
        name = params.get('name')
        reference = params.get('reference')
        new_ref = Reference(dataset_id=dataset_id,
                            name=name,
                            reference=reference)
        db.session.add(new_ref)
        return new_ref

    @classmethod
    def add_source(cls, dataset_id, **params):
        """Add a new Source
        """
        title = params.get('title')
        format = params.get('format')
        access_url = params.get('access_url')
        download_url = params.get('download_url')
        if download_url is None:
            download_url = access_url
        email = params.get('email')
        description = params.get('description')
        media_type = params.get('media_type')
        schema = params.get('schema')

        new_source = Source(dataset_id=dataset_id,
                            title=title,
                            format=format,
                            access_url=access_url,
                            download_url=download_url,
                            email=email,
                            description=description,
                            media_type=media_type,
                            schema=schema)
        db.session.add(new_source)
        return new_source

    def associated_stories_num(self):
        """
        Get the number of associated stories with the dataset
        :return: integer
        """
        return len(list(self.stories_association))
Exemplo n.º 11
0
def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column(
        'project_classes',
        sa.Column('presentation_list', ScalarListType(), nullable=True))