Skip to content

Commit

Permalink
Fix multiple role analysis issues
Browse files Browse the repository at this point in the history
1. Fix issues related to table action buttons.
2. Fix issues related to displaying preview above the business role migration.
3. Add checker for migration role action execution.
4. Optimize displaying pattern on role analysis tables.
5. Fix minor navigation issues.
6. Add javadoc.
7. Optimize extractRoleMembers method (loading mining structure).
8. Check null oid for visualization item panel
  • Loading branch information
tchrapovic committed Nov 2, 2023
1 parent ae435d3 commit b086398
Show file tree
Hide file tree
Showing 65 changed files with 1,223 additions and 424 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
Expand Down Expand Up @@ -358,14 +359,19 @@ protected String load() {
};

AjaxIconButton ajaxIncludeButton = new AjaxIconButton(repeatingView.newChildId(), loadableIncludeModel,
createStringResource("Include")) {
new LoadableDetachableModel<>() {
@Override
protected String load() {
if (model.getObject().isInclude()) {
return createStringResource("RoleAnalysis.exclude").getString();
}
return createStringResource("RoleAnalysis.include").getString();
}
}) {
@Override
public void onClick(AjaxRequestTarget ajaxRequestTarget) {
model.getObject().setInclude(!model.getObject().isInclude());
BusinessRoleApplicationDto patternDeltas = getObjectDetailsModels().getPatternDeltas();
patternDeltas.setBusinessRoleDtos(provider.getAvailableData());
ajaxRequestTarget.add(this);
getTable().replaceWith(generateTable(provider));
ajaxRequestTarget.add(getTable().setOutputMarkupId(true));
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,12 @@ protected void savePerformed(AjaxRequestTarget target) {
PageAssignmentHolderDetails.this.savePerformed(target);
}

@Override
protected void backPerformed(AjaxRequestTarget target) {
super.backPerformed(target);
onBackPerform(target);
}

@Override
protected void addButtons(RepeatingView repeatingView) {
addAdditionalButtons(repeatingView);
Expand All @@ -221,7 +227,9 @@ protected boolean hasUnsavedChanges(AjaxRequestTarget target) {
}

protected void afterDeletePerformed(AjaxRequestTarget target) {
}

protected void onBackPerform(AjaxRequestTarget target) {
}

protected void addAdditionalButtons(RepeatingView repeatingView) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import java.util.List;

import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.impl.page.admin.role.mining.page.page.PageRoleAnalysis;

import com.evolveum.midpoint.gui.impl.util.DetailsPageUtil;
import com.evolveum.midpoint.web.util.OnePageParameterEncoder;
Expand Down Expand Up @@ -54,6 +53,9 @@ public class BusinessRoleWizardPanel extends AbstractWizardPanel<RoleType, Abstr

private static final String DOT_CLASS = BusinessRoleWizardPanel.class.getName() + ".";
private static final String OP_PERFORM_MIGRATION = DOT_CLASS + "performMigration";

private boolean isRoleMigration = false;

public BusinessRoleWizardPanel(String id, WizardPanelHelper<RoleType, AbstractRoleDetailsModel<RoleType>> helper) {
super(id, helper);
}
Expand All @@ -63,8 +65,6 @@ protected void initLayout() {
add(createWizardFragment(new WizardPanel(getIdOfWizardPanel(), new WizardModel(createBasicSteps()))));
}

private boolean isRoleMigration = false;

private List<WizardStep> createBasicSteps() {
List<WizardStep> steps = new ArrayList<>();

Expand All @@ -76,7 +76,7 @@ public VisibleEnableBehaviour getBackBehaviour() {

@Override
protected void onExitPerformed(AjaxRequestTarget target) {
BusinessRoleWizardPanel.this.onExitPerformed(target);
BusinessRoleWizardPanel.this.performExitOperation(target);
}
});
BusinessRoleApplicationDto patterns = getAssignmentHolderModel().getPatternDeltas();
Expand All @@ -87,7 +87,7 @@ protected void onExitPerformed(AjaxRequestTarget target) {

@Override
protected void onExitPerformed(AjaxRequestTarget target) {
BusinessRoleWizardPanel.this.onExitPerformed(target);
BusinessRoleWizardPanel.this.performExitOperation(target);
}

@Override
Expand All @@ -100,7 +100,7 @@ public VisibleEnableBehaviour getBackBehaviour() {

@Override
protected void onExitPerformed(AjaxRequestTarget target) {
BusinessRoleWizardPanel.this.onExitPerformed(target);
BusinessRoleWizardPanel.this.performExitOperation(target);
}

@Override
Expand Down Expand Up @@ -174,13 +174,23 @@ protected boolean isSubmitEnable() {

@Override
protected void onExitPerformed(AjaxRequestTarget target) {
BusinessRoleWizardPanel.this.onExitPerformed(target);
BusinessRoleWizardPanel.this.performExitOperation(target);
}
});

return steps;
}

private void navigateToRoleAnalysis() {
PageParameters parameters = new PageParameters();
String clusterOid = getHelper().getDetailsModel().getPatternDeltas().getCluster().getOid();
parameters.add(OnePageParameterEncoder.PARAMETER, clusterOid);
parameters.add("panelId", "clusterDetails");
Class<? extends PageBase> detailsPageClass = DetailsPageUtil
.getObjectDetailsPage(RoleAnalysisClusterType.class);
getPageBase().navigateToNext(detailsPageClass, parameters);
}

private void onFinishBasicWizardPerformed(AjaxRequestTarget target) {
OperationResult result = onSavePerformed(target);
if (!result.isError()) {
Expand Down Expand Up @@ -235,16 +245,17 @@ private ActivityDefinitionType createActivity(List<BusinessRoleDto> patternDelta
.roleMembershipManagement(roleMembershipManagementWorkDefinitionType));
}

private void performExitOperation(AjaxRequestTarget target) {
if (isRoleMigration) {
navigateToRoleAnalysis();
} else {
BusinessRoleWizardPanel.this.onExitPerformed(target);
}
}

private void exitToPreview(AjaxRequestTarget target) {
if (isRoleMigration) {
setResponsePage(PageRoleAnalysis.class);
PageParameters parameters = new PageParameters();
String clusterOid = getHelper().getDetailsModel().getPatternDeltas().getCluster().getOid();
parameters.add(OnePageParameterEncoder.PARAMETER, clusterOid);
parameters.add("panelId", "clusterDetails");
Class<? extends PageBase> detailsPageClass = DetailsPageUtil
.getObjectDetailsPage(RoleAnalysisClusterType.class);
getPageBase().navigateToNext(detailsPageClass, parameters);
navigateToRoleAnalysis();
} else {
showChoiceFragment(
target,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;

@PanelType(name = "brw-candidateMembers")
@PanelInstance(identifier = "brw-access",
@PanelInstance(identifier = "brw-candidateMembers",
applicableForType = RoleType.class,
applicableForOperation = OperationTypeType.WIZARD,
display = @PanelDisplay(label = "PageRole.wizard.step.access.applicationRole", icon = "fa fa-list"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleAnalysisClusterType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;

/**
* The BusinessRoleApplicationDto class represents a Data Transfer Object (DTO) that holds
* information about a specific role, its associated cluster, and a list of BusinessRoleDtos that holds information
* about a user's delta to a specific role.
*/
public class BusinessRoleApplicationDto implements Serializable {

PrismObject<RoleAnalysisClusterType> cluster;
Expand All @@ -30,7 +35,11 @@ public BusinessRoleApplicationDto(PrismObject<RoleAnalysisClusterType> cluster,
this.businessRoleDtos = businessRoleDtos;
}


/**
* Updates the value of the inducements of the business role.
*
* @param inducements The list of inducements to be updated.
*/
public void updateValue(List<AssignmentType> inducements) {
Set<String> inducementsOidSet = new HashSet<>();
for (AssignmentType inducement : inducements) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.createAssignmentTo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.*;

import com.evolveum.midpoint.prism.PrismContainerValue;

import org.jetbrains.annotations.NotNull;

Expand All @@ -30,6 +29,10 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;

/**
* The BusinessRoleDto class represents a Data Transfer Object (DTO) that holds information
* about a user's assignment to a specific role and associated deltas.
*/
public class BusinessRoleDto implements Serializable {

PrismObject<UserType> prismObjectUser;
Expand All @@ -52,7 +55,6 @@ public BusinessRoleDto(PrismObject<UserType> prismObjectUser, PrismObject<RoleTy
this.include = include;
}


public BusinessRoleDto(@NotNull PrismObject<UserType> prismObjectUser,
@NotNull PrismObject<RoleType> prismObjectRole, PageBase pageBase) {
prepareUserDeltas(prismObjectUser, prismObjectRole, pageBase);
Expand All @@ -66,6 +68,12 @@ private List<DeltaDto> prepareDeltaDtos(List<ObjectDelta<? extends ObjectType>>
return deltaDtoList;
}

/**
* Updates the value of the BusinessRoleDto object for new inducements.
*
* @param inducements The list of inducements to be used for updating the value.
* @param pageBase The pageBase object.
*/
public void updateValue(List<AssignmentType> inducements, PageBase pageBase) {
Set<String> inducementsOidSet = new HashSet<>();
for (AssignmentType inducement : inducements) {
Expand All @@ -79,69 +87,55 @@ public void updateValue(List<AssignmentType> inducements, PageBase pageBase) {
}

private void prepareUserDeltas(@NotNull PrismObject<UserType> prismObjectUser,
@NotNull PrismObject<RoleType> prismObjectRole, PageBase pageBase) {
@NotNull PrismObject<RoleType> businessRole, PageBase pageBase) {
List<ObjectDelta<? extends ObjectType>> deltas = new ArrayList<>();

UserType userObject = prismObjectUser.asObjectable();
String userOid = userObject.getOid();

ObjectDelta<UserType> addDelta = addRoleAssignment(userOid, prismObjectRole, pageBase);
deltas.add(addDelta);

// TODO consider using methods from RoleManagementUtil here

List<String> userRolesAssignmentOids = getRolesOidAssignment(userObject);
List<String> roleRolesAssignmentOids = getRolesOidInducements(prismObjectRole);
List<String> roleRolesAssignmentOids = getRolesOidInducements(businessRole);

int delete = 0;
Collection<PrismContainerValue<AssignmentType>> unassignRoleCollection = new ArrayList<>();
for (String assignmentOid : userRolesAssignmentOids) {
if (roleRolesAssignmentOids.contains(assignmentOid)) {
ObjectDelta<UserType> deleteDelta = deleteRoleAssignment(userOid, assignmentOid, pageBase);
deltas.add(deleteDelta);
AssignmentType assignmentTo = createAssignmentTo(assignmentOid, ObjectTypes.ROLE, pageBase.getPrismContext());
unassignRoleCollection.add(assignmentTo.asPrismContainerValue());
delete++;
}
}

AssignmentType assignmentRole = createAssignmentTo(businessRole);
ObjectDelta<UserType> delta = calculateUserAssignDelta(userOid, unassignRoleCollection, assignmentRole, pageBase);
deltas.add(delta);

int roleAssignmentCount = roleRolesAssignmentOids.size();

int extraAssignmentCount = Math.max(0, roleAssignmentCount - delete);

this.include = delete > 0;
this.prismObjectUser = prismObjectUser;
this.prismRoleObject = prismObjectRole;
this.prismRoleObject = businessRole;
this.objectDeltas = deltas;
this.deltaDtos = prepareDeltaDtos(objectDeltas);
this.assignedCount = extraAssignmentCount;
this.unassignedCount = delete;
}

private ObjectDelta<UserType> deleteRoleAssignment(
private ObjectDelta<UserType> calculateUserAssignDelta(
@NotNull String userOid,
@NotNull String roleOid, PageBase pageBase) {

AssignmentType assignmentTo = createAssignmentTo(roleOid, ObjectTypes.ROLE, pageBase.getPrismContext());
ObjectDelta<UserType> objectDelta = null;
try {
objectDelta = pageBase.getPrismContext()
.deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT)
.delete(assignmentTo)
.asObjectDelta(userOid);
return objectDelta;
} catch (SchemaException e) {
throw new RuntimeException(e);
}
}

private ObjectDelta<UserType> addRoleAssignment(@NotNull String userOid,
@NotNull PrismObject<RoleType> prismObjectRole, PageBase pageBase) {
Collection<PrismContainerValue<AssignmentType>> unasignCollection, AssignmentType assignRole, PageBase pageBase) {

AssignmentType assignmentTo = createAssignmentTo(prismObjectRole);
ObjectDelta<UserType> objectDelta = null;
ObjectDelta<UserType> objectDelta;
try {
objectDelta = pageBase.getPrismContext()
.deltaFor(UserType.class)
.item(UserType.F_ASSIGNMENT)
.add(assignmentTo)
.delete(unasignCollection)
.add(assignRole)
.asObjectDelta(userOid);
return objectDelta;
} catch (SchemaException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@

import java.util.List;

import org.apache.commons.math3.util.MathArrays;
import org.apache.wicket.model.LoadableDetachableModel;

import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.wicket.chartjs.*;


/**
* The RoleAnalysisAggregateChartModel class is a LoadableModel that generates aggregate
* charts for role analysis based on provided data.
*/
public class RoleAnalysisAggregateChartModel extends LoadableModel<ChartConfiguration> {

LoadableDetachableModel<List<RoleAnalysisModel>> roleAnalysisModels;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

package com.evolveum.midpoint.gui.impl.page.admin.role.mining.model;

/**
* The RoleAnalysisModel class stores role analysis data, count of roles and users that are used in the histogram chart.
* It displays the number of grouped roles with same number of users and the number of users that are assigned to the roles.
*/
public class RoleAnalysisModel {

int rolesCount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ protected AssignmentHolderOperationalButtonsPanel<RoleAnalysisClusterType> creat
return super.createButtonsPanel(id, wrapperModel);
}

@Override
protected void onBackPerform(AjaxRequestTarget target) {
PageParameters parameters = new PageParameters();
ObjectReferenceType roleAnalysisSessionRef = getModelObjectType().getRoleAnalysisSessionRef();
parameters.add(OnePageParameterEncoder.PARAMETER, roleAnalysisSessionRef.getOid());
parameters.add("panelId", "clusters");
Class<? extends PageBase> detailsPageClass = DetailsPageUtil
.getObjectDetailsPage(RoleAnalysisSessionType.class);
((PageBase) getPage()).navigateToNext(detailsPageClass, parameters);
}

@Override
public void addAdditionalButtons(RepeatingView repeatingView) {
CompositedIconBuilder iconBuilder = new CompositedIconBuilder().setBasicIcon(GuiStyleConstants.CLASS_OBJECT_TASK_ICON, LayeredIconCssStyle.IN_ROW_STYLE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,11 @@ public IModel<List<ContainerPanelConfigurationType>> getPanelConfigurations() {
return panelConfigurations;
}

@Override
protected void onBackPerform(AjaxRequestTarget target) {
((PageBase) getPage()).navigateToNext(PageRoleAnalysis.class);
}

private DetailsFragment createRoleWizardFragment(Class<? extends AbstractWizardPanel> clazz) {

return new DetailsFragment(ID_DETAILS_VIEW, ID_TEMPLATE_VIEW, PageRoleAnalysisSession.this) {
Expand All @@ -280,7 +285,8 @@ protected void initFragmentLayout() {
Constructor<? extends AbstractWizardPanel> constructor = clazz.getConstructor(String.class, WizardPanelHelper.class);
AbstractWizardPanel wizard = constructor.newInstance(ID_TEMPLATE, createObjectWizardPanelHelper());
add(wizard);
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException ignored) {
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException ignored) {

}
}
Expand Down

0 comments on commit b086398

Please sign in to comment.