/*
* 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.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.page.PageBase;
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.ContainerDelta;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
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.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.assignment.AssignmentEditorDto;
import com.evolveum.midpoint.web.component.assignment.MultipleAssignmentSelectorPanel;
import com.evolveum.midpoint.web.component.breadcrumbs.Breadcrumb;
import com.evolveum.midpoint.web.page.admin.users.dto.UserDtoStatus;
import com.evolveum.midpoint.web.security.SecurityUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.model.Model;
import java.util.*;
/**
* Created by Kate on 31.03.2016.
*/
@PageDescriptor(url = {"/self/requestRole"}, 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_REQUEST_ROLE_URL,
label = "PageSelfCredentials.auth.requestRole.label",
description = "PageSelfCredentials.auth.requestRole.description")})
public class PageRequestRole extends PageSelf {
private static final String ID_MAIN_PANEL = "mainPanel";
private static final String ID_MAIN_FORM = "mainForm";
private static final String ID_SAVE_BUTTON = "save";
private static final String ID_CANCEL_BUTTON = "cancel";
private LoadableModel<List<AssignmentEditorDto>> assignmentsModel;
private PrismObject<UserType> user;
private OperationResult backgroundTaskOperationResult = null;
private static final Trace LOGGER = TraceManager.getTrace(PageRequestRole.class);
private static final String DOT_CLASS = PageRequestRole.class.getName() + ".";
private static final String OPERATION_LOAD_USER = DOT_CLASS + "loadUser";
protected static final String OPERATION_SAVE = DOT_CLASS + "save";
protected static final String OPERATION_WF_TASK_CREATED = "com.evolveum.midpoint.wf.impl.WfHook.invoke";
public PageRequestRole() {
assignmentsModel = new LoadableModel<List<AssignmentEditorDto>>(false) {
@Override
protected List<AssignmentEditorDto> load() {
return loadAssignments();
}
};
loadUser();
initLayout();
}
private void initLayout() {
Form mainForm = new org.apache.wicket.markup.html.form.Form(ID_MAIN_FORM);
add(mainForm);
MultipleAssignmentSelectorPanel<UserType, UserType, RoleType> panel =
new MultipleAssignmentSelectorPanel<>(ID_MAIN_PANEL, assignmentsModel,
user, UserType.class, RoleType.class, this);
mainForm.add(panel);
initButtons(mainForm);
}
private List<AssignmentEditorDto> loadAssignments() {
List<AssignmentEditorDto> list = new ArrayList<AssignmentEditorDto>();
List<AssignmentType> assignments = user.asObjectable().getAssignment();
for (AssignmentType assignment : assignments) {
list.add(new AssignmentEditorDto(UserDtoStatus.MODIFY, assignment, this));
}
Collections.sort(list);
return list;
}
private void initButtons(Form mainForm) {
AjaxSubmitButton save = new AjaxSubmitButton(ID_SAVE_BUTTON, createStringResource("PageBase.button.save")) {
@Override
protected void onError(AjaxRequestTarget target, org.apache.wicket.markup.html.form.Form<?> form) {
target.add(getFeedbackPanel());
}
@Override
protected void onSubmit(AjaxRequestTarget target, org.apache.wicket.markup.html.form.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, org.apache.wicket.markup.html.form.Form<?> form) {
target.add(getFeedbackPanel());
}
@Override
protected void onSubmit(AjaxRequestTarget target, org.apache.wicket.markup.html.form.Form<?> form) {
// onCancelPerformed(target);
}
};
mainForm.add(cancel);
}
private void loadUser() {
LOGGER.debug("Loading user and accounts.");
OperationResult result = new OperationResult(OPERATION_LOAD_USER);
try {
String userOid = SecurityUtils.getPrincipalUser().getOid();
Task task = createSimpleTask(OPERATION_LOAD_USER);
user = WebModelServiceUtils.loadObject(UserType.class, userOid, null, (PageBase) getPage(),
task, result);
result.recordSuccessIfUnknown();
result.recordSuccessIfUnknown();
} catch (Exception ex) {
LoggingUtils.logUnexpectedException(LOGGER, "Couldn't load accounts", ex);
result.recordFatalError("Couldn't load accounts", ex);
} finally {
result.recomputeStatus();
}
if (!result.isSuccess() && !result.isHandledError()) {
showResult(result);
}
}
@Override
protected void createBreadcrumb() {
super.createBreadcrumb();
Breadcrumb bc = getLastBreadcrumb();
bc.setIcon(new Model("fa fa-pencil-square-o"));
}
private void onSavePerformed(AjaxRequestTarget target) {
OperationResult result = new OperationResult(OPERATION_SAVE);
ObjectDelta<UserType> delta;
Collection<ObjectDelta<? extends ObjectType>> deltas = new ArrayList<ObjectDelta<? extends ObjectType>>();
try {
delta = user.createModifyDelta();
deltas.add(delta);
PrismContainerDefinition def = user.getDefinition().findContainerDefinition(UserType.F_ASSIGNMENT);
handleAssignmentDeltas(delta, assignmentsModel.getObject(), def);
getModelService().executeChanges(deltas, null, createSimpleTask(OPERATION_SAVE), result);
result.recordSuccess();
} catch (Exception e) {
LoggingUtils.logUnexpectedException(LOGGER, "Could not save assignments ", e);
error("Could not save assignments. Reason: " + e);
target.add(getFeedbackPanel());
} finally {
result.recomputeStatus();
}
findBackgroundTaskOperation(result);
if (backgroundTaskOperationResult != null
&& StringUtils.isNotEmpty(backgroundTaskOperationResult.getBackgroundTaskOid())){
result.setMessage(createStringResource("operation.com.evolveum.midpoint.web.page.self.PageRequestRole.taskCreated").getString());
showResult(result);
setResponsePage(PageRequestRole.class);
return;
}
showResult(result);
if (!WebComponentUtil.isSuccessOrHandledError(result)) {
target.add(getFeedbackPanel());
} else {
setResponsePage(PageRequestRole.class);
}
}
private void findBackgroundTaskOperation(OperationResult result){
if (backgroundTaskOperationResult != null) {
return;
} else {
List<OperationResult> subresults = result.getSubresults();
if (subresults == null || subresults.size() == 0) {
return;
}
for (OperationResult subresult : subresults) {
if (subresult.getOperation().equals(OPERATION_WF_TASK_CREATED)) {
backgroundTaskOperationResult = subresult;
return;
} else {
findBackgroundTaskOperation(subresult);
}
}
}
return;
}
protected ContainerDelta handleAssignmentDeltas(ObjectDelta<UserType> focusDelta,
List<AssignmentEditorDto> assignments, PrismContainerDefinition def) throws SchemaException {
ContainerDelta assDelta = new ContainerDelta(new ItemPath(), def.getName(), def, getPrismContext());
for (AssignmentEditorDto assDto : assignments) {
PrismContainerValue newValue = assDto.getNewValue(getPrismContext());
switch (assDto.getStatus()) {
case ADD:
newValue.applyDefinition(def, false);
assDelta.addValueToAdd(newValue.clone());
break;
case DELETE:
PrismContainerValue oldValue = assDto.getOldValue();
oldValue.applyDefinition(def);
assDelta.addValueToDelete(oldValue.clone());
break;
case MODIFY:
if (!assDto.isModified(getPrismContext())) {
LOGGER.trace("Assignment '{}' not modified.", new Object[]{assDto.getName()});
continue;
}
handleModifyAssignmentDelta(assDto, def, newValue, focusDelta);
break;
default:
warn(getString("pageAdminUser.message.illegalAssignmentState", assDto.getStatus()));
}
}
if (!assDelta.isEmpty()) {
assDelta = focusDelta.addModification(assDelta);
}
return assDelta;
}
private void handleModifyAssignmentDelta(AssignmentEditorDto assDto,
PrismContainerDefinition assignmentDef, PrismContainerValue newValue, ObjectDelta<UserType> focusDelta)
throws SchemaException {
LOGGER.debug("Handling modified assignment '{}', computing delta.",
new Object[]{assDto.getName()});
PrismValue oldValue = assDto.getOldValue();
Collection<? extends ItemDelta> deltas = oldValue.diff(newValue);
for (ItemDelta delta : deltas) {
ItemPath deltaPath = delta.getPath().rest();
ItemDefinition deltaDef = assignmentDef.findItemDefinition(deltaPath);
delta.setParentPath(WebComponentUtil.joinPath(oldValue.getPath(), delta.getPath().allExceptLast()));
delta.applyDefinition(deltaDef);
focusDelta.addModification(delta);
}
}
}