import dateutil.parser import datetime from werkzeug.security import generate_password_hash, check_password_hash from itsdangerous import TimedJSONWebSignatureSerializer as Serializer from flask import current_app from flask_login import UserMixin, AnonymousUserMixin from . import db from . import login_manager class Role(db.Model): __tablename__ = 'roles' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(128), unique=True) default = db.Column(db.Boolean, default=False, index=True) users = db.relationship('User', backref='role', lazy='dynamic') def __repr__(self): return '' % self.name class User(UserMixin, db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) email = db.Column(db.String(128), unique=True, index=True) username = db.Column(db.String(64), unique=True, index=True) password_hash = db.Column(db.String(128)) full_name = db.Column(db.String(255), index=True) avatar = db.Column(db.String(255), index=True) created_at = db.Column(db.DateTime) role_id = db.Column(db.Integer, db.ForeignKey('roles.id')) provider_password = db.Column(db.Text(255)) confirmed = db.Column(db.Boolean, default=False) suspended = db.Column(db.Boolean, default=False) selected_provider_id = db.Column(db.Integer, db.ForeignKey('providers.id')) @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) # generates confirmation token for user email confirmation def generate_confirmation_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'confirm': self.id}) # confirms user email by id def confirm(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('confirm') != self.id: return False self.confirmed = True db.session.add(self) return True # generates token for password reset def generate_reset_token(self, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'reset': self.id}) def reset_password(self, token, new_password): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) except: return False if data.get('reset') != self.id: return False self.password = new_password db.session.add(self) return True # generates token for email change def generate_email_change_token(self, new_email, expiration=3600): s = Serializer(current_app.config['SECRET_KEY'], expiration) return s.dumps({'change_email': self.id, 'new_email': new_email}) def change_email(self, token): s = Serializer(current_app.config['SECRET_KEY']) try: data = s.loads(token) 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 db.session.add(self) return True def __repr__(self): return '' % self.username, '' % self.selected_provider class Provider(db.Model): __tablename__ = 'providers' id = db.Column(db.Integer, primary_key=True) provider = db.Column(db.String(128), unique=False, index=True) name = db.Column(db.String(128), unique=True, index=True) region = db.Column(db.String(128), unique=False, index=True) project_name = db.Column(db.String(128), unique=False, index=True) default_role = db.Column(db.String(128), unique=False, index=True) username = db.Column(db.String(128), unique=False, index=True) api_version = db.Column(db.String(64), unique=False, index=True) password = db.Column(db.Text(255), unique=False, index=False) url = db.Column(db.Text(512)) created_at = db.Column(db.DateTime) enabled = db.Column(db.Boolean, default=True, nullable=False) validated = db.Column(db.Boolean, default=False, nullable=False) @login_manager.user_loader def load_user(user_id): return User.query.get(int(user_id))