/*
* Copyright 2009-2012 by KNURT Systeme (http://www.knurt.de)
*
* Licensed under the Creative Commons License Attribution-NonCommercial-ShareAlike 3.0 Unported;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://creativecommons.org/licenses/by-nc-sa/3.0/
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.knurt.fam.template.model;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import de.knurt.fam.core.aspects.logging.FamLog;
import de.knurt.fam.core.aspects.security.auth.SessionAuth;
import de.knurt.fam.core.model.config.FileUploadController;
import de.knurt.fam.core.model.persist.User;
import de.knurt.fam.core.persistence.cookie.CookieResolver;
import de.knurt.fam.core.persistence.dao.FamDaoProxy;
import de.knurt.fam.core.util.mvc.RequestInterpreter;
import de.knurt.fam.core.view.text.FamDateFormat;
import de.knurt.fam.template.util.TemplateConfig;
import de.knurt.heinzelmann.util.CookieUtils;
/**
* a bean haveing a name a filename and a suffix for eache resource. this depends on how urlrewrite is mapping it. as a default, mapping works:
*
* <pre>
* http://www.my-address.com/[name]/[filename].[suffix]
* </pre>
*
* @author Daniel Oltmanns
* @since 1.3.0 (10/06/2010)
*/
public class TemplateResource {
public static enum Visibility {
PUBLIC, PROTECTED, ADMIN
};
private TemplateResource(HttpServletRequest request, WritingResultProperties writingResultProperties) {
this.request = request;
this.writingResultProperties = writingResultProperties;
}
private String name, filename, suffix, templateFile = "page.html";
private User authUser;
private boolean invalidSession = false;
private boolean invalidAuth = false;
private boolean lostSession = false;
private boolean loggedOut = false;
private boolean unknownUser = false;
private boolean accountExpired = false;
private final HttpServletRequest request;
private WritingResultProperties writingResultProperties;
public SessionAuth getSession() {
return SessionAuth.getInstance(this.request);
}
public String getTemplateFile() {
return templateFile;
}
public WritingResultProperties getWritingResultProperties() {
return writingResultProperties;
}
/**
* return true, if the session is set to invalid. this is cause of missing inputs - first of all accepting the terms.
*
* @return true, if the session is set to invalid.
*/
public boolean isInvalidSession() {
return invalidSession;
}
public boolean isUnknownUser() {
return unknownUser;
}
public boolean isAccountExpired() {
return accountExpired;
}
public boolean isInvalidAuth() {
return invalidAuth;
}
public boolean isLostSession() {
return lostSession;
}
public boolean isLoggedOut() {
return loggedOut;
}
public User getAuthUser() {
return authUser;
}
/**
* return the visibility of the page on content pages. for other pages (like for images, css or js files) return {@link Visibility#PUBLIC}.
*
* @see Visibility
* @see #isRequestForContent()
* @return the visibility of the page on content pages.
*/
public Visibility getVisibility() {
Visibility result = Visibility.PUBLIC;
if (this.isRequestForContent()) {
// it's a request for html or json
String v = TemplateConfig.me().getContentProperties().getCustomConfigPage(this.name).getAttributeValue("visibility");
if (v.equals("admin")) {
result = Visibility.ADMIN;
} else if (v.equals("protected")) {
result = Visibility.PROTECTED;
} else { // if (v.equals("public")) {
result = Visibility.PUBLIC;
}
}
return result;
}
public HttpServletRequest getRequest() {
return request;
}
public String getName() {
return name;
}
public String getFilename() {
return filename;
}
public String getSuffix() {
return suffix;
}
/** {@inheritDoc} */
@Override
public String toString() {
return String.format("name: %s, suffix: %s, filename: %s, visibility: %s", this.getName(), this.getSuffix(), this.getFilename(), this.getVisibility());
}
public static TemplateResource getTemplateResource(HttpServletResponse response, HttpServletRequest request, String filename, String resourceName, String suffix) {
return getTemplateResource(response, request, filename, resourceName, suffix, null);
}
private static void setCookiePageAfterLogin(TemplateResource tr, HttpServletResponse response, HttpServletRequest request) {
if (!tr.name.equals("logout")) {
CookieResolver.getInstance().addTemplateResourceAfterLogin(response, request, tr);
}
}
private static void killCookiesOnLogoutPage(TemplateResource tr, HttpServletResponse response, HttpServletRequest request) {
if (tr.name.equals("logout")) {
CookieUtils.deleteAll(request, response);
}
}
public static TemplateResource getTemplateResource(HttpServletResponse response, HttpServletRequest request, String filename, String resourceName, String suffix, WritingResultProperties writingResultProperties) {
TemplateResource result = new TemplateResource(request, writingResultProperties);
// set basics template resource
result.authUser = SessionAuth.user(request);
result.filename = filename;
result.name = resourceName;
result.suffix = suffix;
// set basics session vars
boolean hasAuthUser = SessionAuth.authUser(request);
User authUser = hasAuthUser ? SessionAuth.user(request) : null;
// reload the configuration if you have an auth user and a reload of it
// is requested
if (result.configurationReloadIsRequested()) {
TemplateConfig.me().getContentProperties().reload();
FileUploadController.reinitOptions();
}
// correct only on html stuff
if (result.suffix.equals("html")) {
// set invalid session
if (!hasAuthUser || !authUser.hasRight2ViewPage(result.name) || ((authUser.isAcceptedStatementOfAgreement() != true || authUser.hasUnsufficientContactDetails()) && !authUser.isAdmin())) {
result.invalidSession = true;
}
killCookiesOnLogoutPage(result, response, request);
// correct vars on specific pages
try {
// check auth
switch (result.getVisibility()) {
case PROTECTED:
if (!result.name.equals("login") && !hasAuthUser && !RequestInterpreter.containsDirectAccess(resourceName, request)) {
// ↖ login failed
setCookiePageAfterLogin(result, response, request);
result.invalidAuth = request.getMethod().equals("POST") && result.name.equals("corehome");
result.loggedOut = result.name.equals("logout");
result.lostSession = !result.name.equals("corehome") && !result.name.equals("login");
result.name = "login";
}
break;
case ADMIN:
if (result.name.equals("admin") == false && (!hasAuthUser || !authUser.hasAdminTasks()) && !RequestInterpreter.containsDirectAccess(resourceName, request)) {
// ↖ login failed
setCookiePageAfterLogin(result, response, request);
result.invalidAuth = request.getMethod().equals("POST");
result.lostSession = !result.invalidAuth;
result.loggedOut = result.name.equals("logout");
result.name = "admin";
result.invalidSession = true;
}
break;
default:
break;
}
// more detailed message on invalid auth - ticket #262
if (result.invalidAuth) {
String username = request.getParameter("username");
User user = null;
if (username != null) {
user = FamDaoProxy.userDao().getUserFromUsername(username);
};
result.unknownUser = user == null;
if (!result.unknownUser) {
result.accountExpired = user.isAccountExpired();
}
}
// set a redirect in case of invalid session
if (hasAuthUser && authUser.hasUnsufficientContactDetails(false)) {
result.name = "contactdetails";
} else if (hasAuthUser && authUser.isAcceptedStatementOfAgreement() == false) {
result.name = "termsofuse";
} else if (hasAuthUser && result.invalidSession) {
result.name = "login";
}
// correct pages not shown when user is auth ...
if (hasAuthUser && authUser.isAdmin()) {
String[] doNotShowPages = { "admin" };
// do not show this pages
// when someone has admin
// auth
for (String doNotShowPage : doNotShowPages) {
if (result.name.equals(doNotShowPage)) {
result.name = "adminhome";
break;
}
}
}
if (hasAuthUser) {
String[] doNotShowPages = { "register", "registersent", "login" };
// do not show this pages when someone has protected auth
for (String doNotShowPage : doNotShowPages) {
if (result.name.equals(doNotShowPage)) {
result.name = "corehome";
break;
}
}
}
} catch (NullPointerException e) {
// ↖ url hack
result.name = "home";
}
}
if (result.newsReloadIsRequested()) {
result.getSession().setNewsItems(null);
}
return result;
}
public void setTemplateFile(String templateFile) {
this.templateFile = templateFile;
}
public boolean hasAuthUser() {
return this.getAuthUser() != null;
}
public void putWritingResultProperty(Object key, Object value) {
if (writingResultProperties == null) {
writingResultProperties = new WritingResultProperties();
}
writingResultProperties.put(key, value);
}
/**
* return true, if this is a request for content.
*
* @return true, if this is a request for content.
*/
public boolean isRequestForContent() {
return this.suffix.equals("html") || this.suffix.equals("json");
}
public boolean configurationReloadIsRequested() {
return this.hasAuthUser() && request.getParameter("reload") != null && request.getParameter("reload").equals("config");
}
/**
* return true, if the minute in the cookie has a different of five to the minute now. this is unexactly in case of reloading page in 60 minutes
* again, but exactly enough for this.
*/
private boolean newsReloadIsRequested() {
boolean result = false;
int minuteLastUpdate = -1;
if (this.hasAuthUser()) {
result = this.name.equals("corehome");
if (!result) {
try {
minuteLastUpdate = Integer.parseInt(CookieUtils.getCookieValue(this.request, "LastNewsUpdate"));
} catch (Exception e) {
// NOP or NumberFormatException or ???Exception means:
// there is no cookie value!
result = true;
}
}
if (!result) {
try {
int minuteNow = Integer.parseInt(FamDateFormat.getCustomDate("m"));
result = Math.abs(minuteNow - minuteLastUpdate) >= 5;
} catch (NumberFormatException e) {
FamLog.exception(e, 201204270903l);
}
}
}
return result;
}
/**
* short for {@link #getRequest()}.getParameter
*
* @see HttpServletRequest#getParameter(String)
*
* @param key of searched parameter
* @return value
*/
public String getRequestParameter(String key) {
return this.getRequest().getParameter(key);
}
}