class User(db.Model): id = db.Column(db.String(80), unique=True) user_name = db.Column(db.String(80), primary_key=True) password_hash = db.Column(db.String(800)) role = db.Column(db.String(80)) def __init__(self, user_name): self.user_name = user_name self.set_role(default_role) def to_dict(self): t = { 'id': self.id, 'user_name': self.user_name, 'role': self.role, } return t def set_user_id(self, user_id=None): if user_id: self.id = user_id else: self.id = uuid4() def set_role(self, role=None): if role not in role_set: raise Exception(f"role must be in {role_set}") self.role = role def hash_password(self, password): self.password_hash = pwd_context.encrypt(password) def verify_password(self, password): return pwd_context.verify(password, self.password_hash)
class Book(BaseModel, db.Model): __tablename__ = 'books' id = db.Column(db.Integer, primary_key=True, autoincrement=True) name = db.Column(db.String(100), nullable=False) category = db.Column(db.String(50)) price = db.Column(db.Float) user_id = db.Column(db.Integer) status = db.Column(db.Enum('0', '1'), default='0') def __init__(self, name, category, price, user_id): self.name = name self.category = category self.price = price self.user_id = user_id def __repr__(self): return "<Book %r>" % self.name def to_dict(self): res_dict = { 'id': self.id, 'name': self.name, 'category': self.category, 'price': self.price, 'user_id': self.user_id, 'status': self.status } return res_dict def delete(self): self.status = "1" return self.session_commit()
class User(BaseModel, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True, autoincrement=True) mobile = db.Column(db.String(20), unique=True) nickname = db.Column(db.String(50), unique=True) _password = db.Column(db.String(20), nullable=False) last_login = db.Column(db.DateTime, default=datetime.now) def __init__(self, mobile, nickname, passwd): self.mobile = mobile self.nickname = nickname self._password = passwd def __repr__(self): return "<User %r>" % self.nickname def check_password(self, password): return True if password == self._password else False def to_dict(self): res_dict = { 'id': self.id, 'nickname': self.nickname, 'mobile': self.mobile, 'last_login': self.last_login } return res_dict
class Project(db.Model): project_id = db.Column(db.String(80), primary_key=True) created_time = db.Column(db.String(100)) def to_dict(self): t = { 'project_id': self.project_id, 'created_time': self.created_time, } return t
class Ticket(db.Model): __tablename__ = "ticket" id = db.Column(db.Integer, primary_key=True, autoincrement=True) registered_on = db.Column(db.TIMESTAMP, nullable=False, default=datetime.datetime.utcnow) changed_on = db.Column(db.TIMESTAMP, nullable=False, default=datetime.datetime.utcnow) text = db.Column(db.String(200)) theme = db.Column(db.String(50)) email = db.Column(db.String(255), nullable=False) status_id = db.Column(db.Integer, db.ForeignKey(TicketStatus.id)) status = db.relationship('TicketStatus', foreign_keys='Ticket.status_id') comments = db.relationship('Comment', back_populates="ticket", lazy=True) def __init__(self, theme, email, text=''): self.email = email self.text = text self.theme = theme self.status_id = 1 def __repr__(self): return str({"id": str(self.id), "text": self.text, "theme": self.theme}) def json(self): """ JSONify object :return: """ return json.dumps( { "id": self.id, "registered_on": str(self.registered_on), "changed_on": str(self.changed_on), "text": self.text, "theme": self.theme, "email": self.email, "status": TicketStatus.query.filter_by(id=self.status_id).first().json(), "comments": [json.loads(c.json()) for c in self.comments] }) def change_status_check(self, new_status_id): """ Тикет создается в статусе “открыт”, может перейти в “отвечен” или “закрыт”, из отвечен в “ожидает ответа” или TODO(? - как из "отвечен" в "ожидает ответа"). На что может поменяться “ожидает ответа” “закрыт”, статус “закрыт” финальный (нельзя изменить статус или добавить комментарий) :param new_status_id: :return: """ new_status = TicketStatus.query.filter_by(id=new_status_id).first() if self.status.name == "opened" and new_status.name in ["answered", "closed"]: return True elif self.status.name == "answered" and new_status.name in ["waiting", "closed"]: return True return False
class Case(db.Model): project_id = db.Column(db.String(80), primary_key=True) case_id = db.Column(db.String(80), primary_key=True) bugs = db.Column(db.String(512)) comment = db.Column(db.String(512)) def to_dict(self): t = { 'project_id': self.project_id, 'case_id': self.case_id, 'bugs': self.bugs, 'comment': self.comment, } return t
class Test(db.Model): name = db.Column(db.String(20), primary_key=True) def __init__(self, name): self.name = name def __repr__(self): return self.name def save(self): db.session.add(self) db.session.commit() @classmethod def delete_by_name(cls, name): inst = Test.query.filter_by(name=name).first() db.session.delete(inst) db.session.commit() def delete(self): Test.delete_by_name(self.name) @classmethod def delete_all(cls): for t in Test.query.all(): t.delete()
class UnitType(db.Model): __tablename__ = 'unit_type' unit_type_id = db.Column(db.Integer, primary_key=True, autoincrement=True) unit_type = db.Column(db.String(255), nullable=False) def __init__(self, unit_type): self.unit_type = unit_type
class ItemType(db.Model): __tablename__ = 'item_type' item_type_id = db.Column(db.Integer, primary_key=True, autoincrement=True) item_type = db.Column(db.String(255), nullable=False) def __init__(self, item_type): self.item_type = item_type
class Store(db.Model): __tablename__ = 'store' store_id = db.Column(db.Integer, primary_key=True, autoincrement=True) store_name = db.Column(db.String(255), nullable=False) def __init__(self, store_name): self.store_name = store_name
class Comment(db.Model): __tablename__ = "comment" id = db.Column(db.Integer, primary_key=True, autoincrement=True) registered_on = db.Column(db.TIMESTAMP, nullable=False, default=datetime.datetime.utcnow) text = db.Column(db.String(200)) email = db.Column(db.String(255), nullable=False) ticket_id = db.Column(db.Integer, db.ForeignKey(Ticket.id)) ticket = db.relationship('Ticket', foreign_keys='Comment.ticket_id') def json(self): """ JSONify object :return: """ return json.dumps({ "id": self.id, "registered_on": str(self.registered_on), "text": self.text, "email": self.email })
class Location(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), unique=True, nullable=False) other_details = db.Column(db.TEXT) time_created = db.Column(db.TIMESTAMP, server_default=db.func.now()) time_updated = db.Column(db.TIMESTAMP, onupdate=db.func.now(), server_default=db.func.now()) def __str__(self): return "{}".format(self.name) def __repr__(self): return "{}: {}".format(self.id, self.__str__())
class JWTBlacklist(db.Model): __tablename__ = 'jwt_blacklist' id = db.Column('jwt_blacklist_id', db.Integer, primary_key=True, autoincrement=True) token = db.Column('token', db.String(500), unique=True, nullable=False) blacklistedOn = db.Column('blacklisted_on', db.DateTime, nullable=False) def __init__(self, token): self.token = token self.blacklistedOn = datetime.datetime.now() def __repr__(self): return '<id: token: {}>'.format(self.token) @staticmethod def token_blacklisted(access_token): return JWTBlacklist.query.filter_by( token=str(access_token)).count() != 0
class TransactionLine(db.Model): __tablename__ = 'transaction_line' transaction_line_id = db.Column(db.Integer, primary_key=True, autoincrement=True) item_type_id = db.Column(db.Integer, db.ForeignKey('item_type.item_type_id')) unit_type_id = db.Column(db.Integer, db.ForeignKey('unit_type.unit_type_id')) quantity = db.Column(db.Integer, nullable=False) description = db.Column(db.String(500)) transaction_id = db.Column(db.Integer, db.ForeignKey('transaction.transaction_id')) def __init__(self, item_type_id, unit_type_id, quantity, description, transaction_id): self.item_type_id = item_type_id self.unit_type_id = unit_type_id self.quantity = quantity self.description = description self.transaction_id = transaction_id
class ProductRawMaterial(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), unique=True, nullable=False) raw_material_id = db.Column(db.Integer(), db.ForeignKey(RawMaterial.id), nullable=False) raw_material = db.relationship(RawMaterial, foreign_keys=[raw_material_id]) product_id = db.Column(db.Integer(), db.ForeignKey(Product.id), nullable=False) product = db.relationship(Product, foreign_keys=[product_id]) raw_material_quantity = db.Column(db.Integer(), nullable=False) description = db.Column(db.TEXT) time_created = db.Column(db.TIMESTAMP, server_default=db.func.now()) time_updated = db.Column(db.TIMESTAMP, onupdate=db.func.now(), server_default=db.func.now()) def __str__(self): return "{}".format(self.name) def __repr__(self): return "{}: {}".format(self.id, self.__str__())
class User(db.Model): __tablename__ = "user" user_id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_type = db.Column(db.String(4), nullable=False) __mapper_args__ = {"polymorphic_on": user_type} password = db.Column(db.String(255), nullable=False) first_name = db.Column(db.String(255), nullable=False) last_name = db.Column(db.String(255), nullable=False) address1 = db.Column(db.String(255), nullable=True) address2 = db.Column(db.String(255), nullable=True) city = db.Column(db.String(255), nullable=True) state = db.Column(db.String(255), nullable=True) zip_code = db.Column(db.String(5), nullable=True) email = db.Column(db.String(255), nullable=True) phone = db.Column(db.String(255), nullable=True) def __init__(self, user_type, password, first_name, last_name): self.user_type = user_type self.password = bcrypt.generate_password_hash( password, app.config["BCRYPT_LOG_ROUNDS"]).decode() self.first_name = first_name self.last_name = last_name @staticmethod def from_authorization(access_token, expected_type): try: payload = jwt.decode(access_token, app.config["JWT_SECRET"]) if JWTBlacklist.token_blacklisted(access_token): raise APIError.bad_access_token("Session expired (logout).") user = User.query.filter_by(user_id=payload['sub']).first() if not isinstance(user, expected_type): raise APIError.forbidden() return user except jwt.ExpiredSignatureError: raise APIError.bad_access_token("Session expired.") except jwt.InvalidTokenError: raise APIError.bad_access_token("Invalid session.") except jwt.exceptions.InvalidKeyError: #Happens if alg="none" in received header raise APIError.bad_access_token("Invalid session.") def is_authentic(self, candidate_password): return bcrypt.check_password_hash(self.password, candidate_password) def generate_access_token(self, timeout=datetime.timedelta(hours=1)): # SECURITY: This payload is only signed, not encrypted, so do not put # sensitive information inside. Sending a autoincremented user-id may be # a business intelligence security flaw. See for more info: # https://medium.com/lightrail/prevent-business-intelligence-leaks-by-using-uuids-instead-of-database-ids-on-urls-and-in-apis-17f15669fd2e # Another minor security note: we could use a 'jti' to prevent jwt # replay. But doing so would be overkill: we allow unlimited logins and # have no need for / implementation of a "logout of all devices" feature payload = { 'exp': datetime.datetime.utcnow() + timeout, 'iat': datetime.datetime.utcnow(), 'sub': self.user_id } # Are you wondering why encode then decode?, the encode returns a byte-string # the decode at the end converts it into a JSON serializable string return jwt.encode(payload, app.config["JWT_SECRET"], algorithm="HS256").decode()