Пример #1
0
class Grant(db.Model, CRUDMixin):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer)
    user = db.relationship('User',
                           primaryjoin='User.id == Grant.user_id',
                           foreign_keys='Grant.user_id',
                           cascade="all, delete")
    client_id = db.Column(db.String(40), nullable=False)
    client = db.relationship('Client',
                             primaryjoin='Client.client_id == Grant.client_id',
                             foreign_keys='Grant.client_id',
                             cascade="all, delete")
    code = db.Column(db.String(255), index=True, nullable=False)

    redirect_uri = db.Column(db.String(255))
    _scopes = db.Column('scopes', db.Text)
    expires = db.Column(db.DateTime)

    @property
    def scopes(self):
        if self._scopes:
            return self._scopes.split()
        return []

    @scopes.setter
    def scopes(self, scopes):
        self._scopes = ' '.join(scopes)
Пример #2
0
class Permission(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150))
    object_type = db.Column(db.String(150))
    action_name = db.Column(db.String(150))
    action_type = db.Column(db.String(150))
    object_id = db.Column(db.Integer)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)
Пример #3
0
class Setting(db.Model, CRUDMixin):
    id = db.Column(db.Integer, primary_key=True)
    key = db.Column(db.String(150), nullable=False)
    value = db.Column(db.Text)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)
Пример #4
0
class Role(db.Model, CRUDMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    slug = db.Column(db.String(100))
    description = db.Column(db.Text)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)
    permissions = db.relationship(
        'Permission',
        backref='roles',
        secondary=role_permission,
        primaryjoin='Role.id==role_permission.c.role_id',
        secondaryjoin='role_permission.c.permission_id==Permission.id',
        foreign_keys=[
            role_permission.c.role_id, role_permission.c.permission_id
        ])
Пример #5
0
class Token(db.Model, CRUDMixin):
    id = db.Column(db.Integer, primary_key=True)
    client_id = db.Column(db.String(40), nullable=False)
    client = db.relationship('Client',
                             backref=db.backref('tokens',
                                                cascade="all, delete"),
                             primaryjoin='Client.client_id == Token.client_id',
                             foreign_keys='Token.client_id')
    user_id = db.Column(db.Integer)
    user = db.relationship('User',
                           backref=db.backref('token',
                                              uselist=False,
                                              cascade="all, delete"),
                           primaryjoin='User.id == Token.user_id',
                           foreign_keys='Token.user_id')
    token_type = db.Column(db.String(40))
    access_token = db.Column(db.String(255))
    refresh_token = db.Column(db.String(255))
    expires = db.Column(db.DateTime)
    _scopes = db.Column('scopes', db.Text)

    def __init__(self, **kwargs):
        expires_in = kwargs.pop('expires_in')
        self.expires = datetime.utcnow() + timedelta(seconds=expires_in)
        for k, v in kwargs.items():
            setattr(self, k, v)

    @property
    def scopes(self):
        if self._scopes:
            return self._scopes.split()
        return []

    @scopes.setter
    def scopes(self, scopes):
        self._scopes = ' '.join(scopes)

    @property
    def is_expired(self):
        return datetime.utcnow() > self.expires
Пример #6
0
class Tag(db.Model, CRUDMixin):

    STATUS_DRAFT = 0
    STATUS_PUBLIC = 1
    STATUS_REMOVED = 2

    STATUSES = {
        STATUS_DRAFT: 'draft',
        STATUS_PUBLIC: 'public',
        STATUS_REMOVED: 'closed'
    }

    id = db.Column(db.Integer, primary_key=True)
    _name = db.Column('name', db.String(150))
    _slug = db.Column('slug', db.String(150), unique=True)
    description = db.Column(db.Text)
    _image = db.Column('image', db.String(255))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)

    __mapper_args__ = {'order_by': id.desc()}

    @hybrid_property
    def slug(self):
        return self._slug

    @slug.setter
    def slug(self, slug):
        slugify_slug = slugify(slug) if slug else slugify(self.title)
        if not self._slug:
            self._slug = slugify_slug

            for x in itertools.count(1):
                if not db.session.query(
                        db.exists().where(Tag.slug == self._slug)).scalar():
                    break
                self._slug = "{}-{}".format(slugify_slug, x)
            return
        self._slug = slugify_slug

    @hybrid_property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name.strip()
        if self.slug is None:
            self.slug = slugify(name)[:255]

    @hybrid_property
    def num_posts(self):
        return len(self.posts)

    @hybrid_property
    def image(self):
        if self._image:
            return dict(url=storage.url(self._image), filename=self._image)
        return {}

    @image.setter
    def image(self, image=None):
        if image is None:
            image = {}
        self._image = image.get('filename')

    image = db.synonym("_image", descriptor=image)
Пример #7
0
class Post(db.Model, CRUDMixin):

    STATUS_DRAFT = 'draft'
    STATUS_PUBLIC = 'published'
    STATUS_REMOVED = 'removed'

    id = db.Column(db.Integer, primary_key=True)
    _title = db.Column('title', db.String(255))
    _slug = db.Column('slug', db.String(255), unique=True)
    _markdown = db.Column('markdown', db.Text)
    content = db.Column(db.Text)
    excerpt = db.Column(db.Text)
    _image = db.Column('image', db.String(255))
    views = db.Column(db.Integer, default=0)
    status = db.Column(db.String(150), default=STATUS_DRAFT)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    created_by = db.Column(db.Integer, index=True)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)
    updated_by = db.Column(db.Integer, index=True)
    published_at = db.Column(db.DateTime)
    published_by = db.Column(db.Integer, index=True)

    __mapper_args__ = {'order_by': id.desc()}

    tags = db.relationship(
        'Tag',
        secondary=post_tag,
        primaryjoin='Post.id == post_tag.c.post_id',
        secondaryjoin='post_tag.c.tag_id==Tag.id',
        foreign_keys='[post_tag.c.post_id, post_tag.c.tag_id]',
        backref='posts')

    author = db.relationship('User',
                             primaryjoin='Post.created_by == User.id',
                             foreign_keys='Post.created_by',
                             backref='posts')

    @hybrid_property
    def markdown(self):
        return self._markdown

    @markdown.setter
    def markdown(self, markdown):
        self._markdown = markdown
        renderer = mistune.Renderer(escape=False)
        markdown = mistune.Markdown(renderer=renderer)
        self.content = markdown(self._markdown)

    def get_excerpt(self, length=100):
        # return re.sub(r'<.*?>', '', (self.excerpt or self.content))[:length]
        return Markup(self.excerpt or self.content).striptags()[:length]

    @hybrid_property
    def title(self):
        return self._title

    @title.setter
    def title(self, title):
        self._title = title.strip()
        if self.slug is None:
            self.slug = slugify(title)[:255]

    @hybrid_property
    def slug(self):
        return self._slug

    @slug.setter
    def slug(self, slug):
        slugify_slug = slugify(slug) if slug else slugify(self.title)
        if not self._slug:
            self._slug = slugify_slug
            for x in itertools.count(1):
                if not db.session.query(
                        db.exists().where(Post.slug == self._slug)).scalar():
                    break
                self._slug = "{}-{}".format(slugify_slug, x)
            return
        self._slug = slugify_slug

    @hybrid_property
    def image(self):
        if self._image:
            return dict(url=storage.url(self._image), filename=self._image)
        return {}

    @image.setter
    def image(self, image=None):
        if image is None:
            image = {}
        self._image = image.get('filename')

    image = db.synonym("_image", descriptor=image)
Пример #8
0
class User(db.Model, CRUDMixin):
    query_class = UserQuery

    STATUS_ACTIVE = 'active'
    STATUS_FORBIDDEN = 'forbidden'

    id = db.Column(db.Integer, primary_key=True)
    _name = db.Column('name', db.String(100), unique=True, index=True)
    _slug = db.Column('slug', db.String(100), unique=True, index=True)
    _password = db.Column("password", db.String(60), nullable=False)
    email = db.Column(db.String(100), unique=True, nullable=False)
    primary_role_id = db.Column(db.Integer)
    status = db.Column(db.String(100), nullable=False, default=STATUS_ACTIVE)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)

    primary_role = db.relationship('Role',
                                   lazy="joined",
                                   backref="primary_users",
                                   uselist=False,
                                   primaryjoin='User.primary_role_id==Role.id',
                                   foreign_keys=[primary_role_id])

    secondary_roles = db.relationship(
        'Role',
        backref=db.backref('users', lazy='dynamic'),
        secondary=user_role,
        primaryjoin='User.id==user_role.c.user_id',
        secondaryjoin='user_role.c.role_id==Role.id',
        foreign_keys=[user_role.c.user_id, user_role.c.role_id],
        lazy='dynamic')

    @hybrid_property
    def name(self):
        return self._name

    @name.setter
    def name(self, name):
        self._name = name.strip()
        if self.slug is None:
            self.slug = slugify(name)[:255]

    @hybrid_property
    def slug(self):
        return self._slug

    @slug.setter
    def slug(self, slug):
        self._slug = slugify(slug) if slug else slugify(self.name)

    @hybrid_property
    def password(self):
        return self._password

    @password.setter
    def password(self, password):
        self._password = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self._password, password)

    @property
    def roles(self):
        return [self.primary_role] + list(self.secondary_roles)

    @cached_property
    def permissions(self):
        perms = []
        for role in self.roles:
            perms.extend(role.permissions)
        role = Role.query.filter_by(slug='owner').first()
        if role and self.primary_role == role:
            perms.extend(Permission.query.all())
        return list(set(perms))

    @cached_property
    def provides(self):
        needs = [RoleNeed('authenticated'), UserNeed(self.id)]

        needs.extend([
            Need(perm.object_type, perm.action_type, perm.object_id)
            for perm in self.permissions
        ])

        return needs

    @cached_property
    def avatar(self):
        gravatar_url = "https://www.gravatar.com/avatar/"
        return gravatar_url + hashlib.md5(self.email.lower()).hexdigest()
Пример #9
0
class Client(db.Model, CRUDMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(40), unique=True)
    client_id = db.Column(db.String(40), index=True, default=gen_salt(40))
    client_secret = db.Column(db.String(55),
                              unique=True,
                              index=True,
                              nullable=False,
                              default=gen_salt(40))
    _redirect_uris = db.Column('redirect_uris',
                               db.Text,
                               default=" ".join([
                                   'http://localhost:8000/authorized',
                                   'http://127.0.0.1:8000/authorized',
                                   'http://127.0.1:8000/authorized',
                                   'http://127.1:8000/authorized',
                               ]))
    _default_scopes = db.Column('default_scopes',
                                db.Text,
                                default='email address')
    disallow_grant_type = db.Column(db.String(20))
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    updated_at = db.Column(db.DateTime,
                           default=datetime.utcnow,
                           onupdate=datetime.utcnow)

    @hybrid_property
    def redirect_uris(self):
        if self._redirect_uris:
            return self._redirect_uris.split()
        return []

    @redirect_uris.setter
    def redirect_uris(self, redirect_uris):
        self._redirect_uris = ' '.join(redirect_uris)

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

    @hybrid_property
    def default_scopes(self):
        if self._default_scopes:
            return self._default_scopes.split()
        return []

    @default_scopes.setter
    def default_scopes(self, default_scopes):
        self._default_scope = ' '.join(default_scopes)

    @property
    def allowed_grant_types(self):
        types = [
            'authorization_code',
            'password',
            'client_credentials',
            'refresh_token',
        ]
        if self.disallow_grant_type:
            types.remove(self.disallow_grant_type)
        return types