On 9/11/07, Anthony Schexnaildre <[EMAIL PROTECTED]> wrote:
> Please hijack away.
>
> I have been quite happy with Wasp and Swarm. It's simple and painless
> but quite flexible. The examples are the life saver though. To be
> honest, the security framework is why I chose to use Wicket for this
> project instead of Tapestry.
>
> I am however having a few issues figuring out some "best practices"
> that maybe you or some other experienced Wasp/Swarm users may be able
> to shed some light on.
>
> 1. Where would you store a reference to the logged in user. Currently
> have it in a DetachableModel in a custom session. There has to be a
> better place to put the user reference that fits more directly with
> the security framework.
A detachable model in a custom session is as good a place as any, in
fact i keep it there too. Swarm indeed does not keep a ref to your
user object but it does keep a reference to the subject (which
translates into the user rights, but also could be the user itself).
Although you can get this subject by casting the strategy to a
SwarmStrategy, i recommend storing the user yourself like you do now,
which is perfectly compatible with the wicket philosophy that if you
wish to store things in the session you should create a custom session
and provide strongtyped getters / setters for it.
> 2. I very much like your SecureTab example but something like a
> SecurePanelLink within the framework would be helpful.
The ContainerSecurityCheck was created for helping out with panel
replacements by treating panels exactly like pages but if you feel we
need to provide more stuff out of the box here feel free to speak up.
After thinking about this for a bit i think i can come up with a
secure link that automatically replaces one panel with another.
>I have been
> working on my own that mirrors the SecurePageLink as much as possible
> but it is still a bit wonky.
I saw it, and i must admit my first thought was: "couldn't he use ...,
or do ...." but after looking deeper in what you were trying to
accomplish, i think you did alright. Although looking back at my
previous comment about making a panel link i think a combination of
LinkSecurityCheck and ContainerSecurityCheck would be ideal.
>This is helpful because once you get
> into a tab layout, navigation to other panels that are not directly
> attached to a tab becomes annoying at best. I am working through it
> but seems like someone must have solved this issues a few times over
> in an elegant fashion. Maybe some kind of "panel stack" with tab
> integration?
I am not sure i get what it is you are trying to accomplish here. It
should not matter where the panel is located. if you use a regular
ComponentSecurityCheck the full path with the parent is considered but
if you use a ContainerSecurityCheck the panel class is used and where
ever it is placed in the page hierarchy is irrelevant. Personally i
use Swarm in a page based approach, but panels should be just as easy.
>
> 3. I don't understand the DataPermissions, configuration and their
> use cases. I must admit I have not spent the time to dig through the
> example extensively but I don't understand the use cases enough to
> know why I would want to spend the time.
The DataPermissions are indeed a bit under lighted in the examples.
The beauty about them is that you can build entire applications
without ever needing them. They are intended for use cases where it
makes more sense to let the data / model dictate if a user has
permissions for them. One benefit of this is that you can share the
secure model (which is typically used for data permissions) between
multiple components and instead of securing each component the
security is on 1 central place namely the model. An example of this is
the SwarmCompoundPropertyModel.
>
> 4. I am working on an application that will eventually have very
> complicated permission structure. Right now I am fumbling a solution
> together for phase one. Eventually I would like to be able to
> "filter" the date returned to a user based on some permissions while
> not coupling the security layer to the Dao's to tightly.
We have a similar use case in our organization and although you could
use datapermissions to hide components showing restricted data
(completely disconnecting your dao's from your security layer),
consider the following: by letting you security layer provide you with
some sort of filter for your dao (perhaps a list of allowed id's or a
query part) you bypass the need to secure your components as the data
is already made to fit what is allowed to see. In our application we
chose the latter approach.
>A typical
> structure would be as follows:
>
> O - Organisation
> U - User
>
> O
> / / \ \
> / | | \
> U U U O
> / | \
> U O O
> / | | \
> U U U U
>
> Consider a use case where you have a hierarchy of Financial
> Transaction Processors with the following 2 user types/principals:
>
> Customer Service - Allowed to see transactions and act on them if the
> transactions are for their direct organisation
> Billing - Allowed to see transaction and act on them for their direct
> organisation and any sub-organisations
In our application we tackled this problem by introducing a few more
actions (i suggest looking into the custom actionfactory example) by
creating 2 additional actions: 1 for the direct organizations and the
2nd which implies the first for the direct and the sub-organizations.
Then by creating a custom ISecurityCheck you can verify if the
organization is allowed or not.
>
> The final goal would be to have an interface much like that in the
> wicket-phonebook example where the DataProvider ( or something else )
> would feed the appropriate results out of the hibernate dao's into
> the DataTable based on the users permissions.
>
> Any clues to some elegant approach?
Well i can tell you about how we did it. Our dataproviders work with
filters (which are simple pojos with the same fields as the object(s)
we want to display). In addition these filters know the security
privileges of the user and based on that the provide a list of id's
(not that elegant i admit, another option would be to have them donate
a query fragment) of allowed entities. the provider then builds the
query based on the filter and uses an in query on the id's to have the
database only return the allowed records. Note that we have used this
approach only in DataView and not in DataTable. DataTable might make
it a bit more trickier because it gives you less control over the
filtering. Anyway i think having your filter create query fragments
based on security is even more elegant then id's, but try getting time
to refactor that ;)
Maurice
>
> -Anthony
>
>
>
> On Sep 9, 2007, at 6:12 PM, Maurice Marrink wrote:
>
> > Allow me to hijack this topic because my eye sees the magic word
> > ISecureComponent :D
> >
> > Glad to come across another user of Wasp and Swarm. Any comments /
> > questions about them?
> >
> > Maurice
> >
> > On 9/9/07, Igor Vaynberg <[EMAIL PROTECTED]> wrote:
> >> heh, seems a lot of people run into it. the short is that you have
> >> to do
> >> this:
> >>
> >> lets say you have a ref to the panel: private Panel panel;
> >>
> >> what you do is this:
> >> panel.replaceWith(new Panel());
> >>
> >> and then later again
> >> panel.replaceWith(new Panel());
> >>
> >> ^ the second time will fail beause you have removed panel from
> >> hierarchy
> >> already - you replaced it with another panel.
> >>
> >> the proper way to do it is to keep the reference up to date, so
> >> Panel temp=new Panel();
> >> panel.replaceWith(temp);
> >> panel=temp;
> >>
> >> that way when it happens the second time it will properly act on
> >> the new
> >> panel that is inside the hierarchy now.
> >>
> >> -igor
> >>
> >>
> >>
> >>
> >> On 9/9/07, Anthony Schexnaildre <[EMAIL PROTECTED]> wrote:
> >>>
> >>> I am trying to create a link that will replace one panel with
> >>> another
> >>> on the page. This seems as though it should be an easy task but
> >>> after
> >>> many attempts and searching the net for examples I have yet to
> >>> get it
> >>> working so the replacement can happen more than one without the
> >>> component becoming orphaned. On the second replace attempt i get the
> >>> following exception. Anyone have the solution?
> >>>
> >>> Thank you,
> >>>
> >>> Anthony
> >>>
> >>>
> >>> java.lang.IllegalStateException: This method can only be called on a
> >>> component that has already been added to its parent.
> >>> at org.apache.wicket.Component.replaceWith(Component.java:
> >>> 2266)
> >>> at com.pinwise.pinbase.web.components.links.SecurePanelLink
> >>> $4.onClick(SecurePanelLink.java:142)
> >>> at org.apache.wicket.markup.html.link.Link.onLinkClicked
> >>> (Link.java:222)
> >>> at java.lang.reflect.Method.invoke(Method.java:585)
> >>> at org.apache.wicket.RequestListenerInterface.invoke
> >>> (RequestListenerInterface.java:186)
> >>>
> >>>
> >>> =====================================
> >>>
> >>> =====================================
> >>>
> >>> public UserPanel(String id) {
> >>> super(id);
> >>>
> >>>
> >>> UserFormPanel userFormPanel = new
> >>> UserFormPanel("userFormPanel");
> >>> add( userFormPanel );
> >>>
> >>> List<IColumn> columns = new ArrayList<IColumn>();
> >>> final Model m = new Model(userFormPanel);
> >>> columns.add(new PropertyColumn(new Model("Actions"), "id")
> >>> {
> >>> public void populateItem(Item cellItem,
> >>> String
> >>> componentId, final
> >>> IModel model)
> >>> {
> >>> EditActionPanel panel = new
> >>> EditActionPanel(componentId, model);
> >>> panel.add(
> >>> SecurePanelLink.createSecurePanelLink( "edit", m,
> >>> UserFormPanel.class, model ) );
> >>> cellItem.add( panel );
> >>> }
> >>> });
> >>>
> >>> columns.add(new PropertyColumn(new Model("Username"),
> >>> "username", "username"));
> >>> columns.add(new PropertyColumn(new Model("First Name"),
> >>> "firstName", "firstName"));
> >>> columns.add(new PropertyColumn(new Model("Last Name"),
> >>> "lastName", "lastName"));
> >>>
> >>> add(new DefaultDataTable("table", columns, new
> >>> SortableUserDataProvider(), 10));
> >>> }
> >>>
> >>>
> >>> ====================================
> >>> SecurePanelLink
> >>> ====================================
> >>> public class SecurePanelLink extends Link implements
> >>> ISecureComponent {
> >>>
> >>> /**
> >>> *
> >>> */
> >>> private static final long serialVersionUID = 1L;
> >>>
> >>> protected IPanelLink panelLink;
> >>>
> >>> /**
> >>> * @param id
> >>> * @param c
> >>> */
> >>> public SecurePanelLink(String id, final Class c)
> >>> {
> >>> super(id);
> >>> // Ensure that c is a subclass of Panel
> >>> if (!Panel.class.isAssignableFrom(c))
> >>> {
> >>> throw new IllegalArgumentException("Class
> >>> " + c +
> >>> " is not a
> >>> subclass of Panel");
> >>> }
> >>>
> >>> this.panelLink = createIPanelLink( id, c );
> >>> setSecurityCheck(new LinkSecurityCheck(this, c));
> >>> }
> >>>
> >>> public SecurePanelLink(String id, final Class c, Model
> >>> existingPanel)
> >>> {
> >>> super(id);
> >>> // Ensure that c is a subclass of Panel
> >>> if (!Panel.class.isAssignableFrom(c))
> >>> {
> >>> throw new IllegalArgumentException("Class
> >>> " + c +
> >>> " is not a
> >>> subclass of Panel");
> >>> }
> >>>
> >>> this.panelLink = createIPanelLink( id, c );
> >>> setSecurityCheck(new LinkSecurityCheck(this, c));
> >>> }
> >>>
> >>> private IPanelLink createIPanelLink( String id, final
> >>> Class c ) {
> >>> return new IPanelLink()
> >>> {
> >>> private static final long
> >>> serialVersionUID = 1L;
> >>>
> >>> public Panel getPanel( String id )
> >>> {
> >>> // Create panel using panel factory
> >>> return getPanelFactory().newPanel
> >>> (id, c );
> >>> }
> >>>
> >>> public Panel getPanel( String id, IModel
> >>> model)
> >>> {
> >>> // Create panel using panel factory
> >>> return getPanelFactory().newPanel
> >>> (id, c,
> >>> model);
> >>> }
> >>>
> >>> public Panel getPanel( Panel panel,
> >>> IModel model)
> >>> {
> >>> // Create panel using panel factory
> >>> return getPanelFactory().newPanel(
> >>> panel.getId(), c, model);
> >>> }
> >>>
> >>> public Class getPanelIdentity()
> >>> {
> >>> return c;
> >>> }
> >>> };
> >>> }
> >>>
> >>> /**
> >>> *
> >>> */
> >>> public static SecurePanelLink createSecurePanelLink
> >>> ( String id,
> >>> Class clazz ) {
> >>> return new SecurePanelLink( id, clazz ) {
> >>> /**
> >>> *
> >>> */
> >>> private static final long
> >>> serialVersionUID = 1L;
> >>>
> >>> public void onClick() {
> >>> Panel panel = ((Panel)findParent(
> >>> Panel.class));
> >>> panel.replaceWith
> >>> ( panelLink.getPanel(
> >>> panel.getId() ) );
> >>> }
> >>> };
> >>> }
> >>>
> >>> /**
> >>> *
> >>> */
> >>> public static SecurePanelLink createSecurePanelLink
> >>> ( String id,
> >>> Class newPanel, final IModel model ) {
> >>> return new SecurePanelLink( id, newPanel ) {
> >>> /**
> >>> *
> >>> */
> >>> private static final long
> >>> serialVersionUID = 1L;
> >>>
> >>> public void onClick() {
> >>> Panel panel = ((Panel)findParent(
> >>> Panel.class));
> >>> panel.replaceWith
> >>> ( panelLink.getPanel(
> >>> panel.getId(), model ) );
> >>> }
> >>> };
> >>> }
> >>>
> >>> /**
> >>> *
> >>> */
> >>> public static SecurePanelLink createSecurePanelLink
> >>> ( String id,
> >>> final Model existingPanel, Class newPanel, final IModel model ) {
> >>> return new SecurePanelLink( id, newPanel,
> >>> existingPanel )
> >>> {
> >>> /**
> >>> *
> >>> */
> >>> private static final long
> >>> serialVersionUID = 1L;
> >>>
> >>>
> >>> public void onClick() {
> >>> Panel p =
> >>> (Panel)existingPanel.getObject();
> >>> Panel panel = panelLink.getPanel
> >>> ((Panel)existingPanel.getObject
> >>> (), model );
> >>> panel.setOutputMarkupId(true);
> >>> p.getParent().replace( panel );
> >>> p=panel;
> >>> }
> >>> };
> >>> }
> >>>
> >>
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [EMAIL PROTECTED]
> > For additional commands, e-mail: [EMAIL PROTECTED]
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, e-mail: [EMAIL PROTECTED]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]