More standalone operation stuff.
Stop using `edbob.db.engine`, stop using all edbob templates, etc.
This commit is contained in:
		
							parent
							
								
									2a50e704ef
								
							
						
					
					
						commit
						7d19700c3c
					
				
					 22 changed files with 438 additions and 54 deletions
				
			
		| 
						 | 
				
			
			@ -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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										34
									
								
								tailbone/static/css/login.css
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								tailbone/static/css/login.css
									
										
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										24
									
								
								tailbone/static/js/login.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								tailbone/static/js/login.js
									
										
									
									
									
										Normal 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();
 | 
			
		||||
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -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.
 | 
			
		||||
     */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								tailbone/templates/form.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								tailbone/templates/form.mako
									
										
									
									
									
										Normal 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>
 | 
			
		||||
							
								
								
									
										39
									
								
								tailbone/templates/forms/fieldset.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tailbone/templates/forms/fieldset.mako
									
										
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										12
									
								
								tailbone/templates/forms/fieldset_readonly.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								tailbone/templates/forms/fieldset_readonly.mako
									
										
									
									
									
										Normal 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>
 | 
			
		||||
							
								
								
									
										15
									
								
								tailbone/templates/forms/form.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								tailbone/templates/forms/form.mako
									
										
									
									
									
										Normal 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>
 | 
			
		||||
							
								
								
									
										3
									
								
								tailbone/templates/forms/form_readonly.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								tailbone/templates/forms/form_readonly.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
<div class="form">
 | 
			
		||||
  ${form.fieldset.render()|n}
 | 
			
		||||
</div>
 | 
			
		||||
							
								
								
									
										37
									
								
								tailbone/templates/grid.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tailbone/templates/grid.mako
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
<%inherit file="/base.mako" />
 | 
			
		||||
 | 
			
		||||
<%def name="context_menu_items()"></%def>
 | 
			
		||||
 | 
			
		||||
<%def name="form()">
 | 
			
		||||
  % if search:
 | 
			
		||||
      ${search.render()}
 | 
			
		||||
  % else:
 | 
			
		||||
       
 | 
			
		||||
  % 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 -->
 | 
			
		||||
							
								
								
									
										36
									
								
								tailbone/templates/grids/search.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								tailbone/templates/grids/search.mako
									
										
									
									
									
										Normal 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>
 | 
			
		||||
							
								
								
									
										37
									
								
								tailbone/templates/login.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								tailbone/templates/login.mako
									
										
									
									
									
										Normal 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>
 | 
			
		||||
							
								
								
									
										11
									
								
								tailbone/templates/people/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tailbone/templates/people/index.mako
									
										
									
									
									
										Normal 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()}
 | 
			
		||||
							
								
								
									
										18
									
								
								tailbone/templates/roles/crud.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tailbone/templates/roles/crud.mako
									
										
									
									
									
										Normal 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()}
 | 
			
		||||
							
								
								
									
										11
									
								
								tailbone/templates/roles/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tailbone/templates/roles/index.mako
									
										
									
									
									
										Normal 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()}
 | 
			
		||||
							
								
								
									
										11
									
								
								tailbone/templates/users/index.mako
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								tailbone/templates/users/index.mako
									
										
									
									
									
										Normal 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()}
 | 
			
		||||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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'))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue