class User(db.Model): id = db.Column(db.Integer, primary_key=True) mac_address = db.Column(db.String(500), unique=True, nullable=True) username = db.Column(db.String(500), unique=True, nullable=True) password = db.Column(db.String(1000), nullable=True) is_admin = db.Column(db.Boolean, default=False) def __init__(self, username, password, mac_address, is_admin=False): #self.mac_address = str(uuid4()) self.mac_address = mac_address self.username = username self.password = bcrypt.generate_password_hash(password) self.is_admin = is_admin def check_password(self, password): return bcrypt.check_password_hash(self.password, password) def as_dict(self): return { 'id': self.id, 'username': self.username, 'password': self.password, 'mac_address': self.mac_address, 'is_admin': self.is_admin }
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 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 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 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 Role(db.Model, RoleMixin): id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) @classmethod def from_name(cls, session, name): return session.query(cls).filter(cls.name == name).first() def __str__(self): return self.name
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 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 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 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 Role(db.Model, RoleMixin): ROLE_ADMIN = 'admin' ROLE_PROPOSER = 'proposer' ROLE_AUTHORIZER = 'authorizer' ROLE_REFERRAL_CLAIMER = 'referral_claimer' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) @classmethod def from_name(cls, session, name): return session.query(cls).filter(cls.name == name).first() def __str__(self): return f'{self.name}'
class Category(db.Model): CATEGORY_MARKETING = 'marketing' CATEGORY_MISC = 'misc' CATEGORY_TESTING = 'testing' CATEGORY_REFERRAL = 'referral' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) @classmethod def from_name(cls, session, name): return session.query(cls).filter(cls.name == name).first() def __str__(self): return f'{self.name}'
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 Permission(db.Model): PERMISSION_RECIEVE = 'receive' PERMISSION_BALANCE = 'balance' PERMISSION_HISTORY = 'history' PERMISSION_TRANSFER = 'transfer' PERMISSION_ISSUE = 'issue' PERMS_ALL = [PERMISSION_BALANCE, PERMISSION_HISTORY, PERMISSION_ISSUE, PERMISSION_RECIEVE, PERMISSION_TRANSFER] id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(80), unique=True) description = db.Column(db.String(255)) @classmethod def from_name(cls, session, name): return session.query(cls).filter(cls.name == name).first() def __str__(self): return f'{self.name}'
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): id = db.Column(db.Integer, primary_key=True) public_id = db.Column(db.String(500), unique=True, nullable=True) email = db.Column(db.String(100), unique=True, nullable=True) password = db.Column(db.String(1000), nullable=True) is_admin = db.Column(db.Boolean, default=False) def __init__(self, email, password, is_admin=False): self.public_id = str(uuid4()) self.email = email self.password = bcrypt.generate_password_hash(password) self.is_admin = is_admin def check_password(self, password): return bcrypt.check_password_hash(self.password, password) def as_dict(self): return { "id": self.public_id, "mail": self.email, "is_admin": self.is_admin }
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 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 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 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 UserCreateRequest(db.Model): MINUTES_EXPIRY = 30 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)) mobile_number = db.Column(db.String(255)) address = db.Column(db.String(255)) photo = db.Column(db.String()) photo_type = db.Column(db.String(255)) password = db.Column(db.String(255)) expiry = db.Column(db.DateTime()) def __init__(self, first_name, last_name, email, mobile_number, address, photo, photo_type, password): self.token = secrets.token_urlsafe(8) self.first_name = first_name self.last_name = last_name self.email = email self.mobile_number = mobile_number self.address = address self.photo = photo self.photo_type = photo_type self.password = password 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 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 Utility(db.Model): id = db.Column(db.Integer, primary_key=True) date = db.Column(db.DateTime(), nullable=False) name = db.Column(db.String(255), nullable=False) description = db.Column(db.Text()) bank_description = db.Column(db.Text(), nullable=False) def __init__(self, name): self.generate_defaults() def generate_defaults(self): self.date = datetime.datetime.now() @classmethod def count(cls, session): return session.query(cls).count() @classmethod def all(cls, session): return session.query(cls).all() @classmethod def all_alphabetical(cls, session): return session.query(cls).order_by(cls.name).all() @classmethod def from_id(cls, session, utility_id): return session.query(cls).filter(cls.id == utility_id).first() @classmethod def jsonify_bank_descriptions(cls, utilities): for utility in utilities: utility.bank_description_json = json.loads( utility.bank_description) def __repr__(self): return "<Utility %r>" % (self.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 Invoice(db.Model): STATUS_CREATED = "Created" STATUS_READY = "Ready" STATUS_INCOMING = "Incomming" #sp :( STATUS_CONFIRMED = "Confirmed" STATUS_PAYOUTWAIT = "PayoutWait" STATUS_SENT = "Sent" STATUS_EXPIRED = "Expired" id = db.Column(db.Integer, primary_key=True) date = db.Column(db.DateTime(), 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) email = db.Column(db.String(255)) amount = db.Column(db.Integer, nullable=False) amount_zap = db.Column(db.Integer, nullable=False) bronze_broker_token = db.Column(db.String(255), nullable=False) status = db.Column(db.String(255)) tx_seen = db.Column(db.Boolean, nullable=False) utility_name = db.Column(db.String(255)) def __init__(self, email, amount, amount_zap, bronze_broker_token, status, utility_name): self.generate_defaults() self.email = email self.amount = amount self.amount_zap = amount_zap self.bronze_broker_token = bronze_broker_token self.status = status self.tx_seen = False self.utility_name = utility_name def generate_defaults(self): 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 all_with_email_and_not_terminated(cls, session): return session.query(cls).filter( and_( cls.email != None, or_( cls.status == None, and_(cls.status != cls.STATUS_SENT, cls.status != cls.STATUS_EXPIRED)))).all() def __repr__(self): return "<Invoice %r %r>" % (self.token, self.status) def to_json(self): schema = InvoiceSchema() return schema.dump(self).data
class AMWallet(db.Model): __tablename__ = 'amwallet' id = db.Column(db.Integer(), primary_key=True) address = db.Column(db.String(), unique=True) def __init__(self, address): self.address = address @classmethod def from_address(cls, session, address): return session.query(cls).filter(cls.address == address).first() @classmethod def with_multiple_devices(cls, session): ids = [] for wallet in session.query(cls).join(cls.devices).group_by( cls.id).having(func.count(AMDevice.id) > 1): ids.append(wallet.id) return session.query(cls).filter(cls.id.in_(ids)) @classmethod def initialize_wallet_addresses(cls, session): # update txs addrs = {} try: node = cfg.node_http_base_url[:-1] issuer_addr = issuer_address(node, cfg.asset_id) if not issuer_addr: return False limit = 1000 oldest_txid = None txs_count = None txs = [] while True: have_tx = False txs = blockchain_transactions(node, issuer_addr, limit, oldest_txid) for tx in txs: oldest_txid = tx["id"] if tx["type"] == 4 and tx["assetId"] == cfg.asset_id: if 'sender' in tx: addrs[tx['sender']] = 1 if 'recipient' in tx: addrs[tx['recipient']] = 1 # reached end of transaction history for this address if len(txs) < limit: break except requests.exceptions.ConnectionError as ex: logger.error(ex) return False # create all the AMWallet and AMDevice db entries for key, value in addrs.items(): wallet = AMWallet(key) session.add(wallet) session.add( AMDevice(wallet, 'n/a', 'n/a', 'n/a', 'n/a', 'n/a', 'n/a')) session.commit() return True @classmethod def is_empty(cls, session): return not session.query(cls).first() def __repr__(self): return "<AMWallet %r>" % (self.address)
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