|
|
@ -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)) |