Skip to content

Commit

Permalink
TestCsvReportAllAssignments added to report-impl
Browse files Browse the repository at this point in the history
switchAccessesMetadata() pulled up to AbstractModelIntegrationTest
  • Loading branch information
virgo47 committed Feb 14, 2023
1 parent bc117b6 commit 94dbf51
Show file tree
Hide file tree
Showing 5 changed files with 349 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import static com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType.F_ASSIGNMENT;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentHolderType.F_ROLE_MEMBERSHIP_REF;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType.F_ROLE_MANAGEMENT;

import java.io.File;
import java.util.Arrays;
Expand Down Expand Up @@ -299,15 +298,6 @@ public void test910AccessesMetadataDisabledThenEnabledAndAddedAfterRecompute() t
new ExpectedAssignmentPath(businessRole1Oid, appRole1Oid, appService1Oid));
}

private void switchAccessesMetadata(Boolean value, Task task, OperationResult result)
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException,
CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException {
executeChanges(prismContext.deltaFor(SystemConfigurationType.class)
.item(F_ROLE_MANAGEMENT, RoleManagementConfigurationType.F_ACCESSES_METADATA_ENABLED).replace(value)
.<SystemConfigurationType>asObjectDelta(SystemObjectsType.SYSTEM_CONFIGURATION.value()),
null, task, result);
}

// TODO add check of no phantom deltas when no metadata change on refs

private UserType newUserWithBusinessRole1() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import static com.evolveum.midpoint.schema.constants.SchemaConstants.*;
import static com.evolveum.midpoint.util.MiscUtil.argCheck;
import static com.evolveum.midpoint.xml.ns._public.common.audit_3.AuditEventRecordType.F_TIMESTAMP;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType.F_ROLE_MANAGEMENT;

import java.io.*;
import java.net.ConnectException;
Expand Down Expand Up @@ -6808,6 +6809,15 @@ protected String determineSingleInducedRuleId(String roleOid, OperationResult re
return roleOid + ":" + id;
}

protected void switchAccessesMetadata(Boolean value, Task task, OperationResult result)
throws ObjectAlreadyExistsException, ObjectNotFoundException, SchemaException, ExpressionEvaluationException,
CommunicationException, ConfigurationException, PolicyViolationException, SecurityViolationException {
executeChanges(prismContext.deltaFor(SystemConfigurationType.class)
.item(F_ROLE_MANAGEMENT, RoleManagementConfigurationType.F_ACCESSES_METADATA_ENABLED).replace(value)
.<SystemConfigurationType>asObjectDelta(SystemObjectsType.SYSTEM_CONFIGURATION.value()),
null, task, result);
}

public interface FunctionCall<X> {
X execute() throws CommonException, IOException;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* 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.report;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.testng.annotations.Test;

import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.test.TestResource;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;

@ContextConfiguration(locations = { "classpath:ctx-report-test-main.xml" })
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class TestCsvReportAllAssignments extends TestCsvReport {

private static final int USERS = 50;

static final TestResource<ReportType> REPORT_INDIRECT_ASSIGNMENTS = new TestResource<>(TEST_DIR_REPORTS,
"report-indirect-assignments.xml", "7f1695f2-d826-4d78-a046-b8249b79d2b5");

@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
// Only for Native repo, as Generic repo does not support reference search.
if (!isNativeRepository()) {
return;
}
super.initSystem(initTask, initResult);

repoAdd(TASK_EXPORT_CLASSIC, initResult);

repoAdd(REPORT_INDIRECT_ASSIGNMENTS, initResult);

String appServiceOid = addObject(new ServiceType().name("appService").asPrismObject(), initTask, initResult);
String appRoleOid = addObject(new RoleType().name("appRole")
.inducement(new AssignmentType().targetRef(appServiceOid, ServiceType.COMPLEX_TYPE))
.asPrismObject(), initTask, initResult);
String businessRoleOid = addObject(new RoleType().name("businessRole")
.inducement(new AssignmentType().targetRef(appRoleOid, RoleType.COMPLEX_TYPE))
.asPrismObject(), initTask, initResult);

// one user without metadata to check the report's robustness
switchAccessesMetadata(false, initTask, initResult);
addObject(new UserType().name("user-without-metadata")
.assignment(new AssignmentType().targetRef(businessRoleOid, RoleType.COMPLEX_TYPE))
.asPrismObject(), initTask, initResult);
switchAccessesMetadata(true, initTask, initResult);

for (int i = 1; i <= USERS; i++) {
UserType user = new UserType()
.name(String.format("user-%05d", i))
.assignment(new AssignmentType().targetRef(businessRoleOid, RoleType.COMPLEX_TYPE));
if (i % 3 == 0) {
// To mix it up, every third user has also direct assignment to the service.
user.assignment(new AssignmentType()
.targetRef(appServiceOid, ServiceType.COMPLEX_TYPE)
.activation(new ActivationType()
// for some output variation
.validFrom(MiscUtil.asXMLGregorianCalendar(Instant.now().minus(10, ChronoUnit.DAYS)))
.validTo(MiscUtil.asXMLGregorianCalendar(Instant.now().plus(1, ChronoUnit.DAYS)))));
}
addObject(user.asPrismObject(), initTask, initResult);
}
}

@Test
public void test100RunReport() throws Exception {
skipIfNotNativeRepository();
// 50 * 3 (normal) + 50 // 3 (direct assignments) + 3 (without metadata) + jack + header
// (subscription footer is considered automatically later, do not count it here)
runTest(REPORT_INDIRECT_ASSIGNMENTS, 171, 7, null);
}

private void runTest(TestResource<ReportType> reportResource, int expectedRows, int expectedColumns,
String lastLine, ReportParameterType parameters) throws Exception {
given();

Task task = getTestTask();
OperationResult result = task.getResult();

if (parameters != null) {
modifyObjectReplaceContainer(TaskType.class,
TASK_EXPORT_CLASSIC.oid,
ItemPath.create(TaskType.F_ACTIVITY,
ActivityDefinitionType.F_WORK,
WorkDefinitionsType.F_REPORT_EXPORT,
ClassicReportImportWorkDefinitionType.F_REPORT_PARAM),
task,
result,
parameters);
}

dummyTransport.clearMessages();

runExportTaskClassic(reportResource, result);

when();

waitForTaskCloseOrSuspend(TASK_EXPORT_CLASSIC.oid);

then();

assertTask(TASK_EXPORT_CLASSIC.oid, "after")
.assertSuccess()
.display()
.assertHasArchetype(SystemObjectsType.ARCHETYPE_REPORT_EXPORT_CLASSIC_TASK.value());

PrismObject<TaskType> reportTask = getObject(TaskType.class, TASK_EXPORT_CLASSIC.oid);
basicCheckOutputFile(reportTask, expectedRows, expectedColumns, lastLine);

assertNotificationMessage(reportResource);
}

private void runTest(TestResource<ReportType> reportResource, int expectedRows, int expectedColumns, String lastLine)
throws Exception {
runTest(reportResource, expectedRows, expectedColumns, lastLine, null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<report xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:q="http://prism.evolveum.com/xml/ns/public/query-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="7f1695f2-d826-4d78-a046-b8249b79d2b5">
<name>Indirect assignment report</name>
<description>Shows information stored in roleMembershipRef value metadata.</description>
<!--
Serious test would have this archetype, but it's not available for test.
<assignment>
<targetRef oid="00000000-0000-0000-0000-000000000171" type="ArchetypeType"/>
</assignment>
-->
<objectCollection>
<collection>
<!-- Type is declared in the view element. -->
<filter>
<q:text>. ownedBy (@type = UserType and @path = roleMembershipRef
/*and name = 'user-v1'*/)
</q:text>
</filter>
</collection>
<subreport>
<name>data</name>
<order>1</order>
<asRow>true</asRow>
<expression>
<script>
<objectVariableMode>prismReference</objectVariableMode>
<code>
def values = object?.valueMetadata?.realValues?.findAll {
m -> m.provenance.assignmentPath != null
}?.collect { m ->
def assignmentPath = m.provenance.assignmentPath
def directAssignmentId = assignmentPath.segment[0].assignmentId
def owner = midpoint.resolveReferenceIfExists(m.provenance.assignmentPath.sourceRef)
def directAssignment = null
if (owner != null) {
for (def assignment : owner.assignment) {
if (assignment?.id == directAssignmentId) {
directAssignment = assignment
break
}
}
}

// we'll return object/hashmap for each assignment path metadata value
return [
assignmentPath: m.provenance.assignmentPath,
createTimestamp: m.storage?.createTimestamp,
owner: owner,
assignment: directAssignment
]
}
return values
</code>
</script>
</expression>
</subreport>
<view>
<type>c:ObjectReferenceType</type>
<paging>
<q:orderBy>../name</q:orderBy>
</paging>
<column>
<name>user</name>
<display>
<label>User</label>
</display>
<export>
<expression>
<script>
<objectVariableMode>prismReference</objectVariableMode>
<code>
return !data.owner ? 'Unknown owner' : data.owner.name.orig
</code>
</script>
</expression>
</export>
</column>
<column>
<name>nameColumn</name>
<display>
<label>Access</label>
</display>
<previousColumn>user</previousColumn>
<export>
<expression>
<script>
<objectVariableMode>prismReference</objectVariableMode>
<code>
return input?.object?.name
</code>
</script>
</expression>
</export>
</column>
<column>
<name>allPath</name>
<display>
<label>Path</label>
</display>
<previousColumn>nameColumn</previousColumn>
<!-- TODO: currently only one path is shown -->
<export>
<expression>
<script>
<objectVariableMode>prismReference</objectVariableMode>
<code>
//com.evolveum.midpoint.util.DebugUtil.dump(assignmentPaths)
if (!data.assignmentPath) {
return '?'
}

def segments = data.assignmentPath.segment

var rolePaths = []
for (int i = 0; i &lt; segments.size(); i++) {
rolePaths.add(midpoint.resolveReferenceIfExists(segments[i].targetRef)?.
name?.orig)
}
return rolePaths.join(' -&gt; ')
</code>
</script>
</expression>
</export>
</column>
<column>
<!-- This is probably not important column, everything is in the path column anyway. -->
<name>parent</name>
<display>
<label>Parent</label>
</display>
<previousColumn>allPath</previousColumn>
<export>
<expression>
<script>
<code>
if (!data.assignmentPath) {
return "?"
}

def segments = data.assignmentPath.segment
def segLen = segments.size()
if (segLen == 1) {
return 'Direct'
} else {
return midpoint.resolveReferenceIfExists(segments[segLen - 2].targetRef)?.name?.orig
}
</code>
</script>
</expression>
</export>
</column>
<column>
<!-- We don't store refs/metadata for disabled assignments, so this is always Enabled. -->
<name>activation</name>
<display>
<label>Activation</label>
</display>
<previousColumn>parent</previousColumn>
<export>
<expression>
<script>
<code>data.assignment?.activation?.effectiveStatus</code>
</script>
</expression>
</export>
</column>
<column>
<name>validTo</name>
<display>
<label>Valid to</label>
</display>
<previousColumn>activation</previousColumn>
<export>
<expression>
<script>
<code>data.assignment?.activation?.validTo</code>
</script>
</expression>
</export>
</column>
<column>
<name>since</name>
<display>
<label>Since</label>
</display>
<previousColumn>validTo</previousColumn>
<export>
<expression>
<script>
<code>data.createTimestamp</code>
</script>
</expression>
</export>
</column>
</view>
</objectCollection>
</report>

0 comments on commit 94dbf51

Please sign in to comment.