package org.openiam.selfsrvc.pswd;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.text.SimpleDateFormat;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.openiam.base.ws.ResponseStatus;
import org.openiam.idm.srvc.policy.ws.PolicyResponse;
import org.openiam.idm.srvc.pswd.ws.PasswordWebService;
import org.springframework.validation.BindException;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.CancellableFormController;
import org.springframework.web.servlet.mvc.SimpleFormController;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openiam.base.BaseObject;
import org.openiam.idm.srvc.policy.dto.Policy;
import org.openiam.idm.srvc.policy.dto.PolicyAttribute;
import org.openiam.idm.srvc.policy.service.PolicyDataService;
import org.openiam.idm.srvc.pswd.dto.IdentityQuestion;
import org.openiam.idm.srvc.pswd.dto.UserIdentityAnswer;
import org.openiam.idm.srvc.pswd.service.ChallengeResponseService;
import org.openiam.idm.srvc.secdomain.dto.SecurityDomain;
import org.openiam.idm.srvc.secdomain.service.SecurityDomainDataService;
import org.openiam.idm.srvc.user.service.UserDataService;
import org.springframework.web.servlet.view.RedirectView;
/**
* Controller for the new hire form.
* @author suneet
*
*/
public class IdentityQuestionController extends CancellableFormController {
//protected UserDataService userMgr;
protected PasswordConfiguration configuration;
protected PolicyDataService policyDataService;
protected SecurityDomainDataService secDomainService;
protected ChallengeResponseService challengeResponse;
protected PasswordWebService passwordService;
private static final Log log = LogFactory.getLog(IdentityQuestionController.class);
public IdentityQuestionController() {
super();
}
@Override
protected void initBinder(HttpServletRequest request,
ServletRequestDataBinder binder) throws Exception {
binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("MM/dd/yyyy"),true) );
}
@Override
protected Map referenceData(HttpServletRequest request) throws Exception {
// TODO Auto-generated method stub
return super.referenceData(request);
}
@Override
protected Object formBackingObject(HttpServletRequest request) throws Exception {
IdentityQuestionCommand cmd = new IdentityQuestionCommand();
int policyQuestionCount = 0;
Policy passwordPolicy = null;
HttpSession session = request.getSession();
String userId = (String)session.getAttribute("userId");
String login = (String) session.getAttribute("login");
SecurityDomain domain = secDomainService.getSecurityDomain(configuration.getDefaultSecurityDomain());
PolicyResponse policyResponse = passwordService.getPasswordPolicy(
configuration.getDefaultSecurityDomain(),
login, configuration.getDefaultManagedSysId());
if (policyResponse.getStatus() == ResponseStatus.SUCCESS) {
passwordPolicy = policyResponse.getPolicy();
}else {
passwordPolicy = policyDataService.getPolicy(domain.getPasswordPolicyId());
}
log.info("Selected policyId = " + passwordPolicy.getPolicyId() + " - " + passwordPolicy.getName());
// get the policies in place
PolicyAttribute countAttr = passwordPolicy.getAttribute("QUEST_COUNT");
PolicyAttribute questSrcAttr = passwordPolicy.getAttribute("QUEST_SRC");
PolicyAttribute questListAttr = passwordPolicy.getAttribute("QUEST_LIST");
log.info("formBackingObject: Question count=" + countAttr.getValue1());
policyQuestionCount = Integer.valueOf(countAttr.getValue1());
cmd.setQuestionCount(policyQuestionCount );
// check if answers to questions already exist for this user
List<UserIdentityAnswer> answerList = challengeResponse.answersByUser(userId);
if (answerList == null) {
// needed for the UI
answerList = prefillAnswerList(cmd.getQuestionCount());
}else {
setUpdateFlag(answerList);
}
log.info("Size of answerlist=" + answerList.size());
// handle a change in the password policy where we add or remove the number of questions
if (answerList.size() > policyQuestionCount ) {
// make the answerlist smaller
answerList = reduceAnswerList(answerList, policyQuestionCount);
}
if (answerList.size() < policyQuestionCount) {
// add empty nodes to the answer list
answerList = expandAnswerList(answerList, policyQuestionCount);
}
List<IdentityQuestion> questionList = challengeResponse.questionsByGroup(configuration.getDefaultChallengeResponseGroup());
log.info("question list size =" + questionList.size());
cmd.setAnswerList( answerList);
cmd.setQuestionList(questionList);
return cmd;
}
private void setUpdateFlag(List<UserIdentityAnswer> answerList) {
for (UserIdentityAnswer ans : answerList) {
ans.setObjectState(BaseObject.UPDATE);
}
}
private List<UserIdentityAnswer> reduceAnswerList(List<UserIdentityAnswer> answerList, int questionCount) {
List<UserIdentityAnswer> newAnswerList = new ArrayList<UserIdentityAnswer>();
for (int i=0; i < questionCount; i++) {
newAnswerList.add(answerList.get(i));
}
return newAnswerList;
}
private List<UserIdentityAnswer> expandAnswerList(List<UserIdentityAnswer> answerList, int questionCount) {
int curSize = answerList.size();
for (int i = curSize; i < questionCount; i++) {
UserIdentityAnswer ans = new UserIdentityAnswer();
ans.setIdentityAnsId(String.valueOf(i));
ans.setObjectState(BaseObject.NEW);
answerList.add(ans);
}
return answerList;
}
private List<UserIdentityAnswer> prefillAnswerList(int questionCount) {
List<UserIdentityAnswer> answerList = new ArrayList<UserIdentityAnswer>();
for (int i=0; i < questionCount; i++) {
UserIdentityAnswer ans = new UserIdentityAnswer();
ans.setIdentityAnsId(String.valueOf(i));
ans.setObjectState(BaseObject.NEW);
answerList.add(ans);
}
return answerList;
}
@Override
protected ModelAndView onCancel(Object command) throws Exception {
// return super.onCancel(command); //To change body of overridden methods use File | Settings | File Templates.
return new ModelAndView(new RedirectView(getCancelView(),true));
}
@Override
protected ModelAndView onSubmit(HttpServletRequest request,
HttpServletResponse response, Object command, BindException errors) throws Exception {
log.info("onSubmit called.");
System.out.println("submit called.");
HttpSession session = request.getSession();
String userId = (String)session.getAttribute("userId");
IdentityQuestionCommand cmd = (IdentityQuestionCommand) command;
List<UserIdentityAnswer> answerList = cmd.getAnswerList();
// check if the policy has changed the number of challenge response questions
List<UserIdentityAnswer> curAnswerList = challengeResponse.answersByUser(userId);
if (curAnswerList == null) {
// reset the new answerlist so that the services add these objects
for (UserIdentityAnswer ans : answerList) {
ans.setObjectState(BaseObject.NEW);
ans.setIdentityAnsId(null);
}
}else if (curAnswerList.size() != answerList.size()) {
log.info("New answerList size is different from one in the repository. Delete the current list");
// delete the current list and create a new list
for (UserIdentityAnswer ans : curAnswerList) {
log.info("Removing answerId = " + ans.getIdentityAnsId());
challengeResponse.removeAnswer(ans.getIdentityAnsId());
}
// reset the new answerlist so that the services add these objects
for (UserIdentityAnswer ans : answerList) {
ans.setObjectState(BaseObject.NEW);
ans.setIdentityAnsId(null);
}
}
cleanupAnswerList(answerList, userId);
this.challengeResponse.saveAnswers(answerList);
ModelAndView mav = new ModelAndView(getSuccessView());
return mav;
}
private void cleanupAnswerList(List<UserIdentityAnswer> answerList, String userId) {
for (UserIdentityAnswer ans : answerList) {
ans.setUserId(userId);
if (ans.getObjectState().equalsIgnoreCase(BaseObject.NEW)) {
// let hibernate generate the UUID.
ans.setIdentityAnsId(null);
}
// set the question text with the answer. Will need it for the challenge response
IdentityQuestion question = challengeResponse.getQuestion(ans.getIdentityQuestionId());
if (question != null) {
ans.setQuestionText(question.getQuestionText());
}
}
}
public PasswordConfiguration getConfiguration() {
return configuration;
}
public void setConfiguration(PasswordConfiguration configuration) {
this.configuration = configuration;
}
public PolicyDataService getPolicyDataService() {
return policyDataService;
}
public void setPolicyDataService(PolicyDataService policyDataService) {
this.policyDataService = policyDataService;
}
public SecurityDomainDataService getSecDomainService() {
return secDomainService;
}
public void setSecDomainService(SecurityDomainDataService secDomainService) {
this.secDomainService = secDomainService;
}
public ChallengeResponseService getChallengeResponse() {
return challengeResponse;
}
public void setChallengeResponse(ChallengeResponseService challengeResponse) {
this.challengeResponse = challengeResponse;
}
public PasswordWebService getPasswordService() {
return passwordService;
}
public void setPasswordService(PasswordWebService passwordService) {
this.passwordService = passwordService;
}
}