tapestry-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jesse Kuhnert <jkuhn...@gmail.com>
Subject Re: render time element removal question, revisited
Date Wed, 07 Sep 2005 18:38:35 GMT
I will attempt a tiny response, though I'm not as intimately aware of all 
the requirements/workings of tapestry as might be hoped...

I had to provide fine-grained security features in my tapestry app as well, 
but opted for using hivemind to add additional functionality instead of 
trying to manually set properties on components at runtime. As an example, I 
created a "perm" binding that allowed me to write things like this:

<span jwcid="@PageLink" disabled="perm:EditPage" page="EditPage" />

Since tapestry components can arbitrarily have any attributes set at runtime 
or compile-time, as well as the abillity to extend the functionality of 
these attributes via bindings I was able to then create a "perm" binding 
contribution that looks roughly like this in my hivemodule.xml file:

<service-point id="PermBindingFactory" interface="
org.apache.tapestry.binding.BindingFactory">
<invoke-factory>
<construct class="com.eko.app.tapestry.services.PermBindingFactory" >
Ignore this....just a hibernate session..more or less
<set-service property="sessionProvider" service-id="cims.SessionProvider" />
</construct>
</invoke-factory>
</service-point>

<contribution configuration-id="tapestry.bindings.BindingFactories" >
<binding prefix="perm" service-id="cims.PermBindingFactory" />
</contribution>

The service looks like this:

public class PermBindingFactory extends AbstractBindingFactory {

/** Logger */
private static final Logger log = Logger.getLogger(PermBindingFactory.class
);
/** Provided to binding to check user permission */
private SessionStateProvider injectedProvider;

/**
* 
* {@inheritDoc}
*/
public IBinding createBinding(IComponent root, String bindingDescription, 
String path,
Location location)
{
log.debug("createBinding()");
return new PermissionBinding(bindingDescription, getValueConverter(), 
location, path,
injectedProvider);
}

/**
* Set by hivemind during configuration.
* @param provider
*/
public void setSessionProvider(SessionStateProvider provider)
{
injectedProvider = provider;
}
}

And the actual PermissionBinding binding looks like this:

public class PermissionBinding extends AbstractBinding {

private static final Logger log = Logger.getLogger(PermissionBinding.class);

/** Binding reference */
private String objectReference;
/** Reference to session state class */
private SessionStateProvider provider;

/**
* Creates a new permission binding.
* @param description
* @param valueConverter
* @param location
* @param objectReference
* @param provider
*/
public PermissionBinding(String description, ValueConverter valueConverter, 
Location location,
String objectReference, SessionStateProvider provider)
{
super(description, valueConverter, location);

log.debug("Checking for null values in constructor.");
Defense.notNull(objectReference, "objectReference");
Defense.notNull(provider, "provider");

this.objectReference = objectReference;
this.provider = provider;
}

/**
* Called to actually get the binding for this call. 
*/
public Object getObject()
{
return Boolean.valueOf(!provider.inRole(objectReference));
}

The "provider" and "sessionstateprovider" items referenced in the above 
sources are references to my users session state object, which holds a User 
object called "provider". This object has logic in it to determine if the 
specified permission should be granted.

I also have another set of security classes that do runtime checks on page 
listener method calls as well to prevent anyone from mucking around with 
URL's and accidently being able to see/do something they ought not to. (It 
even displays a you've been naughty page to them, as they should never get 
to it unless they've manually modified a url somehow).

Conditionally rendering a component is something I'm less sure about. I do 
perform these sorts of requests over in
tacos.sourceforge.net<http://tacos.sourceforge.net>,
but that is all based around ajax type of logic. You may find inspiration 
for conditional component renders in the source there. I know right away 
that it would be very trivial to add that sort of logic to non-ajax 
responses as well, but can't say that I'll be adding it to tacos anytime 
soon, unless someone wants it for non-security reasons. 

Hope this helps a little. I think
hivetranse.sourceforge.net<http://hivetranse.sourceforge.net>is doing
similar security things "out of the box", you may want to check it
out. You should also go search through this project's wiki, as I seem to 
remember hearing something about someone integrating acegi security into 
tapestry as well. 

jesse 

On 9/7/05, RR <security.identity@gmail.com> wrote:
> 
> I've spent some time analyzing my concerns/requirements and Tapestry's
> abilities. This is what I've come up with (please correct if I'm
> wrong):
> 
> 1. Components must be defined prior to render. Which means, you need
> to have the "disabled" attribute/binding set to false on *every*
> single component you want to protect, at build-time. It is a pain to
> add a "binding" at run-time and highly discouraged.
> (http://article.gmane.org/gmane.comp.java.tapestry.user/25209).
> 
> 2. Tapestry is incapable of removing components at render time. You
> don't have access to the DOM, you can't set a flag, I have not found
> anything to enable this. I should clarify, this is the case for all
> default Tapestry components OR you can sort of work around this by
> wrapping the component in a Conditional component.
> 
> 3. Tapestry default components do not allow render flags. In
> conjunction with issue #2, you can't just set a flag informing
> Tapestry to NOT render the component.
> 
> So, why does this pose a large issue for me? Because I have many pages
> in which I now need to implement security by either
> removing/not-rendering the component or adding/modifying the
> "disabled" attribute. I cannot, out-of-the-box, do what I need with
> Tapestry 3.1. I must go through each component and the add a
> "disabled" attribute (only 130+ of them). I must choose to wrap the
> components in Conditionals if I don't want them rendered. IMO, this is
> a ton of work and really defeats the purpose of dynamic page
> generation and server-side page manipulation. Perhaps this is part of
> the general Tapestry paradigm, but I don't understand that paradigm
> correctly (or not well enough), because this is quite frustrating.
> 
> The only acceptable solution (I've thus found) is to go through and
> create wrapper components for each of the Tapestry components we're
> using. I'll add a default "disabled" attribute that I can hose with at
> run-time (so the designer doesn't have to add it specifically) and a
> flag that determines whether the component should render. This is
> going to take more time than I likely have and is a real pain since
> I'll need to essentially wrap all of the basic Tapestry components
> (ProperSelection, Insert, DirectLink, PageLink, Submit, Button).
> 
> On the other hand, JSF provides the convenience of both the ability to
> update attributes (mutable map, getAttributes()) and set a render flag
> (setRender()). What's prohibiting Tapestry's inclusion of the same
> principles? Has no one else been disturbed because of these inherent
> weaknesses?
> 
> Feedback and correction is appreciated.
> 
> 
> 
> On 9/2/05, Robert Zeigler <robertz@scazdl.org> wrote:
> > I'll try to find the thread information.
> > What concerns me about the original poster's idea is the thought of
> > "removing" the component. Rendering or not rendering the component is
> > fine; that's "dynamic behavior". Adding or removing components at
> > runtime violates the idea of "static structure".
> >
> > The thread subject was "programmatically adding a binding to a 
> component".
> > Gmane:
> > http://article.gmane.org/gmane.comp.java.tapestry.user/25209
> >
> > The thread was talking specifically about component bindings, but the
> > specific quote I was thinking of was:
> >
> > "The various setter methods exist for the framework, you
> > should treat components as immutable."
> >
> > This includes adding and removing components to the component at
> > runtime. Note that pages are just specialized components.
> >
> > Again, the fundamental issue is not rendering vs. not rendering
> > components, but rather adding/removing the components. It sounded to me
> > like the original poster was wanting to do the latter.
> >
> > The "requires role" component that you implemented sounds fine; this is
> > the sort of approach I was advocating.
> >
> > Robert
> >
> > LOCHART,DOUGLAS E wrote:
> > > Robert,
> > >
> > > I am interested in reading this HLS thread. I did a search but did not
> > > find it. Could you possibly point me to the thread (dates, keywords to
> > > search etc)
> > >
> > > I would appreciate it.
> > >
> > > The approach I took was to create a component (based on the 
> Conditional
> > > component) called RequiresRole. If the user logged in does not have 
> the
> > > role, the menu option/links etc are not visible. It works fine for me.
> > > Maybe I am missing the point in "rendering of pages at runtime" but my
> > > component is JUST LIKE Conditional so I do see what is the problem.
> > >
> > > thanks
> > >
> > > Doug
> > >
> > >
> > > To be honest, personally, I don't think that approach is really going 
> to
> > > mix well with tapestry. As was mentioned by HLS in a recent thread, 
> you
> > > should consider pages at runtime as immutable. Removing elements will
> > > prove problematic, I think.
> > > An approach I used was to create a sort of "inRole" component. It 
> takes
> > > as parameters either a requisite permission name or an object for 
> which
> > > permission is required. It's essentially an "if" wrapper, but has the
> > > advantage of centralizing the render-oriented permission logic to a 
> single
> > > component.
> > > You could also create custom wrappers around any components. So you
> > > could, for instance, create a "SecureTable" component which wraps a 
> table
> > > component, adds parameters related to permission checking, and
> > > conditionally renders the component. Then you could use your 
> SecureTable
> > > just like table, and still have your dynamic behavior.... static
> > > structure, dynamic behavior. :)
> > >
> > > Robert
> > >
> > >
> > >>> I'm wondering if anyone has impemented a security model that 
> requires
> > >>> dynamic (render-time) removal of certain HTML elements? And if so,

> how
> > >>> hefty
> > >>> was the work? I need to remove elements at render time based upon 
> roles
> > >>> and
> > >>> rights and *do not* want to wrap all of the secure elements in
> > >>> conditionals.
> > >>> Rather, I'd wish to determine at render time the necessity of 
> removing
> > >>> certain elements and simply not render them.
> > >>>
> > >>> TIA,
> > >>> -RR-
> > >>>
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> > >
> > >
> > >
> > > ---------------------------------------------------------------------
> > > To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> > > For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> > For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> >
> >
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-user-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-user-help@jakarta.apache.org
> 
>

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message