|  |  | @ -2,16 +2,67 @@ from werkzeug.security import generate_password_hash, check_password_hash | 
			
		
	
		
			
				
					|  |  |  | from itsdangerous import TimedJSONWebSignatureSerializer as Serializer | 
			
		
	
		
			
				
					|  |  |  | from itsdangerous import BadSignature | 
			
		
	
		
			
				
					|  |  |  | from flask import current_app | 
			
		
	
		
			
				
					|  |  |  | from flask_login import UserMixin | 
			
		
	
		
			
				
					|  |  |  | from flask_login import UserMixin, AnonymousUserMixin | 
			
		
	
		
			
				
					|  |  |  | from . import db, login_manager | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | class Permission: | 
			
		
	
		
			
				
					|  |  |  | FOLLOW = 1 | 
			
		
	
		
			
				
					|  |  |  | COMMENT = 2 | 
			
		
	
		
			
				
					|  |  |  | WRITE = 4 | 
			
		
	
		
			
				
					|  |  |  | MODERATE = 8 | 
			
		
	
		
			
				
					|  |  |  | ADMIN = 16 | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | 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 perm in roles[r]: | 
			
		
	
		
			
				
					|  |  |  | role.add_permission(perm) | 
			
		
	
		
			
				
					|  |  |  | role.default = (role.name == default_role) | 
			
		
	
		
			
				
					|  |  |  | db.session.add(role) | 
			
		
	
		
			
				
					|  |  |  | db.session.commit() | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def add_permission(self, perm): | 
			
		
	
		
			
				
					|  |  |  | if not self.has_permission(perm): | 
			
		
	
		
			
				
					|  |  |  | self.permissions += perm | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def remove_permission(self, perm): | 
			
		
	
		
			
				
					|  |  |  | if self.has_permission(perm): | 
			
		
	
		
			
				
					|  |  |  | self.permissions -= perm | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def reset_permissions(self): | 
			
		
	
		
			
				
					|  |  |  | self.permissions = 0 | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def has_permission(self, perm): | 
			
		
	
		
			
				
					|  |  |  | return self.permissions & perm == perm | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def __repr__(self): | 
			
		
	
		
			
				
					|  |  |  | return '<Role %r>' % self.name | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
	
		
			
				
					|  |  | @ -25,6 +76,14 @@ class User(UserMixin, db.Model): | 
			
		
	
		
			
				
					|  |  |  | password_hash = db.Column(db.String(128)) | 
			
		
	
		
			
				
					|  |  |  | confirmed = db.Column(db.Boolean, default=False) | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def __init__(self, **kwargs): | 
			
		
	
		
			
				
					|  |  |  | super(User, self).__init__(**kwargs) | 
			
		
	
		
			
				
					|  |  |  | if self.role is None: | 
			
		
	
		
			
				
					|  |  |  | if self.email == current_app.config['FLASKY_ADMIN']: | 
			
		
	
		
			
				
					|  |  |  | self.role = Role.query.filter_by(name='Administrator').first() | 
			
		
	
		
			
				
					|  |  |  | else: | 
			
		
	
		
			
				
					|  |  |  | self.role = Role.query.filter_by(default=True).first() | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | @property | 
			
		
	
		
			
				
					|  |  |  | def password(self): | 
			
		
	
		
			
				
					|  |  |  | raise AttributeError('Password is not a readable attribute') | 
			
		
	
	
		
			
				
					|  |  | @ -92,10 +151,27 @@ class User(UserMixin, db.Model): | 
			
		
	
		
			
				
					|  |  |  | db.session.add(self) | 
			
		
	
		
			
				
					|  |  |  | return True | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def can(self, perm): | 
			
		
	
		
			
				
					|  |  |  | return self.role is not None and self.role.has_permission(perm) | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def is_administrator(self): | 
			
		
	
		
			
				
					|  |  |  | return self.can(Permission.ADMIN) | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def __repr__(self): | 
			
		
	
		
			
				
					|  |  |  | return '<User %r>' % self.username | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | class AnonymousUser(AnonymousUserMixin): | 
			
		
	
		
			
				
					|  |  |  | def can(self, perm): | 
			
		
	
		
			
				
					|  |  |  | return False | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | def is_administrator(self): | 
			
		
	
		
			
				
					|  |  |  | return False | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | login_manager.anonymous_user = AnonymousUser | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  |  | 
			
		
	
		
			
				
					|  |  |  | @login_manager.user_loader | 
			
		
	
		
			
				
					|  |  |  | def load_user(user_id): | 
			
		
	
		
			
				
					|  |  |  | return User.query.get(int(user_id)) |