class ApiKey(db.Model): id = db.Column(db.Integer, primary_key=True) token = db.Column(db.String(255), unique=True, nullable=False) secret = db.Column(db.String(255), nullable=False) nonce = db.Column(db.BigInteger, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('api_keys', lazy='dynamic')) device_name = db.Column(db.String(255)) expiry = db.Column(db.DateTime()) permissions = db.relationship('Permission', secondary=permissions_api_keys, backref=db.backref('api_keys', lazy='dynamic')) def __init__(self, user, device_name): self.user_id = user.id self.token = secrets.token_urlsafe(8) self.secret = secrets.token_urlsafe(16) self.nonce = 0 self.device_name = device_name self.expiry = datetime.datetime.now() + datetime.timedelta(30) def has_permission(self, permission_name): perm = Permission.from_name(db.session, permission_name) if perm: return perm in self.permissions # pylint: disable=unsupported-membership-test return False @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first()
class ApiKeyRequest(db.Model): MINUTES_EXPIRY = 30 id = db.Column(db.Integer, primary_key=True) token = db.Column(db.String(255), unique=True, nullable=False) secret = db.Column(db.String(255), unique=True, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('api_key_requests', lazy='dynamic')) device_name = db.Column(db.String(255)) expiry = db.Column(db.DateTime()) created_api_key_id = db.Column(db.Integer, db.ForeignKey('api_key.id')) created_api_key = db.relationship('ApiKey') def __init__(self, user, device_name): self.token = secrets.token_urlsafe(8) self.secret = secrets.token_urlsafe(16) self.user = user self.device_name = device_name self.expiry = datetime.datetime.now() + datetime.timedelta(self.MINUTES_EXPIRY) @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() def __str__(self): return self.token
class Proposal(db.Model): STATE_CREATED = "created" STATE_AUTHORIZED = "authorized" STATE_DECLINED = "declined" STATE_EXPIRED = "expired" HOURS_EXPIRY = 72 id = db.Column(db.Integer, primary_key=True) date = db.Column(db.DateTime(), nullable=False) proposer_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) proposer = db.relationship('User', foreign_keys=[proposer_id], backref=db.backref('proposals', lazy='dynamic')) reason = db.Column(db.String()) authorizer_id = db.Column(db.Integer, db.ForeignKey('user.id')) authorizer = db.relationship('User', foreign_keys=[authorizer_id], backref=db.backref('proposals_authorized', lazy='dynamic')) date_authorized = db.Column(db.DateTime()) date_expiry = db.Column(db.DateTime()) status = db.Column(db.String(255)) categories = db.relationship('Category', secondary=categories_proposals, backref=db.backref('proposals', lazy='dynamic')) def __init__(self, proposer, reason): self.generate_defaults() self.proposer = proposer self.reason = reason def generate_defaults(self): self.date = datetime.datetime.now() self.proposer = current_user self.authorizer = None self.date_authorized = None self.date_expiry = None self.status = self.STATE_CREATED @classmethod def count(cls, session): return session.query(cls).count() @classmethod def in_status(cls, session, status): return session.query(cls).filter(cls.status == status).all() def __repr__(self): return "<Proposal %r>" % (self.id)
class PayDbTransaction(db.Model): ACTION_ISSUE = "issue" ACTION_TRANSFER = "transfer" ACTION_DESTROY = "destroy" id = db.Column(db.Integer, primary_key=True) token = db.Column(db.String(255), unique=True, nullable=False) date = db.Column(db.DateTime()) action = db.Column(db.String(255), nullable=False) sender_token = db.Column(db.String(255), db.ForeignKey('user.token'), nullable=False) sender = db.relationship('User', foreign_keys=[sender_token], backref=db.backref('sent', lazy='dynamic')) recipient_token = db.Column(db.String(255), db.ForeignKey('user.token'), nullable=True) recipient = db.relationship('User', foreign_keys=[recipient_token], backref=db.backref('recieved', lazy='dynamic')) amount = db.Column(db.Integer()) attachment = db.Column(db.String(255)) def __init__(self, action, sender, recipient, amount, attachment): self.token = secrets.token_urlsafe(8) self.date = datetime.datetime.now() self.action = action self.sender = sender self.recipient = recipient self.amount = amount self.attachment = attachment @property def timestamp(self): if not self.date: return 0 return int(datetime.datetime.timestamp(self.date)) @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() @classmethod def related_to_user(cls, session, user, offset, limit): # pylint: disable=no-member return session.query(cls).filter(or_(cls.sender_token == user.token, cls.recipient_token == user.token)).order_by(cls.id.desc()).offset(offset).limit(limit) @classmethod def all(cls, session): return session.query(cls).all() def __str__(self): return self.token def to_json(self): tx_schema = PayDbTransactionSchema() return tx_schema.dump(self)
class ClaimCode(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('claimcodes', lazy='dynamic')) date = db.Column(db.DateTime()) token = db.Column(db.String(255), unique=True, nullable=False) secret = db.Column(db.String(255)) amount = db.Column(db.Integer) address = db.Column(db.String(255)) status = db.Column(db.String(255)) def __init__(self, user, token, amount): self.user = user self.date = datetime.datetime.now() self.token = token self.secret = None self.amount = amount self.address = None self.status = "created" @classmethod def count(cls, session): return session.query(cls).count() @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() def __repr__(self): return "<ClaimCode %r>" % (self.token) def to_json(self): schema = ClaimCodeSchema() return schema.dump(self).data
class AMDevice(db.Model): __tablename__ = 'amdevice' id = db.Column(db.Integer(), primary_key=True) wallet_id = db.Column(db.Integer, db.ForeignKey('amwallet.id'), nullable=False) wallet = db.relationship('AMWallet', backref=db.backref('devices', lazy='joined')) date = db.Column(db.DateTime()) app_version = db.Column(db.String()) os = db.Column(db.String()) os_version = db.Column(db.String()) manufacturer = db.Column(db.String()) brand = db.Column(db.String()) device_id = db.Column(db.String()) def __init__(self, wallet, app_version, os, os_version, manufacturer, brand, device_id): self.wallet = wallet self.date = datetime.datetime.now() self.app_version = app_version self.os = os self.os_version = os_version self.manufacturer = manufacturer self.brand = brand self.device_id = device_id def __repr__(self): return "<AMDevice %r %r>" % (self.brand, self.device_id)
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) token = db.Column(db.String(255), unique=True, nullable=False) first_name = db.Column(db.String(255)) last_name = db.Column(db.String(255)) email = db.Column(db.String(255), unique=True, nullable=False) password = db.Column(db.String(255)) mobile_number = db.Column(db.String(255)) address = db.Column(db.String(255)) last_login_at = db.Column(db.DateTime()) current_login_at = db.Column(db.DateTime()) last_login_ip = db.Column(db.String(100)) current_login_ip = db.Column(db.String(100)) login_count = db.Column(db.Integer) active = db.Column(db.Boolean()) fs_uniquifier = db.Column(db.String(255), unique=True, nullable=False) confirmed_at = db.Column(db.DateTime()) tf_totp_secret = db.Column(db.String(255)) tf_primary_method = db.Column(db.String(255)) tf_phone_number = db.Column(db.String(255)) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) photo = db.Column(db.String()) photo_type = db.Column(db.String(255)) def __init__(self, **kwargs): super().__init__(**kwargs) self.token = secrets.token_urlsafe(8) @classmethod def from_email(cls, session, email): return session.query(cls).filter(cls.email == email).first() def __str__(self): return f'{self.email}'
class UserUpdateEmailRequest(db.Model): MINUTES_EXPIRY = 30 id = db.Column(db.Integer, primary_key=True) token = db.Column(db.String(255), unique=True, nullable=False) email = db.Column(db.String(255)) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('update_email_requests', lazy='dynamic')) expiry = db.Column(db.DateTime()) def __init__(self, user, email): self.token = secrets.token_urlsafe(8) self.user = user self.email = email self.expiry = datetime.datetime.now() + datetime.timedelta(self.MINUTES_EXPIRY) @classmethod def from_email(cls, session, email): return session.query(cls).filter(cls.email == email).first() @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() def __str__(self): return self.email
class WavesTxSig(db.Model): id = db.Column(db.Integer, primary_key=True) waves_tx_id = db.Column(db.Integer, db.ForeignKey('waves_tx.id'), nullable=False) waves_tx = db.relationship('WavesTx', backref=db.backref('signatures', lazy='dynamic')) signer_index = db.Column(db.Integer, nullable=False) value = db.Column(db.String, unique=False) def __init__(self, waves_tx, signer_index, value): self.waves_tx = waves_tx self.signer_index = signer_index self.value = value
class Transaction(db.Model): __tablename__ = 'transactions' id = db.Column(db.Integer, primary_key=True) txid = db.Column(db.String, nullable=False, unique=True) sender = db.Column(db.String, nullable=False) recipient = db.Column(db.String, nullable=False) amount = db.Column(db.Integer, nullable=False) attachment = db.Column(db.String, nullable=True) invoice_id = db.Column(db.String, nullable=True) block_id = db.Column(db.Integer, db.ForeignKey('blocks.id')) block = db.relationship('Block') def __init__(self, txid, sender, recipient, amount, attachment, invoice_id, block_id): self.txid = txid self.sender = sender self.recipient = recipient self.amount = amount self.attachment = attachment self.invoice_id = invoice_id self.block_id = block_id @classmethod def from_txid(cls, session, txid): return session.query(cls).filter(cls.txid == txid).first() @classmethod def from_invoice_id(cls, session, invoice_id, start_date, end_date, offset, limit): query = session.query(cls) if invoice_id: query = query.filter(cls.invoice_id == invoice_id) if start_date != 0 or end_date != 0: query = query.join(Block) if start_date != 0: query = query.filter(Block.date >= start_date) if end_date != 0: query = query.filter(Block.date <= end_date) query = query.offset(offset).limit(limit) return query.all() @classmethod def count(cls, session): return session.query(cls).count() def __repr__(self): return '<Transaction %r>' % (self.txid) def to_json(self): self.block_num = self.block.num self.block_date = self.block.date tx_schema = TransactionSchema() return tx_schema.dump(self).data
class Referral(db.Model): STATUS_CREATED = 'created' STATUS_CLAIMED = 'claimed' STATUS_DELETED = 'deleted' REWARD_TYPE_PERCENT = 'percent' REWARD_TYPE_FIXED = 'fixed' REWARD_TYPES_ALL = [REWARD_TYPE_PERCENT, REWARD_TYPE_FIXED] id = db.Column(db.Integer, primary_key=True) token = db.Column(db.String(255), unique=True, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('referrals', lazy='dynamic')) date = db.Column(db.DateTime(), nullable=False) recipient = db.Column(db.String, nullable=False) reward_sender_type = db.Column(db.String(255), nullable=False) reward_sender = db.Column(db.Integer, nullable=False) reward_recipient_type = db.Column(db.String(255), nullable=False) reward_recipient = db.Column(db.Integer, nullable=False) recipient_min_spend = db.Column(db.Integer, nullable=False) status = db.Column(db.String, nullable=False) def __init__(self, user, recipient, reward_sender_type, reward_sender, reward_recipient_type, reward_recipient, recipient_min_spend): assert reward_sender_type == self.REWARD_TYPE_FIXED assert reward_recipient_type in self.REWARD_TYPES_ALL self.token = secrets.token_urlsafe(8) self.user = user self.date = datetime.datetime.now() self.recipient = recipient self.reward_sender_type = reward_sender_type self.reward_sender = reward_sender self.reward_recipient_type = reward_recipient_type self.reward_recipient = reward_recipient self.recipient_min_spend = recipient_min_spend self.status = self.STATUS_CREATED def to_json(self): ref_schema = ReferralSchema() return ref_schema.dump(self).data @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() @classmethod def from_token_user(cls, session, token, user): return session.query(cls).filter(and_(cls.token == token, cls.user_id == user.id)).first() @classmethod def from_user(cls, session, user): return session.query(cls).filter(cls.user_id == user.id).all()
class Block(db.Model): __tablename__ = 'blocks' id = db.Column(db.Integer, primary_key=True) date = db.Column(db.Float, nullable=False, unique=False) num = db.Column(db.Integer, nullable=False) hash = db.Column(db.String, nullable=False, unique=True) reorged = db.Column(db.Boolean, nullable=False, default=False) transactions = db.relationship('Transaction') def __init__(self, block_date, block_num, block_hash): self.date = block_date self.num = block_num self.hash = block_hash self.reorged = False def set_reorged(self, session): for tx in self.transactions: session.delete(tx) self.reorged = True session.add(self) @classmethod def last_block(cls, session): return session.query(cls).filter(cls.reorged == False).order_by( cls.id.desc()).first() @classmethod def from_number(cls, session, num): return session.query(cls).filter((cls.num == num) & (cls.reorged == False)).first() @classmethod def from_hash(cls, session, hash): return session.query(cls).filter(cls.hash == hash).first() @classmethod def tx_block_num(cls, session, tx_block_id): if tx_block_id: block = session.query(cls).filter(cls.id == tx_block_id).first() if block: return block.num return -1 @classmethod def tx_confirmations(cls, session, current_block_num, tx_block_id): block_num = cls.tx_block_num(session, tx_block_id) if block_num != -1: return current_block_num - block_num return 0 def __repr__(self): return '<Block %r %r>' % (self.num, self.hash)
class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64), unique=True) default = db.Column(db.Boolean, default=False, index=True) permissions = db.Column(db.Integer) users = db.relationship('User', backref='role', lazy='dynamic') def __init__(self, **kwargs): super(Role, self).__init__(**kwargs) if self.permissions is None: self.permissions = 0 @staticmethod def insert_roles(): roles = { 'User': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE], 'Moderator': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE, Permission.MODERATE], 'Administrator': [Permission.FOLLOW, Permission.COMMENT, Permission.WRITE, Permission.MODERATE, Permission.ADMIN], } default_role = 'User' for r in roles: role = Role.query.filter_by(name=r).first() if role is None: role = Role(name=r) role.reset_permissions() for permission in roles[r]: role.add_permission(permission) role.default = (role.name == default_role) db.session.add(role) db.session.commit() def add_permission(self, permission): if not self.has_permission(permission): self.permissions += permission def remove_permission(self, permission): if self.has_permission(permission): self.permissions -= permission def reset_permissions(self): self.permissions = 0 def has_permission(self, permission): return self.permissions & permission == permission def __repr__(self): return '<Role %r>' % self.name
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) confirmed_at = db.Column(db.DateTime()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) bronze_data = db.relationship('BronzeData', cascade='delete', backref=db.backref('user'), uselist=False) def __init__(self, **kwargs): super().__init__(**kwargs) @classmethod def from_email(cls, session, email): return session.query(cls).filter(cls.email == email).first() def __str__(self): return '%s' % self.email
class UserStashRequest(db.Model): MINUTES_EXPIRY = 30 ACTION_SAVE = 'save' ACTION_LOAD = 'load' id = db.Column(db.Integer, primary_key=True) key = db.Column(db.String) email_hash = db.Column(db.String, nullable=False) iv = db.Column(db.String) cyphertext = db.Column(db.String) question = db.Column(db.String) action = db.Column(db.String) token = db.Column(db.String, unique=True) secret = db.Column(db.String) expiry = db.Column(db.DateTime()) created_stash_id = db.Column(db.Integer, db.ForeignKey('user_stash.id')) created_stash = db.relationship('UserStash', foreign_keys=[created_stash_id]) loaded_stash_id = db.Column(db.Integer, db.ForeignKey('user_stash.id')) loaded_stash = db.relationship('UserStash', foreign_keys=[loaded_stash_id]) def __init__(self, key, email, iv, cyphertext, question, action): self.key = key self.email_hash = sha256(email) self.iv = iv # pylint: disable=invalid-name self.cyphertext = cyphertext self.question = question self.action = action self.token = secrets.token_urlsafe(8) self.secret = secrets.token_urlsafe(16) self.expiry = datetime.datetime.now() + datetime.timedelta(self.MINUTES_EXPIRY) @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first()
class Bank(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('banks', lazy='dynamic')) token = db.Column(db.String(255), unique=True, nullable=False) account_number = db.Column(db.String(255), nullable=False) account_name = db.Column(db.String(255), nullable=False) account_holder_address = db.Column(db.String(255), nullable=False) bank_name = db.Column(db.String(255), nullable=False) default_account = db.Column(db.Boolean, nullable=False) def __init__(self, token, account_number, account_name, account_holder_address, bank_name, default_account): self.account_number = account_number self.account_name = account_name self.account_holder_address = acount_holder_address self.bank_name = bank_name self.default_account = default_account self.generate_defaults() def generate_defaults(self): self.user = current_user self.token = generate_key(4) def ensure_default_account_exclusive(self, session): if self.default_account: session.query(Bank).filter(Bank.user_id == self.user_id, Bank.id != self.id).update( dict(default_account=False)) @classmethod def count(cls, session): return session.query(cls).count() @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() @classmethod def from_user(cls, session, user): return session.query(cls).filter(cls.user_id == user.id).all() def __repr__(self): return self.account_number def to_json(self): schema = BankSchema() return schema.dump(self).data
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) first_name = db.Column(db.String(255)) last_name = db.Column(db.String(255)) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) confirmed_at = db.Column(db.DateTime()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) @classmethod def from_email(cls, session, email): return session.query(cls).filter(cls.email == email).first() def __str__(self): return self.email
class Payment(db.Model): STATE_CREATED = "created" STATE_SENT_CLAIM_LINK = "sent_claim_link" STATE_EXPIRED = "expired" STATE_SENT_FUNDS = "sent_funds" id = db.Column(db.Integer, primary_key=True) proposal_id = db.Column(db.Integer, db.ForeignKey('proposal.id'), nullable=False) proposal = db.relationship('Proposal', backref=db.backref('payments', lazy='dynamic')) token = db.Column(db.String(255), unique=True, nullable=False) mobile = db.Column(db.String(255)) email = db.Column(db.String(255)) wallet_address = db.Column(db.String(255)) message = db.Column(db.String()) amount = db.Column(db.Integer) status = db.Column(db.String(255)) txid = db.Column(db.String(255)) def __init__(self, proposal, mobile, email, wallet_address, message, amount): self.proposal = proposal self.token = generate_key(8) self.mobile = mobile self.email = email self.wallet_address = wallet_address self.message = message self.amount = amount self.status = self.STATE_CREATED self.txid = None @classmethod def count(cls, session): return session.query(cls).count() @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() def __repr__(self): return "<Payment %r>" % (self.token)
class TxNotification(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('txnotifications', lazy='dynamic')) date = db.Column(db.DateTime()) txid = db.Column(db.String(255), unique=True) def __init__(self, user, txid): self.user = user self.date = datetime.datetime.now() self.txid = txid @classmethod def exists(cls, session, txid): return session.query(cls).filter(cls.txid == txid).first() @classmethod def count(cls, session): return session.query(cls).count() def __repr__(self): return "<TxNotification %r>" % (self.txid)
class ApiKey(db.Model): id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('apikeys', lazy='dynamic')) date = db.Column(db.DateTime(), nullable=False) name = db.Column(db.String(255), nullable=False) token = db.Column(db.String(255), unique=True, nullable=False) nonce = db.Column(db.Integer, nullable=False) secret = db.Column(db.String(255), nullable=False) account_admin = db.Column(db.Boolean, nullable=False) def __init__(self, name): self.name = name self.generate_defaults() def generate_defaults(self): self.user = current_user self.date = datetime.datetime.now() self.token = generate_key(8) self.nonce = 0 self.secret = generate_key(16) @classmethod def count(cls, session): return session.query(cls).count() @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() @classmethod def admin_exists(cls, session, user): return session.query(cls).filter(cls.user == user, cls.account_admin == True).first() def __repr__(self): return "<ApiKey %r>" % (self.token)
class Post(db.Model): __tablename__ = 'posts' id = db.Column(db.Integer, primary_key=True) title = db.Column(db.Text) body = db.Column(db.Text) body_html = db.Column(db.Text) timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) author_id = db.Column(db.Integer, db.ForeignKey('users.id')) comments = db.relationship('Comment', backref='post', lazy='dynamic') @staticmethod def on_changed_body(target, value, old_value, initiator): allowed_tags = ['a', 'abbr', 'acronym', 'b', 'blockquote', 'code', 'em', 'i', 'li', 'ol', 'pre', 'strong', 'ul', 'h1', 'h2', 'h3', 'p'] target.body_html = bleach.linkify( bleach.clean(markdown(value, output_format='html'), tags=allowed_tags, strip=True)) def to_json(self): json_post = { 'url': url_for('api.get_post', post_id=self.id), 'title': self.title, 'body': self.body, 'body_html': self.body_html, 'timestamp': self.timestamp, 'author_url': url_for('api.get_user', user_id=self.author_id), 'comments_url': url_for('api.get_post_comments', post_id=self.id), 'comment_count': self.comments.count() } return json_post @staticmethod def from_json(json_post): title = json_post.get('title') body = json_post.get('body') if body is None or body == '' or title is None or title == '': raise ValidationError('post does not have a body') return Post(title=title, body=body)
class User(db.Model, UserMixin): id = db.Column(db.Integer, primary_key=True) merchant_name = db.Column(db.String(255)) merchant_code = db.Column(db.String(255), unique=True) email = db.Column(db.String(255), unique=True) password = db.Column(db.String(255)) active = db.Column(db.Boolean()) confirmed_at = db.Column(db.DateTime()) roles = db.relationship('Role', secondary=roles_users, backref=db.backref('users', lazy='dynamic')) max_settlements_per_month = db.Column(db.Integer) settlement_fee = db.Column(db.Numeric) merchant_rate = db.Column(db.Numeric) customer_rate = db.Column(db.Numeric) wallet_address = db.Column(db.String(255)) def __init__(self, **kwargs): self.merchant_code = generate_key(4) super().__init__(**kwargs) def on_admin_created(self): self.merchant_code = generate_key(4) self.password = encrypt_password(generate_random_password(16)) self.confirmed_at = datetime.datetime.now() self.active = True @classmethod def from_email(cls, session, email): return session.query(cls).filter(cls.email == email).first() @classmethod def all(cls, session): return session.query(cls).all() def __str__(self): return '%s (%s)' % (self.merchant_code, self.merchant_name)
class Gender(db.Model): __tablename__ = 'genders' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(16), unique=True) users = db.relationship('User', backref='gender', lazy='dynamic') @staticmethod def insert_genders(): genders = { "Male", "Female", "Transgender(MTF)", "Transgender(FTM)", "Rather not say" } for g in genders: gender = Gender.query.filter_by(name=g).first() if gender is None: gender = Gender(name=g) db.session.add(gender) db.session.commit() def __repr__(self): return '<Gender %r>' % self.name
class Settlement(db.Model): STATE_CREATED = "created" STATE_SENT_ZAP = "sent_zap" STATE_VALIDATED = "validated" STATE_SENT_NZD = "sent_nzd" STATE_ERROR = "error" STATE_SUSPENDED = "suspended" id = db.Column(db.Integer, primary_key=True) date = db.Column(db.DateTime()) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('settlements', lazy='dynamic')) token = db.Column(db.String(255), nullable=False, unique=True) bank_id = db.Column(db.Integer, db.ForeignKey('bank.id'), nullable=False) bank = db.relationship('Bank', backref=db.backref('settlements', lazy='dynamic')) amount = db.Column(db.Integer, nullable=False) settlement_address = db.Column(db.String(255), nullable=False) amount_receive = db.Column(db.Integer, nullable=False) txid = db.Column(db.String(255)) status = db.Column(db.String(255), nullable=False) def __init__(self, user, bank, amount, settlement_address, amount_receive): self.date = datetime.datetime.now() self.user = user self.token = generate_key(4) self.bank = bank self.amount = amount self.settlement_address = settlement_address self.amount_receive = amount_receive self.txid = None self.status = Settlement.STATE_CREATED @classmethod def count(cls, session): return session.query(cls).count() @classmethod def from_token(cls, session, token): return session.query(cls).filter(cls.token == token).first() @classmethod def count_this_month(cls, session, user): now = datetime.datetime.now() # month start month_start = now.replace(day=1, hour=0, minute=0, second=0, microsecond=0) # month end next_month = now.replace(day=28) + datetime.timedelta( days=4) # this will never fail last_day_of_month = next_month - datetime.timedelta( days=next_month.day) month_end = last_day_of_month.replace(hour=23, minute=59, second=59, microsecond=999999) return session.query(cls).filter(cls.user_id == user.id, cls.date >= month_start, cls.date <= month_end).count() @classmethod def all_sent_zap(cls, session): return session.query(cls).filter( cls.status == cls.STATE_SENT_ZAP).all() @classmethod def all_validated(cls, session): return session.query(cls).filter( cls.status == cls.STATE_VALIDATED).all() @classmethod def from_id_list(cls, session, ids): return session.query(cls).filter(cls.id.in_(ids)).all() def __repr__(self): return "<Settlement %r>" % (self.token) def to_json(self): schema = SettlementSchema() return schema.dump(self).data
class MerchantTx(db.Model): id = db.Column(db.Integer, primary_key=True) date = db.Column(db.DateTime()) user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) user = db.relationship('User', backref=db.backref('merchanttxs', lazy='dynamic')) wallet_address = db.Column(db.String(255), nullable=False) amount = db.Column(db.Integer) amount_nzd = db.Column(db.Integer) txid = db.Column(db.String(255), nullable=False) direction = db.Column(db.Boolean, nullable=False) category = db.Column(db.String(255)) attachment = db.Column(db.String(255)) device_name = db.Column(db.String(255)) __table_args__ = (db.UniqueConstraint('user_id', 'txid', name='user_txid_uc'), ) def __init__(self, user, date, wallet_address, amount, amount_nzd, txid, direction, attachment): self.date = date self.user = user self.wallet_address = wallet_address self.amount = amount self.amount_nzd = amount_nzd self.txid = txid self.direction = direction self.attachment = attachment try: self.device_name = json.loads(attachment)['device_name'] except: pass try: self.category = json.loads(attachment)['category'] except: pass @classmethod def count(cls, session): return session.query(cls).count() @classmethod def from_txid(cls, session, txid): return session.query(cls).filter(cls.txid == txid).first() @classmethod def oldest_txid(cls, session, user): last = session.query(cls).filter(cls.user_id == user.id).order_by( cls.id.desc()).first() if last: return last.txid return None @classmethod def exists(cls, session, user, txid): return session.query(cls).filter(and_(cls.user_id == user.id), (cls.txid == txid)).scalar() @classmethod def update_wallet_address(cls, session, user): if user.wallet_address: # update txs limit = 100 oldest_txid = None txs = [] while True: have_tx = False txs = blockchain_transactions(logger, app.config["NODE_ADDRESS"], user.wallet_address, limit, oldest_txid) for tx in txs: oldest_txid = tx["id"] have_tx = MerchantTx.exists(db.session, user, oldest_txid) if have_tx: break if tx["type"] == 4 and tx["assetId"] == app.config[ "ASSET_ID"]: amount_nzd = apply_merchant_rate(tx['amount'], user, app.config, use_fixed_fee=False) date = datetime.datetime.fromtimestamp( tx['timestamp'] / 1000) session.add( MerchantTx(user, date, user.wallet_address, tx['amount'], amount_nzd, tx['id'], tx['direction'], tx['attachment'])) if have_tx or len(txs) < limit: break session.commit() def __repr__(self): return "<MerchantTx %r>" % (self.txid) def to_json(self): schema = MerchantTxSchema() return schema.dump(self).data
class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128)) email = db.Column(db.String(128), unique=True, index=True) avatar_hash = db.Column(db.String(32)) password_hash = db.Column(db.String(128)) otp_secret = db.Column(db.String(16)) confirmed = db.Column(db.Boolean, default=False) location = db.Column(db.String(128)) about_me = db.Column(db.Text) member_since = db.Column(db.DateTime, default=datetime.utcnow) last_seen = db.Column(db.DateTime, default=datetime.utcnow) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) gender_id = db.Column(db.Integer, db.ForeignKey('genders.id')) posts = db.relationship('Post', backref='author', lazy='dynamic') followed = db.relationship('Follow', foreign_keys=[Follow.follower_id], backref=db.backref('follower', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') followers = db.relationship('Follow', foreign_keys=[Follow.followed_id], backref=db.backref('followed', lazy='joined'), lazy='dynamic', cascade='all, delete-orphan') comments = db.relationship('Comment', backref='author', lazy='dynamic') def __init__(self, **kwargs): super(User, self).__init__(**kwargs) if self.otp_secret is None: # generate a random secret self.generate_otp_secret() if self.role is None: if self.email == current_app.config['LICMS_ADMIN'].lower(): self.role = Role.query.filter_by(name='Administrator').first() if self.role is None: self.role = Role.query.filter_by(default=True).first() if self.email is not None and self.avatar_hash is None: self.avatar_hash = self.gravatar_hash() self.follow(self) @staticmethod def add_self_follows(): for user in User.query.all(): if not user.is_following(user): user.follow(user) db.session.add(user) db.session.commit() def generate_otp_secret(self): self.otp_secret = base64.b32encode(os.urandom(10)).decode('utf-8') def get_totp_uri(self): return 'otpauth://totp/LiCMS:{0}?secret={1}&issuer=LiCMS'.format(self.email, self.otp_secret) def verify_totp(self, token): return onetimepass.valid_totp(token, self.otp_secret) @property def password(self): raise AttributeError('password is not a readable attribute') @password.setter def password(self, password): self.password_hash = generate_password_hash(password) def verify_password(self, password): return check_password_hash(self.password_hash, password) def generate_confirmation_token(self, expiration=600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'confirm': self.id}).decode('utf-8') def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token.encode('utf-8')) except: return False if data.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) return True def generate_reset_token(self, expiration=600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'reset': self.id}).decode('utf-8') @staticmethod def reset_password(token, new_password): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token.encode('utf-8')) except: return False user = User.query.get(data.get('reset')) if user is None: return False user.password = new_password db.session.add(user) return True def generate_email_change_token(self, new_email, expiration=600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'change_email': self.id, 'new_email': new_email}).decode('utf-8') def change_email(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token.encode('utf-8')) except: return False if data.get('change_email') != self.id: return False new_email = data.get('new_email') if new_email is None: return False if self.query.filter_by(email=new_email).first() is not None: return False self.email = new_email self.avatar_hash = self.gravatar_hash() db.session.add(self) return True def generate_two_factor_reset_token(self, expiration=600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'reset_2FA': self.id}).decode('utf-8') def reset_two_factor(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token.encode('utf-8')) except: return False if data.get('reset_2FA') != self.id: return False self.generate_otp_secret() db.session.add(self) return True def can(self, permission): return self.role is not None and self.role.has_permission(permission) def is_administrator(self): return self.can(Permission.ADMIN) def ping(self): self.last_seen = datetime.utcnow() db.session.add(self) def gravatar_hash(self): return hashlib.md5(self.email.lower().encode('utf-8')).hexdigest() def gravatar(self, size=100, default='identicon', rating='g'): url = 'https://secure.gravatar.com/avatar' _hash = self.avatar_hash or self.gravatar_hash() return '{url}/{hash}?s={size}&d={default}&r={rating}'.format( url=url, hash=_hash, size=size, default=default, rating=rating) def follow(self, user): if not self.is_following(user): f = Follow(follower=self, followed=user) db.session.add(f) db.session.commit() def unfollow(self, user): f = self.followed.filter_by(followed_id=user.id).first() if f: db.session.delete(f) db.session.commit() def is_following(self, user): if user.id is None: return False return self.followed.filter_by(followed_id=user.id).first() is not None def is_followed_by(self, user): if user.id is None: return False return self.followers.filter_by(follower_id=user.id).first() is not None @property def followed_posts(self): return Post.query.join(Follow, Follow.followed_id == Post.author_id).filter(Follow.follower_id == self.id) def to_json(self): json_user = { 'url': url_for('api.get_user', user_id=self.id), 'name': self.name, 'member_since': self.member_since, 'last_seen': self.last_seen, 'gender': self.gender.name, 'posts_url': url_for('api.get_user_posts', user_id=self.id), 'followed_posts_url': url_for('api.get_user_followed_posts', user_id=self.id), 'post_count': self.posts.count() } return json_user def generate_auth_token(self, expiration=600): s = Serializer(current_app.config['SECRET_KEY'], expires_in=expiration) return s.dumps({'user_id': self.id}).decode('utf-8') @staticmethod def verify_auth_token(token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return None return User.query.get(data['user_id']) def __repr__(self): return '<User %r>' % self.name