db.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import sqlalchemy
  2. from flask_sqlalchemy import SQLAlchemy
  3. from flask_login import UserMixin, AnonymousUserMixin
  4. from datetime import datetime
  5. from itsdangerous import URLSafeTimedSerializer as Serializer
  6. from itsdangerous.exc import BadData
  7. from werkzeug.security import generate_password_hash, check_password_hash
  8. from configure import conf
  9. db = SQLAlchemy()
  10. class Follow(db.Model):
  11. time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
  12. follower_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True, nullable=True)
  13. followed_id = db.Column(db.Integer, db.ForeignKey("user.id"), primary_key=True, nullable=True)
  14. follower = db.relationship("User", primaryjoin="Follow.follower_id==User.id", back_populates="follower")
  15. followed = db.relationship("User", primaryjoin="Follow.followed_id==User.id", back_populates="followed")
  16. class AnonymousUser(AnonymousUserMixin):
  17. @property
  18. def email(self):
  19. return None
  20. class User(db.Model, UserMixin):
  21. __tablename__ = "user"
  22. id = db.Column(db.Integer, autoincrement=True, primary_key=True, nullable=False)
  23. email = db.Column(db.String(32), nullable=False, unique=True)
  24. passwd_hash = db.Column(db.String(128), nullable=False)
  25. role_id = db.Column(db.Integer, db.ForeignKey("role.id"), default=3)
  26. role = db.relationship("Role", back_populates="user")
  27. comment = db.relationship("Comment", back_populates="auth")
  28. follower = db.relationship("Follow", primaryjoin="Follow.follower_id==User.id", back_populates="follower",
  29. lazy="dynamic")
  30. followed = db.relationship("Follow", primaryjoin="Follow.followed_id==User.id", back_populates="followed",
  31. lazy="dynamic")
  32. @staticmethod
  33. def register_creat_token(email: str, passwd_hash: str):
  34. s = Serializer(conf["SECRET_KEY"])
  35. return s.dumps({"email": email, "passwd_hash": passwd_hash})
  36. @staticmethod
  37. def register_load_token(token: str):
  38. s = Serializer(conf["SECRET_KEY"])
  39. try:
  40. token = s.loads(token, max_age=3600)
  41. return token['email'], token['passwd_hash']
  42. except (BadData, KeyError):
  43. return None
  44. def login_creat_token(self, remember_me=False):
  45. s = Serializer(conf["SECRET_KEY"])
  46. return s.dumps({"email": self.email, "remember_me": remember_me})
  47. @staticmethod
  48. def login_load_token(token: str):
  49. s = Serializer(conf["SECRET_KEY"])
  50. try:
  51. token = s.loads(token, max_age=3600)
  52. return token['email'], token['remember_me']
  53. except (BadData, KeyError):
  54. return None
  55. @staticmethod
  56. def get_passwd_hash(passwd: str):
  57. return generate_password_hash(passwd)
  58. def check_passwd(self, passwd: str):
  59. return check_password_hash(self.passwd_hash, passwd)
  60. @property
  61. def passwd(self):
  62. return None
  63. @passwd.setter
  64. def passwd(self, passwd):
  65. self.passwd_hash = self.get_passwd_hash(passwd)
  66. class Role(db.Model):
  67. __tablename__ = "role"
  68. USABLE = 1 # 账号可使用
  69. CHECK_COMMENT = 2
  70. CHECK_ARCHIVE = 4
  71. CHECK_FOLLOW = 8
  72. CREATE_COMMENT = 16
  73. CREATE_ARCHIVE = 32 # 系统权限
  74. FOLLOW = 64
  75. BLOCK_USER = 128 # 系统权限
  76. DELETE_COMMENT = 256 # 系统权限
  77. DELETE_ARCHIVE = 512 # 系统权限
  78. SYSTEM = 1024 # 系统权限
  79. id = db.Column(db.Integer, autoincrement=True, primary_key=True, nullable=False)
  80. name = db.Column(db.String(32), nullable=False, unique=True)
  81. permission = db.Column(db.Integer, nullable=False, default=95) # 非系统权限
  82. user = db.relationship("User", back_populates="role")
  83. def has_permission(self, permission):
  84. return self.permission & permission == permission
  85. def add_permission(self, permission):
  86. if not self.has_permission(permission):
  87. self.permission += permission
  88. def remove_permission(self, permission):
  89. if self.has_permission(permission):
  90. self.permission -= permission
  91. StudentClass = db.Table("archive_comment",
  92. db.Column("archive_id", db.Integer, db.ForeignKey("archive.id"),
  93. nullable=False, primary_key=True),
  94. db.Column("comment_id", db.Integer, db.ForeignKey("comment.id"),
  95. nullable=False, primary_key=True))
  96. class Comment(db.Model):
  97. __tablename__ = "comment"
  98. id = db.Column(db.Integer, autoincrement=True, primary_key=True, nullable=False)
  99. title = db.Column(db.String(32), nullable=True) # 允许为空
  100. content = db.Column(db.Text, nullable=False)
  101. create_time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
  102. update_time = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
  103. auth_id = db.Column(db.Integer, db.ForeignKey("user.id"), nullable=False)
  104. father_id = db.Column(db.Integer, db.ForeignKey("comment.id"))
  105. auth = db.relationship("User", back_populates="comment")
  106. father = db.relationship("Comment", foreign_keys="[Comment.father_id]", remote_side="[Comment.id]",
  107. back_populates="son")
  108. son = db.relationship("Comment", foreign_keys="[Comment.father_id]", remote_side="[Comment.father_id]",
  109. back_populates="father")
  110. archive = db.relationship("Archive", back_populates="comment", secondary="archive_comment")
  111. class Archive(db.Model):
  112. __tablename__ = "archive"
  113. id = db.Column(db.Integer, autoincrement=True, primary_key=True, nullable=False)
  114. name = db.Column(db.String(32), nullable=False, unique=True)
  115. describe = db.Column(db.String(100), nullable=False)
  116. comment = db.relationship("Comment", back_populates="archive", secondary="archive_comment")
  117. def create_all():
  118. try:
  119. db.create_all()
  120. except Exception:
  121. pass
  122. admin = Role(name="admin", permission=2047)
  123. coordinator = Role(name="coordinator", permission=1023)
  124. default = Role(name="default")
  125. db.session.add_all([admin, coordinator, default])
  126. db.session.commit()
  127. def create_faker_user():
  128. from faker import Faker
  129. from sqlalchemy.exc import IntegrityError
  130. fake = Faker("zh_CN")
  131. count_user = 0
  132. while count_user < 100:
  133. user = User(email=fake.email(), passwd_hash=User.get_passwd_hash("passwd"), role_id=3)
  134. db.session.add(user)
  135. try:
  136. db.session.commit()
  137. except IntegrityError:
  138. db.session.rollback()
  139. else:
  140. count_user += 1
  141. def create_faker_comment(auth_max=100):
  142. from random import randint, random
  143. from faker import Faker
  144. from sqlalchemy.exc import IntegrityError
  145. fake = Faker("zh_CN")
  146. count_comment = 0
  147. while count_comment < 100:
  148. title = None
  149. if random() < 0.5:
  150. title = "加人" + fake.company()
  151. father = None
  152. if count_comment > 10 and random() < 0.5:
  153. father = randint(1, count_comment)
  154. time = fake.past_datetime()
  155. comment = Comment(title=title, content=fake.text(), update_time=time, create_time=time, father_id=father,
  156. auth_id=randint(1, auth_max))
  157. db.session.add(comment)
  158. try:
  159. db.session.commit()
  160. except IntegrityError:
  161. db.session.rollback()
  162. else:
  163. count_comment += 1