db.py 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # **************************************************************************
  4. # Copyright © 2016 jianglin
  5. # File Name: models.py
  6. # Author: jianglin
  7. # Email: xiyang0807@gmail.com
  8. # Created: 2016-12-15 21:09:08 (CST)
  9. # Last Update: Monday 2019-05-06 23:37:21 (CST)
  10. # By:
  11. # Description:
  12. # **************************************************************************
  13. from datetime import datetime, timedelta
  14. from flask import current_app
  15. from flask_babel import lazy_gettext as _
  16. from flask_login import current_user, login_user, logout_user
  17. from flask_principal import Identity, identity_changed, AnonymousIdentity
  18. from pytz import all_timezones
  19. from sqlalchemy import event
  20. from sqlalchemy.orm import object_session
  21. from flask_maple.models import ModelMixin
  22. from flask_maple.auth.models import UserMixin, GroupMixin
  23. from flask_maple.permission.models import PermissionMixin
  24. from forums.common.records import load_online_sign_users
  25. from forums.count import Count
  26. from forums.extension import db, mail
  27. user_follower = db.Table(
  28. 'user_follower',
  29. db.Column('user_id', db.Integer, db.ForeignKey('user.id')),
  30. db.Column('follower_id', db.Integer, db.ForeignKey('user.id')))
  31. class Permission(db.Model, PermissionMixin):
  32. __tablename__ = 'permission'
  33. class Group(db.Model, GroupMixin):
  34. __tablename__ = 'group'
  35. class User(db.Model, UserMixin):
  36. __tablename__ = 'user'
  37. id = db.Column(db.Integer, primary_key=True)
  38. followers = db.relationship(
  39. 'User',
  40. secondary=user_follower,
  41. primaryjoin=(id == user_follower.c.user_id),
  42. secondaryjoin=(id == user_follower.c.follower_id),
  43. backref=db.backref(
  44. 'following_users', lazy='dynamic'),
  45. lazy='dynamic')
  46. def is_followed(self, user=None):
  47. if user is None:
  48. user = current_user
  49. return db.session.query(user_follower).filter(
  50. user_follower.c.user_id == self.id,
  51. user_follower.c.follower_id == user.id).exists()
  52. def login(self, remember=True):
  53. login_user(self, remember)
  54. identity_changed.send(
  55. current_app._get_current_object(), identity=Identity(self.id))
  56. def logout(self):
  57. logout_user()
  58. identity_changed.send(
  59. current_app._get_current_object(), identity=AnonymousIdentity())
  60. @property
  61. def is_not_confirmed(self):
  62. return (not self.is_confirmed and self.id == current_user.id)
  63. @property
  64. def is_online(self):
  65. setting = self.setting
  66. if setting.online_status == UserSetting.STATUS_ALLOW_ALL:
  67. return self.username in load_online_sign_users()
  68. elif setting.online_status == UserSetting.STATUS_ALLOW_AUTHENTICATED:
  69. return self.username in load_online_sign_users(
  70. ) and current_user.is_authenticated
  71. elif setting.online_status == UserSetting.STATUS_ALLOW_OWN:
  72. return current_user.id == self.id
  73. return False
  74. @property
  75. def topic_count(self):
  76. return self.topics.count()
  77. @topic_count.setter
  78. def topic_count(self, value):
  79. return Count.user_topic_count(self.id, value)
  80. @property
  81. def reply_count(self):
  82. return self.replies.count()
  83. @reply_count.setter
  84. def reply_count(self, value):
  85. return Count.user_reply_count(self.id, value)
  86. @property
  87. def message_count(self):
  88. # return self.receive_messages.filter_by(status='0').count()
  89. return Count.user_message_count(self.id)
  90. @message_count.setter
  91. def message_count(self, value):
  92. return Count.user_message_count(self.id, value)
  93. @property
  94. def send_email_time(self):
  95. # return self.receive_messages.filter_by(status='0').count()
  96. return Count.user_email_time(self.id)
  97. @send_email_time.setter
  98. def send_email_time(self, value):
  99. return Count.user_email_time(self.id, value)
  100. @property
  101. def email_is_allowed(self):
  102. t = self.send_email_time
  103. t = datetime.strptime(t, '%Y-%m-%d %H:%M:%S')
  104. now = datetime.now()
  105. if t + timedelta(hours=3) < now:
  106. self.send_email_time = now.strftime('%Y-%m-%d %H:%M:%S')
  107. return True
  108. return False
  109. def send_email(self, *args, **kwargs):
  110. kwargs.update(recipients=[self.email])
  111. mail.send_email(*args, **kwargs)
  112. def send_email_to_admin(self):
  113. ''''
  114. When someone registered an account,send email to admin.
  115. '''
  116. recipients = current_app.config['RECEIVER']
  117. subject = '{} has registered an account.'.format(self.username)
  118. html = '<p>username: {}</p><p>email: {}</p>'.format(self.username,
  119. self.email)
  120. mail.send_email(subject=subject, html=html, recipients=recipients)
  121. class UserInfo(db.Model, ModelMixin):
  122. __tablename__ = 'userinfo'
  123. id = db.Column(db.Integer, primary_key=True)
  124. avatar = db.Column(db.String(128))
  125. school = db.Column(db.String(128), nullable=True)
  126. word = db.Column(db.Text, nullable=True)
  127. introduce = db.Column(db.Text, nullable=True)
  128. user_id = db.Column(
  129. db.Integer, db.ForeignKey(
  130. 'user.id', ondelete="CASCADE"))
  131. user = db.relationship(
  132. User,
  133. backref=db.backref(
  134. "info", uselist=False, cascade='all,delete', lazy='joined'),
  135. uselist=False,
  136. lazy='joined')
  137. def __repr__(self):
  138. return "<UserInfo %r>" % str(self.id)
  139. def __str__(self):
  140. return "%s's info" % self.user_id
  141. class UserSetting(db.Model, ModelMixin):
  142. STATUS_ALLOW_ALL = '0'
  143. STATUS_ALLOW_AUTHENTICATED = '1'
  144. STATUS_ALLOW_OWN = '2'
  145. STATUS = (('0', _('ALLOW ALL USER')), ('1', _('ALLOW AUTHENTICATED USER')),
  146. ('2', _('ALLOW OWN')))
  147. LOCALE_CHINESE = 'zh'
  148. LOCALE_ENGLISH = 'en'
  149. LOCALE = (('zh', _('Chinese')), ('en', _('English')))
  150. TIMEZONE_UTC = 'UTC'
  151. TIMEZONE = [(i, i) for i in all_timezones]
  152. __tablename__ = 'usersetting'
  153. id = db.Column(db.Integer, primary_key=True)
  154. online_status = db.Column(
  155. db.String(10), nullable=False, default=STATUS_ALLOW_ALL)
  156. topic_list = db.Column(
  157. db.String(10), nullable=False, default=STATUS_ALLOW_ALL)
  158. rep_list = db.Column(
  159. db.String(10), nullable=False, default=STATUS_ALLOW_ALL)
  160. ntb_list = db.Column(
  161. db.String(10), nullable=False, default=STATUS_ALLOW_OWN)
  162. collect_list = db.Column(
  163. db.String(10), nullable=False, default=STATUS_ALLOW_AUTHENTICATED)
  164. locale = db.Column(db.String(32), nullable=False, default=LOCALE_CHINESE)
  165. timezone = db.Column(db.String(32), nullable=False, default=TIMEZONE_UTC)
  166. user_id = db.Column(
  167. db.Integer, db.ForeignKey(
  168. 'user.id', ondelete="CASCADE"))
  169. user = db.relationship(
  170. User,
  171. backref=db.backref(
  172. "setting", uselist=False, cascade='all,delete', lazy='joined'),
  173. uselist=False,
  174. lazy='joined')
  175. def __repr__(self):
  176. return "<UserSetting %r>" % str(self.id)
  177. def __str__(self):
  178. return "%s's setting" % self.user_id
  179. @event.listens_for(User, 'before_insert')
  180. def add_info(mapper, connection, target):
  181. info = UserInfo()
  182. setting = UserSetting()
  183. object_session(target).add(info)
  184. object_session(target).add(setting)
  185. target.info = info
  186. target.setting = setting