models.py 7.0 KB

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