11from werkzeug .security import generate_password_hash , check_password_hash
22from itsdangerous import TimedJSONWebSignatureSerializer as Serializer
33from flask import current_app
4- from flask_login import UserMixin
4+ from flask_login import UserMixin , AnonymousUserMixin
55from . import db , login_manager
66
77
8+ class Permission :
9+ FOLLOW = 1
10+ COMMENT = 2
11+ WRITE = 4
12+ MODERATE = 8
13+ ADMIN = 16
14+
15+
816class Role (db .Model ):
917 __tablename__ = 'roles'
1018 id = db .Column (db .Integer , primary_key = True )
1119 name = db .Column (db .String (64 ), unique = True )
20+ default = db .Column (db .Boolean , default = False , index = True )
21+ permissions = db .Column (db .Integer )
1222 users = db .relationship ('User' , backref = 'role' , lazy = 'dynamic' )
1323
24+ def __init__ (self , ** kwargs ):
25+ super (Role , self ).__init__ (** kwargs )
26+ if self .permissions is None :
27+ self .permissions = 0
28+
29+ @staticmethod
30+ def insert_roles ():
31+ roles = {
32+ 'User' : [Permission .FOLLOW , Permission .COMMENT , Permission .WRITE ],
33+ 'Moderator' : [Permission .FOLLOW , Permission .COMMENT ,
34+ Permission .WRITE , Permission .MODERATE ],
35+ 'Administrator' : [Permission .FOLLOW , Permission .COMMENT ,
36+ Permission .WRITE , Permission .MODERATE ,
37+ Permission .ADMIN ],
38+ }
39+ default_role = 'User'
40+ for r in roles :
41+ role = Role .query .filter_by (name = r ).first ()
42+ if role is None :
43+ role = Role (name = r )
44+ role .reset_permissions ()
45+ for perm in roles [r ]:
46+ role .add_permission (perm )
47+ role .default = (role .name == default_role )
48+ db .session .add (role )
49+ db .session .commit ()
50+
51+ def add_permission (self , perm ):
52+ if not self .has_permission (perm ):
53+ self .permissions += perm
54+
55+ def remove_permission (self , perm ):
56+ if self .has_permission (perm ):
57+ self .permissions -= perm
58+
59+ def reset_permissions (self ):
60+ self .permissions = 0
61+
62+ def has_permission (self , perm ):
63+ return self .permissions & perm == perm
64+
1465 def __repr__ (self ):
1566 return '<Role %r>' % self .name
1667
@@ -24,6 +75,14 @@ class User(UserMixin, db.Model):
2475 password_hash = db .Column (db .String (128 ))
2576 confirmed = db .Column (db .Boolean , default = False )
2677
78+ def __init__ (self , ** kwargs ):
79+ super (User , self ).__init__ (** kwargs )
80+ if self .role is None :
81+ if self .email == current_app .config ['FLASKY_ADMIN' ]:
82+ self .role = Role .query .filter_by (name = 'Administrator' ).first ()
83+ if self .role is None :
84+ self .role = Role .query .filter_by (default = True ).first ()
85+
2786 @property
2887 def password (self ):
2988 raise AttributeError ('password is not a readable attribute' )
@@ -91,10 +150,26 @@ def change_email(self, token):
91150 db .session .add (self )
92151 return True
93152
153+ def can (self , perm ):
154+ return self .role is not None and self .role .has_permission (perm )
155+
156+ def is_administrator (self ):
157+ return self .can (Permission .ADMIN )
158+
94159 def __repr__ (self ):
95160 return '<User %r>' % self .username
96161
97162
163+ class AnonymousUser (AnonymousUserMixin ):
164+ def can (self , permissions ):
165+ return False
166+
167+ def is_administrator (self ):
168+ return False
169+
170+ login_manager .anonymous_user = AnonymousUser
171+
172+
98173@login_manager .user_loader
99174def load_user (user_id ):
100175 return User .query .get (int (user_id ))
0 commit comments