/* * Copyright (c) 2010-2016 Evolveum * * 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 com.evolveum.midpoint.web.component.menu; import com.evolveum.midpoint.gui.api.component.BasePanel; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.page.PageBase; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.prism.PrismObject; import com.evolveum.midpoint.prism.crypto.EncryptionException; import com.evolveum.midpoint.prism.crypto.Protector; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.RetrieveOption; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.security.api.MidPointPrincipal; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.logging.LoggingUtils; import com.evolveum.midpoint.util.logging.Trace; import com.evolveum.midpoint.util.logging.TraceManager; import com.evolveum.midpoint.web.component.AjaxButton; import com.evolveum.midpoint.web.component.util.VisibleEnableBehaviour; import com.evolveum.midpoint.web.page.admin.home.PageMyPasswordQuestions; import com.evolveum.midpoint.web.page.admin.home.dto.PasswordQuestionsDto; import com.evolveum.midpoint.web.page.admin.home.dto.SecurityQuestionAnswerDTO; import com.evolveum.midpoint.web.security.SecurityUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.image.ContextImage; import org.apache.wicket.markup.html.image.NonCachingImage; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.model.AbstractReadOnlyModel; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import org.apache.wicket.request.cycle.RequestCycle; import org.apache.wicket.request.resource.AbstractResource; import org.apache.wicket.request.resource.ByteArrayResource; import org.springframework.security.core.context.SecurityContextHolder; import java.util.*; /** * @author lazyman */ public class UserMenuPanel extends BasePanel { private static final Trace LOGGER = TraceManager.getTrace(UserMenuPanel.class); private static final String ID_USERNAME_LINK = "usernameLink"; private static final String ID_LOGOUT_LINK = "logoutLink"; private static final String ID_USERNAME = "username"; private static final String ID_EDIT_PROFILE = "editProfile"; private static final String ID_PASSWORD_QUESTIONS = "passwordQuestions"; private IModel<PasswordQuestionsDto> passwordQuestionsDtoIModel; private IModel<List<SecurityQuestionDefinitionType>> securityPolicyQuestionsModel; // private PrismObject<UserType> userModel; private Model<PrismObject<UserType>> userModel = new Model<PrismObject<UserType>>(); private static final String DOT_CLASS = UserMenuPanel.class.getName() + "."; private static final String OPERATION_LOAD_USER = DOT_CLASS + "loaduser"; private static final String OPERATION_LOAD_QUESTION_POLICY = DOT_CLASS + "LOAD Question Policy"; private static final String ID_ICON_BOX = "menuIconBox"; private static final String ID_PHOTO = "menuPhoto"; private static final String ID_ICON = "menuIcon"; private static final String ID_PANEL_ICON_BOX = "menuPanelIconBox"; private static final String ID_PANEL_PHOTO = "menuPanelPhoto"; private static final String ID_PANEL_ICON = "menuPanelIcon"; private boolean isUserModelLoaded = false; private boolean isPasswordModelLoaded = false; private byte[] jpegPhoto = null; private List<SecurityQuestionDefinitionType> securityPolicyQuestions = new ArrayList<>(); public UserMenuPanel(String id) { super(id); initLayout(); if (!isPasswordModelLoaded) { passwordQuestionsDtoIModel = new LoadableModel<PasswordQuestionsDto>(false) { private static final long serialVersionUID = 1L; @Override protected PasswordQuestionsDto load() { return loadModel(null); } }; isPasswordModelLoaded = true; } securityPolicyQuestionsModel = new LoadableModel<List<SecurityQuestionDefinitionType>>(false) { private static final long serialVersionUID = 1L; @Override protected List<SecurityQuestionDefinitionType> load() { return loadSecurityPloicyQuestionsModel(); } }; } private void initLayout() { WebMarkupContainer iconBox = new WebMarkupContainer(ID_ICON_BOX); add(iconBox); NonCachingImage img = new NonCachingImage(ID_PHOTO, new AbstractReadOnlyModel<AbstractResource>() { @Override public AbstractResource getObject() { if(jpegPhoto == null) { return null; } else { return new ByteArrayResource("image/jpeg",jpegPhoto); } } }); img.add(new VisibleEnableBehaviour(){ @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ loadModel(null); } return jpegPhoto != null; } }); iconBox.add(img); ContextImage icon = new ContextImage(ID_ICON, "img/placeholder.png"); icon.add(new VisibleEnableBehaviour(){ @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ loadModel(null); } return jpegPhoto == null; } }); iconBox.add(icon); Label usernameLink = new Label(ID_USERNAME_LINK, new AbstractReadOnlyModel<String>() { @Override public String getObject() { return getShortUserName(); } }); add(usernameLink); WebMarkupContainer panelIconBox = new WebMarkupContainer(ID_PANEL_ICON_BOX); add(panelIconBox); NonCachingImage panelImg = new NonCachingImage(ID_PANEL_PHOTO, new AbstractReadOnlyModel<AbstractResource>() { @Override public AbstractResource getObject() { if(jpegPhoto == null) { return null; } else { return new ByteArrayResource("image/jpeg",jpegPhoto); } } }); panelImg.add(new VisibleEnableBehaviour(){ @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ loadModel(null); } return jpegPhoto != null; } }); panelIconBox.add(panelImg); ContextImage panelIcon = new ContextImage(ID_PANEL_ICON,"img/placeholder.png"); panelIcon.add(new VisibleEnableBehaviour(){ @Override public boolean isVisible(){ if (userModel != null && userModel.getObject() == null){ loadModel(null); } return jpegPhoto == null; } }); panelIconBox.add(panelIcon); Label username = new Label(ID_USERNAME, new AbstractReadOnlyModel<String>() { @Override public String getObject() { return getShortUserName(); } }); username.setRenderBodyOnly(true); add(username); ExternalLink logoutLink = new ExternalLink(ID_LOGOUT_LINK, new Model<>(RequestCycle.get().getRequest().getContextPath() + "/j_spring_security_logout"), createStringResource("UserMenuPanel.logout")); add(logoutLink); AjaxButton editPasswordQ = new AjaxButton(ID_PASSWORD_QUESTIONS, createStringResource("UserMenuPanel.editPasswordQuestions")) { @Override public void onClick(AjaxRequestTarget target) { PageMyPasswordQuestions myPasswordQuestions = new PageMyPasswordQuestions(passwordQuestionsDtoIModel); setResponsePage(myPasswordQuestions); } }; add(editPasswordQ); if (!isPasswordModelLoaded ){ passwordQuestionsDtoIModel = new LoadableModel<PasswordQuestionsDto>(false) { private static final long serialVersionUID = 1L; @Override protected PasswordQuestionsDto load() { return loadModel(null); } }; isPasswordModelLoaded = true; } securityPolicyQuestionsModel = new LoadableModel<List<SecurityQuestionDefinitionType>>(false) { @Override protected List<SecurityQuestionDefinitionType> load() { return loadSecurityPloicyQuestionsModel(); } }; editPasswordQ.add(new VisibleEnableBehaviour() { @Override public boolean isVisible() { if (securityPolicyQuestionsModel == null || securityPolicyQuestionsModel.getObject() == null) { loadSecurityPloicyQuestionsModel(); } return hasQuestions() || (securityPolicyQuestionsModel.getObject() != null && securityPolicyQuestionsModel.getObject().size() > 0); } }); } private String getShortUserName() { Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); if (principal == null) { return "Unknown"; } if (principal instanceof MidPointPrincipal) { MidPointPrincipal princ = (MidPointPrincipal) principal; return WebComponentUtil.getOrigStringFromPoly(princ.getName()); } return principal.toString(); } private PasswordQuestionsDto loadModel(PageBase parentPage) { LOGGER.trace("Loading user for Security Question Page."); PasswordQuestionsDto dto =new PasswordQuestionsDto(); OperationResult result = new OperationResult(OPERATION_LOAD_USER); if (parentPage == null) { parentPage = ((PageBase)getPage()); } try { MidPointPrincipal principal = SecurityUtils.getPrincipalUser(); if (principal == null) { result.recordNotApplicableIfUnknown(); return null; } String userOid = principal.getOid(); Task task = parentPage.createSimpleTask(OPERATION_LOAD_USER); OperationResult subResult = result.createSubresult(OPERATION_LOAD_USER); Collection options = SelectorOptions.createCollection(UserType.F_JPEG_PHOTO, GetOperationOptions.createRetrieve(RetrieveOption.INCLUDE)); PrismObject<UserType> user = parentPage.getModelService().getObject(UserType.class, userOid, options, task, subResult); userModel.setObject(user); jpegPhoto = user == null ? null : (user.asObjectable() == null ? null : user.asObjectable().getJpegPhoto()); dto.setSecurityAnswers(createUsersSecurityQuestionsList(user)); subResult.recordSuccessIfUnknown(); } catch (Exception ex) { LoggingUtils.logExceptionOnDebugLevel(LOGGER, "Couldn't get user Questions, Probably not set yet", ex); } finally { result.recomputeStatus(); isUserModelLoaded = true; } return dto; } public List<SecurityQuestionAnswerDTO> createUsersSecurityQuestionsList(PrismObject<UserType> user) { SecurityQuestionsCredentialsType credentialsPolicyType = user.asObjectable().getCredentials() .getSecurityQuestions(); if (credentialsPolicyType == null) { return null; } List<SecurityQuestionAnswerType> secQuestAnsList = credentialsPolicyType.getQuestionAnswer(); if (secQuestAnsList != null) { List<SecurityQuestionAnswerDTO> secQuestAnswListDTO = new ArrayList<SecurityQuestionAnswerDTO>(); for (Iterator iterator = secQuestAnsList.iterator(); iterator.hasNext();) { SecurityQuestionAnswerType securityQuestionAnswerType = (SecurityQuestionAnswerType) iterator .next(); Protector protector = ((PageBase) getPage()).getPrismContext().getDefaultProtector(); if (securityQuestionAnswerType.getQuestionAnswer() != null && securityQuestionAnswerType.getQuestionAnswer().getEncryptedDataType() != null) { try { String decoded = protector.decryptString(securityQuestionAnswerType.getQuestionAnswer()); secQuestAnswListDTO.add(new SecurityQuestionAnswerDTO(securityQuestionAnswerType .getQuestionIdentifier(), decoded)); } catch (EncryptionException e) { // TODO do we need to thrown exception here? LOGGER.error("Could not get security questions. Error: " + e.getMessage(), e); continue; } } } return secQuestAnswListDTO; } else { return null; } } private List<SecurityQuestionDefinitionType> loadSecurityPloicyQuestionsModel() { List<SecurityQuestionDefinitionType> questionList = new ArrayList<SecurityQuestionDefinitionType>(); OperationResult result = new OperationResult(OPERATION_LOAD_QUESTION_POLICY); try { Task task = ((PageBase) getPage()).createSimpleTask(OPERATION_LOAD_QUESTION_POLICY); CredentialsPolicyType credPolicy = ((PageBase) getPage()).getModelInteractionService().getCredentialsPolicy(null, task, result); if (credPolicy != null && credPolicy.getSecurityQuestions() != null) { // Actual Policy Question List questionList = credPolicy.getSecurityQuestions().getQuestion(); } } catch (Exception ex) { result.recordFatalError("Couldn't load system security policy" + ex.getMessage(), ex); LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load system security policy", ex); }finally { result.computeStatus(); } return questionList; } private boolean hasQuestions(){ return passwordQuestionsDtoIModel != null && (passwordQuestionsDtoIModel.getObject() != null && (passwordQuestionsDtoIModel.getObject().getPwdQuestion() != null && !passwordQuestionsDtoIModel.getObject().getPwdQuestion().trim().equals(""))); } }