Hello there! On the previous posts I was asking about a better way to
override the LinkComponents from Tapestry in order to add security support
to it. Ron gave an brilliant AOP style solution with Hivemind, thanks. But
in the mean time I was developing a different solution. One thing that came
on my mind. Was, ok for the links, but what if I don't want a user to see an
entire table component? Or a TextField? Well, the solution may be not
elegant, but it's simple. I've created an wrapper component where we could
use to nest components that need security enabled. I've packed it on a
library. I'm posting the codes here, but if anyone cares I could send the
lib for you. It's the beginning of a components libraries that I and some
fellows are planning to create.

SecureComponentWrapper:
The idea here is to provide a wrapper that will render only if a given
requisite is fullfiled

public abstract class SecureComponentWrapper extends AbstractComponent {
public abstract String getRoles();


protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
if(canRender()){
renderBody(writer,cycle);
}
}

public abstract boolean canRender();

}
AcegiComponentWrapper
The idea here is to let the component be rendered only if the user has the
right credetials

public abstract class AcegiComponentWrapper extends SecureComponentWrapper {
@Override
public boolean canRender() {
Collection principalAuthorities = getPrincipalAuthorities();
Collection roles = Arrays.asList(org.apache.commons.lang.StringUtils.split
(getRoles(),","));
boolean permited = CollectionUtils.containsAny(principalAuthorities,roles);
return permited;
}

@SuppressWarnings({"unused","unchecked"})
private Collection getPrincipalAuthorities() {
SecureContext context = (SecureContext) ContextHolder.getContext();
if (context == null) {
return Collections.EMPTY_LIST;
}
Authentication currentUser = context.getAuthentication();
if (currentUser == null) {
return Collections.EMPTY_LIST;
}
if ((null == currentUser.getAuthorities())
|| (currentUser.getAuthorities().length < 1)) {
return Collections.EMPTY_LIST;
}
ArrayList granted = new ArrayList(currentUser.getAuthorities().length);
for(GrantedAuthority ga : currentUser.getAuthorities()){
granted.add(ga.getAuthority());
}
return granted;
}
}

<component-specification allow-body="yes" allow-informal-parameters="no"
class="org.tupiniquim.components.secure.AcegiComponentWrapper">
<parameter required="yes" name="roles"/>
</component-specification>
<page-specification class="org.apache.tapestry.html.BasePage">
<component id="secured" type="tupiniquim:AcegiComponentWrapper">
<binding name="roles" value="literal:ROLE_ADMIN"></binding>
</component>
</page-specification>

<span jwcid="secured">Can you see me?</span>
</span>

Well if the user is not logged or does not has the ROLE_ADMIN he will not
see the body of the component (which could be another component as well).
You can use CSV like literal:ROLE_ADMIN,ROLE_USER,ROLE_DBA for instance.
I still need to test it a little better, and also to add an feature of
deciding if it should be rendered if users has all of permissions or Any of
the permissions.

I don't know if this is come in hand for anyone else, it just fit our needs
in our JUG pages ;)

Regards

--
Vinicius Caldeira Carvalho
Arquiteto de Sistemas
[EMAIL PROTECTED]
www.synos.com.br <http://www.synos.com.br>

"Everything should be made as simple as possible, but not simpler."
Albert Einstein

Reply via email to