-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Chapter 9: User roles and permissions (9a)
- Loading branch information
1 parent
809d39f
commit 97e2ef9
Showing
8 changed files
with
183 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
from functools import wraps | ||
from flask import abort | ||
from flask_login import current_user | ||
from .models import Permission | ||
|
||
|
||
def permission_required(permission): | ||
def decorator(f): | ||
@wraps(f) | ||
def decorated_function(*args, **kwargs): | ||
if not current_user.can(permission): | ||
abort(403) | ||
return f(*args, **kwargs) | ||
return decorated_function | ||
return decorator | ||
|
||
|
||
def admin_required(f): | ||
return permission_required(Permission.ADMIN)(f) | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
miguelgrinberg
Author
Owner
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{% extends "base.html" %} | ||
|
||
{% block title %}Flasky - Forbidden{% endblock %} | ||
|
||
{% block page_content %} | ||
<div class="page-header"> | ||
<h1>Forbidden</h1> | ||
</div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
"""user roles | ||
Revision ID: 56ed7d33de8d | ||
Revises: 190163627111 | ||
Create Date: 2013-12-29 22:19:54.212604 | ||
""" | ||
|
||
# revision identifiers, used by Alembic. | ||
revision = '56ed7d33de8d' | ||
down_revision = '190163627111' | ||
|
||
from alembic import op | ||
import sqlalchemy as sa | ||
|
||
|
||
def upgrade(): | ||
### commands auto generated by Alembic - please adjust! ### | ||
op.add_column('roles', sa.Column('default', sa.Boolean(), nullable=True)) | ||
op.add_column('roles', sa.Column('permissions', sa.Integer(), nullable=True)) | ||
op.create_index('ix_roles_default', 'roles', ['default'], unique=False) | ||
### end Alembic commands ### | ||
|
||
|
||
def downgrade(): | ||
### commands auto generated by Alembic - please adjust! ### | ||
op.drop_index('ix_roles_default', 'roles') | ||
op.drop_column('roles', 'permissions') | ||
op.drop_column('roles', 'default') | ||
### end Alembic commands ### |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
import unittest | ||
import time | ||
from app import create_app, db | ||
from app.models import User | ||
from app.models import User, AnonymousUser, Role, Permission | ||
|
||
|
||
class UserModelTestCase(unittest.TestCase): | ||
|
@@ -10,6 +10,7 @@ def setUp(self): | |
self.app_context = self.app.app_context() | ||
self.app_context.push() | ||
db.create_all() | ||
Role.insert_roles() | ||
|
||
def tearDown(self): | ||
db.session.remove() | ||
|
@@ -102,3 +103,37 @@ def test_duplicate_email_change_token(self): | |
token = u2.generate_email_change_token('[email protected]') | ||
self.assertFalse(u2.change_email(token)) | ||
self.assertTrue(u2.email == '[email protected]') | ||
|
||
def test_user_role(self): | ||
u = User(email='[email protected]', password='cat') | ||
self.assertTrue(u.can(Permission.FOLLOW)) | ||
self.assertTrue(u.can(Permission.COMMENT)) | ||
self.assertTrue(u.can(Permission.WRITE)) | ||
self.assertFalse(u.can(Permission.MODERATE)) | ||
self.assertFalse(u.can(Permission.ADMIN)) | ||
|
||
def test_moderator_role(self): | ||
r = Role.query.filter_by(name='Moderator').first() | ||
u = User(email='[email protected]', password='cat', role=r) | ||
self.assertTrue(u.can(Permission.FOLLOW)) | ||
self.assertTrue(u.can(Permission.COMMENT)) | ||
self.assertTrue(u.can(Permission.WRITE)) | ||
self.assertTrue(u.can(Permission.MODERATE)) | ||
self.assertFalse(u.can(Permission.ADMIN)) | ||
|
||
def test_administrator_role(self): | ||
r = Role.query.filter_by(name='Administrator').first() | ||
u = User(email='[email protected]', password='cat', role=r) | ||
self.assertTrue(u.can(Permission.FOLLOW)) | ||
self.assertTrue(u.can(Permission.COMMENT)) | ||
self.assertTrue(u.can(Permission.WRITE)) | ||
self.assertTrue(u.can(Permission.MODERATE)) | ||
self.assertTrue(u.can(Permission.ADMIN)) | ||
|
||
def test_anonymous_user(self): | ||
u = AnonymousUser() | ||
self.assertFalse(u.can(Permission.FOLLOW)) | ||
self.assertFalse(u.can(Permission.COMMENT)) | ||
self.assertFalse(u.can(Permission.WRITE)) | ||
self.assertFalse(u.can(Permission.MODERATE)) | ||
self.assertFalse(u.can(Permission.ADMIN)) |
return permission_required(Permission.ADMIN)(f)
why this line not use ()
return permission_required(Permission.ADMIN)(f)()