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 os.path
import edbob import edbob
import edbob.db from sqlalchemy import engine_from_config
from .db import Session from .db import Session
from zope.sqlalchemy import ZopeTransactionExtension from zope.sqlalchemy import ZopeTransactionExtension
@ -55,12 +55,11 @@ def main(global_config, **settings):
# Initialize edbob, dammit. # Initialize edbob, dammit.
edbob.init('rattail', os.path.abspath(settings['edbob.config'])) 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 # Configure the primary database session.
# initialization to define the engine connection. engine = engine_from_config(settings)
assert edbob.db.engine Session.configure(bind=engine)
Session.configure(bind=edbob.db.engine)
Session.configure(extension=ZopeTransactionExtension()) Session.configure(extension=ZopeTransactionExtension())
# Configure user authentication / authorization. # Configure user authentication / authorization.

View file

@ -32,7 +32,7 @@ from pyramid.security import Everyone, Authenticated
from .db import Session from .db import Session
from rattail.db.model import User from rattail.db.model import User
from edbob.db.auth import has_permission from rattail.db.auth import has_permission
@implementer(IAuthorizationPolicy) @implementer(IAuthorizationPolicy)
@ -43,9 +43,9 @@ class TailboneAuthorizationPolicy(object):
if userid not in (Everyone, Authenticated): if userid not in (Everyone, Authenticated):
user = Session.query(User).get(userid) user = Session.query(User).get(userid)
assert user assert user
return has_permission(user, permission) return has_permission(Session(), user, permission)
if Everyone in principals: if Everyone in principals:
return has_permission(None, permission, session=Session()) return has_permission(Session(), None, permission)
return False return False
def principals_allowed_by_permission(self, context, permission): 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 autoExpand: true
}); });
/*
* Fix buttons.
*/
$('button').button();
$('input[type=submit]').button();
$('input[type=reset]').button();
/* /*
* When filter labels are clicked, (un)check the associated checkbox. * 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 pyramid.security import authenticated_userid
from .db import Session from .db import Session
from rattail.db.model import User from rattail.db.model import User
from edbob.db.auth import has_permission from rattail.db.auth import has_permission
def before_render(event): def before_render(event):
@ -70,12 +70,12 @@ def context_found(event):
request.user = Session.query(User).get(uuid) request.user = Session.query(User).get(uuid)
def has_perm(perm): def has_perm(perm):
return has_permission(request.user, perm, session=Session()) return has_permission(Session(), request.user, perm)
request.has_perm = has_perm request.has_perm = has_perm
def has_any_perm(perms): def has_any_perm(perms):
for perm in perms: for perm in perms:
if has_permission(request.user, perm, session=Session()): if has_permission(Session(), request.user, perm):
return True return True
return False return False
request.has_any_perm = has_any_perm 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 import edbob
from ..db import Session 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): class UserLogin(formencode.Schema):
@ -58,9 +58,9 @@ def login(request):
form = Form(request, schema=UserLogin) form = Form(request, schema=UserLogin)
if form.validate(): if form.validate():
user = authenticate_user(form.data['username'], user = authenticate_user(Session(),
form.data['password'], form.data['username'],
session=Session()) form.data['password'])
if user: if user:
request.session.flash("%s logged in at %s" % ( request.session.flash("%s logged in at %s" % (
user.display_name, user.display_name,

View file

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

View file

@ -26,43 +26,121 @@
Role Views Role Views
""" """
from . import SearchableAlchemyGridView, CrudView
from pyramid.httpexceptions import HTTPFound 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 import formalchemy
from webhelpers.html import tags from webhelpers.html import tags
from webhelpers.html.builder import HTML from webhelpers.html import HTML
from edbob.db import auth
from ..db import Session
from . import SearchableAlchemyGridView, CrudView
from rattail.db.model import Role
default_permissions = [ 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", [
('people.list', "List People"), ('people.list', "List People"),
('people.read', "View Person"), ('people.read', "View People"),
('people.create', "Create Person"), ('people.create', "Create People"),
('people.update', "Edit Person"), ('people.update', "Edit People"),
('people.delete', "Delete Person"), ('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", [
('roles.list', "List Roles"), ('roles.list', "List Roles"),
('roles.read', "View Role"), ('roles.read', "View Roles"),
('roles.create', "Create Role"), ('roles.create', "Create Roles"),
('roles.update', "Edit Role"), ('roles.update', "Edit Roles"),
('roles.delete', "Delete Role"), ('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", [
('users.list', "List Users"), ('users.list', "List Users"),
('users.read', "View User"), ('users.read', "View Users"),
('users.create', "Create User"), ('users.create', "Create Users"),
('users.update', "Edit User"), ('users.update', "Edit Users"),
('users.delete', "Delete User"), ('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): def _render(self, readonly=False, **kwargs):
role = self.field.model role = self.field.model
admin = auth.administrator_role(Session()) admin = administrator_role(Session())
if role is admin: if role is admin:
html = HTML.tag('p', c="This is the administrative role; " html = HTML.tag('p', c="This is the administrative role; "
"it has full access to the entire system.") "it has full access to the entire system.")
@ -140,8 +218,8 @@ def PermissionsFieldRenderer(permissions, *args, **kwargs):
for group, perms in self.permissions: for group, perms in self.permissions:
inner = HTML.tag('p', c=group) inner = HTML.tag('p', c=group)
for perm, title in perms: for perm, title in perms:
checked = auth.has_permission( checked = has_permission(
role, perm, include_guest=False, session=Session()) Session(), role, perm, include_guest=False)
if readonly: if readonly:
span = HTML.tag('span', c="[X]" if checked else "[ ]") span = HTML.tag('span', c="[X]" if checked else "[ ]")
inner += HTML.tag('p', class_='perm', c=span + ' ' + title) inner += HTML.tag('p', class_='perm', c=span + ' ' + title)
@ -179,8 +257,8 @@ class RoleCrud(CrudView):
return fs return fs
def pre_delete(self, model): def pre_delete(self, model):
admin = auth.administrator_role(Session()) admin = administrator_role(Session())
guest = auth.guest_role(Session()) guest = guest_role(Session())
if model in (admin, guest): if model in (admin, guest):
self.request.session.flash("You may not delete the %s role." % str(model), 'error') self.request.session.flash("You may not delete the %s role." % str(model), 'error')
return HTTPFound(location=self.request.get_referrer()) return HTTPFound(location=self.request.get_referrer())

View file

@ -35,7 +35,7 @@ from . import SearchableAlchemyGridView, CrudView
from ..forms import PersonFieldRenderer from ..forms import PersonFieldRenderer
from ..db import Session from ..db import Session
from rattail.db.model import User, Person, Role 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 tags
from webhelpers.html import HTML from webhelpers.html import HTML