reogranized source code
This commit is contained in:
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2017 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.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.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.Account;
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.annotation.ManagedBean;
|
||||
import javax.ejb.EJB;
|
||||
import javax.enterprise.context.SessionScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ManagedBean
|
||||
@SessionScoped
|
||||
public class AccountProducer implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3806204732038165311L;
|
||||
private final Map<String, Object> objectMap = new ConcurrentHashMap<>();
|
||||
|
||||
@EJB
|
||||
AccountControl accountController;
|
||||
|
||||
private Account account = null;
|
||||
|
||||
@Produces
|
||||
public Account getAccount() {
|
||||
String accountName;
|
||||
if (account == null) {
|
||||
Subject subject = SecurityUtils.getSubject();
|
||||
if (subject == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((subject.isAuthenticated() == false) && (subject.isRemembered() == false)) {
|
||||
accountName = "web";
|
||||
} else {
|
||||
accountName = subject.getPrincipal().toString();
|
||||
}
|
||||
account = accountController.getAccountEntity(accountName, true);
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
public <T> T getValue(String key, Class<T> clazz) {
|
||||
if (objectMap.containsKey(key)) {
|
||||
Object obj = objectMap.get(key);
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return clazz.cast(obj);
|
||||
} catch (ClassCastException ex) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(String key, Object obj) {
|
||||
objectMap.put(key, obj);
|
||||
}
|
||||
|
||||
@Produces
|
||||
public Locale getLocale() {
|
||||
return Locale.ENGLISH; // TODO depend lcoale on account or on incoming request
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
package de.muehlencord.shared.account.business.account.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountStatus;
|
||||
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2018 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.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.muehlencord.shared.account.business.application.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.context.Initialized;
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class StartupBean {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(StartupBean.class);
|
||||
|
||||
@Inject
|
||||
ConfigService configService;
|
||||
|
||||
@Inject
|
||||
ApplicationEntity application;
|
||||
|
||||
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
|
||||
try {
|
||||
LOGGER.info("Starting application {}", application.getApplicationName());
|
||||
String instanceName = configService.getConfigValue("base.instance", "Development System", true);
|
||||
LOGGER.info("instanceName={}", instanceName);
|
||||
|
||||
// ensure maxFailedLogins is available
|
||||
configService.getConfigValue("account.maxFailedLogins", "5", true);
|
||||
|
||||
LOGGER.info("Application startup complete");
|
||||
} catch (ConfigException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.error(ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void shutdown() {
|
||||
LOGGER.info("Shutting down application {}", application.getApplicationName());
|
||||
|
||||
|
||||
LOGGER.info("Application shutdown complete");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright 2018 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.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.muehlencord.shared.account.business.application.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.boundary.ApplicationService;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ejb.EJB;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.inject.Named;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Named("applicationController")
|
||||
@ApplicationScoped
|
||||
public class ApplicationController {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationController.class);
|
||||
|
||||
@EJB
|
||||
ApplicationService applicationService;
|
||||
|
||||
private String version;
|
||||
private String buildDate;
|
||||
private UUID uuid;
|
||||
private ApplicationEntity application = null;
|
||||
|
||||
@PostConstruct
|
||||
public void readBuildInfoProperties() {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Trying to read buildInfo.properties");
|
||||
}
|
||||
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("buildInfo.properties");
|
||||
if (in == null) {
|
||||
return;
|
||||
}
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(in);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("properties read from buildInfo.properties");
|
||||
}
|
||||
|
||||
version = props.getProperty("build.version");
|
||||
buildDate = props.getProperty("build.timestamp");
|
||||
uuid = UUID.fromString(props.getProperty("application.uuid"));
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("buildInfo.properties parsed successfully");
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Cannot find buildInfo.properties. ", ex);
|
||||
version = "??";
|
||||
buildDate = "??";
|
||||
uuid = null;
|
||||
LOGGER.error("Application id not readable, application will not be able to run");
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
this.application = applicationService.findById(uuid);
|
||||
if (application == null) {
|
||||
LOGGER.error("Could not find application with id ");
|
||||
} else {
|
||||
LOGGER.info("Found application {} with id {}", application.getApplicationName(), uuid.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* needs to return link to "Account UI" and not to current selected
|
||||
* application TODO: ensure only Account UI can call functions where
|
||||
* appliction can be handed in - all other applications need to call the
|
||||
* function which use the injected application
|
||||
*/
|
||||
@Produces
|
||||
public ApplicationEntity getApplication() {
|
||||
return application;
|
||||
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getBuildDate() {
|
||||
return buildDate;
|
||||
}
|
||||
|
||||
public UUID getApplicationId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
package de.muehlencord.shared.account.business.application.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.account.entity.ApplicationPermissionEntity;
|
||||
@ -3,7 +3,7 @@
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
package de.muehlencord.shared.account.business.application.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.account.entity.ApplicationPermissionEntity;
|
||||
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.accountconfig.entity.AccountConfigurationKey;
|
||||
import de.muehlencord.shared.account.business.accountconfig.entity.AccountConfigurationValue;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import javax.ejb.EJB;
|
||||
import javax.enterprise.context.Dependent;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.enterprise.inject.spi.Annotated;
|
||||
import javax.enterprise.inject.spi.InjectionPoint;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Dependent
|
||||
public class ConfigurationProducer {
|
||||
|
||||
@EJB
|
||||
ConfigService configService;
|
||||
|
||||
@Produces
|
||||
@AccountConfigurationValue(key = AccountConfigurationKey.Producer)
|
||||
public String produceConfigurationValue(InjectionPoint injectionPoint) {
|
||||
Annotated annotated = injectionPoint.getAnnotated();
|
||||
AccountConfigurationValue annotation = annotated.getAnnotation(AccountConfigurationValue.class);
|
||||
if (annotation != null) {
|
||||
AccountConfigurationKey key = annotation.key();
|
||||
if (key != null) {
|
||||
try {
|
||||
switch (key) {
|
||||
case BaseUrl:
|
||||
return configService.getConfigValue("base.url");
|
||||
case PasswordResetUrl:
|
||||
return configService.getConfigValue("base.url") + "/login.xhtml";
|
||||
default:
|
||||
throw new IllegalStateException("Invalid key " + key + " for injection point: " + injectionPoint);
|
||||
}
|
||||
} catch (ConfigException ex) {
|
||||
throw new IllegalStateException("Invalid key " + key + " for injection point: " + injectionPoint + ". Exception: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No key for injection point: " + injectionPoint);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,185 +1,185 @@
|
||||
package de.muehlencord.shared.account.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.boundary.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Named;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Named(value = "loginView")
|
||||
@ViewScoped
|
||||
public class LoginView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1164860380769648432L;
|
||||
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
|
||||
private String username = null;
|
||||
private String password = null;
|
||||
private boolean rememberMe = false;
|
||||
|
||||
private String resetPasswordToken = null;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class.getName());
|
||||
|
||||
public void authenticate() {
|
||||
|
||||
// Example using most common scenario of username/password pair:
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(getUsername(), getPassword());
|
||||
|
||||
// "Remember Me" built-in:
|
||||
token.setRememberMe(rememberMe);
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
LOGGER.info("Trying to login user {}", username);
|
||||
|
||||
try {
|
||||
currentUser.login(token);
|
||||
LOGGER.info("User {} logged in", username);
|
||||
// user logged in, update account entity
|
||||
AccountEntity account = accountService.getAccountEntity(username, true);
|
||||
accountService.updateLogin(account);
|
||||
|
||||
// redirect to home
|
||||
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
|
||||
ServletResponse servletResponse = (ServletResponse) ec.getResponse();
|
||||
String fallbackUrl = "/web/index.xhtml"; // TODO make configurable
|
||||
// ec.redirect(url);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("redirecting to {}, fallbackUrl={}", servletResponse.toString(), fallbackUrl);
|
||||
}
|
||||
|
||||
WebUtils.redirectToSavedRequest((ServletRequest) ec.getRequest(), servletResponse, fallbackUrl);
|
||||
} catch (IOException | AuthenticationException ex) {
|
||||
// Could catch a subclass of AuthenticationException if you like
|
||||
String hint = "Error while authenticating user " + username;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(hint, ex);
|
||||
}
|
||||
|
||||
if (ex.getMessage() != null) {
|
||||
hint += "Reason: " + ex.getMessage();
|
||||
} else {
|
||||
hint += "Reason: " + ex.toString();
|
||||
}
|
||||
if ((ex.getCause() != null) && (ex.getCause().getMessage() != null)) {
|
||||
hint += "Rootcause: " + ex.getMessage();
|
||||
|
||||
LOGGER.error(hint);
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Login failed", hint);
|
||||
|
||||
AccountEntity account = accountService.getAccountEntity(username, false);
|
||||
if (account != null) {
|
||||
accountService.addLoginError(account);
|
||||
}
|
||||
} finally {
|
||||
token.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
try {
|
||||
currentUser.logout();
|
||||
|
||||
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
|
||||
|
||||
// check if redirect shall be executed
|
||||
// default setting is yes to /login.xhtml
|
||||
// can be overwritten using parameters
|
||||
// de.muehlencord.shared.account.loginview.executeredirect boolean true/false
|
||||
// de.muehlencord.shared.account.loginview.redirecttarget path to redirect to (without external context, will be added automatically)
|
||||
String executeRedirectString = ec.getInitParameter("de.muehlencord.shared.account.loginview.executeredirect");
|
||||
boolean executeRedirect = true;
|
||||
if (executeRedirectString != null) {
|
||||
executeRedirect = Boolean.parseBoolean(executeRedirectString);
|
||||
}
|
||||
|
||||
String redirectTarget = ec.getInitParameter("de.muehlencord.shared.account.loginview.redirecttarget");
|
||||
if ((redirectTarget == null) || (redirectTarget.equals(""))) {
|
||||
redirectTarget = "/login.xhtml";
|
||||
}
|
||||
|
||||
if (executeRedirect) {
|
||||
String url = ec.getRequestContextPath() + redirectTarget;
|
||||
ec.redirect(url);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public String executePasswordReset() {
|
||||
boolean passwordResetted = accountService.resetPassword(username, password, resetPasswordToken);
|
||||
if (passwordResetted) {
|
||||
// TODO add email notification on updated user account
|
||||
FacesUtil.addGlobalInfoMessage("Password resetted", null);
|
||||
return login();
|
||||
} else {
|
||||
// TODO add email notificaton on failed password reset
|
||||
FacesUtil.addGlobalErrorMessage("Password reset failed", null);
|
||||
return login();
|
||||
}
|
||||
}
|
||||
|
||||
/* **** naviation rules **** */
|
||||
public String login() {
|
||||
return "/login.xhtml"; // TODO make configurable
|
||||
}
|
||||
|
||||
/* *** getter / setter */
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String un) {
|
||||
this.username = un;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String pw) {
|
||||
this.password = pw;
|
||||
}
|
||||
|
||||
public boolean isRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public void setRememberMe(boolean rememberMe) {
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
|
||||
public String getResetPasswordToken() {
|
||||
return resetPasswordToken;
|
||||
}
|
||||
|
||||
public void setResetPasswordToken(String resetPasswordToken) {
|
||||
this.resetPasswordToken = resetPasswordToken;
|
||||
}
|
||||
|
||||
}
|
||||
package de.muehlencord.shared.account.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Named;
|
||||
import javax.naming.NamingException;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Named(value = "loginView")
|
||||
@ViewScoped
|
||||
public class LoginView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1164860380769648432L;
|
||||
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
|
||||
private String username = null;
|
||||
private String password = null;
|
||||
private boolean rememberMe = false;
|
||||
|
||||
private String resetPasswordToken = null;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class.getName());
|
||||
|
||||
public void authenticate() {
|
||||
|
||||
// Example using most common scenario of username/password pair:
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(getUsername(), getPassword());
|
||||
|
||||
// "Remember Me" built-in:
|
||||
token.setRememberMe(rememberMe);
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
LOGGER.info("Trying to login user {}", username);
|
||||
|
||||
try {
|
||||
currentUser.login(token);
|
||||
LOGGER.info("User {} logged in", username);
|
||||
// user logged in, update account entity
|
||||
AccountEntity account = accountService.getAccountEntity(username, true);
|
||||
accountService.updateLogin(account);
|
||||
|
||||
// redirect to home
|
||||
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
|
||||
ServletResponse servletResponse = (ServletResponse) ec.getResponse();
|
||||
String fallbackUrl = "/web/index.xhtml"; // TODO make configurable
|
||||
// ec.redirect(url);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("redirecting to {}, fallbackUrl={}", servletResponse.toString(), fallbackUrl);
|
||||
}
|
||||
|
||||
WebUtils.redirectToSavedRequest((ServletRequest) ec.getRequest(), servletResponse, fallbackUrl);
|
||||
} catch (IOException | AuthenticationException ex) {
|
||||
// Could catch a subclass of AuthenticationException if you like
|
||||
String hint = "Error while authenticating user " + username;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(hint, ex);
|
||||
}
|
||||
|
||||
if (ex.getMessage() != null) {
|
||||
hint += "Reason: " + ex.getMessage();
|
||||
} else {
|
||||
hint += "Reason: " + ex.toString();
|
||||
}
|
||||
if ((ex.getCause() != null) && (ex.getCause().getMessage() != null)) {
|
||||
hint += "Rootcause: " + ex.getMessage();
|
||||
|
||||
LOGGER.error(hint);
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Login failed", hint);
|
||||
|
||||
AccountEntity account = accountService.getAccountEntity(username, false);
|
||||
if (account != null) {
|
||||
accountService.addLoginError(account);
|
||||
}
|
||||
} finally {
|
||||
token.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
try {
|
||||
currentUser.logout();
|
||||
|
||||
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
|
||||
|
||||
// check if redirect shall be executed
|
||||
// default setting is yes to /login.xhtml
|
||||
// can be overwritten using parameters
|
||||
// de.muehlencord.shared.account.loginview.executeredirect boolean true/false
|
||||
// de.muehlencord.shared.account.loginview.redirecttarget path to redirect to (without external context, will be added automatically)
|
||||
String executeRedirectString = ec.getInitParameter("de.muehlencord.shared.account.loginview.executeredirect");
|
||||
boolean executeRedirect = true;
|
||||
if (executeRedirectString != null) {
|
||||
executeRedirect = Boolean.parseBoolean(executeRedirectString);
|
||||
}
|
||||
|
||||
String redirectTarget = ec.getInitParameter("de.muehlencord.shared.account.loginview.redirecttarget");
|
||||
if ((redirectTarget == null) || (redirectTarget.equals(""))) {
|
||||
redirectTarget = "/login.xhtml";
|
||||
}
|
||||
|
||||
if (executeRedirect) {
|
||||
String url = ec.getRequestContextPath() + redirectTarget;
|
||||
ec.redirect(url);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public String executePasswordReset() {
|
||||
boolean passwordResetted = accountService.resetPassword(username, password, resetPasswordToken);
|
||||
if (passwordResetted) {
|
||||
// TODO add email notification on updated user account
|
||||
FacesUtil.addGlobalInfoMessage("Password resetted", null);
|
||||
return login();
|
||||
} else {
|
||||
// TODO add email notificaton on failed password reset
|
||||
FacesUtil.addGlobalErrorMessage("Password reset failed", null);
|
||||
return login();
|
||||
}
|
||||
}
|
||||
|
||||
/* **** naviation rules **** */
|
||||
public String login() {
|
||||
return "/login.xhtml"; // TODO make configurable
|
||||
}
|
||||
|
||||
/* *** getter / setter */
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String un) {
|
||||
this.username = un;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String pw) {
|
||||
this.password = pw;
|
||||
}
|
||||
|
||||
public boolean isRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public void setRememberMe(boolean rememberMe) {
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
|
||||
public String getResetPasswordToken() {
|
||||
return resetPasswordToken;
|
||||
}
|
||||
|
||||
public void setResetPasswordToken(String resetPasswordToken) {
|
||||
this.resetPasswordToken = resetPasswordToken;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,48 +1,48 @@
|
||||
package de.muehlencord.shared.account.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.boundary.AccountControl;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Named;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
@Named (value = "lostPasswordView")
|
||||
@ViewScoped
|
||||
public class LostPasswordView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1793445795465830069L;
|
||||
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
|
||||
private String userName;
|
||||
private boolean passwordResetStarted = false;
|
||||
|
||||
public String initPasswordReset() {
|
||||
if (accountService.initPasswordReset(userName)) {
|
||||
passwordResetStarted = true;
|
||||
FacesUtil.addGlobalInfoMessage("Password reset started.", "Please check your email account.");
|
||||
} else {
|
||||
FacesUtil.addGlobalErrorMessage("Error while resetting password.", "Please contact your administrator.");
|
||||
}
|
||||
return "/login.xhtml"; // TODO make configurable, get from LoginView?
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public boolean getPasswordResetStarted() {
|
||||
return passwordResetStarted;
|
||||
}
|
||||
|
||||
}
|
||||
package de.muehlencord.shared.account.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Named;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
@Named (value = "lostPasswordView")
|
||||
@ViewScoped
|
||||
public class LostPasswordView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1793445795465830069L;
|
||||
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
|
||||
private String userName;
|
||||
private boolean passwordResetStarted = false;
|
||||
|
||||
public String initPasswordReset() {
|
||||
if (accountService.initPasswordReset(userName)) {
|
||||
passwordResetStarted = true;
|
||||
FacesUtil.addGlobalInfoMessage("Password reset started.", "Please check your email account.");
|
||||
} else {
|
||||
FacesUtil.addGlobalErrorMessage("Error while resetting password.", "Please contact your administrator.");
|
||||
}
|
||||
return "/login.xhtml"; // TODO make configurable, get from LoginView?
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public boolean getPasswordResetStarted() {
|
||||
return passwordResetStarted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user