class Like(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) value = db.Column(db.Boolean, nullable=True) def __repr__(self): return f"<Like id:{self.id} user_id:{self.user_id} value:{self.value}>"
class Bookings(db.Model): """ Create bookings database table. """ id = db.Column(db.Integer, primary_key=True) resource_id = db.Column(db.Integer, db.ForeignKey("resources.id"), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey("users.id"), nullable=False) booked_from = db.Column(db.DateTime, nullable=False) booked_to = db.Column(db.DateTime, nullable=False) notes = db.Column(db.String) def __repr__(self): # TODO: change notes to something meaningful return "<Booking: {}>" % self.notes
class Application(db.Model): __tablename__ = 'Application' ApplicationID = db.Column(db.Integer, primary_key=True) ApplicationToken = db.Column(db.VARCHAR, nullable=False, unique=True) CreationTime = db.Column(db.Integer, nullable=False) OwnerID = db.Column(db.Integer, db.ForeignKey('User.UserID'), nullable=False) Description = db.Column(db.VARCHAR, nullable=False) ApplicationName = db.Column(db.VARCHAR, nullable=False) url = db.Column(db.VARCHAR, nullable=False) def __init__(self, token, ownerID, description, applicationName, url, time=int(time.time())): self.ApplicationToken = token self.OwnerID = ownerID self.Description = description self.ApplicationName = applicationName self.url = url self.CreationTime = time def create(self): db.session.add(self) db.session.commit()
class Recipe(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) name = db.Column(db.String(80)) ingredients = db.relationship('Ingredients', backref='recipe', lazy='dynamic') imageUrl = db.Column(db.String(80)) created = db.Column(db.DateTime) def __init__(self, user_id, name, ingredients, imageUrl, created=None): self.user_id = user_id self.name = name self.ingredients = [] for ing in ingredients: if 'name' in name: name = ing.name if name is None: name = ing.get('name') self.ingredients.append(Ingredients(self.id, name)) if created is None: created = datetime.utcnow() self.created = created self.imageUrl = imageUrl def __repr__(self): return '<Recipe: user_id: %s, name: %s, imageUrl: %s>' % ( self.user_id, self.name, self.imageUrl)
class PlotModel(db.Model): __tablename__ = 'plot' id = db.Column(db.Integer, primary_key=True) cpm = db.Column(db.String(30)) values = db.Column(db.JSON) data = db.Column(db.JSON) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user = db.relationship('UserModel') # type: src.UserModel def __init__(self, cpm: str, values, data, user_id): self.cpm = cpm self.values = values self.data = data self.user_id = user_id def json(self): return { 'plot': { 'user': self.user.username, 'cpm': self.cpm, 'values': self.values, 'data': self.data } } def save(self): db.session.add(self) db.session.commit() @classmethod def find_by_id(cls, _id) -> PlotModel: return cls.query.get(_id)
class Ingredients(db.Model): id = db.Column(db.Integer, primary_key=True) recipe_id = db.Column(db.Integer, db.ForeignKey('recipe.id')) name = db.Column(db.String(200)) def __init__(self, recipe_id, name): self.recipe_id = recipe_id self.name = name
class UserApplication(db.Model): __tablename__ = 'UserApplication' UserApplicationID = db.Column(db.Integer, primary_key=True) UserID = db.Column(db.Integer, db.ForeignKey('User.UserID'), nullable=False) ApplicationID = db.Column(db.Integer, db.ForeignKey('Application.ApplicationID'), nullable=False) Token = db.Column(db.VARCHAR(126), nullable=False, unique=True) def __init__(self, userID, applicationID, token): self.UserID = userID self.ApplicationID = applicationID self.Token = token def create(self): db.session.add(self) db.session.commit()
class Todos(db.Model): __table_name__ = "todos" id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(50)) contents = db.Column(db.String(200)) created_at = db.Column(db.DateTime, server_default=func.now()) updated_at = db.Column(db.DateTime, onupdate=func.now()) user_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False) user = db.relationship("User", backref="todos", lazy=True) # 객체 이름을 받는다.
class Tweet(db.Model): __tablename__ = "tweets" id = db.Column(db.String(64), primary_key=True, nullable=False, unique=True) message = db.Column(db.String(280), nullable=False) creation_date = db.Column(db.DateTime, nullable=False) update_date = db.Column(db.DateTime, nullable=True) user_id = db.Column(db.String(64), db.ForeignKey(user.User.id)) user = db.relationship('User', back_populates="tweets")
class Message(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) body = db.Column(db.String, nullable=False) author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) timestamp = db.Column(db.DateTime, nullable=False) def resp_dict(self): return { 'id': self.id, 'body': self.body, 'authorId': self.author_id, 'timestamp': int(time.mktime(self.timestamp.timetuple())) * 1000 }
class Post(db.Model): # __tablename__ = 'posts' id = db.Column(db.Integer, primary_key=True, autoincrement=True) author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) comments = db.relationship('Comment', backref='Post', lazy=True) likes = db.relationship('Like', backref='Post', lazy=True) tags = db.relationship( 'Tag', secondary=tags, lazy='subquery', backref=db.backref('posts', lazy=True), ) title = db.Column(db.String, unique=False) desc = db.Column(db.Text, unique=False) # TODO:Check limit and create character limit? s3_name = db.Column(db.String, unique=True, nullable=False) # TODO replace this with a method to return url with s3 name? # s3_url = db.Column(db.String, unique=True, nullable=False) def s3_url(self): return f"https://{s3.bucket_name}.s3.amazonaws.com/{self.s3_name}" def resp_dict(self): get_user = lambda id: User.query.get(id) post_author = User.query.get(self.author_id) return { 'id': self.id, 'title': self.title, 'author_id': self.author_id, # 's3_url': self.s3_url, 's3_url': self.s3_url(), 'description': self.desc, 'author_username': post_author.username, 'author_avi': post_author.avi_url(), 'comments': [ { 'body': comment.body, 'author_id': comment.author_id, 'avi': get_user(comment.author_id).avi_url(), 'username': get_user(comment.author_id).username, } for comment in self.comments ], 'likes': [ { 'value': like.value, 'user_id': like.user_id, 'avi': get_user(like.user_id).avi_url(), 'username': get_user(like.user_id).username } for like in self.likes ], 'tags': [tag.name for tag in self.tags] }
class Chat(db.Model): """ Telegram chat. One user can have multiple chats. """ __tablename__ = "chats" # Columns id = db.Column(db.Integer, primary_key=True) telegram_id = db.Column( db.BigInteger, unique=True, nullable=False, comment="Unique ID to identificate chat in Telegram") type = db.Column(db.Enum(ChatType), nullable=False, comment="Type of Telegram chat") user_id = db.Column( db.Integer, db.ForeignKey("users.id"), nullable=False, comment="Through this chat message can be sent to this user") # Relationships user = db.relationship("User", back_populates="chats", uselist=False) def __repr__(self): return f"<Chat {self.id}>" @staticmethod def create_fake(user): """ Creates fake chat. :param user: User to associate created chat with. """ from faker import Faker fake = Faker() random_number = fake.pyint(min_value=1, max_value=10, step=1) result = Chat(user=user) result.telegram_id = fake.pyint(min_value=10000000, max_value=10000000000, step=1) result.type = (fake.random_element(list(ChatType)) if (random_number % 10 == 0) else ChatType.PRIVATE) return result
class Parent(User): __tablename__ = 'parent' __table_args__ = {'extend_existing': True} __mapper_args__ = {'polymorphic_identity': 'parent'} id = Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) children = relationship('Child', secondary=parents_children, back_populates="parents") def __init__(self, name, surname, email, password, **kwargs): super().__init__(name, surname, email, password, **kwargs) def __repr__(self): """Represent instance as a unique string.""" return '<Parent({name!r})>'.format(name=self.name)
class Session(db.Model): __tablename__ = 'Session' SessionID = db.Column(db.Integer, primary_key=True) SessionToken = db.Column(db.VARCHAR, nullable=False, unique=True) UserID = db.Column(db.Integer, db.ForeignKey('User.UserID'), nullable=True) #, def __init__(self, token, userID): self.SessionToken = token self.UserID = userID def create(self): db.session.add(self) db.session.commit()
class SessionAccess(db.Model): __tablename__ = 'SessionAccess' UsageID = db.Column(db.Integer, primary_key=True) SessionID = db.Column(db.Integer, db.ForeignKey('Session.SessionID'), nullable=False) AccessTime = db.Column(db.Integer, nullable=False) Success = db.Column(db.Integer, nullable=False) def __init__(self, sessionID, success, time=int(time.time())): self.SessionID = sessionID self.AccessTime = time self.Success = success def create(self): db.session.add(self) db.session.commit()
class Task(db.Model): __tablename__ = "tasks" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255), nullable=False) schedule = db.Column(db.DateTime) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) memo = db.Column(db.Text) priority = db.Column(db.Integer, nullable=False, default=5) status = db.Column(db.Boolean, nullable=False, default=False) created_at = db.Column(db.DateTime, nullable=False, server_default=db.text('NOW()')) updated_at = db.Column(db.DateTime, nullable=False, server_default=db.text('NOW()'))
class Todo(Model): id = Column(db.Integer, primary_key=True) title = Column(db.String(255), nullable=False) completed = Column(db.Boolean, default=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) created_at = Column(db.DateTime, nullable=False, default=datetime.utcnow) def save(self): db.session.add(self) db.session.commit() def delete(self): db.session.delete(self) db.session.commit() def __repr__(self): return f'<User {self.title}>'
class Device(db.Model): __tablename__ = 'Device' DeviceID = db.Column(db.Integer, primary_key=True) DeviceToken = db.Column(db.VARCHAR, nullable=False, unique=True) DeviceType = db.Column(db.VARCHAR, nullable=False) OwnerID = db.Column(db.Integer, db.ForeignKey('User.UserID'), nullable=False) def __init__(self, deviceToken, DeviceType, OwnerID): self.DeviceToken = deviceToken self.DeviceType = DeviceType self.OwnerID = OwnerID def create(self): db.session.add(self) db.session.commit()
class Reward(SurrogatePK, Model): __tablename__ = 'reward' nameOf = Column(db.String, nullable=False) description = Column(db.String, nullable=False) reward = Column(db.String, nullable=False) endDate = Column(db.DateTime, nullable=False) startDate = Column(db.DateTime, nullable=False) child_id = Column(db.Integer, db.ForeignKey('child.id'), nullable=False) def __init__(self, nameOf, description, reward, endDate, startDate): db.Model.__init__(self, nameOf=nameOf, description=description, reward=reward, endDate=endDate, startDate=startDate) def __repr__(self): """Represent instance as a unique string.""" return '<Reward({nameOf!r})>'.format(nameOf=self.nameOf)
class RecebimentoModel(db.Model): __tablename__ = 'recebimentos' id = db.Column(db.Integer, primary_key=True) cliente = db.Column(db.String()) valor = db.Column(db.Float()) descricao = db.Column(db.String()) estabelecimento_id = db.Column(db.Integer, db.ForeignKey('estabelecimentos.id')) def __repr__(self): return f"<Recebimento {self.id}>" @property def serialize(self): return { 'cliente': self.cliente, 'valor': self.valor, 'descricao': self.descricao, }
class AdminModel(db.Model): __tablename__ = 'admin' user_id = db.Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) access_level = db.Column(db.Integer, nullable=False) user = db.relationship('UserModel') def __init__(self, user_id, access_level): self.user_id = user_id self.access_level = access_level def json(self): return {'admin': self.user.username, 'access_level': self.access_level} def save(self): db.session.add(self) db.session.commit() @classmethod def find_by_id(cls, user_id) -> AdminModel: return cls.query.get(user_id)
class Child(User): __tablename__ = 'child' __mapper_args__ = {'polymorphic_identity': 'child'} id = Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) parents = relationship('Parent', secondary=parents_children, back_populates="children") ehrid = Column(db.String) timer = Column(db.DateTime, default=None, nullable=True) rewards = relationship('Reward', backref='child', lazy=True) def __init__(self, name, surname, email, password, parent, ehrid, **kwargs): super().__init__(name, surname, email, password, **kwargs) self.parents.append(parent) self.ehrid = ehrid def __repr__(self): """Represent instance as a unique string.""" return '<Child({name!r}{parent!r})>'.format(name=self.name, parent=self.parents)
class YandexDiskToken(db.Model): """ Yandex.Disk token. One user can have only one token. """ __tablename__ = "yandex_disk_tokens" # Columns id = db.Column(db.Integer, primary_key=True) _access_token = db.Column("access_token", db.String, nullable=True, default=null(), comment="Encrypted Y.D. OAuth token") access_token_type = db.Column(db.String, nullable=True, default=null(), comment="Type of access token") access_token_expires_in = db.Column( db.BigInteger, nullable=True, default=null(), comment="Access token lifetime in seconds") _refresh_token = db.Column( "refresh_token", db.String, nullable=True, default=null(), comment="Encrypted Y.D. refresh token to use to update access token") _insert_token = db.Column( "insert_token", db.String, nullable=True, default=null(), comment=( "Encrypted token for DB update controlling. " "i.e., you shouldn't insert values if you don't know insert token" )) insert_token_expires_in = db.Column( db.BigInteger, nullable=True, default=null(), comment="Insert token lifetime in seconds") user_id = db.Column(db.Integer, db.ForeignKey("users.id"), unique=True, nullable=False, comment="Tokens belongs to this user") # Relationships user = db.relationship('User', back_populates="yandex_disk_token", uselist=False) def __init__(self, **kwargs): super(YandexDiskToken, self).__init__(**kwargs) if ("_access_token" in kwargs): raise AttributeError("`access_token` can't be accessed directly") elif ("_refresh_token" in kwargs): raise AttributeError("`refresh_token` can't be accessed directly") elif ("_insert_token" in kwargs): raise AttributeError("`insert_token` can't be accessed directly") def __repr__(self): return f"<YD Token {self.id}>" def __getitem__(self, key): return getattr(self, key) def __setitem__(self, key, value): return setattr(self, key, value) @staticmethod def create_fake(user) -> dict: """ Creates fake Yandex.Disk token. There is two types of token: "pending" or "received". Pending means the app wants to write in `access_token` column, but request to Yandex not maded at the moment. If app received invalid `insert_token` from user, then it shouldn't make request to Yandex. Received means the app successfully made a request to Yandex and `insert_token` not exists in a row, because `INSERT` operation was successfully completed. :param user: User to associate token with. :returns: "Pending" token (chance is 1/10) or "received" token (chance is 9/10). """ from faker import Faker fake = Faker() result = YandexDiskToken(user=user) result_type = None random_number = fake.pyint(min_value=1, max_value=10, step=1) if (random_number % 10): result_type = "pending" result.set_access_token(fake.pystr(min_chars=32, max_chars=32)) result.set_refresh_token(fake.pystr(min_chars=32, max_chars=32)) result.access_token_type = "bearer" result.access_token_expires_in = fake.pyint(min_value=31536000, max_value=63072000, step=1) else: result_type = "received" result.set_insert_token(fake.pystr(min_chars=32, max_chars=32)) result.insert_token_expires_in = fake.pyint(min_value=600, max_value=900, step=100) return {"value": result, "type": result_type} @hybrid_property def access_token(self): raise AttributeError("`access_token` can't be accessed directly") @access_token.setter def access_token(self, new_value): raise AttributeError("`access_token` can't be accessed directly") @hybrid_property def refresh_token(self): raise AttributeError("`refresh_token` can't be accessed directly") @refresh_token.setter def refresh_token(self, new_value): raise AttributeError("`refresh_token` can't be accessed directly") @hybrid_property def insert_token(self): raise AttributeError("`insert_token` can't be accessed directly") @insert_token.setter def insert_token(self, new_value): raise AttributeError("`insert_token` can't be accessed directly") def set_access_token(self, token: Union[str, None]) -> None: """ Sets encrypted access token. """ self._set_token(token_attribute_name="_access_token", value=token) def get_access_token(self) -> Union[str, None]: """ Returns decrypted access token. :raises DataCorruptedError: Data in DB is corrupted. :raises InvalidTokenError: Encrypted token is invalid or expired. """ return self._get_token( token_attribute_name="_access_token", expires_attribute_name="access_token_expires_in") def set_refresh_token(self, token: Union[str, None]) -> None: """ Sets encrypted refresh token. """ self._set_token(token_attribute_name="_refresh_token", value=token) def get_refresh_token(self) -> Union[str, None]: """ Returns decrypted refresh token. :raises DataCorruptedError: Data in DB is corrupted. :raises InvalidTokenError: Encrypted token is invalid. """ return self._get_token(token_attribute_name="_refresh_token") def set_insert_token(self, token: Union[str, None]) -> None: """ Sets encrypted insert token. """ self._set_token(token_attribute_name="_insert_token", value=token) def get_insert_token(self) -> Union[str, None]: """ Returns decrypted insert token. :raises DataCorruptedError: Data in DB is corrupted. :raises InvalidTokenError: Encrypted token is invalid or expired. """ return self._get_token( token_attribute_name="_insert_token", expires_attribute_name="insert_token_expires_in") def have_access_token(self) -> bool: """ :returns: `True` if `access_token` contains any value otherwise `False`. """ return self._have_token(token_attribute_name="_access_token") def have_refresh_token(self) -> bool: """ :returns: `True` if `refresh_token` contains any value otherwise `False`. """ return self._have_token(token_attribute_name="_refresh_token") def have_insert_token(self) -> bool: """ :returns: `True` if `insert_token` contains any value otherwise `False`. """ return self._have_token(token_attribute_name="_insert_token") def clear_access_token(self) -> None: """ Clears all data that belongs to access token. - perform a commit in order to save changes! """ self.access_token_type = null() return self._clear_token( token_attribute_name="_access_token", expires_attribute_name="access_token_expires_in") def clear_refresh_token(self) -> None: """ Clears all data that belongs to refresh token. - perform a commit in order to save changes! """ return self._clear_token(token_attribute_name="_refresh_token") def clear_insert_token(self) -> None: """ Clears all data that belongs to insert token. - perform a commit in order to save changes! """ return self._clear_token( token_attribute_name="_insert_token", expires_attribute_name="insert_token_expires_in") def clear_all_tokens(self) -> None: """ Clears all data that belongs to any kind of token. - perform a commit in order to save changes! """ self.clear_access_token() self.clear_refresh_token() self.clear_insert_token() def _set_token(self, **kwargs) -> None: """ Sets encrypted token. :param token_attribute_name: Name of token attribute in class. :param value: Value to set. """ fernet = Fernet(current_app.secret_key.encode()) token_attribute_name = kwargs["token_attribute_name"] value = kwargs["value"] if (value is None): self[token_attribute_name] = None else: encrypted_data = fernet.encrypt(value.encode()) self[token_attribute_name] = encrypted_data.decode() def _get_token(self, **kwargs) -> Union[str, None]: """ Returns decrypted token. :param token_attribute_name: Name of token attribute in class. :param expires_attribute_name: Optional. Token lifetime in seconds. If specified, expiration date will be checked. :returns: Decrypted token or `None` if value is NULL. :raises DataCorruptedError: Data in DB is corrupted. :raises InvalidTokenError: Encrypted token is invalid. """ fernet = Fernet(current_app.secret_key.encode()) token_attribute_name = kwargs["token_attribute_name"] encrypted_token = self[token_attribute_name] if (encrypted_token is None): return None token_lifetime = None expires_attribute_name = kwargs.get("expires_attribute_name") if (expires_attribute_name is not None): token_lifetime = self[expires_attribute_name] if (not isinstance(token_lifetime, int)): raise DataCorruptedError("Token lifetime is not an integer") encrypted_token = encrypted_token.encode() decrypted_token = None try: decrypted_token = fernet.decrypt(encrypted_token, token_lifetime) except InvalidTokenFernetError: raise InvalidTokenError("Token is invalid or expired") decrypted_token = decrypted_token.decode() return decrypted_token def _have_token(self, **kwargs) -> bool: """ :param token_attribute_name: Name of token attribute in class. :returns: `True` if token contains any value, `False` otherwise. """ token_attribute_name = kwargs["token_attribute_name"] value = self[token_attribute_name] return (isinstance(value, str) and len(value) > 0) def _clear_token(self, **kwargs) -> None: """ Clears token data. - perform a commit in order to save changes! :param token_attribute_name: Name of token attribute in class. :param expires_attribute_name: Optional. Token lifetime in seconds. If specified, expiration date will be cleared. """ token_attribute_name = kwargs["token_attribute_name"] expires_attribute_name = kwargs.get("expires_attribute_name") self[token_attribute_name] = null() if (expires_attribute_name): self[expires_attribute_name] = null()
from src.database import db from src.bcrypt import bcrypt from src.aws import s3 from flask import current_app from datetime import datetime, timedelta import time import jwt import json from src.logging import logger chats = db.Table( 'chats', db.Column('user_id', db.Integer, db.ForeignKey('user.id'), primary_key=True), db.Column('chat_id', db.Integer, db.ForeignKey('chat.id'), primary_key=True) ) messages = db.Table( 'messages', db.Column('message_id', db.Integer, db.ForeignKey('message.id'), primary_key=True), db.Column('chat_id', db.Integer, db.ForeignKey('chat.id'), primary_key=True) ) class Chat(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) room_name = db.Column(db.String, nullable=False, unique=True) messages = db.relationship( 'Message', secondary=messages, lazy='subquery', backref=db.backref('messages', lazy=True), ) users = db.relationship(
def set_password(self, password): """Set password.""" self.password = bcrypt.generate_password_hash(password) def check_password(self, value): """Check password.""" return bcrypt.check_password_hash(self.password, value) def __repr__(self): """Represent instance as a unique string.""" return '<User({name!r})>'.format(name=self.name) parents_children = db.Table( 'parents_children', Column('parent_id', db.Integer, db.ForeignKey('parent.id')), Column('child_id', db.Integer, db.ForeignKey('child.id'))) class Parent(User): __tablename__ = 'parent' __table_args__ = {'extend_existing': True} __mapper_args__ = {'polymorphic_identity': 'parent'} id = Column(db.Integer, db.ForeignKey('user.id'), primary_key=True) children = relationship('Child', secondary=parents_children, back_populates="parents") def __init__(self, name, surname, email, password, **kwargs): super().__init__(name, surname, email, password, **kwargs)
class UserFollow(db.Model): id = db.Column(db.Integer, primary_key=True, autoincrement=True) follower_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False, unique=False) followed_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False, unique=False) follower = db.relationship('User', foreign_keys=[followed_id]) followed = db.relationship('User', foreign_keys=[follower_id])
class Comment(db.Model): # __tablename__ = 'comments' id = db.Column(db.Integer, primary_key=True, autoincrement=True) post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False) author_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) body = db.Column(db.Text) # TODO:Check limit and create character limit?