Skip to content

Commit

Permalink
Update role mining feature
Browse files Browse the repository at this point in the history
1. Clustering.
2. Business roles search.
  • Loading branch information
tchrapovic committed Jun 16, 2023
1 parent d61b9f4 commit 4165c9b
Show file tree
Hide file tree
Showing 32 changed files with 1,788 additions and 64 deletions.
1 change: 1 addition & 0 deletions config/sql/native-new/postgres-new-audit.sql
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ DO $$ BEGIN
'RESOURCE',
'ROLE',
'MINING',
'CLUSTER',
'SECURITY_POLICY',
'SEQUENCE',
'SERVICE',
Expand Down
33 changes: 33 additions & 0 deletions config/sql/native-new/postgres-new.sql
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ CREATE TYPE ContainerType AS ENUM (
'TRIGGER');

ALTER TYPE ObjectType ADD VALUE 'MINING';
ALTER TYPE ObjectType ADD VALUE 'CLUSTER';
-- NOTE: Keep in sync with the same enum in postgres-new-audit.sql!
CREATE TYPE ObjectType AS ENUM (
'ABSTRACT_ROLE',
Expand Down Expand Up @@ -77,6 +78,7 @@ CREATE TYPE ObjectType AS ENUM (
'RESOURCE',
'ROLE',
'MINING',
'CLUSTER',
'SECURITY_POLICY',
'SEQUENCE',
'SERVICE',
Expand Down Expand Up @@ -1185,6 +1187,37 @@ CREATE INDEX m_mining_table_rolesCount_idx ON m_mining_table (rolesCount);
CREATE INDEX m_mining_table_membersCount_idx ON m_mining_table (membersCount);
CREATE INDEX m_mining_table_similarGroupsCount_idx ON m_mining_table (similarGroupsCount);

CREATE TABLE m_cluster_table (
oid UUID NOT NULL PRIMARY KEY REFERENCES m_object_oid(oid),
objectType ObjectType GENERATED ALWAYS AS ('CLUSTER') STORED
CHECK (objectType = 'CLUSTER'),
identifier TEXT,
riskLevel TEXT,
roles TEXT[],
rolesCount INTEGER,
members TEXT[],
membersCount INTEGER,
similarGroups TEXT[],
similarGroupsCount INTEGER,
minOccupation INTEGER,
maxOccupation INTEGER,
mean TEXT,
density TEXT
)
INHERITS (m_assignment_holder);

CREATE TRIGGER m_cluster_table_oid_insert_tr BEFORE INSERT ON m_cluster_table
FOR EACH ROW EXECUTE FUNCTION insert_object_oid();
CREATE TRIGGER m_cluster_table_update_tr BEFORE UPDATE ON m_cluster_table
FOR EACH ROW EXECUTE FUNCTION before_update_object();
CREATE TRIGGER m_cluster_table_oid_delete_tr AFTER DELETE ON m_cluster_table
FOR EACH ROW EXECUTE FUNCTION delete_object_oid();

CREATE INDEX m_cluster_table_identifier_idx ON m_cluster_table (identifier);
CREATE INDEX m_cluster_table_riskLevel_idx ON m_cluster_table (riskLevel);
CREATE INDEX m_cluster_table_rolesCount_idx ON m_cluster_table (rolesCount);
CREATE INDEX m_cluster_table_membersCount_idx ON m_cluster_table (membersCount);
CREATE INDEX m_cluster_table_similarGroupsCount_idx ON m_cluster_table (similarGroupsCount);



Expand Down
5 changes: 5 additions & 0 deletions gui/admin-gui/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
<name>midPoint User Interface - admin web gui</name>

<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2010-2023 Evolveum and contributors
*
* This work is dual-licensed under the Apache License 2.0
* and European Union Public License. See LICENSE file for details.
*/

package com.evolveum.midpoint.gui.api.component.mining.analyse.tools.utils;

import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.model.api.ModelService;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.GetOperationOptionsBuilder;
import com.evolveum.midpoint.schema.ResultHandler;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ClusterType;

public class ClusterObjectUtils {

public static void importClusterTypeObject(OperationResult result, @NotNull PageBase pageBase, @NotNull PrismObject<ClusterType> cluster) {
Task task = pageBase.createSimpleTask("Import ClusterType object");
pageBase.getModelService().importObject(cluster, null, task, result);
}

public static void deleteClusterObjects(OperationResult result, @NotNull PageBase pageBase) throws Exception {
ResultHandler<ClusterType> handler = (object, parentResult) -> {

try {
pageBase.getRepositoryService().deleteObject(ClusterType.class, object.getOid(), result);
} catch (ObjectNotFoundException e) {
throw new RuntimeException(e);
}

return true;
};

ModelService service = pageBase.getModelService();
GetOperationOptionsBuilder optionsBuilder = pageBase.getSchemaService().getOperationOptionsBuilder()
.raw()
.resolveNames();
service.searchObjectsIterative(ClusterType.class, null, handler, optionsBuilder.build(),
pageBase.createSimpleTask("Search iterative cluster objects"), result);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ protected byte[] getImageData(Attributes attributes) {
graphics.fillRect(x, y, 1, 1);
}
}
System.out.println("Image generating end");

graphics.dispose();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,22 @@ public static List<MiningType> getMiningList(@NotNull PageBase pageBase) throws
}
}

public static List<PrismObject<MiningType>> filterMiningTypeObjects(PageBase pageBase) {

String string = DOT_CLASS + "filterMiningTypes";
OperationResult result = new OperationResult(string);

List<PrismObject<MiningType>> prismObjectList = null;
try {
prismObjectList = pageBase.getMidpointApplication().getRepositoryService()
.searchObjects(MiningType.class, null, null, result);
} catch (CommonException e) {
e.printStackTrace();
}

return prismObjectList;
}

public static PrismObject<RoleType> getRoleObject(@NotNull PageBase pageBase, String oid,
OperationResult result) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

<div class="row">
<span class="btn btn-default" style="width:300px"
wicket:id="id_generate_mining_set" >
wicket:id="id_generate_mining_set">
</span>
</div>
<div class="row">
Expand Down Expand Up @@ -63,6 +63,33 @@
<div
wicket:id="datatable_cluster"></div>


<div class="col-xl-12">

<div class="border-top my-3 row justify-content-center"></div>
<div>
<form
wicket:id="thresholds_form_cluster">

<div class="d-flex flex-wrap gap-2 w-100 row">
<input type="text" placeholder="Eps" style="width:200px" class="form-control form-control-sm mp-w-12"
wicket:id="eps_cluster">
<input type="text" placeholder="Intersection" style="width:200px" class="form-control form-control-sm mp-w-12"
wicket:id="intersection_field_min_cluster">
<input type="text" placeholder="Group" style="width:200px" class="form-control form-control-sm mp-w-12"
wicket:id="group_min_cluster">
<input class="btn btn-default" type="submit" value="Update clusters"
wicket:id="ajax_submit_link_cluster"/>

</div>
</form>
</div>

</div>

<div
wicket:id="datatable_cluster_ds"></div>

</wicket:extend>

</body>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,35 @@
package com.evolveum.midpoint.gui.impl.page.admin.role;

import static com.evolveum.midpoint.gui.api.component.mining.DataStorage.resetAll;
import static com.evolveum.midpoint.gui.api.component.mining.analyse.tools.utils.ClusterObjectUtils.deleteClusterObjects;
import static com.evolveum.midpoint.gui.api.component.mining.analyse.tools.utils.ClusterObjectUtils.importClusterTypeObject;
import static com.evolveum.midpoint.gui.api.component.mining.analyse.tools.utils.MiningObjectUtils.*;

import java.util.List;

import org.apache.wicket.Component;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.image.Image;
import org.apache.wicket.model.Model;
import org.apache.wicket.request.resource.PackageResourceReference;
import org.jetbrains.annotations.NotNull;

import com.evolveum.midpoint.authentication.api.authorization.AuthorizationAction;
import com.evolveum.midpoint.authentication.api.authorization.PageDescriptor;
import com.evolveum.midpoint.authentication.api.authorization.Url;
import com.evolveum.midpoint.gui.api.page.PageBase;
import com.evolveum.midpoint.gui.impl.page.admin.role.panels.GenerateDataPanelRBAM;
import com.evolveum.midpoint.gui.impl.page.admin.role.panels.tables.ClusterBasicTable;
import com.evolveum.midpoint.gui.impl.page.admin.role.panels.tables.ClusterTable;
import com.evolveum.midpoint.gui.impl.page.admin.role.test.cluster.ClusterAlgorithm;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.AuthorizationConstants;
import com.evolveum.midpoint.web.component.AjaxButton;
import com.evolveum.midpoint.web.page.admin.PageAdmin;
import com.evolveum.midpoint.web.util.OnePageParameterEncoder;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ClusterType;

@PageDescriptor(
urls = {
Expand All @@ -48,11 +55,19 @@ public class PageRoleMining extends PageAdmin {

private static final String ID_GENERATE_DATA_PANEL = "generate_data_panel";
private static final String ID_FORM_THRESHOLDS = "thresholds_form";

private static final String ID_FORM_THRESHOLDS_CLUSTER = "thresholds_form_cluster";
private static final String ID_DATATABLE_CLUSTER = "datatable_cluster";
private static final String ID_DATATABLE_CLUSTER_DS = "datatable_cluster_ds";

double jcThreshold = 0.80;
int minIntersection = 5;

double eps = 0.2;
int minIntersectionEps = 10;

int minGroup = 10;

public PageRoleMining() {
super();
}
Expand All @@ -63,20 +78,28 @@ protected void onInitialize() {
add(generateObjectsPanel());
add(getGenerateMiningTypeButton());
add(getDeleteMiningTypeButton());

add(getSimilarityTypeButton());
add(similarityMining());
add(new ClusterTable(ID_DATATABLE_CLUSTER));

add(clusterForm());
add(new ClusterTable(ID_DATATABLE_CLUSTER).setOutputMarkupId(true));
add(new ClusterBasicTable(ID_DATATABLE_CLUSTER_DS).setOutputMarkupId(true));

}

protected Component getDSTable() {
return get(((PageBase) getPage()).createComponentPath(ID_DATATABLE_CLUSTER_DS));
}

public AjaxButton getGenerateMiningTypeButton() {
AjaxButton ajaxLinkAssign = new AjaxButton("id_generate_mining_set", Model.of("Import MiningType Objects")) {
@Override
public void onClick(AjaxRequestTarget target) {
OperationResult result = new OperationResult("Generate miningType object");
try {

importMiningGroups(result, getPageBase(),15);
importMiningGroups(result, getPageBase(), 15);
} catch (Exception e) {
throw new RuntimeException(e);
}
Expand Down Expand Up @@ -141,6 +164,67 @@ public void onClick(AjaxRequestTarget target) {
return ajaxLinkAssign;
}

public Form<?> clusterForm() {

Form<?> form = new Form<Void>(ID_FORM_THRESHOLDS_CLUSTER);

TextField<Double> thresholdField = new TextField<>("eps_cluster", Model.of(eps));
thresholdField.setOutputMarkupId(true);
thresholdField.setOutputMarkupPlaceholderTag(true);
thresholdField.setVisible(true);
form.add(thresholdField);

TextField<Integer> minIntersectionField = new TextField<>("intersection_field_min_cluster", Model.of(minIntersectionEps));
minIntersectionField.setOutputMarkupId(true);
minIntersectionField.setOutputMarkupPlaceholderTag(true);
minIntersectionField.setVisible(true);
form.add(minIntersectionField);

TextField<Integer> minGroupField = new TextField<>("group_min_cluster", Model.of(minGroup));
minGroupField.setOutputMarkupId(true);
minGroupField.setOutputMarkupPlaceholderTag(true);
minGroupField.setVisible(true);
form.add(minGroupField);

AjaxSubmitLink ajaxSubmitLink = new AjaxSubmitLink("ajax_submit_link_cluster", form) {
@Override
protected void onSubmit(AjaxRequestTarget target) {
eps = thresholdField.getModelObject();
minIntersectionEps = minIntersectionField.getModelObject();
minGroup = minGroupField.getModelObject();

ClusterAlgorithm clusterAlgorithm = new ClusterAlgorithm(getPageBase());
List<PrismObject<ClusterType>> miningTypeList = clusterAlgorithm.executeClustering(eps, minGroup, minIntersection);
OperationResult resultD = new OperationResult("Delete Cluster object");

try {
deleteClusterObjects(resultD, getPageBase());
} catch (Exception e) {
throw new RuntimeException(e);
}

OperationResult result = new OperationResult("Generate Cluster object");
try {
for (PrismObject<ClusterType> clusterTypePrismObject : miningTypeList) {
importClusterTypeObject(result, getPageBase(), clusterTypePrismObject);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
target.add(getDSTable());

target.add(thresholdField);
target.add(minIntersectionField);
target.add(minGroupField);
}
};

ajaxSubmitLink.setOutputMarkupId(true);
form.add(ajaxSubmitLink);

return form;
}

public Form<?> similarityMining() {

Form<?> form = new Form<Void>(ID_FORM_THRESHOLDS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

<div wicket:id="datatable_extra"></div>


<div class="main-button-bar justify-content-end">
<a class="btn btn-primary btn-sm" wicket:id="cancel"/>
<a class="btn btn-primary btn-sm" wicket:id="ok"/>
Expand Down

0 comments on commit 4165c9b

Please sign in to comment.