initial users/roles/perms admin stuff
This commit is contained in:
parent
02d4cfc6c5
commit
ba94a015a6
24 changed files with 1061 additions and 110 deletions
|
@ -70,10 +70,10 @@ def administrator_role(session):
|
|||
"""
|
||||
|
||||
uuid = 'd937fa8a965611dfa0dd001143047286'
|
||||
admin = session.query(Role).get(uuid)
|
||||
admin = session.query(edbob.Role).get(uuid)
|
||||
if admin:
|
||||
return admin
|
||||
admin = Role(uuid=uuid, name='Administrator')
|
||||
admin = edbob.Role(uuid=uuid, name='Administrator')
|
||||
session.add(admin)
|
||||
return admin
|
||||
|
||||
|
@ -86,15 +86,15 @@ def has_permission(obj, perm):
|
|||
fully-qualified permission name, e.g. ``'users.create'``.
|
||||
"""
|
||||
|
||||
if isinstance(obj, User):
|
||||
if isinstance(obj, edbob.User):
|
||||
roles = obj.roles
|
||||
elif isinstance(obj, Role):
|
||||
elif isinstance(obj, edbob.Role):
|
||||
roles = [obj]
|
||||
else:
|
||||
raise TypeError("You must pass either a User or Role for 'obj'; got: %s" % repr(obj))
|
||||
session = object_session(obj)
|
||||
assert session
|
||||
admin = get_administrator(session)
|
||||
admin = administrator_role(session)
|
||||
for role in roles:
|
||||
if role is admin:
|
||||
return True
|
||||
|
@ -107,15 +107,18 @@ def has_permission(obj, perm):
|
|||
def init_database(engine, session):
|
||||
"""
|
||||
Initialize the auth system within an ``edbob`` database.
|
||||
|
||||
Currently this only creates an :class:`edbob.User` instance with username
|
||||
``'admin'`` (and password the same), and assigns the user to the built-in
|
||||
administrative role (see :func:`administrator_role()`).
|
||||
"""
|
||||
|
||||
# Create 'admin' user with full rights.
|
||||
admin = edbob.User()
|
||||
admin.username = 'admin'
|
||||
admin = edbob.User(username='admin')
|
||||
set_user_password(admin, 'admin')
|
||||
# admin.roles.append(administrator_role(session))
|
||||
admin.roles.append(administrator_role(session))
|
||||
session.add(admin)
|
||||
session.flush()
|
||||
print "Created 'admin' user with password 'admin'"
|
||||
|
||||
|
||||
def set_user_password(user, password):
|
||||
|
|
|
@ -32,9 +32,10 @@ from sqlalchemy.ext.associationproxy import association_proxy
|
|||
|
||||
import edbob
|
||||
from edbob.db.model import Base, uuid_column
|
||||
from edbob.sqlalchemy import getset_factory
|
||||
|
||||
|
||||
__all__ = ['Person', 'User']
|
||||
__all__ = ['Person', 'Role', 'User', 'UserRole', 'Permission']
|
||||
|
||||
|
||||
def get_person_display_name(context):
|
||||
|
@ -65,6 +66,68 @@ class Person(Base):
|
|||
return str(self.display_name or '')
|
||||
|
||||
|
||||
class Permission(Base):
|
||||
"""
|
||||
Represents the fact that a particular :class:`Role` is allowed to do a
|
||||
particular type of thing.
|
||||
"""
|
||||
|
||||
__tablename__ = 'permissions'
|
||||
|
||||
role_uuid = Column(String(32), ForeignKey('roles.uuid'), primary_key=True)
|
||||
permission = Column(String(50), primary_key=True)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Permission: %s, %s>" % (self.role, self.permission)
|
||||
|
||||
def __str__(self):
|
||||
return str(self.permission or '')
|
||||
|
||||
|
||||
class UserRole(Base):
|
||||
"""
|
||||
Represents the association between a :class:`User` and a :class:`Role`.
|
||||
"""
|
||||
|
||||
__tablename__ = 'users_roles'
|
||||
|
||||
uuid = uuid_column()
|
||||
user_uuid = Column(String(32), ForeignKey('users.uuid'))
|
||||
role_uuid = Column(String(32), ForeignKey('roles.uuid'))
|
||||
|
||||
def __repr__(self):
|
||||
return "<UserRole: %s : %s>" % (self.user, self.role)
|
||||
|
||||
|
||||
class Role(Base):
|
||||
"""
|
||||
Represents a role within the system; used to manage permissions.
|
||||
"""
|
||||
|
||||
__tablename__ = 'roles'
|
||||
|
||||
uuid = uuid_column()
|
||||
name = Column(String(25), nullable=False, unique=True)
|
||||
|
||||
_permissions = relationship(
|
||||
Permission, backref='role',
|
||||
cascade='save-update, merge, delete, delete-orphan')
|
||||
permissions = association_proxy('_permissions', 'permission',
|
||||
creator=lambda x: Permission(permission=x),
|
||||
getset_factory=getset_factory)
|
||||
|
||||
_users = relationship(UserRole, backref='role')
|
||||
users = association_proxy('_users', 'user',
|
||||
creator=lambda x: UserRole(user=x),
|
||||
getset_factory=getset_factory)
|
||||
|
||||
def __repr__(self):
|
||||
return "<Role: %s>" % self.name
|
||||
|
||||
def __str__(self):
|
||||
return str(self.name or '')
|
||||
|
||||
|
||||
class User(Base):
|
||||
"""
|
||||
Represents a user of the system. This may or may not correspond to a real
|
||||
|
@ -79,12 +142,11 @@ class User(Base):
|
|||
salt = Column(String(29))
|
||||
person_uuid = Column(String(32), ForeignKey('people.uuid'))
|
||||
|
||||
person = relationship(Person, backref='user')
|
||||
# display_name = association_proxy('person', 'display_name')
|
||||
|
||||
# roles = association_proxy('_roles', 'role',
|
||||
# creator=lambda x: UserRole(role=x),
|
||||
# getset_factory=getset_factory)
|
||||
_roles = relationship(UserRole, backref='user')
|
||||
roles = association_proxy(
|
||||
'_roles', 'role',
|
||||
creator=lambda x: UserRole(role=x),
|
||||
getset_factory=getset_factory)
|
||||
|
||||
def __repr__(self):
|
||||
return "<User: %s>" % self.username
|
||||
|
@ -101,3 +163,14 @@ class User(Base):
|
|||
if self.person and self.person.display_name:
|
||||
return self.person.display_name
|
||||
return self.username
|
||||
|
||||
|
||||
Person.user = relationship(
|
||||
User,
|
||||
back_populates='person',
|
||||
uselist=False)
|
||||
|
||||
User.person = relationship(
|
||||
Person,
|
||||
back_populates='user',
|
||||
uselist=False)
|
||||
|
|
|
@ -29,21 +29,12 @@
|
|||
from sqlalchemy import Column, String, Text
|
||||
|
||||
import edbob
|
||||
# from edbob import Object, get_uuid
|
||||
from edbob.db import Base
|
||||
|
||||
|
||||
__all__ = ['ActiveExtension', 'Setting']
|
||||
|
||||
|
||||
# class ClassWithUuid(Object):
|
||||
# """
|
||||
# Simple mixin class which defines a ``uuid`` column as primary key.
|
||||
# """
|
||||
|
||||
# Column('uuid', String(32), primary_key=True, default=get_uuid)
|
||||
|
||||
|
||||
def uuid_column(*args):
|
||||
"""
|
||||
Convenience function which returns a ``uuid`` column for use as a table's
|
||||
|
@ -81,77 +72,3 @@ class Setting(Base):
|
|||
|
||||
def __repr__(self):
|
||||
return "<Setting: %s>" % self.name
|
||||
|
||||
|
||||
# def get_metadata(*args, **kwargs):
|
||||
# """
|
||||
# Returns the core ``edbob`` schema definition.
|
||||
|
||||
# Note that when :func:`edbob.init()` is called, the ``sqlalchemy.MetaData``
|
||||
# instance which is returned from this function will henceforth be available
|
||||
# as ``edbob.metadata``. However, ``edbob.init()`` may extend
|
||||
# ``edbob.metadata`` as well, depending on which extensions are activated
|
||||
# within the primary database.
|
||||
|
||||
# This function then serves two purposes: First, it provides the core
|
||||
# metadata instance. Secondly, it allows edbob to always know what its core
|
||||
# schema looks like, as opposed to what's held in the current
|
||||
# ``edbob.metadata`` instance, which may have been extended locally. (The
|
||||
# latter use is necessary in order for edbob to properly manage its
|
||||
# extensions.)
|
||||
|
||||
# All arguments (positional and keyword) are passed directly to the
|
||||
# ``sqlalchemy.MetaData()`` constructor.
|
||||
# """
|
||||
|
||||
# metadata = MetaData(*args, **kwargs)
|
||||
|
||||
# active_extensions = Table(
|
||||
# 'active_extensions', metadata,
|
||||
# Column('name', String(50), primary_key=True),
|
||||
# )
|
||||
|
||||
# def get_person_display_name(context):
|
||||
# first_name = context.current_parameters['first_name']
|
||||
# last_name = context.current_parameters['last_name']
|
||||
# if not (first_name or last_name):
|
||||
# return None
|
||||
# return '%(first_name)s %(last_name)s' % locals()
|
||||
|
||||
# people = table_with_uuid(
|
||||
# 'people', metadata,
|
||||
# Column('first_name', String(50)),
|
||||
# Column('last_name', String(50)),
|
||||
# Column('display_name', String(100), default=get_person_display_name),
|
||||
# )
|
||||
|
||||
# permissions = Table(
|
||||
# 'permissions', metadata,
|
||||
# Column('role_uuid', String(32), ForeignKey('roles.uuid'), primary_key=True),
|
||||
# Column('permission', String(50), primary_key=True),
|
||||
# )
|
||||
|
||||
# roles = table_with_uuid(
|
||||
# 'roles', metadata,
|
||||
# Column('name', String(25), nullable=False, unique=True),
|
||||
# )
|
||||
|
||||
# settings = Table(
|
||||
# 'settings', metadata,
|
||||
# Column('name', String(255), primary_key=True),
|
||||
# Column('value', Text),
|
||||
# )
|
||||
|
||||
# users = table_with_uuid(
|
||||
# 'users', metadata,
|
||||
# Column('username', String(25), nullable=False, unique=True),
|
||||
# Column('person_uuid', String(32), ForeignKey('people.uuid')),
|
||||
# )
|
||||
|
||||
# users_roles = table_with_uuid(
|
||||
# 'users_roles', metadata,
|
||||
# Column('user_uuid', String(32), ForeignKey('users.uuid')),
|
||||
# Column('role_uuid', String(32), ForeignKey('roles.uuid')),
|
||||
# )
|
||||
|
||||
# return metadata
|
||||
|
|
|
@ -35,10 +35,29 @@ import edbob.db
|
|||
__all__ = ['Session']
|
||||
|
||||
Session = scoped_session(edbob.db.Session)
|
||||
Session.configure(extension=ZopeTransactionExtension())
|
||||
|
||||
|
||||
def includeme(config):
|
||||
"""
|
||||
Adds ``edbob``-specific features to the application. Currently this does
|
||||
two things:
|
||||
|
||||
It adds a ``ZopeTransactionExtension`` instance as an extension to the
|
||||
SQLAlchemy scoped ``Session`` class. This is necessary for most view code
|
||||
that ships with ``edbob``, so you will most likely need to specify
|
||||
``config.include('edbob.pyramid')`` somewhere in your app config (i.e. your
|
||||
``main()`` function).
|
||||
|
||||
The other thing added is the ``edbob`` static view for CSS files etc.
|
||||
"""
|
||||
|
||||
# Session is extended here instead of at module scope to prevent import
|
||||
# side-effects.
|
||||
Session.configure(extension=ZopeTransactionExtension())
|
||||
|
||||
# Forbidden view is configured here instead of within edbob.pyramid.views
|
||||
# since it's so "important."
|
||||
config.add_forbidden_view('edbob.pyramid.views.forbidden')
|
||||
|
||||
# Same goes with the edbob static route; we need that JS.
|
||||
config.include('edbob.pyramid.static')
|
||||
config.include('edbob.pyramid.subscribers')
|
||||
# config.include('edbob.pyramid.views')
|
||||
|
|
57
edbob/pyramid/auth.py
Normal file
57
edbob/pyramid/auth.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# edbob -- Pythonic Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
#
|
||||
# This file is part of edbob.
|
||||
#
|
||||
# edbob is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with edbob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.pyramid.auth`` -- Authentication & Authorization
|
||||
"""
|
||||
|
||||
from zope.interface import implementer
|
||||
|
||||
from pyramid.interfaces import IAuthorizationPolicy
|
||||
from pyramid.security import Everyone, Authenticated
|
||||
|
||||
import edbob
|
||||
from edbob.db.auth import has_permission
|
||||
from edbob.pyramid import Session
|
||||
|
||||
|
||||
# def groupfinder(userid, request):
|
||||
# q = Session.query(edbob.UserRole)
|
||||
# q = q.filter(edbob.UserRole.user_uuid == userid)
|
||||
# return [x.role_uuid for x in q]
|
||||
|
||||
|
||||
@implementer(IAuthorizationPolicy)
|
||||
class EdbobAuthorizationPolicy(object):
|
||||
|
||||
def permits(self, context, principals, permission):
|
||||
for userid in principals:
|
||||
if userid not in (Everyone, Authenticated):
|
||||
user = Session.query(edbob.User).get(userid)
|
||||
assert user
|
||||
return has_permission(user, permission)
|
||||
return False
|
||||
|
||||
def principals_allowed_by_permission(self, context, permission):
|
||||
raise NotImplementedError
|
|
@ -57,7 +57,6 @@ class InitCommand(commands.Subcommand):
|
|||
# activate_extension('shrubbery')
|
||||
|
||||
# Okay, on to bootstrapping...
|
||||
|
||||
session = Session()
|
||||
|
||||
# This creates an 'admin' user with 'admin' password.
|
||||
|
|
|
@ -385,6 +385,7 @@ div.field-couple div.field {
|
|||
}
|
||||
|
||||
div.field-couple div.field input[type=text],
|
||||
div.field-couple div.field input[type=password],
|
||||
div.field-couple div.field select {
|
||||
width: 320px;
|
||||
}
|
||||
|
@ -393,11 +394,12 @@ div.checkbox {
|
|||
margin: 15px 0px;
|
||||
}
|
||||
|
||||
table.fieldset tr {
|
||||
table.fieldset tbody tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
table.fieldset td {
|
||||
table.fieldset tbody td {
|
||||
height: 30px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
|
@ -406,6 +408,16 @@ table.fieldset td.label {
|
|||
width: 120px;
|
||||
}
|
||||
|
||||
table.fieldset tbody td ul {
|
||||
padding-left: 15px;
|
||||
}
|
||||
|
||||
table.fieldset tbody td ul li {
|
||||
line-height: 1em;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
|
||||
/******************************
|
||||
* Sub-Grids
|
||||
******************************/
|
||||
|
|
17
edbob/pyramid/static/css/perms.css
Normal file
17
edbob/pyramid/static/css/perms.css
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
/******************************
|
||||
* perms.css
|
||||
******************************/
|
||||
|
||||
div.field-couple.permissions div.field p.group {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
div.field-couple.permissions div.field label {
|
||||
float: none;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
div.field-couple.permissions div.field label input {
|
||||
margin-right: 10px;
|
||||
}
|
|
@ -69,9 +69,9 @@ def context_found(event):
|
|||
return has_perm
|
||||
|
||||
request = event.request
|
||||
request.user = None
|
||||
request.has_perm = has_perm_func(request)
|
||||
|
||||
request.user = None
|
||||
uuid = authenticated_userid(request)
|
||||
if uuid:
|
||||
request.user = Session.query(edbob.User).get(uuid)
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
${h.stylesheet_link(request.static_url('edbob.pyramid:static/css/login.css'))}
|
||||
</%def>
|
||||
|
||||
${h.image(logo_url, "${self.global_title()} logo", id='login-logo')}
|
||||
${h.image(logo_url, "${self.global_title()} logo", id='login-logo', **logo_kwargs)}
|
||||
|
||||
<div class="fieldset">
|
||||
${h.form('')}
|
||||
|
|
2
edbob/pyramid/templates/people/base.mako
Normal file
2
edbob/pyramid/templates/people/base.mako
Normal file
|
@ -0,0 +1,2 @@
|
|||
<%inherit file="/base.mako" />
|
||||
${parent.body()}
|
12
edbob/pyramid/templates/people/index.mako
Normal file
12
edbob/pyramid/templates/people/index.mako
Normal file
|
@ -0,0 +1,12 @@
|
|||
<%inherit file="/people/base.mako" />
|
||||
<%inherit file="/index.mako" />
|
||||
|
||||
<%def name="title()">People</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
% if request.has_perm('people.create'):
|
||||
<p>${h.link_to("Create a new Person", url('person.new'))}</p>
|
||||
% endif
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
29
edbob/pyramid/templates/people/person.mako
Normal file
29
edbob/pyramid/templates/people/person.mako
Normal file
|
@ -0,0 +1,29 @@
|
|||
<%inherit file="/people/base.mako" />
|
||||
<%inherit file="/crud.mako" />
|
||||
|
||||
<%def name="crud_name()">Person</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Back to People", url('people.list'))}</p>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
||||
|
||||
% if fieldset.edit:
|
||||
<h2>User Info</h2>
|
||||
% if user:
|
||||
${user.render()|n}
|
||||
<div class="buttons">
|
||||
<button type="button" onclick="location.href = '${url('user.edit', uuid=user.model.uuid)}';">Edit User</button>
|
||||
</div>
|
||||
% else:
|
||||
<p>This person does not have a user account.</p>
|
||||
${h.form(url('user.new'))}
|
||||
${h.hidden('User--person_uuid', value=fieldset.model.uuid)}
|
||||
${h.hidden('User--username')}
|
||||
<div class="buttons">
|
||||
${h.submit('submit', "Create User")}
|
||||
</div>
|
||||
${h.end_form()}
|
||||
% endif
|
||||
% endif
|
2
edbob/pyramid/templates/roles/base.mako
Normal file
2
edbob/pyramid/templates/roles/base.mako
Normal file
|
@ -0,0 +1,2 @@
|
|||
<%inherit file="/base.mako" />
|
||||
${parent.body()}
|
10
edbob/pyramid/templates/roles/index.mako
Normal file
10
edbob/pyramid/templates/roles/index.mako
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%inherit file="/roles/base.mako" />
|
||||
<%inherit file="/index.mako" />
|
||||
|
||||
<%def name="title()">Roles</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Create a new Role", url('role.new'))}</p>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
15
edbob/pyramid/templates/roles/role.mako
Normal file
15
edbob/pyramid/templates/roles/role.mako
Normal file
|
@ -0,0 +1,15 @@
|
|||
<%inherit file="/roles/base.mako" />
|
||||
<%inherit file="/crud.mako" />
|
||||
|
||||
<%def name="crud_name()">Role</%def>
|
||||
|
||||
<%def name="head_tags()">
|
||||
${parent.head_tags()}
|
||||
${h.stylesheet_link(request.static_url('edbob.pyramid:static/css/perms.css'))}
|
||||
</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Back to Roles", url('roles.list'))}</p>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
2
edbob/pyramid/templates/users/base.mako
Normal file
2
edbob/pyramid/templates/users/base.mako
Normal file
|
@ -0,0 +1,2 @@
|
|||
<%inherit file="/base.mako" />
|
||||
${parent.body()}
|
10
edbob/pyramid/templates/users/index.mako
Normal file
10
edbob/pyramid/templates/users/index.mako
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%inherit file="/users/base.mako" />
|
||||
<%inherit file="/index.mako" />
|
||||
|
||||
<%def name="title()">Users</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Create a new User", url('user.new'))}</p>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
10
edbob/pyramid/templates/users/user.mako
Normal file
10
edbob/pyramid/templates/users/user.mako
Normal file
|
@ -0,0 +1,10 @@
|
|||
<%inherit file="/users/base.mako" />
|
||||
<%inherit file="/crud.mako" />
|
||||
|
||||
<%def name="crud_name()">User</%def>
|
||||
|
||||
<%def name="menu()">
|
||||
<p>${h.link_to("Back to Users", url('users.list'))}</p>
|
||||
</%def>
|
||||
|
||||
${parent.body()}
|
|
@ -26,6 +26,32 @@
|
|||
``edbob.pyramid.views`` -- Views
|
||||
"""
|
||||
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
from pyramid.security import authenticated_userid
|
||||
|
||||
# def includeme(config):
|
||||
# config.include('edbob.pyramid.views.auth')
|
||||
from webhelpers.html import literal
|
||||
from webhelpers.html.tags import link_to
|
||||
|
||||
|
||||
def forbidden(request):
|
||||
"""
|
||||
The forbidden view. This is triggered whenever access rights are denied
|
||||
for an otherwise-appropriate view.
|
||||
"""
|
||||
|
||||
msg = literal("You do not have permission to do that.")
|
||||
if not authenticated_userid(request):
|
||||
msg += literal(" (Perhaps you should %s?)" %
|
||||
link_to("log in", request.route_url('login')))
|
||||
request.session.flash(msg)
|
||||
|
||||
url = request.referer
|
||||
if not url or url == request.current_route_url():
|
||||
url = request.route_url('home')
|
||||
return HTTPFound(location=url)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
config.include('edbob.pyramid.views.auth')
|
||||
config.include('edbob.pyramid.views.people')
|
||||
config.include('edbob.pyramid.views.users')
|
||||
|
|
|
@ -78,17 +78,29 @@ def login(context, request):
|
|||
|
||||
url = edbob.config.get('edbob.pyramid', 'login.logo_url',
|
||||
default=request.static_url('edbob.pyramid:static/img/logo.jpg'))
|
||||
kwargs = eval(edbob.config.get('edbob.pyramid', 'login.logo_kwargs',
|
||||
default="dict(width=500)"))
|
||||
|
||||
return {'form': FormRenderer(form), 'referer': referer, 'logo_url': url}
|
||||
return {'form': FormRenderer(form), 'referer': referer,
|
||||
'logo_url': url, 'logo_kwargs': kwargs}
|
||||
|
||||
|
||||
def logout(context, request):
|
||||
"""
|
||||
View responsible for logging out the current user.
|
||||
|
||||
This deletes/invalidates the current session and then redirects to the
|
||||
login page.
|
||||
"""
|
||||
|
||||
request.session.delete()
|
||||
request.session.invalidate()
|
||||
headers = forget(request)
|
||||
return HTTPFound(location=request.route_url('login'), headers=headers)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
config.add_route('login', '/login')
|
||||
config.add_view(login, route_name='login', renderer='/login.mako')
|
||||
|
||||
|
|
180
edbob/pyramid/views/people.py
Normal file
180
edbob/pyramid/views/people.py
Normal file
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# edbob -- Pythonic Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
#
|
||||
# This file is part of edbob.
|
||||
#
|
||||
# edbob is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with edbob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.pyramid.views.people`` -- Person Views
|
||||
"""
|
||||
|
||||
import transaction
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
|
||||
from formalchemy import Field
|
||||
|
||||
import edbob
|
||||
from edbob.pyramid import filters
|
||||
from edbob.pyramid import forms
|
||||
from edbob.pyramid import grids
|
||||
from edbob.pyramid import Session
|
||||
|
||||
|
||||
def filter_map():
|
||||
return filters.get_filter_map(
|
||||
edbob.Person,
|
||||
ilike=['first_name', 'last_name', 'display_name'])
|
||||
|
||||
def search_config(request, fmap):
|
||||
return filters.get_search_config(
|
||||
'people.list', request, fmap,
|
||||
include_filter_display_name=True,
|
||||
filter_type_display_name='lk')
|
||||
|
||||
def search_form(config):
|
||||
return filters.get_search_form(config)
|
||||
|
||||
def grid_config(request, search, fmap):
|
||||
return grids.get_grid_config(
|
||||
'people.list', request, search,
|
||||
filter_map=fmap, sort='display_name')
|
||||
|
||||
def sort_map():
|
||||
return grids.get_sort_map(
|
||||
edbob.Person,
|
||||
['first_name', 'last_name', 'display_name'])
|
||||
|
||||
def query(config):
|
||||
smap = sort_map()
|
||||
q = Session.query(edbob.Person)
|
||||
q = filters.filter_query(q, config)
|
||||
q = grids.sort_query(q, config, smap)
|
||||
return q
|
||||
|
||||
|
||||
def people(context, request):
|
||||
|
||||
fmap = filter_map()
|
||||
config = search_config(request, fmap)
|
||||
search = search_form(config)
|
||||
config = grid_config(request, search, fmap)
|
||||
people = grids.get_pager(query, config)
|
||||
|
||||
g = forms.AlchemyGrid(
|
||||
edbob.Person, people, config,
|
||||
gridurl=request.route_url('people.list'),
|
||||
objurl='person.edit')
|
||||
|
||||
g.configure(
|
||||
include=[
|
||||
g.first_name,
|
||||
g.last_name,
|
||||
g.display_name,
|
||||
],
|
||||
readonly=True)
|
||||
|
||||
grid = g.render(class_='clickable people')
|
||||
return grids.render_grid(request, grid, search)
|
||||
|
||||
|
||||
def person_fieldset(person, request):
|
||||
fs = forms.make_fieldset(person, url=request.route_url,
|
||||
url_action=request.current_route_url(),
|
||||
route_name='people.list')
|
||||
fs.configure(
|
||||
include=[
|
||||
fs.first_name,
|
||||
fs.last_name,
|
||||
fs.display_name,
|
||||
])
|
||||
return fs
|
||||
|
||||
|
||||
def new_person(context, request):
|
||||
|
||||
fs = person_fieldset(edbob.Person, request)
|
||||
if not fs.readonly and request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
fs.sync()
|
||||
Session.add(fs.model)
|
||||
Session.flush()
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
|
||||
return HTTPFound(location=request.route_url('people.list'))
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def edit_person(request):
|
||||
"""
|
||||
View for editing a :class:`edbob.Person` instance.
|
||||
"""
|
||||
|
||||
from edbob.pyramid.views.users import user_fieldset
|
||||
|
||||
uuid = request.matchdict['uuid']
|
||||
person = Session.query(edbob.Person).get(uuid) if uuid else None
|
||||
assert person
|
||||
|
||||
fs = person_fieldset(person, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
fs.sync()
|
||||
fs.model = Session.merge(fs.model)
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('people.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
user = fs.model.user
|
||||
if user:
|
||||
user = user_fieldset(user, request)
|
||||
user.readonly = True
|
||||
del user.person
|
||||
del user.password
|
||||
del user.confirm_password
|
||||
|
||||
return {'fieldset': fs, 'crud': True, 'user': user}
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
config.add_route('people.list', '/people')
|
||||
config.add_view(people, route_name='people.list', renderer='/people/index.mako',
|
||||
permission='people.list', http_cache=0)
|
||||
|
||||
config.add_route('person.new', '/people/new')
|
||||
config.add_view(new_person, route_name='person.new', renderer='/people/person.mako',
|
||||
permission='people.create', http_cache=0)
|
||||
|
||||
config.add_route('person.edit', '/people/{uuid}/edit')
|
||||
config.add_view(edit_person, route_name='person.edit', renderer='/people/person.mako',
|
||||
permission='people.edit', http_cache=0)
|
255
edbob/pyramid/views/roles.py
Normal file
255
edbob/pyramid/views/roles.py
Normal file
|
@ -0,0 +1,255 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# edbob -- Pythonic Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
#
|
||||
# This file is part of edbob.
|
||||
#
|
||||
# edbob is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with edbob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.pyramid.views.roles`` -- Role Views
|
||||
"""
|
||||
|
||||
import transaction
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
|
||||
from formalchemy import Field, FieldRenderer
|
||||
from webhelpers.html import literal
|
||||
from webhelpers.html.tags import checkbox, hidden
|
||||
|
||||
import edbob
|
||||
from edbob.db.auth import administrator_role, has_permission
|
||||
from edbob.pyramid import filters
|
||||
from edbob.pyramid import forms
|
||||
from edbob.pyramid import grids
|
||||
from edbob.pyramid import Session
|
||||
|
||||
|
||||
def filter_map():
|
||||
return filters.get_filter_map(
|
||||
edbob.Role,
|
||||
ilike=['name'])
|
||||
|
||||
def search_config(request, fmap):
|
||||
return filters.get_search_config(
|
||||
'roles.list', request, fmap,
|
||||
include_filter_name=True,
|
||||
filter_type_name='lk')
|
||||
|
||||
def search_form(config):
|
||||
return filters.get_search_form(config)
|
||||
|
||||
def grid_config(request, search, fmap):
|
||||
return grids.get_grid_config(
|
||||
'roles.list', request, search,
|
||||
filter_map=fmap, sort='name')
|
||||
|
||||
def sort_map():
|
||||
return grids.get_sort_map(edbob.Role, ['name'])
|
||||
|
||||
def query(config):
|
||||
smap = sort_map()
|
||||
q = Session.query(edbob.Role)
|
||||
q = filters.filter_query(q, config)
|
||||
q = grids.sort_query(q, config, smap)
|
||||
return q
|
||||
|
||||
|
||||
def roles(request):
|
||||
|
||||
fmap = filter_map()
|
||||
config = search_config(request, fmap)
|
||||
search = search_form(config)
|
||||
config = grid_config(request, search, fmap)
|
||||
roles = grids.get_pager(query, config)
|
||||
|
||||
g = forms.AlchemyGrid(
|
||||
edbob.Role, roles, config,
|
||||
gridurl=request.route_url('roles.list'),
|
||||
objurl='role.edit')
|
||||
|
||||
g.configure(
|
||||
include=[
|
||||
g.name,
|
||||
],
|
||||
readonly=True)
|
||||
|
||||
grid = g.render(class_='clickable roles')
|
||||
return grids.render_grid(request, grid, search)
|
||||
|
||||
|
||||
class PermissionsField(Field):
|
||||
|
||||
def sync(self):
|
||||
if not self.is_readonly():
|
||||
role = self.model
|
||||
role.permissions = self.renderer.deserialize()
|
||||
|
||||
|
||||
class PermissionsFieldRenderer(FieldRenderer):
|
||||
|
||||
available_permissions = [
|
||||
|
||||
("Batches", [
|
||||
('batches.list', "List Batches"),
|
||||
('batches.edit', "Edit Batch"),
|
||||
('batches.create', "Create Batch"),
|
||||
]),
|
||||
|
||||
("Roles", [
|
||||
('roles.list', "List Roles"),
|
||||
('roles.edit', "Edit Role"),
|
||||
('roles.create', "Create Role"),
|
||||
]),
|
||||
]
|
||||
|
||||
def deserialize(self):
|
||||
perms = []
|
||||
i = len(self.name) + 1
|
||||
for key in self.params:
|
||||
if key.startswith(self.name):
|
||||
perms.append(key[i:])
|
||||
return perms
|
||||
|
||||
def _render(self, readonly=False, **kwargs):
|
||||
# result = literal('')
|
||||
# for group_name, group_label, perm_list in self.field.model_value:
|
||||
# rendered_group_name = literal('<p class="permission-group">' + group_label + '</p>\n')
|
||||
# if readonly:
|
||||
# result += literal('<tr><td colspan="2">') + rendered_group_name + literal('</td></tr>')
|
||||
# else:
|
||||
# result += rendered_group_name
|
||||
# result += literal('<div>')
|
||||
# for perm_name, perm_label, checked in perm_list:
|
||||
# if readonly:
|
||||
# result += literal('<tr>'
|
||||
# + '<td class="permission">' + ('[X]' if checked else '[ ]') + '</td>'
|
||||
# + '<td class="permission-label">' + perm_label + '</td>'
|
||||
# + '</tr>\n')
|
||||
# else:
|
||||
# name = '.'.join((self.name, group_name, perm_name))
|
||||
# result += check_box(name, label=perm_label, checked=checked)
|
||||
# if not readonly:
|
||||
# result += literal('</div>')
|
||||
# if readonly:
|
||||
# return literal('<table class="permissions">') + result + literal('</table>')
|
||||
# return literal('<div class="permissions">') + result + literal('</div>')
|
||||
|
||||
role = self.field.model
|
||||
if role is administrator_role(Session()):
|
||||
res = literal('<p>This is the administrative role; '
|
||||
'it has full access to the entire system.</p>')
|
||||
if not readonly:
|
||||
res += hidden(self.name, value='') # ugly hack..or good idea?
|
||||
else:
|
||||
res = ''
|
||||
for group, perms in self.available_permissions:
|
||||
res += literal('<p class="group">%s</p>' % group)
|
||||
for perm, title in perms:
|
||||
if readonly:
|
||||
res += literal('<p>%s</p>' % title)
|
||||
else:
|
||||
checked = has_permission(role, perm)
|
||||
res += checkbox(self.name + '-' + perm,
|
||||
checked=checked, label=title)
|
||||
return res
|
||||
|
||||
def render(self, **kwargs):
|
||||
return self._render(**kwargs)
|
||||
|
||||
def render_readonly(self, **kwargs):
|
||||
return self._render(readonly=True, **kwargs)
|
||||
|
||||
|
||||
def role_fieldset(role, request):
|
||||
fs = forms.make_fieldset(role, url=request.route_url,
|
||||
url_action=request.current_route_url(),
|
||||
route_name='roles.list')
|
||||
|
||||
fs.append(PermissionsField('permissions',
|
||||
renderer=PermissionsFieldRenderer))
|
||||
|
||||
fs.configure(
|
||||
include=[
|
||||
fs.name,
|
||||
fs.permissions,
|
||||
])
|
||||
|
||||
if not fs.edit:
|
||||
del fs.permissions
|
||||
|
||||
return fs
|
||||
|
||||
|
||||
def new_role(request):
|
||||
|
||||
fs = role_fieldset(edbob.Role, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
fs.sync()
|
||||
fs.model = Session.merge(fs.model)
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('roles.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def edit_role(request):
|
||||
uuid = request.matchdict['uuid']
|
||||
role = Session.query(edbob.Role).get(uuid) if uuid else None
|
||||
assert role
|
||||
|
||||
fs = role_fieldset(role, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
Session.add(fs.model)
|
||||
fs.sync()
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('roles.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
config.add_route('roles.list', '/roles')
|
||||
config.add_view(roles, route_name='roles.list', renderer='/roles/index.mako',
|
||||
permission='roles.list', http_cache=0)
|
||||
|
||||
config.add_route('role.new', '/roles/new')
|
||||
config.add_view(new_role, route_name='role.new', renderer='/roles/role.mako',
|
||||
permission='roles.create', http_cache=0)
|
||||
|
||||
config.add_route('role.edit', '/roles/{uuid}/edit')
|
||||
config.add_view(edit_role, route_name='role.edit', renderer='/roles/role.mako',
|
||||
permission='roles.edit', http_cache=0)
|
289
edbob/pyramid/views/users.py
Normal file
289
edbob/pyramid/views/users.py
Normal file
|
@ -0,0 +1,289 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
################################################################################
|
||||
#
|
||||
# edbob -- Pythonic Software Framework
|
||||
# Copyright © 2010-2012 Lance Edgar
|
||||
#
|
||||
# This file is part of edbob.
|
||||
#
|
||||
# edbob is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# edbob is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
|
||||
# more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with edbob. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
|
||||
"""
|
||||
``edbob.pyramid.views.users`` -- User Views
|
||||
"""
|
||||
|
||||
import transaction
|
||||
from pyramid.httpexceptions import HTTPFound
|
||||
|
||||
import formalchemy
|
||||
from formalchemy.fields import SelectFieldRenderer
|
||||
from webhelpers.html import literal
|
||||
from webhelpers.html.tags import hidden, link_to, password
|
||||
|
||||
import edbob
|
||||
from edbob.db.auth import set_user_password
|
||||
from edbob.pyramid import filters
|
||||
from edbob.pyramid import forms
|
||||
from edbob.pyramid import grids
|
||||
from edbob.pyramid import Session
|
||||
|
||||
|
||||
def filter_map():
|
||||
return filters.get_filter_map(
|
||||
edbob.User,
|
||||
ilike=['username'],
|
||||
person=filters.filter_ilike(edbob.Person.display_name))
|
||||
|
||||
def search_config(request, fmap):
|
||||
return filters.get_search_config(
|
||||
'users.list', request, fmap,
|
||||
include_filter_username=True,
|
||||
filter_type_username='lk')
|
||||
|
||||
def search_form(config):
|
||||
return filters.get_search_form(config)
|
||||
|
||||
def grid_config(request, search, fmap):
|
||||
return grids.get_grid_config(
|
||||
'users.list', request, search,
|
||||
filter_map=fmap, sort='username')
|
||||
|
||||
def sort_map():
|
||||
return grids.get_sort_map(
|
||||
edbob.User, ['username'],
|
||||
person=grids.sorter(edbob.Person.display_name))
|
||||
|
||||
def query(config):
|
||||
jmap = {'person': lambda q: q.outerjoin(edbob.Person)}
|
||||
smap = sort_map()
|
||||
q = Session.query(edbob.User)
|
||||
q = filters.filter_query(q, config, jmap)
|
||||
q = grids.sort_query(q, config, smap, jmap)
|
||||
return q
|
||||
|
||||
|
||||
def users(context, request):
|
||||
|
||||
fmap = filter_map()
|
||||
config = search_config(request, fmap)
|
||||
search = search_form(config)
|
||||
config = grid_config(request, search, fmap)
|
||||
users = grids.get_pager(query, config)
|
||||
|
||||
g = forms.AlchemyGrid(
|
||||
edbob.User, users, config,
|
||||
gridurl=request.route_url('users.list'),
|
||||
objurl='user.edit')
|
||||
|
||||
g.configure(
|
||||
include=[
|
||||
g.username,
|
||||
g.person,
|
||||
],
|
||||
readonly=True)
|
||||
|
||||
grid = g.render(class_='clickable users')
|
||||
return grids.render_grid(request, grid, search)
|
||||
|
||||
|
||||
class _RolesFieldRenderer(SelectFieldRenderer):
|
||||
|
||||
def render_readonly(self, **kwargs):
|
||||
roles = Session.query(edbob.Role)
|
||||
res = literal('<ul>')
|
||||
for uuid in self.value:
|
||||
role = roles.get(uuid)
|
||||
res += literal('<li>%s</li>' % (
|
||||
link_to(role.name,
|
||||
self.request.route_url('role.edit', uuid=role.uuid))))
|
||||
res += literal('</ul>')
|
||||
return res
|
||||
|
||||
|
||||
def RolesFieldRenderer(request):
|
||||
return type('RolesFieldRenderer', (_RolesFieldRenderer,), {'request': request})
|
||||
|
||||
|
||||
class RolesField(formalchemy.Field):
|
||||
|
||||
def __init__(self, name, **kwargs):
|
||||
kwargs.setdefault('value', self.get_value)
|
||||
kwargs.setdefault('options', self.get_options())
|
||||
kwargs.setdefault('multiple', True)
|
||||
super(RolesField, self).__init__(name, **kwargs)
|
||||
|
||||
def get_value(self, user):
|
||||
return [x.uuid for x in user.roles]
|
||||
|
||||
def get_options(self):
|
||||
q = Session.query(edbob.Role.name, edbob.Role.uuid)
|
||||
q = q.order_by(edbob.Role.name)
|
||||
return q.all()
|
||||
|
||||
def sync(self):
|
||||
if not self.is_readonly():
|
||||
user = self.model
|
||||
roles = Session.query(edbob.Role)
|
||||
data = self.renderer.deserialize()
|
||||
user.roles = [roles.get(x) for x in data]
|
||||
|
||||
|
||||
class _ProtectedPersonRenderer(formalchemy.FieldRenderer):
|
||||
|
||||
def render_readonly(self, **kwargs):
|
||||
res = str(self.person)
|
||||
res += hidden('User--person_uuid',
|
||||
value=self.field.parent.person_uuid.value)
|
||||
return res
|
||||
|
||||
|
||||
def ProtectedPersonRenderer(uuid):
|
||||
person = Session.query(edbob.Person).get(uuid)
|
||||
assert person
|
||||
return type('ProtectedPersonRenderer', (_ProtectedPersonRenderer,),
|
||||
{'person': person})
|
||||
|
||||
|
||||
class _LinkedPersonRenderer(formalchemy.FieldRenderer):
|
||||
|
||||
def render_readonly(self, **kwargs):
|
||||
return link_to(str(self.raw_value),
|
||||
self.request.route_url('person.edit', uuid=self.value))
|
||||
|
||||
|
||||
def LinkedPersonRenderer(request):
|
||||
return type('LinkedPersonRenderer', (_LinkedPersonRenderer,), {'request': request})
|
||||
|
||||
|
||||
class PasswordFieldRenderer(formalchemy.PasswordFieldRenderer):
|
||||
|
||||
def render(self, **kwargs):
|
||||
return password(self.name, value='', maxlength=self.length, **kwargs)
|
||||
|
||||
|
||||
def passwords_match(value, field):
|
||||
if field.parent.confirm_password.value != value:
|
||||
raise formalchemy.ValidationError("Passwords do not match")
|
||||
return value
|
||||
|
||||
|
||||
class PasswordField(formalchemy.Field):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault('value', lambda x: x.password)
|
||||
kwargs.setdefault('renderer', PasswordFieldRenderer)
|
||||
kwargs.setdefault('validate', passwords_match)
|
||||
super(PasswordField, self).__init__(*args, **kwargs)
|
||||
|
||||
def sync(self):
|
||||
if not self.is_readonly():
|
||||
password = self.renderer.deserialize()
|
||||
if password:
|
||||
set_user_password(self.model, password)
|
||||
|
||||
|
||||
def user_fieldset(user, request):
|
||||
fs = forms.make_fieldset(user, url=request.route_url,
|
||||
url_action=request.current_route_url(),
|
||||
route_name='users.list')
|
||||
|
||||
fs.append(PasswordField('password'))
|
||||
fs.append(formalchemy.Field('confirm_password',
|
||||
renderer=PasswordFieldRenderer))
|
||||
|
||||
fs.append(RolesField(
|
||||
'roles', renderer=RolesFieldRenderer(request)))
|
||||
|
||||
fs.configure(
|
||||
include=[
|
||||
fs.person,
|
||||
fs.username,
|
||||
fs.password.label("Set Password"),
|
||||
fs.confirm_password,
|
||||
fs.roles,
|
||||
])
|
||||
|
||||
if isinstance(user, edbob.User) and user.person:
|
||||
fs.person.set(readonly=True,
|
||||
renderer=LinkedPersonRenderer(request))
|
||||
|
||||
return fs
|
||||
|
||||
|
||||
def new_user(request):
|
||||
"""
|
||||
View for creating a new :class:`edbob.User` instance.
|
||||
"""
|
||||
|
||||
fs = user_fieldset(edbob.User, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
Session.add(fs.model)
|
||||
fs.sync()
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('users.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
if fs.person_uuid.value:
|
||||
fs.person.set(readonly=True,
|
||||
renderer=ProtectedPersonRenderer(fs.person_uuid.value))
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def edit_user(request):
|
||||
uuid = request.matchdict['uuid']
|
||||
user = Session.query(edbob.User).get(uuid) if uuid else None
|
||||
assert user
|
||||
|
||||
fs = user_fieldset(user, request)
|
||||
if request.POST:
|
||||
fs.rebind(data=request.params)
|
||||
if fs.validate():
|
||||
|
||||
with transaction.manager:
|
||||
Session.add(fs.model)
|
||||
fs.sync()
|
||||
request.session.flash("%s \"%s\" has been %s." % (
|
||||
fs.crud_title, fs.get_display_text(),
|
||||
'updated' if fs.edit else 'created'))
|
||||
home = request.route_url('users.list')
|
||||
|
||||
return HTTPFound(location=home)
|
||||
|
||||
return {'fieldset': fs, 'crud': True}
|
||||
|
||||
|
||||
def includeme(config):
|
||||
|
||||
config.add_route('users.list', '/users')
|
||||
config.add_view(users, route_name='users.list', renderer='/users/index.mako',
|
||||
permission='users.list', http_cache=0)
|
||||
|
||||
config.add_route('user.new', '/users/new')
|
||||
config.add_view(new_user, route_name='user.new', renderer='/users/user.mako',
|
||||
permission='users.create', http_cache=0)
|
||||
|
||||
config.add_route('user.edit', '/users/{uuid}/edit')
|
||||
config.add_view(edit_user, route_name='user.edit', renderer='/users/user.mako',
|
||||
permission='users.edit', http_cache=0)
|
Loading…
Add table
Add a link
Reference in a new issue