Java tutorial
/* * 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.page.self; import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition; import com.evolveum.midpoint.gui.api.model.LoadableModel; import com.evolveum.midpoint.gui.api.util.WebComponentUtil; import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils; import com.evolveum.midpoint.prism.*; import com.evolveum.midpoint.prism.delta.ObjectDelta; import com.evolveum.midpoint.prism.delta.PropertyDelta; import com.evolveum.midpoint.prism.path.ItemPath; import com.evolveum.midpoint.prism.schema.SchemaRegistry; import com.evolveum.midpoint.schema.GetOperationOptions; import com.evolveum.midpoint.schema.SchemaConstantsGenerated; import com.evolveum.midpoint.schema.SelectorOptions; import com.evolveum.midpoint.schema.result.OperationResult; import com.evolveum.midpoint.security.api.AuthorizationConstants; import com.evolveum.midpoint.task.api.Task; import com.evolveum.midpoint.util.exception.ObjectNotFoundException; import com.evolveum.midpoint.util.exception.SchemaException; 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.application.AuthorizationAction; import com.evolveum.midpoint.web.application.PageDescriptor; import com.evolveum.midpoint.web.component.AjaxSubmitButton; import com.evolveum.midpoint.web.component.TabbedPanel; import com.evolveum.midpoint.web.component.breadcrumbs.Breadcrumb; import com.evolveum.midpoint.web.component.data.TablePanel; import com.evolveum.midpoint.web.component.prism.ContainerStatus; import com.evolveum.midpoint.web.component.prism.ObjectWrapper; import com.evolveum.midpoint.web.component.util.ObjectWrapperUtil; import com.evolveum.midpoint.web.page.admin.home.PageDashboard; import com.evolveum.midpoint.web.page.admin.home.dto.MyPasswordsDto; import com.evolveum.midpoint.web.page.admin.home.dto.PasswordAccountDto; import com.evolveum.midpoint.web.page.admin.users.dto.FocusSubwrapperDto; import com.evolveum.midpoint.web.page.self.component.ChangePasswordPanel; import com.evolveum.midpoint.web.security.SecurityUtils; import com.evolveum.midpoint.xml.ns._public.common.common_3.*; import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; import org.apache.wicket.Component; import org.apache.wicket.ajax.AjaxRequestTarget; import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink; import org.apache.wicket.extensions.markup.html.tabs.AbstractTab; import org.apache.wicket.extensions.markup.html.tabs.ITab; import org.apache.wicket.markup.html.WebMarkupContainer; import org.apache.wicket.markup.html.form.CheckBox; import org.apache.wicket.markup.html.form.Form; import org.apache.wicket.model.IModel; import org.apache.wicket.model.Model; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; /** * @author Viliam Repan (lazyman) */ @PageDescriptor(url = { "/self/credentials" }, action = { @AuthorizationAction(actionUri = PageSelf.AUTH_SELF_ALL_URI, label = PageSelf.AUTH_SELF_ALL_LABEL, description = PageSelf.AUTH_SELF_ALL_DESCRIPTION), @AuthorizationAction(actionUri = AuthorizationConstants.AUTZ_UI_SELF_CREDENTIALS_URL, label = "PageSelfCredentials.auth.credentials.label", description = "PageSelfCredentials.auth.credentials.description") }) public class PageSelfCredentials extends PageSelf { private static final long serialVersionUID = 1L; private static final String ID_MAIN_FORM = "mainForm"; private static final String ID_TAB_PANEL = "tabPanel"; private static final String ID_SAVE_BUTTON = "save"; private static final String ID_CANCEL_BUTTON = "cancel"; private static final String ID_PANEL = "panel"; private static final Trace LOGGER = TraceManager.getTrace(PageSelfCredentials.class); private static final String DOT_CLASS = PageSelfCredentials.class.getName() + "."; private static final String OPERATION_LOAD_USER_WITH_ACCOUNTS = DOT_CLASS + "loadUserWithAccounts"; private static final String OPERATION_LOAD_USER = DOT_CLASS + "loadUser"; private static final String OPERATION_LOAD_ACCOUNT = DOT_CLASS + "loadAccount"; private static final String OPERATION_SAVE_PASSWORD = DOT_CLASS + "savePassword"; private static final String OPERATION_CHECK_PASSWORD = DOT_CLASS + "checkPassword"; private static final String OPERATION_LOAD_SHADOW = DOT_CLASS + "loadShadow"; private static final String OPERATION_GET_CREDENTIALS_POLICY = DOT_CLASS + "getCredentialsPolicy"; private LoadableModel<MyPasswordsDto> model; private PrismObject<UserType> user; public PageSelfCredentials() { model = new LoadableModel<MyPasswordsDto>(false) { private static final long serialVersionUID = 1L; @Override protected MyPasswordsDto load() { return loadPageModel(); } }; initLayout(); } @Override protected void createBreadcrumb() { super.createBreadcrumb(); Breadcrumb bc = getSessionStorage().peekBreadcrumb(); bc.setIcon(new Model<String>("fa fa-shield")); } public PageSelfCredentials(final MyPasswordsDto myPasswordsDto) { model = new LoadableModel<MyPasswordsDto>(myPasswordsDto, false) { private static final long serialVersionUID = 1L; @Override protected MyPasswordsDto load() { return myPasswordsDto; } }; initLayout(); } private MyPasswordsDto loadPageModel() { LOGGER.debug("Loading user and accounts."); MyPasswordsDto dto = new MyPasswordsDto(); OperationResult result = new OperationResult(OPERATION_LOAD_USER_WITH_ACCOUNTS); try { String userOid = SecurityUtils.getPrincipalUser().getOid(); Task task = createSimpleTask(OPERATION_LOAD_USER); OperationResult subResult = result.createSubresult(OPERATION_LOAD_USER); user = getModelService().getObject(UserType.class, userOid, null, task, subResult); subResult.recordSuccessIfUnknown(); dto.getAccounts().add(createDefaultPasswordAccountDto(user)); CredentialsPolicyType credentialsPolicyType = getPasswordCredentialsPolicy(); if (credentialsPolicyType != null) { PasswordCredentialsPolicyType passwordCredentialsPolicy = credentialsPolicyType.getPassword(); if (passwordCredentialsPolicy != null) { CredentialsPropagationUserControlType propagationUserControl = passwordCredentialsPolicy .getPropagationUserControl(); if (propagationUserControl != null) { dto.setPropagation(propagationUserControl); } PasswordChangeSecurityType passwordChangeSecurity = passwordCredentialsPolicy .getPasswordChangeSecurity(); if (passwordChangeSecurity != null) { dto.setPasswordChangeSecurity(passwordChangeSecurity); } } } if (dto.getPropagation() == null || dto.getPropagation().equals(CredentialsPropagationUserControlType.USER_CHOICE)) { PrismReference reference = user.findReference(UserType.F_LINK_REF); if (reference == null || reference.getValues() == null) { LOGGER.debug("No accounts found for user {}.", new Object[] { userOid }); return dto; } final Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions .createCollection(ShadowType.F_RESOURCE, GetOperationOptions.createResolve()); List<PrismReferenceValue> values = reference.getValues(); for (PrismReferenceValue value : values) { subResult = result.createSubresult(OPERATION_LOAD_ACCOUNT); try { String accountOid = value.getOid(); task = createSimpleTask(OPERATION_LOAD_ACCOUNT); PrismObject<ShadowType> account = getModelService().getObject(ShadowType.class, accountOid, options, task, subResult); dto.getAccounts().add(createPasswordAccountDto(account)); subResult.recordSuccessIfUnknown(); } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load account", ex); subResult.recordFatalError("Couldn't load account.", ex); } } } result.recordSuccessIfUnknown(); } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load accounts", ex); result.recordFatalError("Couldn't load accounts", ex); } finally { result.recomputeStatus(); } Collections.sort(dto.getAccounts()); if (!result.isSuccess() && !result.isHandledError()) { showResult(result); } return dto; } private void initLayout() { Form mainForm = new Form(ID_MAIN_FORM); List<ITab> tabs = new ArrayList<>(); tabs.add(new AbstractTab(createStringResource("PageSelfCredentials.tabs.password")) { private static final long serialVersionUID = 1L; @Override public WebMarkupContainer getPanel(String panelId) { return new ChangePasswordPanel(panelId, model, model.getObject()); } }); TabbedPanel<ITab> credentialsTabPanel = new TabbedPanel<ITab>(ID_TAB_PANEL, tabs) { private static final long serialVersionUID = 1L; @Override protected WebMarkupContainer newLink(String linkId, final int index) { return new AjaxSubmitLink(linkId) { private static final long serialVersionUID = 1L; @Override protected void onError(AjaxRequestTarget target, Form<?> form) { super.onError(target, form); target.add(getFeedbackPanel()); } @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { super.onSubmit(target, form); setSelectedTab(index); if (target != null) { target.add(findParent(TabbedPanel.class)); } } }; } }; credentialsTabPanel.setOutputMarkupId(true); mainForm.add(credentialsTabPanel); initButtons(mainForm); add(mainForm); } private void initButtons(Form mainForm) { AjaxSubmitButton save = new AjaxSubmitButton(ID_SAVE_BUTTON, createStringResource("PageBase.button.save")) { @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(getFeedbackPanel()); } @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { onSavePerformed(target); } }; mainForm.setDefaultButton(save); mainForm.add(save); AjaxSubmitButton cancel = new AjaxSubmitButton(ID_CANCEL_BUTTON, createStringResource("PageBase.button.back")) { @Override protected void onError(AjaxRequestTarget target, Form<?> form) { target.add(getFeedbackPanel()); } @Override protected void onSubmit(AjaxRequestTarget target, Form<?> form) { onCancelPerformed(target); } }; mainForm.add(cancel); } private PasswordAccountDto createDefaultPasswordAccountDto(PrismObject<UserType> user) { return new PasswordAccountDto(user.getOid(), user.getName().getOrig(), getString("PageSelfCredentials.resourceMidpoint"), WebComponentUtil.isActivationEnabled(user), true); } private PasswordAccountDto createPasswordAccountDto(PrismObject<ShadowType> account) { PrismReference resourceRef = account.findReference(ShadowType.F_RESOURCE_REF); String resourceName; if (resourceRef == null || resourceRef.getValue() == null || resourceRef.getValue().getObject() == null) { resourceName = getString("PageSelfCredentials.couldntResolve"); } else { resourceName = WebComponentUtil.getName(resourceRef.getValue().getObject()); } PasswordAccountDto passwordAccountDto = new PasswordAccountDto(account.getOid(), WebComponentUtil.getName(account), resourceName, WebComponentUtil.isActivationEnabled(account)); passwordAccountDto.setPasswordOutbound(getPasswordOutbound(account)); return passwordAccountDto; } private void onSavePerformed(AjaxRequestTarget target) { List<PasswordAccountDto> selectedAccounts = getSelectedAccountsList(); if ((model.getObject().getPasswordChangeSecurity() == null) || (model.getObject().getPasswordChangeSecurity() != null && model.getObject() .getPasswordChangeSecurity().equals(PasswordChangeSecurityType.OLD_PASSWORD))) { LOGGER.debug("Check old password"); if (model.getObject().getOldPassword() == null || model.getObject().getOldPassword().trim().equals("")) { warn(getString("PageSelfCredentials.specifyOldPasswordMessage")); target.add(getFeedbackPanel()); return; } else { OperationResult checkPasswordResult = new OperationResult(OPERATION_CHECK_PASSWORD); Task checkPasswordTask = createSimpleTask(OPERATION_CHECK_PASSWORD); try { ProtectedStringType oldPassword = new ProtectedStringType(); oldPassword.setClearValue(model.getObject().getOldPassword()); boolean isCorrectPassword = getModelInteractionService().checkPassword(user.getOid(), oldPassword, checkPasswordTask, checkPasswordResult); if (!isCorrectPassword) { warn(getString("PageSelfCredentials.incorrectOldPassword")); target.add(getFeedbackPanel()); return; } } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't check password", ex); checkPasswordResult.recordFatalError("Couldn't check password." + ex.getMessage(), ex); target.add(getFeedbackPanel()); return; } finally { checkPasswordResult.computeStatus(); } } } if (selectedAccounts.isEmpty()) { warn(getString("PageSelfCredentials.noAccountSelected")); target.add(getFeedbackPanel()); return; } OperationResult result = new OperationResult(OPERATION_SAVE_PASSWORD); try { MyPasswordsDto dto = model.getObject(); ProtectedStringType password = dto.getPassword(); WebComponentUtil.encryptProtectedString(password, true, getMidpointApplication()); final ItemPath valuePath = new ItemPath(SchemaConstantsGenerated.C_CREDENTIALS, CredentialsType.F_PASSWORD, PasswordType.F_VALUE); SchemaRegistry registry = getPrismContext().getSchemaRegistry(); Collection<ObjectDelta<? extends ObjectType>> deltas = new ArrayList<ObjectDelta<? extends ObjectType>>(); for (PasswordAccountDto accDto : selectedAccounts) { PrismObjectDefinition objDef = accDto.isMidpoint() ? registry.findObjectDefinitionByCompileTimeClass(UserType.class) : registry.findObjectDefinitionByCompileTimeClass(ShadowType.class); PropertyDelta delta = PropertyDelta.createModificationReplaceProperty(valuePath, objDef, password, password); Class<? extends ObjectType> type = accDto.isMidpoint() ? UserType.class : ShadowType.class; deltas.add(ObjectDelta.createModifyDelta(accDto.getOid(), delta, type, getPrismContext())); } getModelService().executeChanges(deltas, null, createSimpleTask(OPERATION_SAVE_PASSWORD), result); result.recordSuccess(); } catch (Exception ex) { MyPasswordsDto dto = model.getObject(); ProtectedStringType password = dto.getPassword(); if (password != null) { password.setEncryptedData(null); } LoggingUtils.logUnexpectedException(LOGGER, "Couldn't save password changes", ex); result.recordFatalError("Couldn't save password changes.", ex); } finally { result.recomputeStatus(); } if (!WebComponentUtil.isSuccessOrHandledError(result)) { showResult(result); target.add(getFeedbackPanel()); } else { showResult(result); if (WebComponentUtil.isAuthorized(AuthorizationConstants.AUTZ_UI_DASHBOARD_URL, AuthorizationConstants.AUTZ_UI_HOME_ALL_URL)) { setResponsePage(PageDashboard.class); } else { setResponsePage(PageSelfDashboard.class); } } } private List<PasswordAccountDto> getSelectedAccountsList() { List<PasswordAccountDto> passwordAccountDtos = model.getObject().getAccounts(); List<PasswordAccountDto> selectedAccountList = new ArrayList<>(); if (model.getObject().getPropagation() != null && model.getObject().getPropagation().equals(CredentialsPropagationUserControlType.MAPPING)) { selectedAccountList.addAll(passwordAccountDtos); } else { for (PasswordAccountDto passwordAccountDto : passwordAccountDtos) { if (passwordAccountDto.getCssClass().equals(ChangePasswordPanel.SELECTED_ACCOUNT_ICON_CSS)) { selectedAccountList.add(passwordAccountDto); } } } return selectedAccountList; } private void onCancelPerformed(AjaxRequestTarget target) { redirectBack(); } private List<ShadowType> loadShadowTypeList() { List<ObjectReferenceType> references = user.asObjectable().getLinkRef(); Task task = createSimpleTask(OPERATION_LOAD_SHADOW); List<ShadowType> shadowTypeList = new ArrayList<>(); for (ObjectReferenceType reference : references) { OperationResult subResult = new OperationResult(OPERATION_LOAD_SHADOW); try { Collection<SelectorOptions<GetOperationOptions>> options = SelectorOptions .createCollection(ShadowType.F_RESOURCE, GetOperationOptions.createResolve()); if (reference.getOid() == null) { continue; } PrismObject<ShadowType> shadow = WebModelServiceUtils.loadObject(ShadowType.class, reference.getOid(), options, this, task, subResult); shadowTypeList.add(shadow.asObjectable()); } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load account", ex); subResult.recordFatalError("Couldn't load account." + ex.getMessage(), ex); } finally { subResult.computeStatus(); } } return shadowTypeList; } private boolean getPasswordOutbound(PrismObject<ShadowType> shadow) { try { RefinedObjectClassDefinition rOCDef = getModelInteractionService().getEditObjectClassDefinition(shadow, shadow.asObjectable().getResource().asPrismObject(), AuthorizationPhaseType.REQUEST); if (rOCDef != null && rOCDef.getPasswordOutbound() != null) { return true; } } catch (SchemaException ex) { } return false; } public PrismObject<UserType> getUser() { return user; } private CredentialsPolicyType getPasswordCredentialsPolicy() { LOGGER.debug("Getting credentials policy"); Task task = createSimpleTask(OPERATION_GET_CREDENTIALS_POLICY); OperationResult result = new OperationResult(OPERATION_GET_CREDENTIALS_POLICY); CredentialsPolicyType credentialsPolicyType = null; try { credentialsPolicyType = getModelInteractionService().getCredentialsPolicy(user, task, result); result.recordSuccessIfUnknown(); } catch (Exception ex) { LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load credentials policy", ex); result.recordFatalError("Couldn't load credentials policy." + ex.getMessage(), ex); } finally { result.computeStatus(); } return credentialsPolicyType; } }