models.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. import os
  2. import datetime
  3. import hashlib
  4. import flask_whooshalchemyplus
  5. from nova import app, db
  6. from sqlalchemy_utils import PasswordType, force_auto_coercion
  7. from itsdangerous import Signer, BadSignature
  8. force_auto_coercion()
  9. class User(db.Model):
  10. __tablename__ = 'users'
  11. __searchable__ = ['name']
  12. id = db.Column(db.Integer, primary_key=True)
  13. name = db.Column(db.String, unique=True)
  14. email = db.Column(db.String)
  15. fullname = db.Column(db.String)
  16. is_admin = db.Column(db.Boolean, default=False)
  17. password = db.Column(PasswordType(
  18. schemes=['pbkdf2_sha512'],
  19. pbkdf2_sha512__default_rounds=50000,
  20. pbkdf2_sha512__salt_size=16),
  21. nullable=False)
  22. token = db.Column(db.String)
  23. token_time = db.Column(db.DateTime)
  24. gravatar = db.Column(db.String)
  25. first_time = db.Column(db.Boolean, default=True)
  26. def __init__(self, name=None, fullname=None, email=None, password=None, is_admin=False):
  27. self.name = name
  28. self.fullname = fullname
  29. self.email = email
  30. self.password = password
  31. self.is_admin = is_admin
  32. self.gravatar = hashlib.md5(email.lower()).hexdigest()
  33. self.generate_token()
  34. def __repr__(self):
  35. return '<User(name={}, fullname={}>'.format(self.name, self.fullname)
  36. def get_signer(self):
  37. return Signer(self.password.hash + self.token_time.isoformat())
  38. def generate_token(self):
  39. self.token_time = datetime.datetime.utcnow()
  40. self.token = self.get_signer().sign(str(self.id))
  41. db.session.commit()
  42. def is_token_valid(self, token):
  43. try:
  44. if str(self.id) != self.get_signer().unsign(token):
  45. return False
  46. except BadSignature:
  47. return False
  48. return True
  49. def is_authenticated(self):
  50. return True
  51. def is_active(self):
  52. return True
  53. def is_anonymous(self):
  54. False
  55. def get_id(self):
  56. return self.name
  57. class Dataset(db.Model):
  58. __tablename__ = 'datasets'
  59. __searchable__ = ['name']
  60. id = db.Column(db.Integer, primary_key=True)
  61. type = db.Column(db.String(50))
  62. name = db.Column(db.String)
  63. description = db.Column(db.String)
  64. path = db.Column(db.String)
  65. created = db.Column(db.DateTime, default=datetime.datetime.utcnow)
  66. closed = db.Column(db.Boolean, default=False)
  67. collection_id = db.Column(db.Integer, db.ForeignKey('collections.id'))
  68. has_thumbnail = db.Column(db.Boolean, default=False)
  69. collection = db.relationship('Collection')
  70. accesses = db.relationship('Access', cascade='all, delete, delete-orphan')
  71. __mapper_args__ = {
  72. 'polymorphic_identity': 'dataset',
  73. 'polymorphic_on': type
  74. }
  75. def to_dict(self):
  76. path = os.path.join(app.config['NOVA_ROOT_PATH'], self.path)
  77. return dict(name=self.name, path=path, closed=self.closed)
  78. def __repr__(self):
  79. return '<Dataset(name={}, path={}>'.format(self.name, self.path)
  80. class Taxon(db.Model):
  81. __tablename__ = 'taxons'
  82. id = db.Column(db.Integer, primary_key=True)
  83. name = db.Column(db.String)
  84. def __repr__(self):
  85. return '<Taxon(name={}>'.format(self.name)
  86. class Order(db.Model):
  87. __tablename__ = 'orders'
  88. id = db.Column(db.Integer, primary_key=True)
  89. name = db.Column(db.String)
  90. def __repr__(self):
  91. return '<Order(name={}>'.format(self.name)
  92. class Family(db.Model):
  93. __tablename__ = 'families'
  94. id = db.Column(db.Integer, primary_key=True)
  95. name = db.Column(db.String)
  96. def __repr__(self):
  97. return '<Family(name={}>'.format(self.name)
  98. class Genus(db.Model):
  99. __tablename__ = 'genuses'
  100. id = db.Column(db.Integer, primary_key=True)
  101. name = db.Column(db.String)
  102. def __repr__(self):
  103. return '<Genus(name={}>'.format(self.name)
  104. class SampleScan(Dataset):
  105. __tablename__ = 'samplescans'
  106. __mapper_args__ = {
  107. 'polymorphic_identity': 'samplescan'
  108. }
  109. id = db.Column(db.Integer, db.ForeignKey('datasets.id'), primary_key=True)
  110. taxon_id = db.Column(db.Integer, db.ForeignKey('taxons.id'), nullable=True)
  111. genus_id = db.Column(db.Integer, db.ForeignKey('genuses.id'), nullable=True)
  112. family_id = db.Column(db.Integer, db.ForeignKey('families.id'), nullable=True)
  113. order_id = db.Column(db.Integer, db.ForeignKey('orders.id'), nullable=True)
  114. taxon = db.relationship('Taxon')
  115. genus = db.relationship('Genus')
  116. family = db.relationship('Family')
  117. order = db.relationship('Order')
  118. class Volume(Dataset):
  119. __tablename__ = 'volumes'
  120. __mapper_args__ = {
  121. 'polymorphic_identity': 'volume'
  122. }
  123. id = db.Column(db.Integer, db.ForeignKey('datasets.id'), primary_key=True)
  124. slices = db.Column(db.String)
  125. class Access(db.Model):
  126. __tablename__ = 'accesses'
  127. id = db.Column(db.Integer, primary_key=True)
  128. user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
  129. dataset_id = db.Column(db.Integer, db.ForeignKey('datasets.id'))
  130. owner = db.Column(db.Boolean)
  131. writable = db.Column(db.Boolean)
  132. seen = db.Column(db.Boolean, default=False)
  133. user = db.relationship('User')
  134. dataset = db.relationship('Dataset', back_populates='accesses')
  135. def __repr__(self):
  136. return '<Access(user={}, dataset={}, owner={}, writable={}>'.format(self.user.name, self.dataset.name, self.owner, self.writable)
  137. class Collection(db.Model):
  138. __tablename__ = 'collections'
  139. id = db.Column(db.Integer, primary_key=True)
  140. user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
  141. name = db.Column(db.String)
  142. description = db.Column(db.String)
  143. user = db.relationship('User')
  144. datasets = db.relationship('Dataset', cascade='all, delete, delete-orphan')
  145. def __repr__(self):
  146. return '<Collection(name={})>'.format(self.name)
  147. class Notification(db.Model):
  148. __tablename__ = 'notifications'
  149. id = db.Column(db.Integer, primary_key=True)
  150. message = db.Column(db.String)
  151. user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
  152. user = db.relationship('User')
  153. def __repr__(self):
  154. return '<Notification(user={}, message={})>'.format(self.user.name, self.message)
  155. class Process(db.Model):
  156. __tablename__ = 'processes'
  157. id = db.Column(db.Integer, primary_key=True)
  158. type = db.Column(db.String(50))
  159. task_uuid = db.Column(db.String)
  160. source_id = db.Column(db.Integer, db.ForeignKey('datasets.id'))
  161. destination_id = db.Column(db.Integer, db.ForeignKey('datasets.id'))
  162. source = db.relationship('Dataset', foreign_keys=[source_id])
  163. destination = db.relationship('Dataset', foreign_keys=[destination_id])
  164. __mapper_args__ = {
  165. 'polymorphic_identity': 'process',
  166. 'polymorphic_on': type
  167. }
  168. def __repr__(self):
  169. return '<Process(src={}, dst={})>'.format(self.source.name, self.destination.name)
  170. class Reconstruction(Process):
  171. __tablename__ = 'reconstructions'
  172. __mapper_args__ = {
  173. 'polymorphic_identity': 'reconstruction'
  174. }
  175. id = db.Column(db.Integer, db.ForeignKey('processes.id'), primary_key=True)
  176. flats = db.Column(db.String())
  177. darks = db.Column(db.String())
  178. projections = db.Column(db.String())
  179. output = db.Column(db.String())
  180. flask_whooshalchemyplus.whoosh_index(app, Dataset)
  181. flask_whooshalchemyplus.whoosh_index(app, User)