-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi,
i'm currently trying to use the new zk security features from http://docs.zkoss.org/wiki/Spring#Spring_Security.
I created an app and set it up like the given example.
Also when i access the page secure/page.zul directly, i get redirected to the login page.
but if i load a page via Executions.createComponents("secure/page.zul", x, y); the page is displayed without any login required.
I placed a button on the secured page, and if i press the button i get the login...
did i miss something? is it intended or is it a bug?
i think this is the relevant part of my security-context.xml:
<zksp:zk-event login-template-close-delay="5"> <zksp:intercept-event event="onClick" path="//**/btn_*" access="ROLE_TELLER"/> <zksp:intercept-event path="/secure/**" access="ROLE_TELLER"/> <zksp:intercept-event path="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/> </zksp:zk-event>
cheers,
chris
Are your called pages are stand alone pages ?
Or do you create a page in a area of a borderlayout? (So it's all time the same <outer> page.)
Stephan
hi,
i have an outer page that loads and adds additional sub-pages via Executions.createComponents(). Those sub-pages can be included as Tab into the outer page or shown as addinitonal (modal popup) window.
But the browser is never redirected directly to the 'inner' page...
cheers,
chris
yes, that's ok (a browser doesn't directly render to an 'inner' page)!
look at my first headache with this.
I work with this logic. Only one page is addressed the index.zul page.
All new pages are created in the center area of the borderlayout.
So how should spring work with a page based security means he intercept the calling of
the new address ??
In this case i have secure the components like page/windows/tabs by code.
Have a look here on a working sample.
admin/admin (full rights)
user1/user1 (less rights)
user2/user2 (less rights)
The other side is to render all times with a new page the whole stuff again like menu, header, footer. Like jsf/jsp and templates. Than you can configure a page based (http address) security.
regards
Stephan
Hi Stephan,
First, nice application.
One question to your securityconcept.
The admin (in your appliaction) could allow any button for any role.
Is there any help from Spring Security? Or is this a self-coded securiylayer?
/Robert
Hi Robert,
thx.
| The admin (in your appliaction) could allow any button for any role. |
Theoretically yes, but normally not (It's only in the sample)!!!!
3 parts are should only modified by the developer. see explanation below.
1.
Like previous writing. I have not seen a chance to do the securing like in
my szenario (only one page: index.zul) over a page based configuration file.
2.
- I want to permit that a admin can made changes without modifying a
configuration file and so must restart the tomcat.
- I want to permit that the admin can extend/modify the rights-management.
So i have decided to store the security in tables.
So in my case the application admin can add/extend/modify the
- user-roles
- roles
- role-groups.
---------------------
Single-Rights need a look in the code what components are in there.
Following the Group-Rights must knows which components are work together for a
logic one. So these parts are fixed entries from the developer.
I have all times a group for a closed logic like view, create, edit, delete
3.
- So my spring-using implements the login/logout for a secured/not-secured index.zul
wich redirect to the login mask.
- By logging in filling the GrantedAuthorities with the users rights.
- Calling a checkSecurity() methode in
a. creating the menu
b. on every onCreate$myWindow event.
regards
Stephan
PS: Robert reich doch mal deine email adresse durch an: sge(at)forsthaus(dot)de
hi there,
@terrytornado: Really a very nice application. it seems you had quite the same idea's i had ;)
To resolve this issue: it seems we have to find a way to pipe the "internal" requests done via Executions.create.. through the spring security system.
i'm not sure if it worked with the "old" acegi security system. i can remember playing with those features in former times and i think it worked in the past...
but i have a lack of time to dig out my old tests...
Bye,
chris
Hi Chris,
the 'old aecegi' system works equal. Mainly the package names are changed for
better 'integrating' in the spring framework.
Formerly the sample app runs on aecegi. We have only update to 2.0.4 for beeing up to date.
I don't know what's the best way. But it works for my needs and i haven't a ground to change the security framework, so i have security code in my project and not only in the configuration files.
@bdrhoa
it's grows to big:
- meanwhile there are changes on the tomcat server.xml, for working with a jndi datasource
- a postgresql must be installed
- a tokenizer project is integrated for simulating one-time passwords.
- normally it changed all few days. Next changing is migrating all listboxes with paging/sorting.
See my smalltalk published next week.
So it's better to ask for special parts of it. No problem to post code.
regards
Stephan
The main problem I have is that I want to display components, especially tabs, based on the user. It looks looks like you've solved that problem. I see there are different menus, based on which user is logged in. I assume the logic to handle tabs would be similar. BTW - that would be a nice addition to your demo. Turn off the Customer tab for user2, for example.
I'll look forward to your smalltalk.
Thanks!
@bdrhoa,
:-) Done. New user on sampleApp: bdrhoa/bdrhoa
only access to CustomerList/ CustomerDialog --> Tab Address
doing by a new role --> group --> group/rights
all with _bdrhoa in the names.
This is done only by adding bellow records in the rights-management. Nothing have changed in the application code.
(Until next deployment!! included the testdata script. Testdata scripting is hard work without autoinc keys! )
The Smalltalk in work is not about security. It's the second Part for Marcos de Sousas smalltalk about paging in hugh tables.
It extends it about sorting under help with a filter object.
Ok.
----
Here are the code pieces that calls the Customer Modal Dialog. You can see the little logic that do the
visible/unVisible of the components depending on the logged-in user.
To remember: this is all times the same construction by extending from the BaseController that do all
the autowiring stuff. Look at the code samples here
CustomerDialog.zul
<?xml version="1.0" encoding="UTF-8"?> <?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?> <?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?> <zk xmlns="http://www.zkoss.org/2005/zul" xmlns:h="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.zkoss.org/2005/zul http://www.zkoss.org/2005/zul/zul.xsd"> <window id="window_customerDialog" title="${c:l('window_customerDialog.title')}" border="none" use="org.myfirm.webui.customer.CustomerDialogCtrl" closable="true" width="800px" height="550px" sizable="true"> <borderlayout id="borderlayoutCustomer"> <north border="none" margins="0,0,0,0"> <div id="divNorthCustomer"> <toolbar> <button id="btnHelp" image="/images/icons/light_16x16.gif" tooltiptext="${c:l('btnHelp.tooltiptext')}" /> </toolbar> </div> </north> <center border="none" margins="0,0,0,0"> <div id="divCenterCustomer"> <tabbox id="tabBoxCustomer" width="100%"> <tabs> <tab id="tabCustomerDialogAddress" label="${c:l('tabCustomerDialogAddress.label')}" /> <tab id="tabCustomerDialogAddition" label="${c:l('tabCustomerDialogAddition.label')}" /> <tab id="tabCustomerDialogOrders" label="${c:l('tabCustomerDialogOrders.label')}" /> <tab id="tabCustomerDialogMemos" label="${c:l('tabCustomerDialogMemos.label')}" /> </tabs> <tabpanels> <!-- Tab Address --> <tabpanel id="tabPanelCustomerAddress" height="100%" style="border: 0px"> <columnlayout> <columnchildren width="50%" style="padding: 5px"> <panel id="panel_CustomerDialog_Address" title="${c:l('panel_CustomerDialog_Address.title')}" style="margin-bottom:10px" border="normal" collapsible="true"> <panelchildren> <grid fixedLayout="true" style="border:0px"> <columns> <column width="150px" /> <column width="100%" /> </columns> <rows> <row> <label id="label_CustomerDialog_kunNr" value="${c:l('label_CustomerDialog_kunNr.value')}" /> <textbox id="kunNr" width="150px" /> </row> <row> <separator bar="true"> </separator> <separator bar="true"> </separator> </row> <row> <label id="label_CustomerDialog_kunMatchcode" value="${c:l('label_CustomerDialog_kunMatchcode.value')}" /> <textbox id="kunMatchcode" width="150px" /> </row> <row> <separator bar="true"> </separator> <separator bar="true"> </separator> </row> <row> <label id="label_CustomerDialog_kunName1" value="${c:l('label_CustomerDialog_kunName1.value')}" /> <textbox id="kunName1" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunName2" value="${c:l('label_CustomerDialog_kunName2.value')}" /> <textbox id="kunName2" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunOrt" value="${c:l('label_CustomerDialog_kunOrt.value')}" /> <textbox id="kunOrt" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunBranche" value="${c:l('label_CustomerDialog_kunBranche.value')}" /> <listbox id="kunBranche" width="100%" mold="select" rows="1" /> </row> </rows> </grid> </panelchildren> </panel> <panel id="panel_CustomerDialog_Addition" title="${c:l('panel_CustomerDialog_Addition.title')}" style="margin-bottom:10px" border="normal"> <panelchildren> <grid fixedLayout="true" style="border:0px"> <columns> <column width="150px" /> <column width="100%" /> </columns> <rows> <row> <label id="label_CustomerDialog_kunMahnsperre" value="${c:l('label_CustomerDialog_kunMahnsperre.value')}" /> <checkbox id="kunMahnsperre" /> </row> </rows> </grid> </panelchildren> </panel> <panel id="panel_CustomerDialog_Phone" title="${c:l('panel_CustomerDialog_Phone.title')}" border="normal"> <panelchildren> <grid fixedLayout="true" style="border:0px"> <columns> <column width="150px" /> <column width="100%" /> </columns> <rows> <row> <label id="label_CustomerDialog_kunPhone1" value="${c:l('label_CustomerDialog_kunPhone1.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunPhone2" value="${c:l('label_CustomerDialog_kunPhone2.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunMobile" value="${c:l('label_CustomerDialog_kunMobile.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunFax1" value="${c:l('label_CustomerDialog_kunFax1.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_kunFax2" value="${c:l('label_CustomerDialog_kunFax2.value')}" /> <textbox value="not used in example" width="99%" /> </row> </rows> </grid> </panelchildren> </panel> </columnchildren> <columnchildren width="50%" style="padding: 5px"> <panel id="panel_CustomerDialog_PayConditions" title="${c:l('panel_CustomerDialog_PayConditions.title')}" style="margin-bottom:10px" border="normal" collapsible="true"> <panelchildren> <grid fixedLayout="true" style="border:0px"> <columns> <column width="150px" /> <column width="100%" /> </columns> <rows> <row> <label id="label_CustomerDialog_kunPayCondition" value="${c:l('label_CustomerDialog_kunPayCondition.value')}" /> <listbox mold="select" rows="1" width="100%" /> </row> <row> <label id="label_CustomerDialog_kunBonitaet" value="${c:l('label_CustomerDialog_kunBonitaet.value')}" /> <intbox id="intbox_CustomerDialog_kunBonitaet" width="40px" /> </row> <row> <label id="label_CustomerDialog_AmountLastYear" value="${c:l('label_CustomerDialog_AmountLastYear.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_AmountCurrentYear" value="${c:l('label_CustomerDialog_AmountCurrentYear.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_AmountCurrentMonth" value="${c:l('label_CustomerDialog_AmountCurrentMonth.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_AmountLastInvoice" value="${c:l('label_CustomerDialog_AmountLastInvoice.value')}" /> <textbox value="not used in example" width="99%" /> </row> </rows> </grid> </panelchildren> </panel> <panel id="panel_CustomerDialog_Addition2" title="${c:l('panel_CustomerDialog_Addition2.title')}" border="normal"> <panelchildren> <grid fixedLayout="true" style="border:0px"> <columns> <column width="150px" /> <column width="100%" /> </columns> <rows> <row> <label id="label_CustomerDialog_Addition1" value="${c:l('label_CustomerDialog_Addition1.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_Addition2" value="${c:l('label_CustomerDialog_Addition2.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_Addition3" value="${c:l('label_CustomerDialog_Addition3.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_Addition4" value="${c:l('label_CustomerDialog_Addition4.value')}" /> <textbox value="not used in example" width="99%" /> </row> <row> <label id="label_CustomerDialog_Addition5" value="${c:l('label_CustomerDialog_Addition5.value')}" /> <textbox value="not used in example" width="99%" /> </row> </rows> </grid> </panelchildren> </panel> </columnchildren> </columnlayout> </tabpanel> <tabpanel id="tabPanelCustomerAddition" height="100%" style="border: 0px"> Text im Tabpanel 2 </tabpanel> <tabpanel id="tabPanelCustomerOrders" height="100%" style="border: 0px" /> <tabpanel id="tabPanelCustomerMemos" height="100%" style="border: 0px"> Text im Tabpanel 4 Akquisation </tabpanel> </tabpanels> </tabbox> </div> </center> <east border="none"></east> <west border="none"></west> <south border="none" margins="1,0,0,0" size="26px"> <div id="divSouth" align="right"> <hbox spacing="3px" style="padding:3px" align="end"> <button id="btnNew" height="20" label="${c:l('btnNew.label')}" tooltiptext="${c:l('btnNew.tooltiptext')}" /> <button id="btnEdit" height="20" label="${c:l('btnEdit.label')}" tooltiptext="${c:l('btnEdit.tooltiptext')}" /> <button id="btnDelete" height="20" label="${c:l('btnDelete.label')}" tooltiptext="${c:l('btnDelete.tooltiptext')}" /> <button id="btnSave" height="20" label="${c:l('btnSave.label')}" tooltiptext="${c:l('btnSave.tooltiptext')}" /> <button id="btnClose" height="20" label="${c:l('btnClose.label')}" tooltiptext="${c:l('btnClose.tooltiptext')}" /> </hbox> </div> </south> </borderlayout> </window> </zk>
CustomerDialogCtrl.java
package org.myfirm.webui.customer; import java.util.HashMap; import org.apache.log4j.Logger; import org.myfirm.UserWorkspace; import org.myfirm.webui.customer.model.CustomerBrancheListModelItemRenderer; import org.myfirm.webui.util.BaseCtrl; import org.myfirm.webui.util.ButtonStatusCtrl; import org.zkoss.util.resource.Labels; import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Path; import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zkplus.spring.SpringUtil; import org.zkoss.zul.Button; import org.zkoss.zul.Checkbox; import org.zkoss.zul.ListModelList; import org.zkoss.zul.Listbox; import org.zkoss.zul.Listitem; import org.zkoss.zul.Messagebox; import org.zkoss.zul.Panel; import org.zkoss.zul.Panelchildren; import org.zkoss.zul.Tab; import org.zkoss.zul.Tabpanel; import org.zkoss.zul.Textbox; import org.zkoss.zul.Window; import de.daibutsu.backend.model.Branche; import de.daibutsu.backend.model.Kunde; import de.daibutsu.backend.service.BrancheService; import de.daibutsu.backend.service.KundeService; /** * This is the controller class for the customer dialog described in the <br> * customerDialog.zul file. <br> * <br> * 1. In this dialog we can do the mainly database oriented methods like <br> * new, edit, save, delete a customer. Please attention, we have a relation to <br> * the table 'filiale'. <br> * <br> * 2. Before closing this dialog we check if there are unsaved changes. <br> * <br> * 3. We show the components corresponding to the logged-in user rights. <br> * 4. We have a little validation implemented. <br> * <br> * 5. By selecting the order tab we load a new zul-file in it for showing <br> * the orders and the orderpositions. They have their own controllers. <br> * <br> * * @author sge */ public class CustomerDialogCtrl extends BaseCtrl { private static Logger logger = Logger.getLogger(CustomerDialogCtrl.class); private static final long serialVersionUID = -546886879998950467L; /* * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ * All the components that are defined here and have a corresponding * component with the same 'id' in the zul-file are getting autowired by our * 'extends BaseCtrl' class wich extends Window and implements AfterCompose. * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ protected Window window_customerDialog; // autowired // tab Address protected Tab tabCustomerDialogAddress; // autowired protected Tabpanel tabPanelCustomerAddress; // autowired protected Textbox kunNr; // autowired protected Textbox kunMatchcode; // autowired protected Textbox kunName1; // autowired protected Textbox kunName2; // autowired protected Textbox kunOrt; // autowired protected Listbox kunBranche; // autowired protected Checkbox kunMahnsperre; // autowired // tab Additionally protected Tab tabCustomerDialogAddition; // autowired protected Tabpanel tabPanelCustomerAddition; // autowired // tab Orders protected Tab tabCustomerDialogOrders; // autowired protected Tabpanel tabPanelCustomerOrders; // autowired // tab Memos protected Tab tabCustomerDialogMemos; // autowired protected Tabpanel tabPanelCustomerMemos; // autowired // not auto wired vars private Listbox lbCustomer; // overhanded per param private Kunde kunde; // overhanded per param private CustomerListCtrl customerCtrl; // overhanded per param // old value vars for edit mode. that we can check if something // on the values are edited since the last init. private String oldVar_kunNr; private String oldVar_kunMatchcode; private String oldVar_kunName1; private String oldVar_kunName2; private String oldVar_kunOrt; private Listitem oldVar_kunBranche; private boolean oldVar_kunMahnsperre; private boolean validationOn; public void setValidationOn(boolean validationOn) { this.validationOn = validationOn; } public boolean isValidationOn() { return validationOn; } // Button Controller private ButtonStatusCtrl btnCtrl; protected Button btnNew; // autowire protected Button btnEdit; // autowire protected Button btnDelete; // autowire protected Button btnSave; // autowire protected Button btnClose; // autowire protected Button btnHelp; // autowire // ServiceDAOs / Domain Classes private BrancheService brancheService; private KundeService kundeService; public KundeService getKundeService() { if (kundeService == null) { kundeService = (KundeService) SpringUtil.getBean("kundeService"); setKundeService(kundeService); } return kundeService; } public void setKundeService(KundeService kundeService) { this.kundeService = kundeService; } public BrancheService getBrancheService() { if (brancheService == null) { brancheService = (BrancheService) SpringUtil.getBean("brancheService"); setBrancheService(brancheService); } return brancheService; } public void setBrancheService(BrancheService brancheService) { this.brancheService = brancheService; } public Kunde getKunde() { return kunde; } public void setKunde(Kunde kunde) { this.kunde = kunde; } /** * constructor */ public CustomerDialogCtrl() { super(); } /** * Before binding the data and calling the dialog window we check, if the * zul-file is called with a parameter for a selected customer object in a Map. * * @param event * @throws Exception */ public void onCreate$window_customerDialog(Event event) throws Exception { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } /* autowire the vars */ doOnCreateCommon(window_customerDialog, event); /* set components visible dependent of the users rights */ doCheckRights(); // create the Button Controller. Disable not used buttons during working btnCtrl = new ButtonStatusCtrl("button_CustomerDialog_", btnNew, btnEdit, btnDelete, btnSave, btnClose); // READ OVERHANDED params ! if (args.containsKey("kunde")) { kunde = (Kunde) args.get("kunde"); setKunde(kunde); } else { setKunde(null); } // READ OVERHANDED params ! // we get the listBox Object for the customers list. So we have access // to it and can synchronize the shown data when we do insert, edit or // delete customers here. if (args.containsKey("lbCustomer")) { lbCustomer = (Listbox) args.get("lbCustomer"); } else { lbCustomer = null; } // READ OVERHANDED params ! // we get the customerListWindow controller if (args.containsKey("customerCtrl")) { customerCtrl = (CustomerListCtrl) args.get("customerCtrl"); } else { customerCtrl = null; } // +++++++++ DropDown ListBox +++++++++++++++++++ // // set listModel and itemRenderer for the Branch dropdown listbox kunBranche.setModel(new ListModelList(getBrancheService().getAlleBranche())); kunBranche.setItemRenderer(new CustomerBrancheListModelItemRenderer()); ListModelList lml = (ListModelList) kunBranche.getModel(); // get and select the customers branch Branche branche = kunde.getBranche(); kunBranche.setSelectedIndex(lml.indexOf(branche)); doShowDialog(getKunde()); } /** * User rights check. <br> * Only components are set visible=true if the logged-in <br> * user have the right for it. <br> * * The rights are get from the spring framework users * grantedAuthority(). A right is only a string. <br> */ private void doCheckRights() { UserWorkspace workspace = UserWorkspace.getInstance(); window_customerDialog.setVisible(workspace.isAllowed("window_customerDialog")); tabCustomerDialogAddress.setVisible(workspace.isAllowed("tab_CustomerDialog_Address")); tabPanelCustomerAddress.setVisible(workspace.isAllowed("tab_CustomerDialog_Address")); tabCustomerDialogAddition.setVisible(workspace.isAllowed("tab_CustomerDialog_Addition")); tabPanelCustomerAddition.setVisible(workspace.isAllowed("tab_CustomerDialog_Addition")); tabCustomerDialogOrders.setVisible(workspace.isAllowed("tab_CustomerDialog_Orders")); tabPanelCustomerOrders.setVisible(workspace.isAllowed("tab_CustomerDialog_Orders")); tabCustomerDialogMemos.setVisible(workspace.isAllowed("tab_CustomerDialog_Memos")); tabPanelCustomerMemos.setVisible(workspace.isAllowed("tab_CustomerDialog_Memos")); // TODO we must check wich TabPanel is the first so we can FORCE // a click that it become to front. btnHelp.setVisible(workspace.isAllowed("button_CustomerDialog_btnHelp")); btnNew.setVisible(workspace.isAllowed("button_CustomerDialog_btnNew")); btnEdit.setVisible(workspace.isAllowed("button_CustomerDialog_btnEdit")); btnDelete.setVisible(workspace.isAllowed("button_CustomerDialog_btnDelete")); btnSave.setVisible(workspace.isAllowed("button_CustomerDialog_btnSave")); btnClose.setVisible(workspace.isAllowed("button_CustomerDialog_btnClose")); } public void onSelect$tabCustomerDialogOrders(Event event) { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } kunde = getKunde(); /* overhanded params to the zul file */ HashMap map = new HashMap(); map.put("kunde", kunde); map.put("customerDialogCtrl", this); Tabpanel orderTab = (Tabpanel) Path.getComponent("/window_customerDialog/tabPanelCustomerOrders"); orderTab.getChildren().clear(); Panel panel = new Panel(); Panelchildren pChildren = new Panelchildren(); panel.appendChild(pChildren); orderTab.appendChild(panel); // call the zul-file and put it in the center layout area Executions.createComponents("/WEB-INF/pages/order/orderList.zul", pChildren, map); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // +++++++++++++++++++++++ Components events +++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * If we close the dialog window. <br> * * @param event * @throws Exception */ public void onClose$window_customerDialog(Event event) throws Exception { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } doClose(); } /** * when the "save" button is clicked. * * @param event */ public void onClick$btnSave(Event event) { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } doSave(); } /** * when the "edit" button is clicked. * * @param event */ public void onClick$btnEdit(Event event) { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } doEdit(); } /** * onClick button help. <br> * * @param event */ public void onClick$btnHelp(Event event) throws InterruptedException { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } Messagebox.show(Labels.getLabel("message_Not_Implemented_Yet")); } /** * when the "new" button is clicked. * * @param event */ public void onClick$btnNew(Event event) { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } doNew(); } /** * when the "delete" button is clicked. * * @param event */ public void onClick$btnDelete(Event event) throws InterruptedException { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } doDelete(); } /** * when the "close" button is clicked. * * @param event */ public void onClick$btnClose(Event event) throws InterruptedException { if (logger.isDebugEnabled()) { logger.debug("--> " + event.toString()); } try { doClose(); } catch (Exception e) { // close anyway window_customerDialog.onClose(); // Messagebox.show(e.toString()); } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // ++++++++++++++++++++++++ GUI operations +++++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * Closes the dialog window. <br> * <br> * Before closing we check if there are unsaved changes in <br> * the components and ask the user if saving the modifications. <br> * */ private void doClose() throws Exception { if (logger.isDebugEnabled()) { logger.debug("--> DataIsChanged :" + isDataChanged()); } if (isDataChanged()) { // Show a confirm box String msg = Labels.getLabel("message_Data_Modified_Save_Data_YesNo"); String title = Labels.getLabel("message_Information"); if (Messagebox.show(msg, title, Messagebox.YES | Messagebox.NO, Messagebox.QUESTION, new EventListener() { public void onEvent(Event evt) { switch (((Integer) evt.getData()).intValue()) { case Messagebox.YES: doSave(); case Messagebox.NO: break; // } } } ) == Messagebox.YES) { } } window_customerDialog.onClose(); } /** * Opens the Dialog window modal. * * It checks if the dialog opens with a new or existing object, if so they * set the readOnly mode accordingly. */ public void doShowDialog(Kunde kunde) throws InterruptedException { // if customer == null then we opened the customerDialog.zul without // args for a given customer, so we do a new Kunde() if (kunde == null) { // !!! DO NOT BREAK THE TIERS !!! // we don't create a new Kunde() in the frontend. // we get it from the backend. kunde = getKundeService().getNewKunde(); setKunde(kunde); } else { setKunde(kunde); } // set Readonly mode accordingly if the object is new or not. if (kunde.isNew()) { btnCtrl.setInitNew(); doEdit(); } else { btnCtrl.setInitEdit(); doReadOnly(); } try { // fill the components with the data kunNr.setValue(kunde.getKunNr()); kunMatchcode.setValue(kunde.getKunMatchcode()); kunName1.setValue(kunde.getKunName1()); kunName2.setValue(kunde.getKunName2()); kunOrt.setValue(kunde.getKunOrt()); kunMahnsperre.setChecked(kunde.getKunMahnsperre()); // stores the inital data for comparing if they are changed // during user action. doStoreInitValues(); window_customerDialog.doModal(); // open the dialog in modal mode } catch (Exception e) { Messagebox.show(e.toString()); } } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // +++++++++++++++++++++++++ helpers +++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ /** * Stores the old values */ private void doStoreInitValues() { oldVar_kunNr = kunNr.getValue(); oldVar_kunMatchcode = kunMatchcode.getValue(); oldVar_kunName1 = kunName1.getValue(); oldVar_kunName2 = kunName2.getValue(); oldVar_kunOrt = kunOrt.getValue(); oldVar_kunBranche = kunBranche.getSelectedItem(); oldVar_kunMahnsperre = kunMahnsperre.isChecked(); } /** * Checks, if data are changed since the last call of <br> * doStoreInitData() . <br> * * @return true, if data are changed, otherwise false */ private boolean isDataChanged() { boolean changed = false; if (oldVar_kunNr != kunNr.getValue()) { changed = true; } if (oldVar_kunMatchcode != kunMatchcode.getValue()) { changed = true; } if (oldVar_kunName1 != kunName1.getValue()) { changed = true; } if (oldVar_kunName2 != kunName2.getValue()) { changed = true; } if (oldVar_kunOrt != kunOrt.getValue()) { changed = true; } if (oldVar_kunBranche != kunBranche.getSelectedItem()) { changed = true; } if (oldVar_kunMahnsperre != kunMahnsperre.isChecked()) { changed = true; } return changed; } /** * Sets the Validation by setting the accordingly constraints to the fields. */ private void doSetValidation() { setValidationOn(true); kunNr.setConstraint("NO EMPTY"); kunMatchcode.setConstraint("NO EMPTY"); kunName1.setConstraint("NO EMPTY"); kunOrt.setConstraint("NO EMPTY"); // TODO helper textbox for selectedItem ????? // kunBranche.setConstraint(new SimpleConstraint("NO EMPTY")); } /** * Disables the Validation by setting the empty constraints. */ private void doRemoveValidation() { setValidationOn(false); kunNr.setConstraint(""); kunMatchcode.setConstraint(""); kunName1.setConstraint(""); kunOrt.setConstraint(""); } // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // +++++++++++++++++++++++++ crud operations +++++++++++++++++++++++ // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ private void doDelete() throws InterruptedException { final Kunde kunde = getKunde(); // Show a confirm box String msg = "Are you sure to delete this customer ?" + kunde.getKunName1() + " " + kunde.getKunName2() + " ," + kunde.getKunOrt(); if (Messagebox.show(msg, "Deleting a customer", Messagebox.YES | Messagebox.NO, Messagebox.QUESTION, new EventListener() { public void onEvent(Event evt) { switch (((Integer) evt.getData()).intValue()) { case Messagebox.YES: deleteCustomer(); case Messagebox.NO: break; // } } private void deleteCustomer() { // delete from database getKundeService().delete(kunde); // now synchronize the customers listBox ListModelList lml = (ListModelList) lbCustomer.getListModel(); // Check if the customer object is new or updated // -1 means that the obj is not in the list, so it's new.. if (lml.indexOf(kunde) == -1) { } else { lml.remove(lml.indexOf(kunde)); } window_customerDialog.onClose(); // close the dialog } } ) == Messagebox.YES) { } } private void doNew() { // !!! DO NOT BREAK THE TIERS !!! // we don't create a new Kunde() in the frontend. // we get it from the backend. Kunde kunde = getKundeService().getNewKunde(); // our customer have a table-reference on filiale // we take the filiale we have become by logged in kunde.setFiliale(UserWorkspace.getInstance().getFiliale()); setKunde(kunde); doClear(); // clear all commponents doEdit(); // edit mode btnCtrl.setBtnStatus_New(); // remember the old vars doStoreInitValues(); } private void doEdit() { kunNr.setReadonly(false); kunMatchcode.setReadonly(false); kunName1.setReadonly(false); kunName2.setReadonly(false); kunOrt.setReadonly(false); kunBranche.setDisabled(false); kunMahnsperre.setDisabled(false); btnCtrl.setBtnStatus_Edit(); // remember the old vars doStoreInitValues(); } public void doReadOnly() { kunNr.setReadonly(true); kunMatchcode.setReadonly(true); kunName1.setReadonly(true); kunName2.setReadonly(true); kunOrt.setReadonly(true); kunBranche.setDisabled(true); kunMahnsperre.setDisabled(true); } public void doClear() { // remove validation, if there are a save before doRemoveValidation(); kunNr.setValue(""); kunMatchcode.setValue(""); kunName1.setValue(""); kunName2.setValue(""); kunOrt.setValue(""); kunMahnsperre.setChecked(false); // unselect the last customers branch kunBranche.setSelectedIndex(0); } public void doSave() { Kunde kunde = getKunde(); // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // force validation, if on, than execute by component.getValue() // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if (!isValidationOn()) { doSetValidation(); } // fill the customer object with the components data kunde.setKunNr(kunNr.getValue()); kunde.setKunMatchcode(kunMatchcode.getValue()); kunde.setKunName1(kunName1.getValue()); kunde.setKunName2(kunName2.getValue()); kunde.setKunOrt(kunOrt.getValue()); // get the selected branch object from the listbox Listitem item = kunBranche.getSelectedItem(); if (item == null) { try { Messagebox.show("Please select a branch !"); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return; } ListModelList lml1 = (ListModelList) kunBranche.getListModel(); Branche branche = (Branche) lml1.get(item.getIndex()); kunde.setBranche(branche); if (kunMahnsperre.isChecked() == true) { kunde.setKunMahnsperre(true); } else { kunde.setKunMahnsperre(false); } // save it to database getKundeService().saveOrUpdate(kunde); // call from cusromerList then synchronize the customers listBox if (lbCustomer != null) { ListModelList lml = (ListModelList) lbCustomer.getListModel(); // Check if the customer object is new or updated // -1 means that the obj is not in the list, so it's new. if (lml.indexOf(kunde) == -1) { lml.add(kunde); } else { lml.set(lml.indexOf(kunde), kunde); } } doReadOnly(); btnCtrl.setBtnStatus_Save(); // init the old values vars new doStoreInitValues(); } }
UserWorkspace.java
package org.myfirm; import java.io.Serializable; import java.util.HashSet; import java.util.Properties; import java.util.Set; import org.apache.log4j.Logger; import org.myfirm.policy.model.UserImpl; import org.springframework.security.Authentication; import org.springframework.security.GrantedAuthority; import org.springframework.security.context.SecurityContextHolder; import org.zkoss.zk.ui.Executions; import org.zkoss.zul.Window; import de.daibutsu.backend.model.Filiale; /** * Workspace for the user. One workspace per userSession. <br> * <br> * Every logged in user have his own workspace. <br> * Here are stored several properties for the user. <br> * <br> * 1. Access the rights that the user have. <br> * 2. The office for that the user are logged in. <br> * 3. This is a spring-framework weight class. * * */ public class UserWorkspace implements Serializable { private static final long serialVersionUID = -3936210543827830197L; final private static Logger logger = Logger.getLogger(UserWorkspace.class); static private Authentication getAuthentication() { return SecurityContextHolder.getContext().getAuthentication(); } /** * Get a logged-in users WorkSpace which holds all necessary vars. <br> * * @return the users WorkSpace */ public static UserWorkspace getInstance() { return ((UserImpl) getAuthentication().getPrincipal()).getWorkspace(); } private String userLanguage; private Properties userLanguageProperty; private Filiale filiale; // office private int currentDesktopHeight; // actual Desktop Height private int currentDesktopWidth; // actual Desktop Width private Set<String> grantedAuthoritySet = null; /** * Default Constructor */ public UserWorkspace() { if (logger.isDebugEnabled()) { logger.debug("create new Workspace [" + this + "]"); } // speed up the ModalDialogs while disabling the animation Window.setDefaultActionOnShow(""); } /** * Logout with the spring-security.<br> * Therefore we make a sendRedirect() to the logout uri we <br> * have configured in the spring-config.br> */ public void doLogout() { // Sessions.getCurrent().invalidate(); Executions.sendRedirect("/j_spring_logout"); } /** * Copied the grantedAuthorities to a Set of strings <br> * for a faster searching in it. * * @return String set of GrantedAuthorities (rightNames) */ private Set<String> getGrantedAuthoritySet() { if (grantedAuthoritySet == null) { GrantedAuthority[] list = getAuthentication().getAuthorities(); grantedAuthoritySet = new HashSet<String>(list.length); for (GrantedAuthority grantedAuthority : list) { grantedAuthoritySet.add(grantedAuthority.getAuthority()); } } return grantedAuthoritySet; } /** * Checks if a right is in the <b>granted rights</b> that the logged in user * have. <br> * * @param rightName * @return true, if the right is in the granted user rights.<br> * false, if the right is not granted to the user.<br> */ public boolean isAllowed(String rightName) { if (getGrantedAuthoritySet().contains(rightName)) { return true; } else { return false; } } public void setFiliale(Filiale filiale) { this.filiale = filiale; } public Filiale getFiliale() { return this.filiale; } public void setCurrentDesktopHeight(int currentDesktopHeight) { this.currentDesktopHeight = currentDesktopHeight; } public int getCurrentDesktopHeight() { return currentDesktopHeight; } public void setCurrentDesktopWidth(int currentDesktopWidth) { this.currentDesktopWidth = currentDesktopWidth; } public int getCurrentDesktopWidth() { return currentDesktopWidth; } public void setUserLanguage(String userLanguage) { this.userLanguage = userLanguage; } public String getUserLanguage() { return userLanguage; } public void setUserLanguageProperty(Properties userLanguageProperty) { this.userLanguageProperty = userLanguageProperty; } public Properties getUserLanguageProperty() { // // TODO only for testing. we must get the language from // // the users table filed // userLanguageProperty = // ApplicationWorkspace.getInstance().getPropEnglish(); // userLanguageProperty = // ApplicationWorkspace.getInstance().getPropGerman(); // // return userLanguageProperty; return null; } }
ButtonStatusCtrl.java
package org.myfirm.webui.util; import org.myfirm.UserWorkspace; import org.zkoss.zul.Button; /** * Button controller for the buttons in the dialog windows. <br> * <br> * Works by calling the setBtnStatus_xxx where xxx is the kind of pressed <br> * button action, i.e. new delete or save. After calling these methods <br> * all buttons are disabled/enabled or visible/not visible by <br> * param disableButtons. <br> * <br> * disableButtons = true --> Buttons are disabled/enabled <br> * disableButtons = false --> Buttons are visible/not visible <br> * * * * @author sge * @changes 03/25/2009 sge Extended for security. So we need a right prefix.<br> * That suppose that we have a convention in writing the prefix like <br> * if (workspace.isAllowed(_rightPrefix + "_btnNew"))) {<br> * means that the right have following name: * "button_CustomerDialog_btnNew" <br> * */ public class ButtonStatusCtrl { /** NEW Button */ private Button _btnNew; /** EDIT Button */ private Button _btnEdit; /** DELETE Button */ private Button _btnDelete; /** SAVE Button */ private Button _btnSave; /** CLOSE Button */ private Button _btnClose; /** rightName prefix */ private String _rightPrefix; /** * var for disable/enable or visible/not visible mode of the butttons. <br> * true = disable the button <br> * false = make the button unvisible<br> */ private boolean disableButtons = false; /** * Constructor * * @param btnNew * (New Button) * @param btnEdit * (Edit Button) * @param btnDelete * (Delete Button) * @param btnSave * (Save Button) * @param btnClose * (Close Button) */ public ButtonStatusCtrl(String rightPrefix, Button btnNew, Button btnEdit, Button btnDelete, Button btnSave, Button btnClose) { super(); this._btnNew = btnNew; this._btnEdit = btnEdit; this._btnDelete = btnDelete; this._btnSave = btnSave; this._btnClose = btnClose; this._rightPrefix = rightPrefix; // PREPARED FOR: application wide properties // this.disableButtons = // AppWorkspace().getInstance().isDisabledButtonsVisible(); } /** * Set all Buttons for the Mode NEW is pressed. <br> */ public void setBtnStatus_New() { UserWorkspace workspace = UserWorkspace.getInstance(); if (disableButtons) { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setDisabled(false); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setDisabled(false); } } else { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setVisible(true); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setVisible(true); } } } /** * Set all Buttons for the Mode EDIT is pressed. <br> */ public void setBtnStatus_Edit() { UserWorkspace workspace = UserWorkspace.getInstance(); if (disableButtons) { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setDisabled(false); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setDisabled(false); } } else { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setVisible(true); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setVisible(true); } } } /** * Not needed yet, because after pressed the delete button <br> * the window is closing. <br> */ public void setBtnStatus_Delete() { } /** * Set all Buttons for the Mode SAVE is pressed. <br> */ public void setBtnStatus_Save() { setInitEdit(); } /** * Set all Buttons for the Mode INIT in EDIT mode. <br> * This means that the Dialog window is opened and <br> * shows data. <br> */ public void setInitEdit() { UserWorkspace workspace = UserWorkspace.getInstance(); if (disableButtons) { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setDisabled(false); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setDisabled(false); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setDisabled(false); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setDisabled(false); } } else { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setVisible(true); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setVisible(true); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setVisible(true); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setVisible(true); } } } /** * Set all Buttons for the Mode INIT in NEW mode. <br> * This means that the Dialog window is freshly new <br> * and have no data. <br> */ public void setInitNew() { UserWorkspace workspace = UserWorkspace.getInstance(); if (disableButtons) { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setDisabled(true); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setDisabled(false); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setDisabled(false); } } else { if (workspace.isAllowed(_rightPrefix + "btnNew")) { _btnNew.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnEdit")) { _btnEdit.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnDelete")) { _btnDelete.setVisible(false); } if (workspace.isAllowed(_rightPrefix + "btnSave")) { _btnSave.setVisible(true); } if (workspace.isAllowed(_rightPrefix + "btnClose")) { _btnClose.setVisible(true); } } } }
UserImpl.java
package org.myfirm.policy.model; import org.apache.commons.lang.StringUtils; import org.myfirm.UserWorkspace; import org.springframework.security.GrantedAuthority; import org.springframework.security.userdetails.User; import de.daibutsu.backend.model.SecUser; import de.daibutsu.token.Md5Token; /** * The user implementation of spring-frameworks user class. <br> * Extends for our simulation of a one-time-password .<br> * <br> * Great thanks to Bjoern. <br> * Good work. Tokenizer is not for everybody, sorry. <br> * <br> * Extends for a user-id (type long). <br> * <br> * * @author bj * */ public class UserImpl extends User { private static final long serialVersionUID = 7682359879431168931L; final private UserWorkspace workspace = new UserWorkspace(); final private String usrToken; final private long userId; /** * @param username * @param password * @param enabled * @param accountNonExpired * @param credentialsNonExpired * @param accountNonLocked * @param authorities * @throws IllegalArgumentException */ public UserImpl(SecUser user, GrantedAuthority[] grantedAuthorities) throws IllegalArgumentException { super(user.getUsrLoginname(), user.getUsrPassword(), user.isUsrEnabled(), user.isUsrAccountnonexpired(), user .isUsrCredentialsnonexpired(), user.isUsrAccountnonlocked(), grantedAuthorities); this.usrToken = user.getUsrToken(); this.userId = user.getUsrId(); } public UserWorkspace getWorkspace() { return workspace; } /* * gets the token for our simulating of a one-time-password tokenizer. */ public Md5Token getToken() { if (StringUtils.isBlank(getUsrToken())) { return null; } return new Md5Token(getUsrToken()); } private String getUsrToken() { return this.usrToken; } public long getUserId() { return this.userId; } }
That's not all for running alone. But i hope that helps for the next steps. :-)
With a last mans standing words. In spring-security: all is only a string!
regards
Stephan
Asked: 2009-05-09 12:56:42 +0800
Seen: 751 times
Last updated: Jul 17 '09