More standalone operation stuff.

Stop using `edbob.db.engine`, stop using all edbob templates, etc.
This commit is contained in:
Lance Edgar 2013-09-01 20:25:34 -07:00
parent 2a50e704ef
commit 7d19700c3c
22 changed files with 438 additions and 54 deletions

View file

@ -31,7 +31,7 @@ from pyramid.config import Configurator
import os.path
import edbob
import edbob.db
from sqlalchemy import engine_from_config
from .db import Session
from zope.sqlalchemy import ZopeTransactionExtension
@ -55,12 +55,11 @@ def main(global_config, **settings):
# Initialize edbob, dammit.
edbob.init('rattail', os.path.abspath(settings['edbob.config']))
edbob.init_modules(['edbob.time', 'edbob.db', 'rattail.db'])
edbob.init_modules(['edbob.time'])
# Configure the primary database session. For now, this leverages edbob's
# initialization to define the engine connection.
assert edbob.db.engine
Session.configure(bind=edbob.db.engine)
# Configure the primary database session.
engine = engine_from_config(settings)
Session.configure(bind=engine)
Session.configure(extension=ZopeTransactionExtension())
# Configure user authentication / authorization.

View file

@ -32,7 +32,7 @@ from pyramid.security import Everyone, Authenticated
from .db import Session
from rattail.db.model import User
from edbob.db.auth import has_permission
from rattail.db.auth import has_permission
@implementer(IAuthorizationPolicy)
@ -43,9 +43,9 @@ class TailboneAuthorizationPolicy(object):
if userid not in (Everyone, Authenticated):
user = Session.query(User).get(userid)
assert user
return has_permission(user, permission)
return has_permission(Session(), user, permission)
if Everyone in principals:
return has_permission(None, permission, session=Session())
return has_permission(Session(), None, permission)
return False
def principals_allowed_by_permission(self, context, permission):

View file

@ -0,0 +1,34 @@
/******************************
* login.css
******************************/
#logo {
margin: auto;
}
div.form {
margin: auto;
float: none;
text-align: center;
}
div.field-wrapper {
margin: 10px auto;
width: 300px;
}
div.field-wrapper label {
margin: 0px;
padding-top: 3px;
text-align: right;
width: 100px;
}
div.field-wrapper input {
width: 150px;
}
div.buttons input {
margin: auto 5px;
}

View file

@ -0,0 +1,24 @@
$(function() {
$('form').submit(function() {
if (! $('#username').val()) {
with ($('#username').get(0)) {
select();
focus();
}
return false;
}
if (! $('#password').val()) {
with ($('#password').get(0)) {
select();
focus();
}
return false;
}
return true;
});
$('#username').focus();
});

View file

@ -105,6 +105,13 @@ $(function() {
autoExpand: true
});
/*
* Fix buttons.
*/
$('button').button();
$('input[type=submit]').button();
$('input[type=reset]').button();
/*
* When filter labels are clicked, (un)check the associated checkbox.
*/

View file

@ -33,7 +33,7 @@ from . import helpers
from pyramid.security import authenticated_userid
from .db import Session
from rattail.db.model import User
from edbob.db.auth import has_permission
from rattail.db.auth import has_permission
def before_render(event):
@ -70,12 +70,12 @@ def context_found(event):
request.user = Session.query(User).get(uuid)
def has_perm(perm):
return has_permission(request.user, perm, session=Session())
return has_permission(Session(), request.user, perm)
request.has_perm = has_perm
def has_any_perm(perms):
for perm in perms:
if has_permission(request.user, perm, session=Session()):
if has_permission(Session(), request.user, perm):
return True
return False
request.has_any_perm = has_any_perm

View file

@ -0,0 +1,13 @@
<%inherit file="/base.mako" />
<%def name="context_menu_items()"></%def>
<div class="form-wrapper">
<ul class="context-menu">
${self.context_menu_items()}
</ul>
${form.render()|n}
</div>

View file

@ -0,0 +1,39 @@
<% _focus_rendered = False %>
% for error in fieldset.errors.get(None, []):
<div class="fieldset-error">${error}</div>
% endfor
% for field in fieldset.render_fields.itervalues():
% if field.requires_label:
<div class="field-wrapper ${field.name}">
% for error in field.errors:
<div class="field-error">${error}</div>
% endfor
${field.label_tag()|n}
<div class="field">
${field.render()|n}
</div>
% if 'instructions' in field.metadata:
<span class="instructions">${field.metadata['instructions']}</span>
% endif
</div>
% if not _focus_rendered and (fieldset.focus == field or fieldset.focus is True):
% if not field.is_readonly() and getattr(field.renderer, 'needs_focus', True):
<script language="javascript" type="text/javascript">
$(function() {
% if hasattr(field.renderer, 'focus_name'):
$('#${field.renderer.focus_name}').focus();
% else:
$('#${field.renderer.name}').focus();
% endif
});
</script>
<% _focus_rendered = True %>
% endif
% endif
% endif
% endfor

View file

@ -0,0 +1,12 @@
<div class="fieldset">
% for field in fieldset.render_fields.itervalues():
% if field.requires_label:
<div class="field-wrapper ${field.name}">
${field.label_tag()|n}
<div class="field">
${field.render_readonly()}
</div>
</div>
% endif
% endfor
</div>

View file

@ -0,0 +1,15 @@
<div class="form">
${h.form(form.action_url, enctype='multipart/form-data')}
${form.fieldset.render()|n}
<div class="buttons">
${h.submit('create', form.create_label if form.creating else form.update_label)}
% if form.creating and form.allow_successive_creates:
${h.submit('create_and_continue', form.successive_create_label)}
% endif
<button type="button" onclick="location.href = '${form.cancel_url}';">Cancel</button>
</div>
${h.end_form()}
</div>

View file

@ -0,0 +1,3 @@
<div class="form">
${form.fieldset.render()|n}
</div>

View file

@ -0,0 +1,37 @@
<%inherit file="/base.mako" />
<%def name="context_menu_items()"></%def>
<%def name="form()">
% if search:
${search.render()}
% else:
&nbsp;
% endif
</%def>
<%def name="tools()"></%def>
<div class="grid-wrapper">
<table class="grid-header">
<tr>
<td rowspan="2" class="form">
${self.form()}
</td>
<td class="context-menu">
<ul>
${self.context_menu_items()}
</ul>
</td>
</tr>
<tr>
<td class="tools">
${self.tools()}
</td>
</tr>
</table><!-- grid-header -->
${grid}
</div><!-- grid-wrapper -->

View file

@ -0,0 +1,36 @@
<div class="filters" url="${search.request.current_route_url()}">
${search.begin()}
${search.hidden('filters', 'true')}
<% visible = [] %>
% for f in search.sorted_filters():
<div class="filter" id="filter-${f.name}"${' style="display: none;"' if not search.config.get('include_filter_'+f.name) else ''|n}>
${search.checkbox('include_filter_'+f.name)}
<label for="${f.name}">${f.label}</label>
${f.types_select()}
<div class="value">
${f.value_control()}
</div>
</div>
% if search.config.get('include_filter_'+f.name):
<% visible.append(f.name) %>
% endif
% endfor
<div class="buttons">
${search.add_filter(visible)}
${search.submit('submit', "Search", style='display: none;' if not visible else None)}
<button type="reset"${' style="display: none;"' if not visible else ''|n}>Reset</button>
</div>
${search.end()}
% if visible:
<script language="javascript" type="text/javascript">
filters_to_disable = [
% for field in visible:
'${field}',
% endfor
];
$(function() {
disable_filter_options();
});
</script>
% endif
</div>

View file

@ -0,0 +1,37 @@
<%inherit file="/base.mako" />
<%def name="title()">Login</%def>
<%def name="head_tags()">
${parent.head_tags()}
${h.javascript_link(request.static_url('tailbone:static/js/login.js'))}
${h.stylesheet_link(request.static_url('tailbone:static/css/login.css'))}
</%def>
${h.image(request.static_url('tailbone:static/img/home_logo.png'), "Rattail Logo", id='logo')}
<div class="form">
${h.form('')}
<input type="hidden" name="referrer" value="${referrer}" />
% if error:
<div class="error">${error}</div>
% endif
<div class="field-wrapper">
<label for="username">Username</label>
<input type="text" name="username" id="username" value="" />
</div>
<div class="field-wrapper">
<label for="password">Password</label>
<input type="password" name="password" id="password" value="" />
</div>
<div class="buttons">
${h.submit('submit', "Login")}
<input type="reset" value="Reset" />
</div>
${h.end_form()}
</div>

View file

@ -0,0 +1,11 @@
<%inherit file="/grid.mako" />
<%def name="title()">People</%def>
<%def name="context_menu_items()">
## % if request.has_perm('people.create'):
## <li>${h.link_to("Create a new Person", url('person.new'))}</li>
## % endif
</%def>
${parent.body()}

View file

@ -0,0 +1,18 @@
<%inherit file="edbob.pyramid:templates/crud.mako" />
<%def name="head_tags()">
${parent.head_tags()}
${h.stylesheet_link(request.static_url('edbob.pyramid:static/css/perms.css'))}
</%def>
<%def name="context_menu_items()">
<li>${h.link_to("Back to Roles", url('roles'))}</li>
% if form.readonly:
<li>${h.link_to("Edit this Role", url('role.update', uuid=form.fieldset.model.uuid))}</li>
% elif form.updating:
<li>${h.link_to("View this Role", url('role.read', uuid=form.fieldset.model.uuid))}</li>
% endif
<li>${h.link_to("Delete this Role", url('role.delete', uuid=form.fieldset.model.uuid), class_='delete')}</li>
</%def>
${parent.body()}

View file

@ -0,0 +1,11 @@
<%inherit file="/grid.mako" />
<%def name="title()">Roles</%def>
<%def name="context_menu_items()">
% if request.has_perm('roles.create'):
<li>${h.link_to("Create a new Role", url('role.create'))}</li>
% endif
</%def>
${parent.body()}

View file

@ -0,0 +1,11 @@
<%inherit file="/grid.mako" />
<%def name="title()">Users</%def>
<%def name="context_menu_items()">
% if request.has_perm('users.create'):
<li>${h.link_to("Create a new User", url('user.create'))}</li>
% endif
</%def>
${parent.body()}

View file

@ -35,7 +35,7 @@ from ..forms.simpleform import FormRenderer
import edbob
from ..db import Session
from edbob.db.auth import authenticate_user, set_user_password
from rattail.db.auth import authenticate_user, set_user_password
class UserLogin(formencode.Schema):
@ -58,9 +58,9 @@ def login(request):
form = Form(request, schema=UserLogin)
if form.validate():
user = authenticate_user(form.data['username'],
form.data['password'],
session=Session())
user = authenticate_user(Session(),
form.data['username'],
form.data['password'])
if user:
request.session.flash("%s logged in at %s" % (
user.display_name,

View file

@ -26,12 +26,11 @@
Batch Row Views
"""
from .. import SearchableAlchemyGridView, CrudView
from pyramid.httpexceptions import HTTPFound
from ...db import Session
from .. import SearchableAlchemyGridView, CrudView
import rattail
from rattail.db.model import Batch, LabelProfile
from ...forms import GPCFieldRenderer
@ -41,8 +40,8 @@ def field_with_renderer(field, column):
field = field.with_renderer(GPCFieldRenderer)
elif column.sil_name == 'F95': # Shelf Tag Type
q = Session.query(rattail.LabelProfile)
q = q.order_by(rattail.LabelProfile.ordinal)
q = Session.query(LabelProfile)
q = q.order_by(LabelProfile.ordinal)
field = field.dropdown(options=[(x.description, x.code) for x in q])
return field
@ -50,7 +49,7 @@ def field_with_renderer(field, column):
def BatchRowsGrid(request):
uuid = request.matchdict['uuid']
batch = Session.query(rattail.Batch).get(uuid) if uuid else None
batch = Session.query(Batch).get(uuid) if uuid else None
if not batch:
return HTTPFound(location=request.route_url('batches'))
@ -141,7 +140,7 @@ def batch_rows_delete(request):
def batch_row_crud(request, attr):
batch_uuid = request.matchdict['batch_uuid']
batch = Session.query(rattail.Batch).get(batch_uuid)
batch = Session.query(Batch).get(batch_uuid)
if not batch:
return HTTPFound(location=request.route_url('batches'))

View file

@ -26,43 +26,121 @@
Role Views
"""
from . import SearchableAlchemyGridView, CrudView
from pyramid.httpexceptions import HTTPFound
from ..db import Session
from rattail.db.model import Role
from rattail.db.auth import has_permission, administrator_role, guest_role
import formalchemy
from webhelpers.html import tags
from webhelpers.html.builder import HTML
from edbob.db import auth
from ..db import Session
from . import SearchableAlchemyGridView, CrudView
from rattail.db.model import Role
from webhelpers.html import HTML
default_permissions = [
("Batches", [
('batches.list', "List Batches"),
('batches.read', "View Batches"),
('batches.create', "Create Batches"),
('batches.update', "Edit Batches"),
('batches.delete', "Delete Batches"),
('batches.execute', "Execute Batches"),
('batch_rows.read', "View Batch Rows"),
('batch_rows.update', "Edit Batch Rows"),
('batch_rows.delete', "Delete Batch Rows"),
]),
("Brands", [
('brands.list', "List Brands"),
('brands.read', "View Brands"),
('brands.create', "Create Brands"),
('brands.update', "Edit Brands"),
('brands.delete', "Delete Brands"),
('brands.force_sync', "Forcibly Sync Brands"),
]),
("Customers", [
('customers.list', "List Customers"),
('customers.read', "View Customers"),
('customers.force_sync', "Forcibly Sync Customers"),
('customer_groups.list', "List Customer Groups"),
('customer_groups.read', "View Customer Groups"),
('customer_groups.force_sync', "Forcibly Sync Customer Groups"),
]),
("Departments", [
('departments.list', "List Departments"),
('departments.read', "View Departments"),
('departments.create', "Create Departments"),
('departments.update', "Edit Departments"),
('departments.delete', "Delete Departments"),
('departments.force_sync', "Forcibly Sync Departments"),
]),
("Employees", [
('employees.list', "List Employees"),
('employees.force_sync', "Forcibly Sync Employees"),
]),
("Label Profiles", [
('label_profiles.list', "List Label Profiles"),
('label_profiles.view', "View Label Profiles"),
('label_profiles.create', "Create Label Profiles"),
('label_profiles.update', "Edit Label Profiles"),
('label_profiles.delete', "Delete Label Profiles"),
]),
("People", [
('people.list', "List People"),
('people.read', "View Person"),
('people.create', "Create Person"),
('people.update', "Edit Person"),
('people.delete', "Delete Person"),
('people.read', "View People"),
('people.create', "Create People"),
('people.update', "Edit People"),
('people.delete', "Delete People"),
('people.force_sync', "Forcibly Sync People"),
]),
("Products", [
('products.list', "List Products"),
('products.read', "View Products"),
('products.create', "Create Products"),
('products.update', "Edit Products"),
('products.delete', "Delete Products"),
('products.print_labels', "Print Product Labels"),
('products.force_sync', "Forcibly Sync Products"),
]),
("Roles", [
('roles.list', "List Roles"),
('roles.read', "View Role"),
('roles.create', "Create Role"),
('roles.update', "Edit Role"),
('roles.delete', "Delete Role"),
('roles.read', "View Roles"),
('roles.create', "Create Roles"),
('roles.update', "Edit Roles"),
('roles.delete', "Delete Roles"),
]),
("Stores", [
('stores.list', "List Stores"),
('stores.read', "View Stores"),
('stores.create', "Create Stores"),
('stores.update', "Edit Stores"),
('stores.delete', "Delete Stores"),
('stores.force_sync', "Forcibly Sync Stores"),
]),
("Subdepartments", [
('subdepartments.list', "List Subdepartments"),
('subdepartments.read', "View Subdepartments"),
('subdepartments.create', "Create Subdepartments"),
('subdepartments.update', "Edit Subdepartments"),
('subdepartments.delete', "Delete Subdepartments"),
('subdepartments.force_sync', "Forcibly Sync Subdepartments"),
]),
("Users", [
('users.list', "List Users"),
('users.read', "View User"),
('users.create', "Create User"),
('users.update', "Edit User"),
('users.delete', "Delete User"),
('users.read', "View Users"),
('users.create', "Create Users"),
('users.update', "Edit Users"),
('users.delete', "Delete Users"),
('users.force_sync', "Forcibly Sync Users"),
]),
("Vendors", [
('vendors.list', "List Vendors"),
('vendors.read', "View Vendors"),
('vendors.create', "Create Vendors"),
('vendors.update', "Edit Vendors"),
('vendors.delete', "Delete Vendors"),
('vendors.import_catalog', "Import Vendor Catalogs"),
('vendors.force_sync', "Forcibly Sync Vendors"),
]),
]
@ -129,7 +207,7 @@ def PermissionsFieldRenderer(permissions, *args, **kwargs):
def _render(self, readonly=False, **kwargs):
role = self.field.model
admin = auth.administrator_role(Session())
admin = administrator_role(Session())
if role is admin:
html = HTML.tag('p', c="This is the administrative role; "
"it has full access to the entire system.")
@ -140,8 +218,8 @@ def PermissionsFieldRenderer(permissions, *args, **kwargs):
for group, perms in self.permissions:
inner = HTML.tag('p', c=group)
for perm, title in perms:
checked = auth.has_permission(
role, perm, include_guest=False, session=Session())
checked = has_permission(
Session(), role, perm, include_guest=False)
if readonly:
span = HTML.tag('span', c="[X]" if checked else "[ ]")
inner += HTML.tag('p', class_='perm', c=span + ' ' + title)
@ -179,8 +257,8 @@ class RoleCrud(CrudView):
return fs
def pre_delete(self, model):
admin = auth.administrator_role(Session())
guest = auth.guest_role(Session())
admin = administrator_role(Session())
guest = guest_role(Session())
if model in (admin, guest):
self.request.session.flash("You may not delete the %s role." % str(model), 'error')
return HTTPFound(location=self.request.get_referrer())

View file

@ -35,7 +35,7 @@ from . import SearchableAlchemyGridView, CrudView
from ..forms import PersonFieldRenderer
from ..db import Session
from rattail.db.model import User, Person, Role
from edbob.db.auth import guest_role
from rattail.db.auth import guest_role
from webhelpers.html import tags
from webhelpers.html import HTML