Let any 'admin' user elevate to 'root' for full system access
But otherwise, let the Administrator role be "normal" and have perms of its own. Hopefully cuts down on unwanted screen noise for admins.
This commit is contained in:
parent
4599eaad97
commit
6bf60365ba
|
@ -106,11 +106,22 @@ def provide_postgresql_settings(settings):
|
|||
settings.setdefault('tm.attempts', 2)
|
||||
|
||||
|
||||
class Root(dict):
|
||||
"""
|
||||
Root factory for Pyramid. This is necessary to make the current request
|
||||
available to the authorization policy object, which needs it to check if
|
||||
the current request "is root".
|
||||
"""
|
||||
|
||||
def __init__(self, request):
|
||||
self.request = request
|
||||
|
||||
|
||||
def make_pyramid_config(settings):
|
||||
"""
|
||||
Make a Pyramid config object from the given settings.
|
||||
"""
|
||||
config = Configurator(settings=settings)
|
||||
config = Configurator(settings=settings, root_factory=Root)
|
||||
|
||||
# Configure user authentication / authorization.
|
||||
config.set_authentication_policy(SessionAuthenticationPolicy())
|
||||
|
|
|
@ -43,9 +43,14 @@ class TailboneAuthorizationPolicy(object):
|
|||
def permits(self, context, principals, permission):
|
||||
for userid in principals:
|
||||
if userid not in (Everyone, Authenticated):
|
||||
if context.request.user and context.request.user.uuid == userid:
|
||||
return context.request.has_perm(permission)
|
||||
else:
|
||||
assert False # should no longer happen..right?
|
||||
user = Session.query(model.User).get(userid)
|
||||
if user:
|
||||
return has_permission(Session(), user, permission)
|
||||
if has_permission(Session(), user, permission):
|
||||
return True
|
||||
if Everyone in principals:
|
||||
return has_permission(Session(), None, permission)
|
||||
return False
|
||||
|
|
|
@ -61,12 +61,6 @@ def PermissionsFieldRenderer(permissions, include_guest=False, include_authentic
|
|||
|
||||
def _render(self, readonly=False, **kwargs):
|
||||
principal = self.field.model
|
||||
if isinstance(principal, model.Role) and principal is administrator_role(Session()):
|
||||
html = HTML.tag('p', c="This is the administrative role; "
|
||||
"it has full access to the entire system.")
|
||||
if not readonly:
|
||||
html += tags.hidden(self.name, value='') # ugly hack..or good idea?
|
||||
else:
|
||||
html = ''
|
||||
for groupkey in sorted(permissions, key=lambda k: permissions[k]['label'].lower()):
|
||||
inner = HTML.tag('p', c=permissions[groupkey]['label'])
|
||||
|
@ -87,9 +81,7 @@ def PermissionsFieldRenderer(permissions, include_guest=False, include_authentic
|
|||
rendered = True
|
||||
if rendered:
|
||||
html += HTML.tag('div', class_='group', c=inner)
|
||||
if not html:
|
||||
return "(none granted)"
|
||||
return html
|
||||
return html or "(none granted)"
|
||||
|
||||
def render(self, **kwargs):
|
||||
return self._render(**kwargs)
|
||||
|
|
|
@ -99,3 +99,18 @@ ul.error li {
|
|||
ul.ui-menu {
|
||||
max-height: 30em;
|
||||
}
|
||||
|
||||
/******************************
|
||||
* tweaks for root user
|
||||
******************************/
|
||||
|
||||
.menubar .root-user .ui-button-text,
|
||||
.menubar .root-user.ui-menu-item a {
|
||||
background-color: red;
|
||||
color: black;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.menubar .root-user.ui-menu-item a {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ from __future__ import unicode_literals, absolute_import
|
|||
import rattail
|
||||
from rattail import enum
|
||||
from rattail.db import model
|
||||
from rattail.db.auth import has_permission
|
||||
from rattail.db.auth import has_permission, administrator_role
|
||||
|
||||
from pyramid import threadlocal
|
||||
from pyramid.security import authenticated_userid
|
||||
|
@ -108,6 +108,10 @@ def context_found(event):
|
|||
|
||||
* The currently logged-in user instance (if any), as ``user``.
|
||||
|
||||
* ``is_admin`` flag indicating whether user has the Administrator role.
|
||||
|
||||
* ``is_root`` flag indicating whether user is currently elevated to root.
|
||||
|
||||
* A shortcut method for permission checking, as ``has_perm()``.
|
||||
|
||||
* A shortcut method for fetching the referrer, as ``get_referrer()``.
|
||||
|
@ -122,13 +126,18 @@ def context_found(event):
|
|||
if request.user:
|
||||
Session().set_continuum_user(request.user)
|
||||
|
||||
def has_perm(perm):
|
||||
return has_permission(Session(), request.user, perm)
|
||||
request.is_admin = request.user and administrator_role(Session()) in request.user.roles
|
||||
request.is_root = request.is_admin and request.session.get('is_root', False)
|
||||
|
||||
def has_perm(name):
|
||||
if has_permission(Session(), request.user, name):
|
||||
return True
|
||||
return request.is_root
|
||||
request.has_perm = has_perm
|
||||
|
||||
def has_any_perm(*perms):
|
||||
for perm in perms:
|
||||
if has_permission(Session(), request.user, perm):
|
||||
def has_any_perm(*names):
|
||||
for name in names:
|
||||
if has_perm(name):
|
||||
return True
|
||||
return False
|
||||
request.has_any_perm = has_any_perm
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2015 Lance Edgar
|
||||
# Copyright © 2010-2016 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
|
@ -24,20 +24,19 @@
|
|||
Auth Views
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
from rattail.db.auth import authenticate_user, set_user_password
|
||||
|
||||
import formencode
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
from pyramid.security import remember, forget, authenticated_userid
|
||||
|
||||
from pyramid_simpleform import Form
|
||||
from webhelpers.html import literal
|
||||
from webhelpers.html import tags
|
||||
|
||||
import formencode
|
||||
from pyramid_simpleform import Form
|
||||
from ..forms.simpleform import FormRenderer
|
||||
|
||||
from ..db import Session
|
||||
from rattail.db.auth import authenticate_user, set_user_password
|
||||
from tailbone.db import Session
|
||||
from tailbone.forms.simpleform import FormRenderer
|
||||
|
||||
|
||||
def forbidden(request):
|
||||
|
@ -104,6 +103,24 @@ def logout(request):
|
|||
return HTTPFound(location=referrer, headers=headers)
|
||||
|
||||
|
||||
def become_root(request):
|
||||
"""
|
||||
Elevate the current request to 'root' for full system access.
|
||||
"""
|
||||
request.session['is_root'] = True
|
||||
request.session.flash("You have been elevated to 'root' and now have full system access", 'error')
|
||||
return HTTPFound(location=request.get_referrer())
|
||||
|
||||
|
||||
def stop_root(request):
|
||||
"""
|
||||
Lower the current request from 'root' back to normal access.
|
||||
"""
|
||||
request.session['is_root'] = False
|
||||
request.session.flash("Your normal system access has been restored")
|
||||
return HTTPFound(location=request.get_referrer())
|
||||
|
||||
|
||||
class CurrentPasswordCorrect(formencode.validators.FancyValidator):
|
||||
|
||||
def _to_python(self, value, state):
|
||||
|
@ -148,6 +165,8 @@ def change_password(request):
|
|||
def add_routes(config):
|
||||
config.add_route('login', '/login')
|
||||
config.add_route('logout', '/logout')
|
||||
config.add_route('become_root', '/root/yes')
|
||||
config.add_route('stop_root', '/root/no')
|
||||
config.add_route('change_password', '/change-password')
|
||||
|
||||
|
||||
|
@ -161,5 +180,8 @@ def includeme(config):
|
|||
|
||||
config.add_view(logout, route_name='logout')
|
||||
|
||||
config.add_view(become_root, route_name='become_root')
|
||||
config.add_view(stop_root, route_name='stop_root')
|
||||
|
||||
config.add_view(change_password, route_name='change_password',
|
||||
renderer='/change_password.mako')
|
||||
|
|
Loading…
Reference in a new issue