Skip to content
This repository has been archived by the owner on Jun 23, 2020. It is now read-only.

Commit

Permalink
More extensions:
Browse files Browse the repository at this point in the history
10. Navigation
11. Restricting pages to logged in users only
  • Loading branch information
Adam Warski committed May 24, 2010
1 parent 2f43e8e commit 677b786
Show file tree
Hide file tree
Showing 6 changed files with 223 additions and 1 deletion.
20 changes: 19 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,22 @@ By Gaving King, see http://in.relation.to/13053.lace.
A component for enqueing faces messages, which will survive redirects. Use:

@Inject
private FacesMessages facesMessages;
private FacesMessages facesMessages;

10. Navigation

Extend the NavBase to create a "nav" component and define any pages that you use the following way, using the PageBuilder:

private final Page page1 = new PageBuilder("/page1.xhtml").setRequiresLogin(true).b();
private final Page login = new PageBuilder("/login.xhtml").b();
...

And define a getter for each page.

You can then use the component either to return results of action methods or to create links:

<h:link outcome="#{nav.page1.s}">Page 1</h:link>

11. Restricting pages to logged in users only

There must be a bean implementing the LoginBean interface; the bean controls if there's a logged in user.
54 changes: 54 additions & 0 deletions src/main/java/pl/softwaremill/cdiext/navigation/NavBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package pl.softwaremill.cdiext.navigation;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* @author Adam Warski (adam at warski dot org)
*/
public abstract class NavBase {
private Map<String, Page> pagesByViewId= new HashMap<String, Page>();

public void register(String viewId, Page page) {
pagesByViewId.put(viewId, page);
}

public Page lookup(String viewId) {
Page p = pagesByViewId.get(viewId);
if (p == null) {
throw new RuntimeException("Page with view id " + viewId + " not found.");
}
return p;
}

protected class PageBuilder {
private final String viewId;

private boolean requiresLogin;

public PageBuilder(String viewId) {
this.viewId = viewId;
requiresLogin = false;
}

public PageBuilder setRequiresLogin(boolean requiresLogin) {
this.requiresLogin = requiresLogin;
return this;
}

public Page b() {
Page p = new Page(viewId, new LinkedHashMap<String, String>(), requiresLogin);
register(viewId, p);
return p;
}
}

private final Page currentPage = new PageBuilder("").b();

public Page getCurrentPage() {
return currentPage;
}

public abstract Page getLogin();
}
88 changes: 88 additions & 0 deletions src/main/java/pl/softwaremill/cdiext/navigation/Page.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package pl.softwaremill.cdiext.navigation;

import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewParameter;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.view.ViewDeclarationLanguage;
import javax.faces.view.ViewMetadata;
import java.util.LinkedHashMap;
import java.util.Map;

/**
* @author Adam Warski (adam at warski dot org)
*/
public class Page {
private final String viewId;
private final Map<String, String> params;
private final boolean requiresLogin;

public Page(String viewId, Map<String, String> params, boolean requiresLogin) {
this.viewId = viewId;
this.params = params;
this.requiresLogin = requiresLogin;
}

public Page redirect() {
return includeParam("faces-redirect", "true");
}

public Page includeViewParams() {
return includeParam("includeViewParams", "true");
}

public Page includeViewParam(String name) {
// Getting the metadata facet of the view
FacesContext ctx = FacesContext.getCurrentInstance();
ViewDeclarationLanguage vdl = ctx.getApplication().getViewHandler().getViewDeclarationLanguage(ctx, viewId);
ViewMetadata viewMetadata = vdl.getViewMetadata(ctx, viewId);
UIViewRoot viewRoot = viewMetadata.createMetadataView(ctx);
UIComponent metadataFacet = viewRoot.getFacet(UIViewRoot.METADATA_FACET_NAME);

// Looking for a view parameter with the specified name
UIViewParameter viewParam = null;
for (UIComponent child : metadataFacet.getChildren()) {
if (child instanceof UIViewParameter) {
UIViewParameter tempViewParam = (UIViewParameter) child;
if (name.equals(tempViewParam.getName())) {
viewParam = tempViewParam;
break;
}
}
}

if (viewParam == null) {
throw new FacesException("Unknown parameter: '" + name + "' for view: " + viewId);
}

// Getting the value
String value = viewParam.getStringValue(ctx);
return includeParam(name, value);
}

public Page includeParam(String name, String value) {
Map<String, String> newParams = new LinkedHashMap<String, String>(params);
newParams.put(name, value);
return new Page(viewId, newParams, requiresLogin);
}

public String s() {
StringBuilder sb = new StringBuilder();
sb.append(viewId);

String paramSeparator = "?";
for (Map.Entry<String, String> nameValue : params.entrySet()) {
sb.append(paramSeparator).append(nameValue.getKey()).append("=").append(nameValue.getValue());
paramSeparator = "&amp;";
}

return sb.toString();
}

public String getS() { return s(); }

public boolean isRequiresLogin() {
return requiresLogin;
}
}
12 changes: 12 additions & 0 deletions src/main/java/pl/softwaremill/cdiext/security/LoginBean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package pl.softwaremill.cdiext.security;

/**
* Should be implemented by the bean which controls the logged-in status of the user.
* @author Adam Warski (adam at warski dot org)
*/
public interface LoginBean {
/**
* @return True iff a user is currently logged in.
*/
boolean isLoggedIn();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package pl.softwaremill.cdiext.security;

import pl.softwaremill.cdiext.navigation.NavBase;
import pl.softwaremill.cdiext.util.BeanInject;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import java.io.IOException;

/**
* TODO: go back after a redirect to login
*
* TODO: secure the cache:
* //Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control","no-cache");
//Directs caches not to store the page under any circumstance
response.setHeader("Cache-Control","no-store");
//Causes the proxy cache to see the page as "stale"
response.setDateHeader("Expires", 0);
//HTTP 1.0 backward compatibility
response.setHeader("Pragma","no-cache");
* @author Adam Warski (adam at warski dot org)
*/
public class SecurityPhaseListener implements PhaseListener {
public void beforePhase(PhaseEvent event) {
NavBase nav = BeanInject.lookup(NavBase.class);
LoginBean login = BeanInject.lookup(LoginBean.class);

if (nav.lookup(event.getFacesContext().getViewRoot().getViewId()).isRequiresLogin() && !login.isLoggedIn()) {
FacesContext ctx = event.getFacesContext();
String url = ctx.getApplication().getViewHandler().getActionURL(ctx, nav.getLogin().s());
try {
ctx.getExternalContext().redirect(ctx.getExternalContext().encodeActionURL(url));
} catch (IOException e) {
throw new RuntimeException(e);
}
ctx.responseComplete();
}
}

public void afterPhase(PhaseEvent event) { }

@Override
public PhaseId getPhaseId() {
return PhaseId.RENDER_RESPONSE;
}
}
1 change: 1 addition & 0 deletions src/main/resources/META-INF/faces-config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">
<lifecycle>
<phase-listener>pl.softwaremill.cdiext.transaction.TransactionPhaseListener</phase-listener>
<phase-listener>pl.softwaremill.util.SecurityPhaseListener</phase-listener>
</lifecycle>

<application>
Expand Down

0 comments on commit 677b786

Please sign in to comment.