Source code for hapcat.models

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Hapcat database models.
"""

from __future__ import absolute_import, with_statement, print_function

from sqlalchemy_utils.types import (
    EmailType,
    PasswordType,
    URLType,
    UUIDType,
)

from hapcat import (
    app,
    db,
)

from zxcvbn import zxcvbn

import sqlalchemy.ext.associationproxy
db.association_proxy = sqlalchemy.ext.associationproxy.association_proxy

import sqlalchemy.ext.hybrid
db.hybrid_property = sqlalchemy.ext.hybrid.hybrid_property
db.hybrid_method = sqlalchemy.ext.hybrid.hybrid_method

# Set the constraint naming conventions.

db.Model.metadata.naming_convention = {
    'fk': 'fk-%(table_name)s-%(column_0_name)s-'
        '%(referred_table_name)s-%(referred_column_0_name)s',
    'pk': 'pk-%(table_name)s',
    'ix': 'ix-%(table_name)s-%(column_0_label)s',
    'ck': 'ck-%(table_name)s-%(constraint_name)s',
    'uq': 'uq-%(table_name)s-%(column_0_name)s',
}


[docs]class UUIDObject(db.Model): __tablename__ = 'uuidobject' id = db.Column(UUIDType, primary_key=True) type = db.Column(db.String(32)) __mapper_args__ = { 'polymorphic_identity': 'uuidobject', 'polymorphic_on': type }
[docs]class Tag(UUIDObject): __tablename__ = 'tag' id = db.Column( UUIDType, db.ForeignKey('uuidobject.id', ondelete='cascade'), primary_key=True ) name = db.Column(db.UnicodeText, nullable=False) __mapper_args__ = { 'polymorphic_identity': 'tag' }
[docs] def serialize(self): return { 'id': self.id, 'name': self.name, 'type': 'tag', }
[docs]class RawLocation(UUIDObject): __tablename__ = 'rawlocation' id = db.Column( UUIDType, db.ForeignKey('uuidobject.id', ondelete='cascade'), primary_key=True ) address = db.Column(db.UnicodeText) __mapper_args__ = { 'polymorphic_identity': 'rawlocation', }
[docs] def serialize(self): return { 'id': self.id, 'address': self.address, 'ephemeral': True, 'type': 'rawlocation', }
[docs]class Location(RawLocation): __tablename__ = 'location' id = db.Column( UUIDType, db.ForeignKey('rawlocation.id', ondelete='cascade'), primary_key=True ) name = db.Column(db.UnicodeText, nullable=False) tags = db.association_proxy( 'location_tags', 'tag', creator=lambda tag: LocationTag(tag_id=tag) ) photos = db.association_proxy( 'location_photos', 'photo', creator=lambda photo: LocationPhoto(photo_id=photo) ) __mapper_args__ = { 'polymorphic_identity': 'location', }
[docs] def serialize(self): return { 'id': self.id, 'address': self.address, 'name': self.name, 'ephemeral': False, 'tags': [tag.id for tag in self.tags], 'type': 'location', 'photos': [str(photo.photourl) for photo in self.photos], }
[docs]class LocationTag(db.Model): __tablename__ = 'location_tag' location_id = db.Column( UUIDType, db.ForeignKey('location.id', ondelete='cascade'), primary_key=True ) tag_id = db.Column( UUIDType, db.ForeignKey('tag.id', ondelete='cascade'), primary_key=True ) location = db.relationship( Location, backref=db.backref('location_tags', cascade='all, delete-orphan') ) tag = db.relationship('Tag')
[docs]class Event(UUIDObject): __tablename__ = 'event' id = db.Column( UUIDType, db.ForeignKey('uuidobject.id', ondelete='cascade'), primary_key=True ) name = db.Column( db.UnicodeText, nullable=False ) rawlocation_id = db.Column( UUIDType, db.ForeignKey('rawlocation.id', ondelete='cascade'), nullable=False ) rawlocation = db.relationship( 'RawLocation', foreign_keys=[rawlocation_id], ) tags = db.association_proxy( 'event_tags', 'tag', creator=lambda tag: EventTag(tag_id=tag) ) photos = db.association_proxy( 'event_photos', 'photo', creator=lambda photo: EventPhoto(photo_id=photo) ) __mapper_args__ = { 'polymorphic_identity': 'event', }
[docs] def serialize(self): return { 'id': self.id, 'name': self.name, 'location': self.rawlocation_id, 'tags': [tag.id for tag in self.tags], 'type': 'event', 'photos': [str(photo.photourl) for photo in self.photos], }
[docs]class EventTag(db.Model): __tablename__ = 'event_tag' event_id = db.Column( UUIDType, db.ForeignKey('event.id', ondelete='cascade'), primary_key=True ) tag_id = db.Column( UUIDType, db.ForeignKey('tag.id', ondelete='cascade'), primary_key=True ) event = db.relationship( Event, backref=db.backref('event_tags', cascade='all, delete-orphan') ) tag = db.relationship('Tag')
[docs]class Photo(UUIDObject): __tablename__ = 'photo' id = db.Column( UUIDType, db.ForeignKey('uuidobject.id', ondelete='cascade'), primary_key=True, ) photourl = db.Column( URLType, nullable=False, unique=True, ) events = db.association_proxy( 'event_photos', 'event', creator=lambda event: EventPhoto(event_id=event), ) locations = db.association_proxy( 'location_photos', 'location', creator=lambda location: LocationPhoto(location_id=location), ) __mapper_args__ = { 'polymorphic_identity': 'photo' }
[docs]class EventPhoto(db.Model): __tablename__ = 'event_photo' event_id = db.Column( UUIDType, db.ForeignKey('event.id', ondelete='cascade'), primary_key=True, ) photo_id = db.Column( UUIDType, db.ForeignKey('photo.id', ondelete='cascade'), primary_key=True, ) event = db.relationship( Event, backref=db.backref('event_photos', cascade='all, delete-orphan'), ) photo = db.relationship( Photo, backref=db.backref('event_photos', cascade='all, delete-orphan'), )
[docs]class LocationPhoto(db.Model): __tablename__ = 'location_photo' location_id = db.Column( UUIDType, db.ForeignKey('location.id', ondelete='cascade'), primary_key=True, ) photo_id = db.Column( UUIDType, db.ForeignKey('photo.id', ondelete='cascade'), primary_key=True, ) location = db.relationship( Location, backref=db.backref('location_photos', cascade='all, delete-orphan'), ) photo = db.relationship( Photo, backref=db.backref('location_photos', cascade='all, delete-orphan'), )
[docs]class User(UUIDObject): __tablename__ = 'user' def __init__(self, id, username, email, date_of_birth, password): self.id = id self.username = username self.email = email self.date_of_birth = date_of_birth self.password = password id = db.Column( UUIDType, db.ForeignKey('uuidobject.id', ondelete='cascade'), primary_key=True ) username = db.Column( db.UnicodeText, nullable=False, index=True, unique=True, ) email = db.Column( EmailType, nullable=False, ) date_of_birth = db.Column( db.Date, nullable=False, ) password = db.Column( PasswordType( schemes=[ 'argon2', 'bcrypt', ], default='argon2', deprecated=['auto'], ), nullable=False, unique=False, ) __mapper_args__ = { 'polymorphic_identity': 'user' }
[docs] @staticmethod def checkpwstrength( password, username, email, minscore=3, ): """Check the user's password strength. """ results = zxcvbn(password, user_inputs=[username, email]) if results['score'] >= minscore: return (True, results['feedback']) else: return (False, results['feedback'])
[docs]class Secret(db.Model): __tablename__ = 'secret' id = db.Column( db.Unicode, primary_key=True, ) payload = db.Column( db.LargeBinary, nullable=False, )