class User(db.Model): id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(80), unique=True, index=True) password_hash = db.Column(db.String(120), unique=False) def __init__(self, username, password): self.username = username self.email = password 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) def generate_auth_token(self, expiration=TOKEN_DURATION): s = Serializer(SECRET_KEY, expires_in=expiration) return s.dumps({'id': self.id}) @staticmethod def verify_auth_token(token): s = Serializer(SECRET_KEY) try: data = s.loads(token) except SignatureExpired: return None # valid token, but expired except BadSignature: return None # invalid token user = User.query.get(data['id']) return user
class Artist(db.Model, TimestampMixin): __tablename__ = "Artist" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String) address = db.Column(db.String(120)) city = db.Column(db.String(120)) state = db.Column(db.String(120)) phone = db.Column(db.String(120)) genres = db.Column(db.String(120)) image_link = db.Column(db.String(500)) facebook_link = db.Column(db.String(120)) website = db.Column(db.String(120)) genres = db.relationship( "Genre", secondary=genre_artist, backref=db.backref("artists", lazy=True), ) seeking_venue = db.Column(db.Boolean) seeking_description = db.Column(db.String(500)) shows = db.relationship("Show", backref=db.backref("artist", lazy=True), cascade="all, delete-orphan") week_days_availability = db.Column(db.String())
class Venue(db.Model, TimestampMixin): __tablename__ = "Venue" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, unique=True) city = db.Column(db.String(120)) state = db.Column(db.String(120)) address = db.Column(db.String(120)) phone = db.Column(db.String(120)) image_link = db.Column(db.String(500)) facebook_link = db.Column(db.String(120)) website = db.Column(db.String(120)) genres = db.relationship( "Genre", secondary=genre_venue, backref=db.backref("venues", lazy=True), ) seeking_talent = db.Column(db.Boolean) seeking_description = db.Column(db.String(500)) shows = db.relationship("Show", backref=db.backref("venue", lazy=True), cascade="all, delete-orphan")
class Admin(db.Model, UserMixin): id = db.Column(db.Integer, autoincrement=True, primary_key=True, nullable=False) username = db.Column(db.String(32)) password = db.Column(db.String(100)) phoneNum = db.Column(db.Integer, unique=True) email = db.Column(db.String(120), unique=True) store_name = db.Column(db.String(32)) store_id = db.Column(db.String(32)) header = db.Column(db.String(256)) token = db.Column(db.String(50), unique=True) is_super = db.Column(db.Boolean, default=False) def __init__(self, username, phoneNum, password): self.username = username self.phoneNum = phoneNum self.password = password def __repr__(self): return '<User %r>' % self.phoneNum
class Conversation(db.Model): __tablename__ = "conversations" id = db.Column(db.Integer, primary_key=True) circle_id = db.Column(db.Integer, db.ForeignKey("circles.id")) name = db.Column(db.String(120)) created = db.Column(db.DateTime) updated = db.Column(db.DateTime) device_access = db.Column(db.Boolean) circle = db.relationship("Circle", back_populates="conversations") links = db.relationship("UserToConversation", back_populates="conversation") messages = db.relationship("Message", back_populates="conversation", order_by="Message.id", cascade="all, delete-orphan") def __repr__(self): return "<Conversation(id='%d' name='%s' created='%s' updated='%s')>" % ( self.id, self.name, str(self.created), str(self.updated)) def __init__(self, name=None, created=datetime.datetime.now(), updated=datetime.datetime.now(), device_access=False, circle=None): if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if name is not None and name != "": self.name = name else: self.name = "Conversation" if circle is not None: self.circle = circle self.device_access = device_access db.session.add(self) db.session.flush() logger.debug( "Database add: conversations%s", { "id": self.id, "name": self.name, "circle_id": self.circle_id, "device_access": self.device_access }) def mobile_notification(self, title, body): for link in self.links: #ios.send_notification(link.user, alert) android.send_notification(link.user, title=title, body=body) def has_members(self, *args): for member in args: tf = False for link in self.links: if link.user_id == member.id: tf = True if tf is False: return False return True def update_content(self, created=None, updated=datetime.datetime.now(), name=None, device_access=None): if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if name is not None and name != "": self.name = name if device_access is not None: self.device_access = device_access db.session.commit() db.session.flush() logger.debug( "Database update: conversations%s", { "id": self.id, "name": self.name, "circle_id": self.circle_id, "device_access": self.device_access }) def notify_users(self, p1='conversation', p2=None): if p2 is None: p2 = {} p2['conversation_id'] = self.id emit(p1, p2, room='conversation_' + str(self.id), namespace='/') def set_other_admin(self): for link in self.links: link.update_content(privilege="ADMIN") return True def check_validity(self): if (len(self.links) + (1 if self.device_access else 0)) <= 1: for link in self.links: db.session.delete(link) db.session.delete(self) return False return True def get_content(self): return { "id": self.id, "name": self.name, "created": self.created, "updated": self.updated, "circle": self.circle.get_simple_content(), "links": [link.get_content() for link in self.links], "messages": [message.get_simple_content() for message in self.messages], "device_access": self.device_access } def get_simple_content(self): return { "id": self.id, "name": self.name, "created": self.created, "updated": self.updated, "circle_id": self.circle_id, "device_access": self.device_access }
class Message(db.Model): __tablename__ = "messages" id = db.Column(db.Integer, primary_key=True) conversation_id = db.Column(db.Integer, db.ForeignKey("conversations.id")) link_id = db.Column(db.Integer, db.ForeignKey("user_to_conversation.id"), nullable=True) device_id = db.Column(db.Integer, db.ForeignKey("devices.id"), nullable=True) sent = db.Column(db.DateTime) read = db.Column(db.DateTime) text_content = db.Column(db.String(8192)) is_user = db.Column(db.Boolean) link = db.relationship("UserToConversation", back_populates="messages") conversation = db.relationship("Conversation", back_populates="messages") media_links = db.relationship("MessageToMedia", back_populates="message", order_by="MessageToMedia.id", cascade="all, delete-orphan") device = db.relationship("Device", back_populates="messages") def __repr__(self): return "<NeoMessage(id='%d' sent='%s' read='%s')>" % ( self.id, str(self.sent), str(self.read)) def __init__(self, sent=datetime.datetime.now(), read=None, content=None, is_user=True, link=None, conversation=None): if sent is not None: if type(sent) is str: self.sent = DateParser.parse(sent) else: self.sent = sent if read is not None: if type(read) is str: self.read = DateParser.parse(read) else: self.reed = read if content is not None: self.text_content = content if link is not None: self.link = link if conversation is not None: self.conversation = conversation self.is_user = is_user db.session.add(self) db.session.flush() logger.debug("Database add: messages%s", self.get_simple_content()) def update_content(self, sent=None, read=datetime.datetime.now(), content=None, is_user=None): if sent is not None: if type(sent) is str: self.sent = DateParser.parse(sent) else: self.sent = sent if read is not None: if type(read) is str: self.read = DateParser.parse(read) else: self.reed = read if content is not None: self.text_content = content if is_user is not None: self.is_user = is_user db.session.commit() db.session.flush() logger.debug("Database update: messages%s", self.get_simple_content()) def get_content(self): if self.is_user: return { "id": self.id, "link": self.link.get_simple_content() if self.link is not None else {}, "sent": self.sent, "read": self.read, "content": self.text_content, "medias": [media.get_content() for media in self.media_links] } else: return { "id": self.id, "sent": self.sent, "read": self.read, "content": self.text_content, "medias": [media.get_content() for media in self.media_links], "device": self.device.get_simple_content() } def get_simple_json_compliant_content(self): if self.is_user: return { "id": self.id, "link_id": self.link_id, "sent": None if self.sent is None else self.sent.isoformat(), "read": None if self.read is None else self.read.isoformat(), "content": self.text_content, "medias": len(self.media_links) if self.media_links is not None else 0 } else: return { "id": self.id, "device_id": self.device_id, "sent": None if self.sent is None else self.sent.isoformat(), "read": None if self.read is None else self.read.isoformat(), "content": self.text_content, "medias": len(self.media_links) if self.media_links is not None else 0 } def get_simple_content(self): if self.is_user: return { "id": self.id, "link_id": self.link_id, "sent": self.sent, "read": self.read, "content": self.text_content, "medias": len(self.media_links) if self.media_links is not None else 0 } else: return { "id": self.id, "device_id": self.device_id, "sent": self.sent, "read": self.read, "content": self.text_content, "medias": len(self.media_links) if self.media_links is not None else 0 }
class Order(db.Model): id = db.Column(db.String(32), nullable=True) oid = db.Column(db.String(32), primary_key=True, nullable=False) # 设置外键 uid = db.Column(db.Integer, db.ForeignKey('user.id')) user_phone = db.Column(db.String(20), nullable=False) user = relationship("User", backref="order_of_user") good_id = db.Column(db.String(32), nullable=False) count = db.Column(db.Integer, default=1) unit_price = db.Column(db.Float) total_price = db.Column(db.Float) discount_info = db.Column(db.String(100)) create_time = db.Column(db.Integer) change_time = db.Column(db.Integer) status = db.Column(db.Integer, default=1) is_del = db.Column(db.Boolean, default=False) store_id = db.Column(db.String(32), default='0') phoneNum = db.Column(db.String(20), nullable=False) name = db.Column(db.String(10)) address = db.Column(db.String(100)) paymethod = db.Column(db.String(32)) actual_price = db.Column(db.Float) paytime = db.Column(db.Integer) express = db.Column(db.String(32)) delivery_time = db.Column(db.Integer) group_time = db.Column(db.Integer) confirm_time = db.Column(db.Integer) cancel_time = db.Column(db.Integer) text = db.Column(db.String(100)) is_group = db.Column(db.Boolean, default=False, nullable=True) coupon_id = db.Column(db.String(32)) coupon_name = db.Column(db.String(32)) coupon_discount = db.Column(db.Float) integral_count = db.Column(db.Integer) integral_discount = db.Column(db.Float) def __init__(self, *args): self.id = args[0] self.oid = args[0] self.uid = args[1] self.user_phone = args[2] self.good_id = args[3] self.count = args[4] self.unit_price = args[5] self.total_price = args[6] self.create_time = args[7] self.status = args[8] self.store_id = args[9] self.phoneNum = args[10] self.name = args[11] self.address = args[12] __mapper_args__ = {"order_by": change_time.desc()} def to_dict(self): return {c.name: getattr(self, c.name) for c in self.__table__.columns} def __repr__(self): return '<Order %r>' % self.oid
class Genre(db.Model, TimestampMixin): __tablename__ = "Genre" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(), nullable=False, unique=True) label = db.Column(db.String(), nullable=False, unique=True)
class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(120), unique=True) password = db.Column(db.String(2048)) first_name = db.Column(db.String(50)) last_name = db.Column(db.String(50)) birthday = db.Column(db.DateTime) created = db.Column(db.DateTime) updated = db.Column(db.DateTime) json_token = db.Column(db.String(4096)) facebook_psid = db.Column(db.String(256)) hangout_space = db.Column(db.String(256)) type = db.Column(db.String(10)) is_online = db.Column(db.Boolean) ios_token = db.Column(db.String(64)) android_token = db.Column(db.String(2048)) # RELATIONS circle_link = db.relationship("UserToCircle", back_populates="user", order_by="UserToCircle.id", cascade="all, delete-orphan") conversation_links = db.relationship("UserToConversation", back_populates="user", order_by="UserToConversation.id", cascade="all, delete-orphan") circle_invite = db.relationship("CircleInvite", back_populates="user", order_by="CircleInvite.id", cascade="all, delete-orphan") media_links = db.relationship("UserToMedia", back_populates="user", order_by="UserToMedia.id", cascade="all, delete-orphan") def __init__(self, email=None, password=None, first_name=None, last_name=None, birthday=None): self.email = email self.password = hashlib.sha512(password.encode('utf-8')).hexdigest() self.first_name = first_name self.last_name = last_name self.birthday = DateParser.parse(birthday) self.created = datetime.datetime.utcnow() self.updated = datetime.datetime.utcnow() self.json_token = None self.facebook_psid = None self.hangout_space = None self.type = "DEFAULT" self.is_online = False db.session.add(self) db.session.flush() logger.debug("Database add: users%s", self.get_simple_content()) def __repr__(self): return '<User %r %r>' % (self.first_name, self.last_name) def disconnect_old(self): try: self.json_token = "" db.session.commit() return True, None except Exception as e: return False, str(e) def disconnect(self): self.json_token = None db.session.commit() return True def has_matching_circle(self, user): for link in self.circle_link: for link2 in user.circle_link: if link.circle_id == link2.circle_id: return True return False def is_in_conversation(self, conversation_id): for link in self.conversation_links: if link.conversation_id == conversation_id: return True return False def is_in_circle(self, circle_id): for link in self.circle_link: if link.circle_id == circle_id: return True return False @staticmethod def decode_auth_token_old(auth_token): try: payload = jwt.decode(auth_token, SECRET_KEY) try: user = db.session.query(User).filter( User.id == payload['sub']).first() if user is not None: if user.json_token == "" or user.json_token is None: return False, 'Utilisateur non authentifié' return True, user else: return False, 'Utilisateur introuvable' except Exception as e: return False, "Une erreur est survenue : " + str(e) except jwt.ExpiredSignatureError: return False, 'La session a expiré, authentifiez vous a nouveau' except jwt.InvalidTokenError: return False, 'Token invalide, authentifiez vous a nouveau' @staticmethod def decode_auth_token(auth_token): try: payload = jwt.decode(auth_token, SECRET_KEY) user = db.session.query(User).filter( User.id == payload['sub']).first() if user is None: raise TokenNotBoundToUser if user.json_token is None: raise UnauthenticatedUser return user except jwt.ExpiredSignatureError: raise ExpiredUserSession except jwt.InvalidTokenError: raise InvalidJwtToken return None def notify_circles(self, p2): for link in self.circle_link: link.circle.notify_users(p2=p2) def notify_me(self, body, title): android.send_notification(self, title=title, body=body) def encode_auth_token(self): try: payload = { 'exp': datetime.datetime.utcnow() + datetime.timedelta(days=1, seconds=1), 'iat': datetime.datetime.utcnow(), 'sub': self.id } token = jwt.encode(payload, SECRET_KEY, algorithm="HS256") self.json_token = token.decode() db.session.commit() return token.decode() except Exception as e: return None def encode_api_token(self): payload = { 'exp': datetime.datetime.utcnow() + datetime.timedelta(days=1, seconds=1), 'iat': datetime.datetime.utcnow(), 'sub': self.id, 'first_name': self.first_name, 'last_name': self.last_name } token = jwt.encode(payload, SECRET_KEY_BOT, algorithm="HS256") return token.decode() def check_password(self, password=None): if password is not None and password != "": if self.password != hashlib.sha512( password.encode("utf-8")).hexdigest(): return False return True return False def old_authenticate(self, password=None): if password is not None and password != "": if self.password != hashlib.sha512( password.encode('utf-8')).hexdigest(): return False, "Mot de passe invalide" try: if self.json_token is not None: jwt.decode(self.json_token, SECRET_KEY) return True, self.json_token return True, self.encode_auth_token() except jwt.ExpiredSignatureError: return True, self.encode_auth_token() except Exception: return True, self.encode_auth_token() return False, "Aucun mot de passe fourni" def authenticate(self, password=None): if self.password != hashlib.sha512( password.encode('utf-8')).hexdigest(): raise InvalidPassword if self.json_token is not None: try: jwt.decode(self.json_token, SECRET_KEY) return self.json_token except jwt.ExpiredSignature: pass return self.encode_auth_token() def update_password(self, password=None): if password is not None and password != "": self.password = hashlib.sha512( password.encode('utf-8')).hexdigest() db.session.commit() def update_content(self, email=None, first_name=None, last_name=None, birthday=None, facebook_psid=None, hangout_space=None, is_online=None, created=None, updated=datetime.datetime.now()): if email is not None and email is not "": self.email = email if first_name is not None and first_name is not "": self.first_name = first_name if last_name is not None and last_name is not "": self.last_name = last_name if birthday is not None and birthday is not "" and type( birthday) is str: self.birthday = DateParser.parse(birthday) if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if type(created) is str: self.created = DateParser.parse(created) elif created is not None: self.created = created if hangout_space is not None: self.hangout_space = hangout_space if facebook_psid is not None: self.facebook_psid = facebook_psid if is_online is not None: self.is_online = is_online db.session.commit() db.session.flush() logger.debug("Database update: users%s", self.get_simple_content()) def promote_admin(self): self.type = "ADMIN" db.session.commit() @staticmethod def CreateNeoAdmin(password): admin = db.session.query(User).filter( User.email == "*****@*****.**").first() if admin is None: user = User(email="*****@*****.**", password=password, first_name="Neo", last_name="Admin", birthday="1995/02/02") user.promote_admin() def get_simple_content(self): return { "id": self.id, "email": self.email, "first_name": self.first_name, "last_name": self.last_name, "birthday": self.birthday, "created": self.created, "updated": self.updated, "isOnline": self.is_online, "type": self.type, } def get_simple_json_compliant_content(self): return { "id": self.id, "email": self.email, "first_name": self.first_name, "last_name": self.last_name, "birthday": None if self.birthday is None else self.birthday.isoformat(), "created": None if self.created is None else self.created.isoformat(), "updated": None if self.updated is None else self.updated.isoformat(), "isOnline": self.is_online, "type": self.type, } def get_content(self): return { "id": self.id, "email": self.email, "first_name": self.first_name, "last_name": self.last_name, "birthday": self.birthday, "created": self.created, "updated": self.updated, "isOnline": self.is_online, "type": self.type, "hangout": False if (self.hangout_space is None or len(self.hangout_space) == 0) else True, "facebook": False if (self.facebook_psid is None or len(self.facebook_psid) == 0) else True, "ios_token": False if (self.ios_token is None or len(self.ios_token == 0)) else True, "circles": [link.get_content() for link in self.circle_link], "invites": [invite.get_content() for invite in self.circle_invite], "conversations": [link.get_simple_content() for link in self.conversation_links], "medias": [link.get_content() for link in self.media_links] }
class UserToConversation(db.Model): __tablename__ = "user_to_conversation" id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id")) conversation_id = db.Column(db.Integer, db.ForeignKey("conversations.id")) privilege = db.Column(db.String(10)) created = db.Column(db.DateTime) updated = db.Column(db.DateTime) messages = db.relationship("Message", back_populates="link", order_by="Message.sent") conversation = db.relationship("Conversation", back_populates="links") user = db.relationship("User", back_populates="conversation_links") def __repr__(self): return "<UserToConversation(id='%d' user_id='%d' conversation_id='%d' privilege='%s')>" % ( self.id, self.user_id, self.conversation_id, self.privilege) def __init__(self, created=datetime.datetime.now(), updated=datetime.datetime.now(), privilege=None, user=None, conversation=None): if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if privilege is not None and privilege != "": self.privilege = privilege else: self.privilege = "STANDARD" if user is not None: self.user = user if conversation is not None: self.conversation = conversation db.session.add(self) db.session.flush() logger.debug( "Database add: user_to_conversation%s", { "id": self.id, "privilege": self.privilege, "user_id": self.user_id, "conversation_id": None if self.conversation is None else self.conversation.id, "circle_id": None if self.conversation is None else self.conversation.circle_id }) def update_content(self, created=None, updated=datetime.datetime.now(), privilege=None): if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if privilege is not None and privilege != "": self.privilege = privilege db.session.commit() db.session.flush() logger.debug( "Database update: user_to_conversation%s", { "id": self.id, "privilege": self.privilege, "user_id": self.user_id, "conversation_id": None if self.conversation is None else self.conversation.id, "circle_id": None if self.conversation is None else self.conversation.circle_id }) def get_simple_content(self): return { "id": self.id, "created": self.created, "updated": self.updated, "privilege": self.privilege, "user_id": self.user_id, "conversation_id": self.conversation_id, "circle_id": None if self.conversation is None else self.conversation.circle_id } def get_content(self): return { "id": self.id, "created": self.created, "updated": self.updated, "privilege": self.privilege, "user_id": self.user.get_simple_content(), "conversation_id": self.conversation.get_simple_content(), "circle_id": None if self.conversation is None else self.conversation.circle_id, "messages": [message.get_simple_content() for message in self.messages] } def get_messages(self): return { "id": self.id, "messages": [message.get_content() for message in self.messages] }
class Media(db.Model): __tablename__ = "medias" id = db.Column(db.Integer, primary_key=True) filename = db.Column(db.String(120)) extension = db.Column(db.String(10)) directory = db.Column(db.String(1024)) identifier = db.Column(db.String(1024)) uploaded = db.Column(db.Boolean) message_link = db.relationship("MessageToMedia", back_populates="media", uselist=False, cascade="all, delete-orphan") user_link = db.relationship("UserToMedia", back_populates="media", uselist=False, cascade="all, delete-orphan") device_link = db.relationship("DeviceToMedia", back_populates="media", uselist=False, cascade="all, delete-orphan") circle_link = db.relationship("CircleToMedia", back_populates="media", uselist=False, cascade="all, delete-orphan") def __repr__(self): return "<Media(id='%d' filename='%s' extension='%s' directory='%s')>" % ( self.id, self.filename, self.extension, self.directory ) def file_exist(self): if self.filename is None or self.extension is None or self.directory is None: return False if os.path.isfile(self.get_directory() + self.get_full_name()): return True return False def upload(self, file): file_name = secure_filename(file.filename) if not os.path.exists(UPLOAD_FOLDER + self.directory + os.path.sep): os.makedirs(UPLOAD_FOLDER + self.directory + os.path.sep) file.save(os.path.join(UPLOAD_FOLDER + self.directory + os.path.sep, file_name)) self.uploaded = True def upload_bot(self, url, my_filename): file_name = secure_filename(my_filename) if not os.path.exists(UPLOAD_FOLDER + self.directory + os.path.sep): os.makedirs(UPLOAD_FOLDER + self.directory + os.path.sep) urllib.request.urlretrieve(url, os.path.join(UPLOAD_FOLDER + self.directory + os.path.sep, file_name)) self.uploaded = True def clear_file(self): try: os.remove(os.path.join(UPLOAD_FOLDER + self.directory + os.path.sep, self.filename + self.extension)) self.uploaded = False return True except Exception as e: return False def can_be_accessed_by_device(self, device): if self.message_link is not None: if self.message_link.message.conversation.device_access is True: return self.message_link.message.conversation.circle_id == device.circle_id elif self.user_link is not None: return self.user_link.user.is_in_circle(device.circle_id) elif self.device_link is not None: return self.device_link.device_id == device.id elif self.circle_link is not None: return self.circle_link.circle.device.id == device.id return False def can_be_accessed_by_user(self, user): if self.message_link is not None: return user.is_in_conversation(self.message_link.message.conversation_id) elif self.user_link is not None: if self.user_link.user_id == user.id: return True return user.has_matching_circle(self.user_link.user) elif self.device_link is not None: return user.is_in_circle(self.device_link.device.circle_id) elif self.circle_link is not None: return self.circle_link.circle.has_admin(user) return False def can_be_uploaded_by_device(self, device): if self.message_link is not None: if self.message_link.message.is_user is False: if self.message_link.message.conversation.device_access is True: return self.message_link.message.conversation.circle_id == device.circle_id elif self.user_link is not None: return False elif self.device_link is not None: return self.device_link.device_id == device.id elif self.circle_link is not None: return self.circle_link.circle.device.id == device.id return False def can_be_uploaded_by_user(self, user): if self.message_link is not None: if self.message_link.message.is_user is True: return self.message_link.message.link.user_id == user.id elif self.user_link is not None: return self.user_link.user_id == user.id elif self.device_link is not None: return False elif self.circle_link is not None: return self.circle_link.circle.has_admin(user) return False def is_attached_to_message(self): if self.message_link is not None: return True return False def __init__(self, filename=None, extension=None, identifier=None, directory='default'): if filename is not None and filename != "": self.filename = filename if extension is not None and extension != "": self.extension = extension if identifier is not None and identifier != "": self.identifier = identifier self.directory = directory self.uploaded = False db.session.add(self) db.session.flush() logger.debug("Database add: medias %s", {"id": self.id, "filename": self.filename, "extension": self.extension, "identifier": self.identifier, "uploaded": self.uploaded}) def set_content(self, file): file_name = secure_filename(file.filename) f, e = os.path.splitext(file_name) self.filename = f self.extension = e if self.message_link is not None: self.directory = "conversation_" + str(self.message_link.message.conversation_id) elif self.user_link is not None: self.directory = "user_" + str(self.user_link.user_id) elif self.circle_link is not None: self.directory = "circle_" + str(self.circle_link.circle_id) elif self.device_link is not None: self.directory = "device_" + str(self.device_link.device_id) else: raise Exception("Ce media est corrompu, vous ne pouvez pas upload de fichier") def set_content_bot(self, my_filename): file = str(my_filename).split('.') self.filename = file[0] self.extension = "."+file[1] if self.message_link is not None: self.directory = "conversation_" + str(self.message_link.message.conversation_id) elif self.user_link is not None: self.directory = "user_" + str(self.user_link.user_id) elif self.circle_link is not None: self.directory = "circle_" + str(self.circle_link.circle_id) elif self.device_link is not None: self.directory = "device_" + str(self.device_link.device_id) else: raise Exception("Ce media est corrompu, vous ne pouvez pas upload de fichier") def get_directory(self): return UPLOAD_FOLDER + self.directory + os.path.sep def get_full_name(self): return self.filename + self.extension def get_full_path(self): return os.path.join(self.get_directory(), self.get_full_name()) def update_content(self, filename=None, extension=None, directory=None, identifier=None): if filename is not None and filename != "": self.filename = filename if extension is not None and extension != "": self.extension = extension if directory is not None and directory != "": self.directory = directory if identifier is not None and identifier != "": self.identifier = identifier db.session.commit() logger.debug("Database update: medias%s", {"id": self.id, "filename": self.filename, "extension": self.extension, "identifier": self.identifier, "uploaded": self.uploaded}) def get_link_type(self): if self.message_link is not None: return "conversation" elif self.user_link is not None: return "user" elif self.circle_link is not None: return "circle" elif self.device_link is not None: return "device" else: return "error" def get_link_content(self): if self.message_link is not None: return self.message_link.get_content() elif self.user_link is not None: return self.user_link.get_content() elif self.circle_link is not None: return self.circle_link.get_content() elif self.device_link is not None: return self.device_link.get_content() else: return "error" def get_content(self): return { "id": self.id, "media_link": self.get_link_type(), "link_content": self.get_link_content(), "filename": self.filename, "extension": self.extension, "directory": self.directory, "identifier": self.identifier, "uploaded": self.uploaded } def get_json_compliant_content(self): return { "id": self.id, "media_link": self.get_link_type(), "link_content": self.get_link_content(), "filename": self.filename, "extension": self.extension, "directory": self.directory, "identifier": self.identifier, "uploaded": "true" if self.uploaded else "false" } def get_simple_content(self): return { "id": self.id, "filename": self.filename, "extension": self.extension, "identifier": self.identifier, "uploaded": str(self.uploaded) }
class UserToCircle(db.Model): __tablename__ = "user_to_circle" id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey("users.id")) circle_id = db.Column(db.Integer, db.ForeignKey("circles.id")) created = db.Column(db.DateTime) updated = db.Column(db.DateTime) privilege = db.Column(db.String(10)) user = db.relationship("User", back_populates="circle_link") circle = db.relationship("Circle", back_populates="user_link") def __repr__(self): return "<UserToCircle(id='%d' user_id='%d' circle_id='%d' created='%s' updated='%s' privilege='%s')>"\ % (self.id, self.user_id, self.circle_id, str(self.created), str(self.updated), self.privilege) def __init__(self, created=datetime.datetime.now(), updated=datetime.datetime.now(), privilege="DEFAULT", user=None, circle=None): if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if privilege is not None: self.privilege = privilege if user is not None: self.user = user if circle is not None: self.circle = circle db.session.add(self) db.session.flush() logger.debug("Database add: user_to_circle%s", {"id": self.id, "user_id": self.user_id, "circle_id": self.circle_id, "privilege": self.privilege}) def update_content(self, created=None, updated=datetime.datetime.now(), privilege=None): if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated if privilege is not None and privilege != "": self.privilege = privilege db.session.commit() db.session.flush() logger.debug("Database update: user_to_circle%s", {"id": self.id, "user_id": self.user_id, "circle_id": self.circle_id, "privilege": self.privilege}) def get_content(self, user=True): if user: return { "id": self.id, "user": self.user_id, "circle": self.circle.get_simple_content(), "created": self.created, "updated": self.updated, "privilege": self.privilege } else: return { "id": self.id, "user": self.user.get_simple_content(), "circle": self.circle_id, "created": self.created, "updated": self.updated, "privilege": self.privilege }
class DeviceToMedia(db.Model): __tablename__ = "device_to_media" id = db.Column(db.Integer, primary_key=True) device_id = db.Column(db.Integer, db.ForeignKey('devices.id')) media_id = db.Column(db.Integer, db.ForeignKey('medias.id')) upload_time = db.Column(db.DateTime) purpose = db.Column(db.String(16)) device = db.relationship("Device", back_populates="media_links") media = db.relationship("Media", back_populates="device_link") def __repr__(self): return "<DeviceToMedia(id=%d, device_id=%d, media_id=%d)>" % ( self.id, self.device_id, self.media_id) def __init__(self, device=None, media=None, upload_time=datetime.datetime.now(), purpose="default"): if device is not None: self.device = device if media is not None: self.media = media if upload_time is not None: if type(upload_time) is str: self.upload_time = DateParser.parse(upload_time) else: self.upload_time = upload_time if purpose is not None: self.purpose = purpose db.session.add(self) db.session.flush() logger.debug( "Database add: device_to_media%s", { "id": self.id, "device_id": self.device_id, "media_id": self.media_id, "purpose": self.purpose }) def update_content(self, device=None, media=None, upload_time=None, purpose=None): if device is not None: self.device = device if media is not None: self.media = media if upload_time is not None: if type(upload_time) is str: self.upload_time = DateParser.parse(upload_time) else: self.upload_time = upload_time if purpose is not None: self.purpose = purpose db.session.commit() db.session.flush() logger.debug( "Database update: device_to_media%s", { "id": self.id, "device_id": self.device_id, "media_id": self.media_id, "purpose": self.purpose }) def get_content(self): return { "id": self.id, "device": self.device.get_simple_content(), "media": self.media.get_simple_content(), "upload_time": self.upload_time, "purpose": self.purpose } def get_simple_content(self): return { "id": self.id, "device_id": self.device_id, "media_id": self.media_id, "upload_time": self.upload_time, "purpose": self.purpose }
class Circle(db.Model): __tablename__ = "circles" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(120)) created = db.Column(db.DateTime) updated = db.Column(db.DateTime) device = db.relationship("Device", uselist=False, back_populates="circle", cascade="all") user_link = db.relationship("UserToCircle", back_populates="circle", order_by="UserToCircle.id", cascade="all, delete-orphan") circle_invite = db.relationship("CircleInvite", back_populates="circle", order_by="CircleInvite.id", cascade="all, delete-orphan") conversations = db.relationship("Conversation", back_populates="circle", order_by="Conversation.id", cascade="all, delete-orphan") media_links = db.relationship("CircleToMedia", back_populates="circle", order_by="CircleToMedia.id", cascade="all, delete-orphan") def __repr__(self): return "<Circle(id='%d' device_id='%d' users='%s')>" % ( self.id, self.device.id, str(self.user_link)) def __init__(self, name=None, created=datetime.datetime.now(), updated=datetime.datetime.now(), device=None): if name is not None and name != "": self.name = name if device is not None: self.device = device self.device.circle = self if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated db.session.add(self) db.session.flush() logger.debug( "Database add: circles%s", { "id": self.id, "name": self.name, "device": self.device.id if self.device is not None else -1 }) def has_member(self, member): for link in self.user_link: if link.user_id == member.id: return True return False def has_admin(self, member): for link in self.user_link: if link.user_id == member.id and link.privilege == "ADMIN": return True return False def has_invite(self, user): for invite in self.circle_invite: if invite.user_id == user.id: return True return False def check_validity(self): if len(self.user_link) == 0: db.session.delete(self) db.session.commit() def notify_users(self, p1='circle', p2=None): if p2 is None: p2 = {} p2['circle_id'] = self.id emit(p1, p2, room='circle_' + str(self.id), namespace='/') def notify_mobile(self, title, body, ignore=[]): for user_link in self.user_link: if user_link.user.id not in ignore: android.send_notification(user_link.user, title=title, body=body) def update_content(self, name=None, created=None, updated=datetime.datetime.now()): if name is not None and name != "": self.name = name if created is not None: if type(created) is str: self.created = DateParser.parse(created) else: self.created = created if updated is not None: if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = updated db.session.commit() db.session.flush() logger.debug( "Database update: circles%s", { "id": self.id, "name": self.name, "device": self.device.id if self.device is not None else -1 }) def remove_user(self, user): for user_link in self.user_link: if user_link.user_id == user.id: db.session.delete(user_link) db.session.commit() return True return False def get_simple_content(self): return { "id": self.id, "name": self.name, "created": self.created, "updated": self.updated, "device": self.device.id if self.device is not None else -1, } def get_content(self): return { "id": self.id, "name": self.name, "created": self.created, "updated": self.updated, "users": [link.get_content(False) for link in self.user_link], "device": self.device.get_simple_content() if self.device is not None else {}, "invites": [invite.get_content(False) for invite in self.circle_invite], "conversations": [conv.get_simple_content() for conv in self.conversations], "medias": [link.get_content() for link in self.media_links] }
class Device(db.Model): __tablename__ = "devices" id = db.Column(db.Integer, primary_key=True) circle_id = db.Column(db.Integer, db.ForeignKey('circles.id')) key = db.Column(db.String(20)) activated = db.Column(db.Boolean) username = db.Column(db.String(120), unique=True) password = db.Column(db.String(2048)) json_token = db.Column(db.String(2048)) name = db.Column(db.String(120)) created = db.Column(db.DateTime) updated = db.Column(db.DateTime) is_online = db.Column(db.Boolean) # RELATIONS circle = db.relationship("Circle", back_populates="device") messages = db.relationship("Message", back_populates="device") media_links = db.relationship("DeviceToMedia", back_populates="device", order_by="DeviceToMedia.id", cascade="all, delete-orphan") def __init__(self, created=datetime.datetime.now(), updated=datetime.datetime.now(), username=None, name=None, activated=False, is_online=None): if type(created) is str: self.created = DateParser.parse(created) else: self.created = datetime.datetime.now() if type(updated) is str: self.updated = DateParser.parse(updated) else: self.updated = datetime.datetime.now() if name is not None and name != "": self.name = name else: self.name = "My Device %d" % self.id if activated is not None: self.activated = activated if is_online is not None: self.is_online = is_online else: self.is_online = False # USERNAME / PASSWORD AND KEY GENERATION # NEED TO INSTALL pycrypto and cypher the password for the storage before activation if username is not None: self.username = username else: c = True while c: username = ''.join(random.choice(string.ascii_uppercase) for _ in range(12)) if db.session.query(Device).filter(Device.username == username).first() is None: c = False self.username = username password = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(10)) self.password = base64.b64encode(str.encode(password)).decode('utf-8') self.key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ in range(20)) db.session.add(self) db.session.flush() logger.debug("Database add: devices%s", {"id": self.id, "name": self.name, "circle_id": self.circle.id if self.circle is not None else -1, "activated": self.activated, "username": self.username, "is_online": self.is_online}) def set_password(self, password): self.password = base64.b64encode(str.encode(password)).decode('utf-8') def __repr__(self): return "<Device(id='%s' name='%s' created='%s' updated='%s')>" % \ (self.id, self.name, str(self.created), str(self.updated)) def update_content(self, created=None, updated=datetime.datetime.now(), name=None, activated=None, is_online=None): if type(created) is str: self.created = DateParser.parse(created) elif created is not None: self.created = created if type(updated) is str: self.updated = DateParser.parse(updated) elif updated is not None: self.updated = updated if name is not None and name != "": self.name = name if activated is not None: self.activated = activated if is_online is not None: self.is_online = is_online db.session.commit() db.session.flush() logger.debug("Database update: devices%s", {"id": self.id, "name": self.name, "circle_id": self.circle.id if self.circle is not None else -1, "activated": self.activated, "username": self.username, "is_online": self.is_online}) def disconnect(self): self.json_token = "" db.session.commit() @staticmethod def decode_auth_token_old(auth_token): try: payload = jwt.decode(auth_token, SECRET_KEY) device = db.session.query(Device).filter(Device.id == payload['sub']).first() if device is not None: if device.json_token == "" or device.json_token is None: return False, "Device non authentifié" if not device.activated: return False, "Device non activé" return True, device else: return False, "Device Neo introuvable" except jwt.ExpiredSignatureError: return False, "La session a expiré, authentifiez vous a nouveau" except jwt.InvalidTokenError: return False, 'Token invalide, authentifiez vous a nouveau' except Exception as e: return False, 'Une erreur est survenue : ' + str(e) def decode_auth_token(auth_token): try: payload = jwt.decode(auth_token, SECRET_KEY) device = db.session.query(Device).filter(Device.id == payload['sub']).first() if device is None: raise TokenNotBoundToDevice if device.json_token is None: raise UnauthenticatedDevice if not device.activated: raise UnactivatedDevice return device except jwt.ExpiredSignatureError: raise ExpiredUserSession except jwt.InvalidTokenError: raise InvalidJwtToken return None def encode_auth_token(self): try: payload = { 'exp': datetime.datetime.utcnow() + datetime.timedelta(days=30, seconds=1), 'iat': datetime.datetime.utcnow(), 'sub': self.id } token = jwt.encode(payload, SECRET_KEY, algorithm="HS256") self.json_token = token.decode() db.session.commit() return token.decode() except Exception as e: print(e) return None def check_password(self, password=None): if password is not None and password != "": if self.password == hashlib.sha512(password.encode("utf-8")).hexdigest(): return True return False def authenticate(self, password=None): if self.password != hashlib.sha512(password.encode('utf-8')).hexdigest(): raise InvalidPassword if self.json_token is not None: try: jwt.decode(self.json_token, SECRET_KEY) return self.json_token except jwt.ExpiredSignature: pass return self.encode_auth_token() def update_password(self, password=None): if password is not None and password != "": self.password = hashlib.sha512(password.encode('utf-8')).hexdigest() db.session.commit() def activate(self, activation_key): if self.key == activation_key: self.activated = True pw = base64.b64decode(str.encode(self.password)) self.password = hashlib.sha512(pw).hexdigest() db.session.commit() return self.activated def get_pre_activation_password(self): if self.activated is False: return base64.b64decode(str.encode(self.password)).decode('utf-8') raise Exception("Ce device est active") def get_simple_content(self): return { "id": self.id, "name": self.name, "created": self.created, "updated": self.updated, "circle_id": self.circle.id if self.circle is not None else -1, "activated": self.activated, "username": self.username, "is_online": self.is_online } def get_simple_json_compliant_content(self): return { "id": self.id, "name": self.name, "created": None if self.created is None else self.created.isoformat(), "updated": None if self.updated is None else self.updated.isoformat(), "circle_id": self.circle.id if self.circle is not None else -1, "activated": self.activated, "username": self.username, "is_online": self.is_online } def get_content(self): return { "id": self.id, "name": self.name, "created": self.created, "updated": self.updated, "activated": self.activated, "username": self.username, "circle": self.circle.get_simple_content() if self.circle is not None else {}, "messages": [message.get_simple_content() for message in self.messages], "medias": [link.get_content() for link in self.media_links], "is_online": self.is_online }