Ejemplo n.º 1
0
class Parameter(db.Model):
    __tablename__ = 'parameters'

    key = db.Column(db.String, primary_key=True)
    value = db.Column(db.String, nullable=False)

    cache = timestamp = None

    @classmethod
    def get_all(cls):
        items = Parameter.query \
                .all()

        values = {}
        for item in items:
            values[item.key] = item.value

        return values

    @classmethod
    def get(cls, key, default='', cast=None):
        now = time.time()

        if not cls.cache or cls.timestamp + CACHE_DELAY > now:
            cls.cache = cls.get_all()
            cls.timestamp = now

        value = cls.cache.get(key, default)

        if cast:
            value = cast(value)

        return value

    @classmethod
    def clear_cache(cls):
        cls.cache = cls.timestamp = None

    @classmethod
    def set(cls, key, value):
        items = Parameter.query \
                .filter(Parameter.key == key)

        for item in items:
            db.session.delete(item)

        Parameter(key=key, value=value) \
                .save()

    def save(self):
        db.session.add(self)

        return self
Ejemplo n.º 2
0
class Metadata(db.Model):
    __tablename__ = 'metadata'

    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String, nullable=False)
    key = db.Column(db.String, nullable=False)
    value = db.Column(db.String, nullable=False)

    structural_keys = ('previous', 'next', 'type')

    @classmethod
    def get(cls, slug, key=None, ignores=None, structural=True):
        items = Metadata.query \
                .filter(Metadata.slug == slug) \

        if key:
            items = items.filter(Metadata.key == key) \
                    .all()

            return [item.value for item in items]

        if ignores:
            items = items.filter(Metadata.key.notin_(ignores))

        if not structural:
            items = items.filter(Metadata.key.notin_(Metadata.structural_keys))

        return items.order_by(Metadata.key, Metadata.value) \
                .all()

    @classmethod
    def search(cls, key, value):
        items = db.session.query(Metadata.slug) \
                .filter(Metadata.key == key) \
                .filter(Metadata.value == value) \
                .order_by(Metadata.key, Metadata.value)

        return set([item[0] for item in items])

    @classmethod
    def deactivate(cls, slug):
        for item in Metadata.get(slug):
            db.session.delete(item)

    def save(self):
        db.session.add(self)

        return self
Ejemplo n.º 3
0
class Token(db.Model):
    __tablename__ = 'tokens'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, nullable=False)
    digest = db.Column(db.String, nullable=False)
    payload = db.Column(db.String, nullable=False)
    nonce = db.Column(db.String, nullable=False)
    expiry = db.Column(db.DateTime, nullable=False)
    timestamp = db.Column(db.DateTime,
                          nullable=False,
                          default=datetime.datetime.utcnow)

    @classmethod
    def get(cls, user, digest):
        return Token.query \
            .filter(Token.user_id == user.id) \
            .filter(Token.digest == digest) \
            .one_or_none()

    @classmethod
    def make(cls, user, payload, duration=DEFAULT_DURATION):
        nonce = secret(size=10)
        duration = datetime.timedelta(seconds=duration)
        timestamp = datetime.datetime.utcnow()
        expiry = timestamp + duration

        token = Token(user_id=user.id,
                      payload=payload,
                      expiry=expiry,
                      nonce=nonce,
                      timestamp=timestamp)

        token.digest = token.make_digest(payload)

        return token

    def make_digest(self, payload):
        message = self.nonce + str(self.timestamp) + payload

        if isinstance(message, six.text_type):
            message = message.encode('utf-8')

        return hashlib.sha256(message) \
            .hexdigest()

    def valid(self, payload):
        expired = datetime.datetime.utcnow() > self.expiry
        invalid = self.make_digest(self.payload) != self.make_digest(payload)

        return not expired and not invalid

    def save(self):
        db.session.add(self)

        return self
Ejemplo n.º 4
0
class Notification(db.Model):
    __tablename__ = 'notifications'

    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    slug = db.Column(db.String, nullable=False)
    reason = db.Column(db.String, nullable=False)
    active = db.Column(db.Boolean, nullable=False, default=True)
    timestamp = db.Column(db.DateTime,
                          nullable=False,
                          default=datetime.datetime.utcnow)

    user = db.relationship('User')

    @classmethod
    def get(cls, id=None, slug=None, user=None, active=None):
        query = Notification.query \
                .order_by(db.desc(Notification.timestamp))

        if id is not None:
            return query.filter(Notification.id == id) \
                    .one_or_none()

        if active is not None:
            query = query.filter(Notification.active == active)

        if slug is not None:
            query = query.filter(Notification.slug == slug)

        if user is not None:
            query = query.filter(Notification.user_id == user.id)

        if slug and user:
            return query.one_or_none()

        return query

    @classmethod
    def exists(cls, slug, user):
        return Notification.query \
                .filter(Notification.slug == slug) \
                .filter(Notification.user_id == user.id) \
                .count() != 0

    @classmethod
    def add(cls, slug, user, reason):
        if Notification.exists(slug, user):
            return

        notification = Notification(slug=slug, user_id=user.id, reason=reason)
        notification.save()

    @classmethod
    def send(cls, page, current_user):
        for notification in Notification.get(slug=page.slug, active=True):
            if notification.user == current_user:
                continue

            if not notification.user.notifications:
                continue

            notification.user.sendmail('modified', slug=page.slug)

    @cached_property
    def ymd(self):
        return self.timestamp.strftime('%Y-%m-%d') if self.timestamp else None

    @cached_property
    def hm(self):
        return self.timestamp.strftime('%H:%M') if self.timestamp else None

    @cached_property
    def ymd_hm(self):
        return self.timestamp.strftime('%Y-%m-%d %H:%M') if self.timestamp \
                else None

    @cached_property
    def page(self):
        return Document.get(self.slug)

    def save(self):
        db.session.add(self)

        return self
Ejemplo n.º 5
0
class Document(db.Model):
    __tablename__ = 'documents'

    id = db.Column(db.Integer, primary_key=True)
    slug = db.Column(db.String, nullable=False)
    title = db.Column(db.String, nullable=False)
    body = db.Column(db.Text, nullable=False)
    bytes_delta = db.Column(db.Integer, nullable=False, default=0)
    user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
    comment = db.Column(db.Text)
    active = db.Column(db.Boolean, nullable=False, default=False)
    timestamp = db.Column(db.DateTime,
                          nullable=False,
                          default=datetime.datetime.utcnow)

    user = db.relationship('User')

    @property
    def initial(self):
        return self.title[0].lower() if self.title else self.slug[0]

    @cached_property
    def ymd(self):
        return self.timestamp.strftime('%Y-%m-%d') if self.timestamp else None

    @cached_property
    def hm(self):
        return self.timestamp.strftime('%H:%M') if self.timestamp else None

    @cached_property
    def ymd_hm(self):
        return self.timestamp.strftime('%Y-%m-%d %H:%M') if self.timestamp \
                else None

    @memoized
    def meta(self, key=None, ignores=None, structural=True):
        return Metadata.get(self.slug, key, ignores, structural)

    @memoized
    def keys(self, ignores=None, structural=True):
        return set([
            item.key
            for item in self.meta(ignores=ignores, structural=structural)
        ])

    @classmethod
    def count(cls):
        return Document.query \
                .filter(Document.active == True) \
                .count()

    @classmethod
    def get(cls, slug, version=None):
        if version:
            return Document.query \
                    .filter(Document.id == version) \
                    .filter(Document.slug == slug) \
                    .one_or_none()

        item = Document.query \
                .filter(Document.active == True) \
                .filter(Document.slug == slug) \
                .one_or_none()

        if not item:
            item = Document(slug=slug,
                            body=DEFAULT_BODY %
                            {'slug': slug.replace('_', ' ')})

        return item

    @classmethod
    def changes(cls):
        return Document.query \
                .order_by(db.desc(Document.timestamp))

    @classmethod
    def titles(cls):
        return Document.query \
                .filter(Document.active == True) \
                .order_by(Document.title)

    @classmethod
    def search(cls, query=None, filters=None):
        slugs = None
        if filters:
            filters = [Metadata.search(key, value) for key, value in filters]

            slugs = None
            for filter in filters:
                if slugs is None:
                    slugs = filter
                else:
                    slugs = slugs.intersection(filter)

        items = Document.query \
                .filter(Document.active == True) \
                .order_by(Document.slug)

        if slugs is not None:
            items = items.filter(Document.slug.in_(slugs))

        if query:
            items = items.filter(Document.body.like('%' + query + '%'))

        return items.all()

    @classmethod
    def facets(cls, pages, ignores=None, all=False):
        if not pages:
            return {}

        ignores = ignores or []
        ignores.extend(Metadata.structural_keys)

        slugs = [page.slug for page in pages]

        count = db.func.count
        items = db.session.query(Metadata.key, Metadata.value, count()) \
                .filter(Metadata.slug.in_(slugs)) \
                .group_by(Metadata.key, Metadata.value) \
                .order_by(Metadata.key, Metadata.value)

        facets = {}
        for item in items:
            if item[0] in ignores:
                continue

            facets.setdefault(item[0], []) \
                    .append((item[1], item[2]))

        return facets

    @classmethod
    def deactivate(cls, slug):
        item = Document.get(slug)

        if not item.id:
            return

        item.active = False
        db.session.add(item)

    def save(self):
        self.active = True
        db.session.add(self)

        return self

    def history(self):
        return Document.query \
                .filter(Document.slug == self.slug) \
                .order_by(db.desc(Document.timestamp))
Ejemplo n.º 6
0
class User(UserMixin, db.Model):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String, nullable=False)
    email = db.Column(db.String, nullable=False)
    validated = db.Column(db.Boolean, nullable=False, default=False)
    password = db.Column(db.String, nullable=False)
    admin = db.Column(db.Boolean, nullable=False, default=False)
    notifications = db.Column(db.Boolean, nullable=False, default=True)
    timestamp = db.Column(db.DateTime,
                          nullable=False,
                          default=datetime.datetime.utcnow)

    @cached_property
    def document(self):
        return Document.get(slugify(self.name))

    @cached_property
    def ymd(self):
        return self.timestamp.strftime('%Y-%m-%d') if self.timestamp else None

    @cached_property
    def hm(self):
        return self.timestamp.strftime('%H:%M') if self.timestamp else None

    @cached_property
    def ymd_hm(self):
        return self.timestamp.strftime('%Y-%m-%d %H:%M') if self.timestamp \
                else None

    @classmethod
    def is_first(cls):
        return User.query.count() == 0

    @classmethod
    def exists(cls, email=None, name=None):
        if email is not None:
            return User.query.filter(User.email == email) \
                    .count() != 0

        if name is not None:
            return User.query.filter(User.name == name) \
                    .count() != 0

        return True

    @classmethod
    def get(cls, email=None, id=None):
        if email:
            return User.query.filter(User.email == email) \
                    .one_or_none()
        elif id:
            return User.query.filter(User.id == id) \
                    .one_or_none()
        else:
            return User.query

    def get_id(self):
        return self.id

    def set_password(self, password):
        if isinstance(password, six.text_type):
            password = password.encode('utf-8')

        self.password = bcrypt.hashpw(password, bcrypt.gensalt())

        return self

    def check_password(self, password):
        self_password = self.password

        if isinstance(password, six.text_type):
            password = password.encode('utf-8')

        if isinstance(self_password, six.text_type):
            self_password = self_password.encode('utf-8')

        return bcrypt.checkpw(password, self_password)

    def sendmail(self, template, **kwargs):
        context = make_context(request, self)
        sendmail = getattr(tasks, 'send_' + template)

        if tasks.with_celery():
            sendmail = sendmail.delay

        sendmail(context, **kwargs)

    def save(self):
        db.session.add(self)

        return self