mirror of
https://github.com/wassname/flask-security.git
synced 2026-07-07 00:06:15 +08:00
Add customizable unauthorized URL. Fixes #23
This commit is contained in:
@@ -106,6 +106,10 @@ def create_app(auth_config):
|
||||
def admin_or_editor():
|
||||
return render_template('index.html', content='Admin or Editor Page')
|
||||
|
||||
@app.route('/unauthorized')
|
||||
def unauthorized():
|
||||
return render_template('unauthorized.html')
|
||||
|
||||
return app
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
{% include "_messages.html" %}
|
||||
{% include "_nav.html" %}
|
||||
<h1>You are not allowed to access the requested resouce</h1>
|
||||
@@ -42,6 +42,7 @@ _default_config = {
|
||||
'RESET_PASSWORD_ERROR_VIEW': '/',
|
||||
'POST_REGISTER_VIEW': None,
|
||||
'POST_CONFIRM_VIEW': None,
|
||||
'UNAUTHORIZED_VIEW': None,
|
||||
'DEFAULT_ROLES': [],
|
||||
'CONFIRMABLE': False,
|
||||
'REGISTERABLE': False,
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
from functools import wraps
|
||||
|
||||
from flask import current_app as app, Response, request, abort, redirect
|
||||
from flask import current_app as app, Response, request, redirect
|
||||
from flask.ext.login import login_required, login_url, current_user
|
||||
from flask.ext.principal import RoleNeed, Permission
|
||||
from werkzeug.local import LocalProxy
|
||||
@@ -23,18 +23,26 @@ from . import utils
|
||||
_security = LocalProxy(lambda: app.security)
|
||||
|
||||
|
||||
_default_http_auth_msg = """
|
||||
_default_unauthorized_txt = """
|
||||
<h1>Unauthorized</h1>
|
||||
<p>The server could not verify that you are authorized to access the URL
|
||||
requested. You either supplied the wrong credentials (e.g. a bad password),
|
||||
or your browser doesn't understand how to supply the credentials required.</p>
|
||||
<p>In case you are allowed to request the document, please check your
|
||||
user-id and password and try again.</p>
|
||||
"""
|
||||
|
||||
|
||||
def _check_token():
|
||||
def _get_unauthorized_response(text=None, headers=None):
|
||||
text = text or _default_unauthorized_txt
|
||||
headers = headers or {}
|
||||
return Response(_default_unauthorized_txt, 401, headers)
|
||||
|
||||
|
||||
def _get_unauthorized_view():
|
||||
cv = utils.get_url(utils.config_value('UNAUTHORIZED_VIEW'))
|
||||
return (cv or request.referrer or '/')
|
||||
|
||||
|
||||
def _check_token():
|
||||
header_key = app.security.token_authentication_header
|
||||
args_key = app.security.token_authentication_key
|
||||
|
||||
@@ -77,7 +85,7 @@ def http_auth_required(fn):
|
||||
if _check_http_auth():
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
return Response(_default_http_auth_msg, 401, headers)
|
||||
return _get_unauthorized_response(headers=headers)
|
||||
|
||||
return decorated
|
||||
|
||||
@@ -89,7 +97,7 @@ def auth_token_required(fn):
|
||||
if _check_token():
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
abort(401)
|
||||
return _get_unauthorized_response()
|
||||
|
||||
return decorated
|
||||
|
||||
@@ -111,6 +119,7 @@ def roles_required(*roles):
|
||||
perms = [Permission(RoleNeed(role)) for role in roles]
|
||||
|
||||
def wrapper(fn):
|
||||
|
||||
@wraps(fn)
|
||||
def decorated_view(*args, **kwargs):
|
||||
if not current_user.is_authenticated():
|
||||
@@ -120,10 +129,14 @@ def roles_required(*roles):
|
||||
for perm in perms:
|
||||
if not perm.can():
|
||||
app.logger.debug('Identity does not provide the '
|
||||
'roles: %s' % [r for r in roles])
|
||||
return redirect(request.referrer or '/')
|
||||
'roles: %s' % [r for r in roles])
|
||||
|
||||
return redirect(_get_unauthorized_view())
|
||||
|
||||
return fn(*args, **kwargs)
|
||||
|
||||
return decorated_view
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
@@ -144,6 +157,7 @@ def roles_accepted(*roles):
|
||||
perm = Permission(*[RoleNeed(role) for role in roles])
|
||||
|
||||
def wrapper(fn):
|
||||
|
||||
@wraps(fn)
|
||||
def decorated_view(*args, **kwargs):
|
||||
if not current_user.is_authenticated():
|
||||
@@ -162,6 +176,8 @@ def roles_accepted(*roles):
|
||||
utils.do_flash('You do not have permission to '
|
||||
'view this resource', 'error')
|
||||
|
||||
return redirect(request.referrer or '/')
|
||||
return redirect(_get_unauthorized_view())
|
||||
|
||||
return decorated_view
|
||||
|
||||
return wrapper
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{% include "security/messages.html" %}
|
||||
<h1>Change password</h1>
|
||||
<form action="{{ url_for('flask_security.reset_password', token=reset_token) }}" method="POST" name="reset_password_form">
|
||||
<form action="{{ url_for('flask_security.reset_password', token=password_reset_token) }}" method="POST" name="reset_password_form">
|
||||
{{ reset_password_form.hidden_tag() }}
|
||||
{{ reset_password_form.password.label }} {{ reset_password_form.password }}<br/>
|
||||
{{ reset_password_form.password_confirm.label }} {{ reset_password_form.password_confirm }}<br/>
|
||||
|
||||
@@ -140,7 +140,8 @@ class ConfiguredURLTests(SecurityTest):
|
||||
'SECURITY_LOGIN_VIEW': '/custom_login',
|
||||
'SECURITY_POST_LOGIN_VIEW': '/post_login',
|
||||
'SECURITY_POST_LOGOUT_VIEW': '/post_logout',
|
||||
'SECURITY_POST_REGISTER_VIEW': '/post_register'
|
||||
'SECURITY_POST_REGISTER_VIEW': '/post_register',
|
||||
'SECURITY_UNAUTHORIZED_VIEW': '/unauthorized'
|
||||
}
|
||||
|
||||
def test_login_view(self):
|
||||
@@ -157,10 +158,19 @@ class ConfiguredURLTests(SecurityTest):
|
||||
self.assertIn('Post Logout', r.data)
|
||||
|
||||
def test_register(self):
|
||||
data = dict(email='dude@lp.com', password='password', password_confirm='password')
|
||||
data = dict(email='dude@lp.com',
|
||||
password='password',
|
||||
password_confirm='password')
|
||||
|
||||
r = self.client.post('/register', data=data, follow_redirects=True)
|
||||
self.assertIn('Post Register', r.data)
|
||||
|
||||
def test_unauthorized(self):
|
||||
self.authenticate("joe@lp.com", endpoint="/custom_auth")
|
||||
r = self._get("/admin", follow_redirects=True)
|
||||
msg = 'You are not allowed to access the requested resouce'
|
||||
self.assertIn(msg, r.data)
|
||||
|
||||
|
||||
class RegisterableTests(SecurityTest):
|
||||
AUTH_CONFIG = {
|
||||
|
||||
Reference in New Issue
Block a user