Authorization in JSF2 components - jsf-2

In our project we have JSF2 pages used in internal network of a company. But we are going to open those pages to Internet. So pages will be available to everybody. But some fields will not be rendered if a user comes from Internet.
I know it is possible to write a rendered attribute for each component such as "userIsInRole". But additional "rendered" control doesn't seem to be efficient and elegant method. So I plan to mark the components which are going to be rendered online by using a custom attribute as shown below:
<h:inputText context="internet" />
...
In the renderer of the inputText or component code:
if(user is from Internet && context = "internet") {
return true; // or render... whatever
}
If a component is not marked as Internet, then it means it will be available (rendered) only from inside of the company.
Is it possible implement authorization by using JSF2 components according to a given attribute? Is there any better options? Or should I design separate pages for internet users?
We use: PrimeFaces + Spring in our project.
Thank you

This is ridiculous. What's the difference in effort of ultimately using
<h:inputText context="internet" />
versus
<h:inputText rendered="#{intranet}" />
?
If your sole problem is that you need to repeat the whole condition everytime ending up in ugly code like so
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
<h:inputText rendered="#{not (user.hasRole('internet') and context eq 'internet')}" />
...
then just refactor the condition to a single request scoped variable
<c:set var="intranet" value="#{not (user.hasRole('internet') and context eq 'internet')}" scope="request" />
...
<h:inputText rendered="#{intranet}" />
<h:inputText rendered="#{intranet}" />
<h:inputText rendered="#{intranet}" />
...

Related

Does not work properly id generation on ui:repeat My faces 2.2.9 + prime faces 5.3

Actually I'm working with Myfaces version 2.2.9 and I've the following structure to generate any panel according with a specific number selected by the user.
...
<ui:repeat value="#{garajes}" var="garaje" varStatus="loop">
<p:panelGrid >
<h:outputLabel value="Numero de garaje #{loop.index+1}: " />
<h:outputLabel value="Matricula #{loop.index+1}: " />
<p:inputText value="#{garaje.numeroGaraje}" maxlength="5" >
</p:inputText>
<p:inputText id="matriculaInmobiliariaGaraje-#{loop.index+1}" value="#{garaje.matriculaInmobiliaria}"
maxlength="20">
</p:inputText>
...
</p:panelGrid>
</ui:repeat>
....
So, when is rendered the above code the identifiers are weird, has another things like the following image:
So I don't know how to remove this weird things inside of id
Note: I need a specific id to update another component inside of the loop.
What can I do to get a right identifiers inside of ui:repeat?
As to the concrete problem, just give all NamingContainer components a fixed ID. This includes the <ui:repeat> itself.
<ui:repeat id="garajes" ...>
As to the concrete requirement, you're overcomplicating things. A NamingContainer will all by itself worry about uniqueness of IDs of children. Your attempt in id="matriculaInmobiliariaGaraje-#{loop.index+1}" won't work at all as #{loop} variable isn't available during view build time, when the component is being instantiated with id. Get rid of it. You can inside a NamingContainer just use a relative ID to reference another component in the same NamingContainer.
<ui:repeat ...>
<p:inputText id="foo" />
<p:inputText ...><p:ajax ... update="foo" /></p:inputText>
</ui:repeat>
This will work just fine.
See also:
How to find out client ID of component for ajax update/render? Cannot find component with expression "foo" referenced from "bar"
How to use EL with <ui:repeat var> in id attribute of a JSF component

How to use generated ids in EL (jsf, composite)?

I want to have a composite that composes
<h:form id="f_imgA" >
<h:graphicImage id="imgA"
onclick="document.getElementById('#{k_imgA.clientId}').value=mods(event)"
value="images/img?r=#{Math.random()}">
<f:ajax event="click" listener="#{mBean.handleEvent}"
execute="#this k_imgA" render="#this"></f:ajax>
</h:graphicImage>
<h:inputHidden id="k_imgA" binding="#{k_imgA}" value="#{mBean.keyX}" />
</h:form>
when I write
<comps:cimg imgId="imgA" />
The original purpose of this code is to send the modifier-states (Ctrl, Shift, Alt) to the server.
I have
<composite:interface>
<composite:attribute name="imgId" />
</composite:interface>
<composite:implementation>
<h:form id="f_#{cc.attrs.imgId}">
<h:graphicImage id="#{cc.attrs.imgId}"
onclick="document.getElementById('#{k_${cc.attrs.imgId}.clientId}').value=mods(event)"
value="images/img?r=#{Math.random()}">
<f:ajax event="click" execute="#this k_#{cc.attrs.imgId}"
listener="#{mBean.handleEvent}" render="#this">
</f:ajax>
</h:graphicImage>
<h:inputHidden id="k_#{cc.attrs.imgId}"
binding="k_#{cc.attrs.imgId}" value="#{mBean.keyX}" />
</h:form>
</composite:implementation>
which, quite expected, does not work. The offending expression is
#{k_${cc.attrs.imgId}.clientId}
which is intended to return the clientId of the hiddenInput with id k_imgA . As far as I know, EL cannot handle nested expressions like the one above, but it was worth a try. So is there a simple, straightforward way to get the clientId of k_imgA? I don't want to use more javascript, if this can be avoided.
Edit:
don't get confused about #{Math.random()}, it works just because I have a bean called "Math".
The javascript function mods is given by
<h:outputScript target="body">function mods(event) {return ((event.ctrlKey)?1:0)+((event.shiftKey)?2:0)+((event.altKey)?4:0)} </h:outputScript>
You don't need to fiddle with all those _#{cc.attrs.imgId}. Just give the composite a fixed id. They are already naming containers themselves. JSF will then worry about the rest.
<composite:implementation>
<h:form id="f">
<h:graphicImage id="i" ... />
<h:inputHidden id="k" ... />
</h:form>
</composite:implementation>
Usage:
<comps:cimg id="imgA" />
Generated HTML:
<form id="imgA:f" ...>
<img id="imgA:f:i" ... />
<input id="imgA:f:k" ... />
</form>
As to the JS attempt, you'd best use element's own ID as base:
<h:graphicImage onclick="document.getElementById(id.substring(0,id.lastIndexOf(':')+1)+'k').value='...'" />
Or, easier, if the hidden element is guaranteed to be the direct sibling of the image element in the generated HTML DOM tree, then just grab it by Node#nextSibling:
<h:graphicImage onclick="nextSibling.value='...'" />
<h:inputHidden ... />
The binding will never work as in your attempted construct, and even then you'd best do it via a Map in request scope or a so-called backing component.
See also:
Accessing JSF nested composite component elements in JavaScript
Integrate JavaScript in JSF composite component, the clean way
Rerendering composite component by ajax

JSF User Management

Im building a few JSF interfaces that im going to embedd into a website. I want though to allow the user to log into the website inorder to view another JSF interface where they can update details about the services the website will offer.
What I want to know is, do I need to implemented a Login/Registration facility from scratch or is there an existing system already out there that I can easily use. The db im using is a derby db and the application runs on a GF server.
Or can someone recommend some good resources on building a custom user site using JSF?
Sorry if this question has been asked before and I missed it in my searches before.
P
All the textbooks seem to mention container-managed security but I have always stayed away from it. In every application I have done so far I have implemented application-managed authentication, which gives you much more flexibility with regard to how authentication is done. The price of course is you will have to allocate a couple of days to implementing and fiddling with it.
The key to making it easy is to 1) incorporate the authentication right in your Facelets template that all pages use so you always have it, and 2) have a #SessionScoped bean which holds the state of the user login. In the application I am working on now the top part of the template looks like this:
<div id="top" class="top" style="min-height: 40px">
<h:form id="formLogout" style="float: right"
rendered="#{userSession.loggedIn}">
<h:outputText
value="Logged In As: #{userSession.sysUser.handle} "
rendered="#{userSession.loggedIn}" />
<p:commandLink value="Logout"
ajax="false"
action="#{userSession.logoutUser}" />
</h:form>
<h:panelGrid style="float: right" rendered="#{!userSession.loggedIn}" >
<h:form id="formLogin">
<h:outputLabel value="User Handle: " />
<p:inputText size="16" value="#{userSession.loginHandle}" />
<h:outputLabel value=" Password: " />
<p:password value="#{userSession.loginPassword}" />
<p:commandButton value="Login"
ajax="false"
action="#{userSession.login}" />
<h:link outcome="/newUser" value=" New User" />
<h:commandLink action="#{userSession.loginAlan}" value="A" />
</h:form>
</h:panelGrid>
<h:link outcome="/index" value="MyWebApp v#{wisApp.ver}" />
<h:outputText value=" " />
</div>
I'll not bore you with the UserSession bean since it should be pretty obvious. The sysUser property is actually a JPA entity fetched from the Derby data base.
(Note the extra h:commandLink value="A". That's a link that automatically logs me in so I don't have to type my username and password over and over again while developing.)
That should probably be what you need.

JSF datatable with paging and sorting and browser-back

We are using Primefaces datatable component with sorting, pagination and a LazyDataModel in order to display search results. The backing bean of the search page is ViewScoped.
From the search result list a user can select a result item in order to view the details. This is implemented as a new page request, e.g. <h:link value="Show Details" outcome="showDetails?id=11234"/>. By clicking the browser back button the user will navigate back to the search result list.
The problem is that the datatable will be in initial state again, so it wont display the last selected sort order and page. This is the case in most browsers, only Firefox 11 seems to keep those DOM changes in cache. Neither IE nor Chrome.
Does anybody has a good approach how to handle this? We actually don't need "ajaxified" sorting and paging. We would prefer handling everything through ViewParams, but this seems not to be supported by primefaces.
I ran into this as well, and I developed a coding pattern that might help. It isn't really a PrimeFaces thing (which I am using as well) -- more of a technique for using book-markable links with JSF 2.
In the markup, I include all the parameters for the page as follows:
<f:metadata>
<f:viewParam name="orderID" value="#{bean.orderID}" />
<f:viewParam name="sortMode" value="#{bean.sortMode}" />
<f:viewParam name="firstRecord" value="#{bean.firstRecord}" />
<f:viewParam name="pageSize" value="#{bean.pageSize}" />
</f:metadata>
Each of those values is backed in the backing bean such that, if they are not set, they produce a suitable default value. For example:
public int getPageSize() {
if (pageSize < MIN_PAGE_SIZE) pageSize = DEF_PAGE_SIZE;
if (pageSize > MAX_PAGE_SIZE) pageSize = DEF_PAGE_SIZE;
return pageSize;
}
A link to this view can be generated as follows:
Now you implement user controls to change those values, and regenerate the table each time they are changed. You should still use AJAX for that -- for example:
<p:spinner value=#{bean.pageSize} >
<p:ajax update="tableID" />
</p:spinner>
In the setter methods, you have to trigger the re-generation of the table, but that's the gist of it. I hope this helps.
UPDATE:
To handle pagination, you simply need to add links for first page, prior page, next page, etc. The links will look something like this:
<h:link value="First Page" outcome="thisPage">
<f:param name="orderID" value="#{bean.orderID}" />
<f:param name="sortMode" value="#{bean.sortMode}" />
<f:param name="firstRecord" value="0" />
<f:param name="pageSize" value="#{bean.pageSize}" />
</h:link>
<h:link value="Next Page" outcome="thisPage">
<f:param name="orderID" value="#{bean.orderID}" />
<f:param name="sortMode" value="#{bean.sortMode}" />
<f:param name="firstRecord" value="#{bean.nextRecord}" />
<f:param name="pageSize" value="#{bean.pageSize}" />
</h:link>
etc. You need to implement properties in the backing bean to calculate what the firstRecord param ought to be.

Java facelets dynamic loading and composite component attributes

Currently I'm trying to implement webpart technology with JavaServer Faces 2.0 with Facelets view technology for educational purposes. I have created facelet templates, facelet custom components and made a few facelet "template" clients. But in one thing I'm stuck. I can't dynamically load controls and put them cc:attributes.
If I have a page for example with static text or bind it with ManagedBean the property ui:include everything works well.
<ui:define name="right-column">
right-column asd
<h:link outcome="asdf" value="link_get">
<f:param name="aa" value="123" />
<f:param name="a" value="123 dd + 20" />
</h:link>
<h:commandLink action="asdf?faces-redirect=true" value="asdf">
<f:param name="aa" value="123" />
</h:commandLink><br />
<ui:include src="./resources/Controls/CategoryTree.xhtml"/><br />
This works even if I put src with MenageBean property.
<ui:include src="#{browseProducts.incudePath}"/>
</ui:define>
Here is my facelet control (data binding is inside this control within #{TreeBean.root}:
<!-- NO INTERFACE -->
<cc:interface>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<!-- This is a very simply scaffolding for Category Three Control.
-->
<p:tree value="#{TreeBean.root}" var="node"
expandAnim="FADE_IN" collapseAnim="FADE_OUT">
<p:treeNode>
<h:outputText value="#{node}" />
</p:treeNode>
</p:tree>
</cc:implementation>
But I have problem when ui:include points to a control with cc:attribute. I don't know how to initialize this attribute from backing bean and do "stuff".
For example I have this page:
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
template="./resources/layout/Template.xhtml"
xmlns:sc="http://java.sun.com/jsf/composite/Controls">
<ui:define name="right-column">
<sc:dummy ItemCount="10" />
<ui:include src="./resources/Controls/dummy.xhtml" />
</ui:define>
</ui:composition>
Here goes the composite control:
<cc:interface>
<cc:attribute name="ItemCount" required="true"
shortDescription="This attribute is meaningful " />
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<!-- How to pass ItemCount to my dummy bean to create so many items in
list as ItemCount value -->
<ui:repeat value="#{dummy.dummyList}" var="dummyItem">
<h:outputText value="#{dummyItem}" />
</ui:repeat>
</cc:implementation>
And backing bean code:
public ArrayList<String> getDummyList() {
//Here I try to get dummy list work.
dummyList = new ArrayList<String>(getDummyCount());
for (int i=0;i< getDummyCount();i++){
dummyList.add(i + "" + i);
}
return dummyList;
}
How can this be done?
I think you have two problems:
calling a method with parameter from a composite component
specifying some parameter to an included page
For 1., since jsf 2, you could call the method directly, specifying the parameter (which should be part of method signature):
<ui:repeat value="#{dummy.getDummyList(cc.attrs.dummyCode)}" var="dummyItem">
<h:outputText value="#{dummyItem}" />
</ui:repeat>
But I suspect you are trying to use a backing for something that it isn't designed for. Maybe you'll be interested in writing backing java code for your composite component, which is different. It's difficult to master if you are a beginner, though. I'd first try to design my pages and bean interactions differently. I don't know which problem you are trying to solve, but at first look, this solution looks too complicated.
For 2., you should have a look at ui:param. A quick google search gives me this: http://www.jsfcentral.com/articles/facelets_3.html

Resources