From b09ce89b5a2dc684816ed0e6efeac9a56fd211e4 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 9 Mar 2020 11:09:42 +0100 Subject: [PATCH 1/5] Experiments with AD connector --- pom.xml | 4221 +++++++-------- testing/conntest/pom.xml | 5 + .../AbstractLdapSynchronizationTest.java | 1027 ++-- .../ad/AbstractAdLdapMultidomainTest.java | 4693 +++++++++-------- .../conntest/ad/AbstractAdLdapTest.java | 2513 +++++---- .../ad-ldap-multidomain/resource-chimera.xml | 1711 +++--- .../ad-ldap-multidomain/task-sync.xml | 28 + .../src/test/resources/logback-test.xml | 141 +- 8 files changed, 7227 insertions(+), 7112 deletions(-) create mode 100644 testing/conntest/src/test/resources/ad-ldap-multidomain/task-sync.xml diff --git a/pom.xml b/pom.xml index 5cf468d864b..f2b01b435d7 100644 --- a/pom.xml +++ b/pom.xml @@ -1,2108 +1,2113 @@ - - - - - 4.0.0 - - - - com.evolveum.midpoint - midpoint - 4.1-SNAPSHOT - pom - - midPoint Project - Utility module to compile all of the maven based midPoint projects. - - evolveum - https://www.evolveum.com - - - - Apache License v2.0 - https://www.apache.org/licenses/LICENSE-2.0.txt - repo - - - European Union Public License - https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 - repo - - - - - tools - infra - repo - provisioning - model - custom - gui - icf-connectors - testing - - - - https://github.com/Evolveum/midpoint.git - git@github.com:Evolveum/midpoint.git - https://github.com/Evolveum/midpoint.git - - - Atlassian JIRA - https://jira.evolveum.com/browse/MID - - - - evolveum-nexus - Internal Releases - https://nexus.evolveum.com/nexus/content/repositories/releases/ - - - evolveum-nexus - Internal Snapshots - https://nexus.evolveum.com/nexus/content/repositories/snapshots/ - - - - - - - UTF-8 - 1.8 - en_US - true - false - false - - - ${describe} - ${maven.build.timestamp} - EEE, d MMM yyyy HH:mm:ss Z - - - -Xms1024m -Xmx4096m - -Xms1024m -Xmx4096m -Duser.language=en - - full - - true - - - 2.6 - 2.6 - 3.7 - 1.2 - 3.3.1 - 3.3.0 - 2.2.0 - 2.4.7 - 2.3.1 - 2.3.0.1 - 2.3.0.1 - 2.6.2 - 2.3.0.e3 - 3.141.59 - 1.7.25 - 1.2.3 - 2.1.8.RELEASE - - 5.1.9.RELEASE - 5.1.6.RELEASE - 2.0.0.M30 - 1.2.1.Final - 3.5.0 - 6.14.3 - 1.2 - 2.1.1 - 2.2.3 - 5.2.12.Final - 1.4.193 - 42.2.2 - 6.4.0.jre8 - 2.3.0 - 6.0.6 - 8.6.0 - 2.5.8 - 1.3 - 2.1.4 - 1.5.0.10 - 6.5.0 - 10.11.1.1 - 1.8.0 - 2.10.0 - 1.23 - 3.0.0-M3 - 0.9.11 - 28.1-jre - 1.72 - 3.0.0-M3 - 1.8 - 1.4.0 - 7.1.1 - 2.3.2 - 7.0 - 2.3.1 - 1.1.3 - 1.2.0 - 9.4.20.v20190813 - 3.6.2 - 3.1.0 - 2.7.2 - 2.12.0 - - - - - - - - javax.xml.soap - javax.xml.soap-api - ${javax.xml.soap.version} - - - javax.xml.ws - jaxws-api - ${jaxws-api.version} - - - org.apache.geronimo.specs - geronimo-ws-metadata_2.0_spec - ${geronimo-ws-metadata_2.0_spec.version} - - - com.sun.activation - javax.activation - ${activation.version} - - - - - org.springframework.boot - spring-boot-dependencies - ${spring.boot.version} - pom - import - - - org.springframework.boot - spring-boot-starter-test - ${spring.boot.version} - - - org.ow2.asm - asm - - - - - - - org.reflections - reflections - ${reflections.version} - - - com.google.guava - guava - - - - - - - org.apache.wicket - wicket-core - ${wicket.version} - - - org.apache.wicket - wicket-request - ${wicket.version} - - - org.apache.wicket - wicket-ioc - ${wicket.version} - - - org.ow2.asm - asm - - - org.apache.ant - ant - - - - - org.apache.wicket - wicket-util - ${wicket.version} - - - org.apache.wicket - wicket-devutils - ${wicket.version} - - - org.apache.wicket - wicket-auth-roles - ${wicket.version} - - - org.apache.wicket - wicket-spring - ${wicket.version} - - - org.springframework - * - - - - - org.apache.wicket - wicket-extensions - ${wicket.version} - - - org.apache.wicket - wicket-datetime - 8.0.0-M7 - - - org.ow2.asm - asm - ${asm.version} - - - org.apache.commons - commons-email - ${commons-email.version} - - - javax.activation - activation - - - - - org.codehaus.groovy - groovy-all - ${groovy.version} - pom - - - org.codehaus.groovy - groovy-ant - - - org.codehaus.groovy - groovy-test-junit5 - - - org.codehaus.groovy - groovy-test - - - org.codehaus.groovy - groovy-testng - - - - - org.codehaus.groovy - groovy - ${groovy.version} - - - org.python - jython - 2.5.3 - - - com.h2database - h2 - ${h2.version} - - - org.hibernate - hibernate-core - ${hibernate.version} - - - javax.annotation - jsr250-api - - - - - org.hibernate.javax.persistence - hibernate-jpa-2.1-api - 1.0.0.Final - - - org.javassist - javassist - - 3.25.0-GA - - - com.zaxxer - HikariCP - 3.3.1 - - - org.slf4j - jul-to-slf4j - ${slf4j.version} - - - ch.qos.logback - logback-classic - ${logback.version} - - - ch.qos.logback - logback-core - ${logback.version} - - - org.codehaus.janino - janino - 3.0.10 - - - com.sleepycat - je - 5.0.103 - - - - xerces - xercesImpl - ${xerces.version} - - - xalan - xalan - ${xalan.version} - - - org.codehaus.staxmate - staxmate - 2.0.1 - - - stax - stax-api - - - - - javax.xml.bind - jaxb-api - ${jaxb-api.version} - - - com.sun.xml.bind - jaxb-impl - ${jaxb.version} - - - com.sun.xml.bind - jaxb-core - ${jaxb.version} - - - com.sun.xml.bind - jaxb-xjc - ${jaxb-xjc.version} - - - net.sourceforge.ccxjc - cc-xjc-plugin - 2.0 - - - com.sun.xsom - xsom - 20140925 - - - commons-validator - commons-validator - 1.5.1 - - - - commons-logging - commons-logging - - - commons-digester - commons-digester - - - - - commons-beanutils - commons-beanutils - 1.9.4 - - - - commons-logging - commons-logging - - - - - commons-codec - commons-codec - 1.10 - - - commons-collections - commons-collections - 3.2.2 - - - org.apache.commons - commons-configuration2 - 2.6 - - - - commons-logging - commons-logging - - - - - org.apache.commons - commons-text - 1.8 - - - - com.google.code.findbugs - jsr305 - 3.0.2 - - - commons-io - commons-io - ${commons.io.version} - - - commons-lang - commons-lang - ${commons.lang.version} - - - org.apache.commons - commons-lang3 - ${commons.lang3.version} - - - commons-pool - commons-pool - 1.5.6 - - - commons-javaflow - commons-javaflow - 20060411 - - - org.jetbrains - annotations - 18.0.0 - - - javax.annotation - jsr250-api - 1.0 - - - javax.jws - jsr181-api - 1.0-MR1 - - - javax.inject - javax.inject - 1 - - - javax.persistence - persistence-api - 1.0 - true - - - javax.servlet - servlet-api - 2.5 - provided - - - javax.ws.rs - javax.ws.rs-api - 2.1 - - - - org.apache.httpcomponents - httpclient - 4.5.3.e3 - - - - commons-logging - commons-logging - - - - - - org.apache.httpcomponents - httpcore - 4.4.6 - - - org.apache.cxf - cxf-rt-core - ${cxf.version} - - - - org.apache.geronimo.specs - geronimo-javamail_1.4_spec - - - org.apache.geronimo.specs - geronimo-activation_1.1_spec - - - javax.activation - activation - - - - - org.apache.cxf - cxf-core - ${cxf.version} - - - org.jvnet.staxex - stax-ex - - - javax.xml.soap - javax.xml.soap-api - - - - org.glassfish.jaxb - jaxb-xjc - - - - - org.apache.cxf - cxf-rt-frontend-simple - ${cxf.version} - - - org.apache.cxf - cxf-rt-wsdl - ${cxf.version} - - - javax.activation - activation - - - - - org.apache.cxf - cxf-tools-common - ${cxf.version} - - - org.jvnet.staxex - stax-ex - - - javax.xml.soap - javax.xml.soap-api - - - - - org.apache.cxf - cxf-rt-frontend-jaxws - ${cxf.version} - - - org.apache.cxf - cxf-rt-databinding-aegis - ${cxf.version} - - - org.apache.cxf - cxf-rt-transports-local - ${cxf.version} - - - org.apache.cxf - cxf-rt-transports-http - ${cxf.version} - - - - org.apache.httpcomponents - httpclient - - - - org.apache.httpcomponents - httpcore - - - - - org.apache.cxf - cxf-rt-transports-http-jetty - ${cxf.version} - - - org.apache.cxf - cxf-rt-transports-jms - ${cxf.version} - - - org.apache.cxf - cxf-rt-management - ${cxf.version} - - - org.apache.cxf - cxf-rt-bindings-soap - ${cxf.version} - - - org.apache.cxf - cxf-rt-ws-security - ${cxf.version} - - - org.codehaus.woodstox - woodstox-core-asl - - - - - org.apache.cxf - cxf-rt-frontend-jaxrs - ${cxf.version} - - - jakarta.ws.rs - jakarta.ws.rs-api - - - - - org.apache.cxf - cxf-rt-rs-client - ${cxf.version} - - - org.jvnet.staxex - stax-ex - - - javax.xml.soap - javax.xml.soap-api - - - - - org.apache.cxf - cxf-rt-rs-extension-providers - ${cxf.version} - - - org.apache.cxf.xjc-utils - cxf-xjc-runtime - ${cxf-xjc.version} - - - javax.activation - activation - - - - - org.apache.wss4j - wss4j-ws-security-common - ${wss4j.version} - - - org.apache.geronimo.javamail - geronimo-javamail_1.4_mail - - - org.bouncycastle - bcprov-jdk15on - - - com.google.guava - guava - - - - - com.google.guava - guava - ${guava.version} - - - org.apache.wss4j - wss4j-ws-security-dom - ${wss4j.version} - - - org.bouncycastle - bcprov-jdk15on - - - - - - org.codehaus.woodstox - stax2-api - 3.1.4 - - - org.apache.felix - org.osgi.core - 1.4.0 - - - org.forgerock.opendj - opendj - ${opendj.version} - - - - net.tirasa.connid - connector-framework - ${connid.version} - - - net.tirasa.connid - connector-framework-internal - ${connid.version} - - - com.evolveum.polygon - connector-databasetable - 1.4.3.0 - - - com.evolveum.polygon - connector-csv - 2.3 - - - com.evolveum.polygon - connector-ldap - 3.0-M1 - - - - org.slf4j - slf4j-jdk14 - - - - - - com.evolveum.icf - dummy - 1.1.0.0-e1 - - - org.scannotation - scannotation - 1.0.3 - - - - org.slf4j - jcl-over-slf4j - ${slf4j.version} - - - org.slf4j - log4j-over-slf4j - ${slf4j.version} - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.quartz-scheduler - quartz - ${quartz.version} - - - com.mchange - c3p0 - - - com.mchange - mchange-commons-java - - - com.zaxxer - * - - - - - - org.apache.santuario - xmlsec - ${xmlsec.version} - - - javax.xml.stream - stax-api - - - org.codehaus.woodstox - woodstox-core-asl - - - - - org.springframework - spring-core - ${spring.version} - - - - org.springframework - spring-jcl - - - - - org.springframework.security.extensions - spring-security-saml2-core - ${spring.security.saml2.version} - - - commons-logging - commons-logging - - - org.bouncycastle - bcpkix-jdk15on - - - org.bouncycastle - bcprov-jdk15on - - - - - org.cache2k - cache2k-api - ${cache2k.version} - - - org.cache2k - cache2k-core - ${cache2k.version} - - - aopalliance - aopalliance - 1.0 - - - - org.xmlunit - xmlunit-core - ${xmlunit.version} - - - org.xmlunit - xmlunit-legacy - ${xmlunit.version} - - - xml-resolver - xml-resolver - ${xml.resolver.version} - - - mysql - mysql-connector-java - ${jdbc.mysql} - - - org.postgresql - postgresql - ${jdbc.postgres} - - - com.microsoft.sqlserver - mssql-jdbc - ${jdbc.sqlserver} - - - org.mariadb.jdbc - mariadb-java-client - ${jdbc.mariadb} - - - commons-cli - commons-cli - ${commons.cli} - - - org.forgerock.opendj - opendj-ldap-sdk - ${opendj.version} - - - org.apache.velocity - velocity - 1.7 - - - org.apache.derby - derby - ${derby.version} - - - org.apache.derby - derbynet - ${derby.version} - - - org.apache.derby - derbyclient - ${derby.version} - - - - - net.sf.jasperreports - jasperreports - ${jasper.version} - - - xml-apis - xml-apis - - - com.fasterxml.jackson.core - jackson-core - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-annotations - - - - commons-logging - commons-logging - - - bouncycastle - bcmail-jdk14 - - - org.bouncycastle - bcmail-jdk14 - - - bouncycastle - bcprov-jdk14 - - - org.bouncycastle - bcprov-jdk14 - - - org.bouncycastle - bctsp-jdk14 - - - - javax.xml.stream - stax-api - - - - - - stax - stax - 1.2.0 - - - stax - stax-api - - - - - - - org.apache.poi - poi - 3.17 - - - com.fasterxml.jackson.core - jackson-core - ${jackson.version} - - - com.fasterxml.jackson.core - jackson-annotations - ${jackson.version} - - - com.fasterxml.jackson.jaxrs - jackson-jaxrs-base - ${jackson.version} - - - org.yaml - snakeyaml - ${snakeyaml.version} - - - com.fasterxml.jackson.core - jackson-databind - ${jackson.version} - - - com.fasterxml.jackson.module - jackson-module-jaxb-annotations - ${jackson.version} - - - com.fasterxml.jackson.dataformat - jackson-dataformat-yaml - ${jackson.version} - - - org.apache.ws.xmlschema - xmlschema-core - 2.1.0 - - - org.jvnet.jaxb2_commons - jaxb2-basics-runtime - 0.6.3 - - - - - org.apache.maven - maven-plugin-api - ${maven.api.version} - - - org.codehaus.plexus - plexus-component-annotations - - - org.codehaus.plexus - plexus-classworlds - - - - - org.apache.maven - maven-model - ${maven.api.version} - - - org.apache.maven - maven-artifact - ${maven.api.version} - - - org.apache.maven - maven-core - ${maven.api.version} - - - org.apache.maven - maven-archiver - 3.4.0 - - - org.codehaus.plexus - plexus-container-default - - - org.codehaus.plexus - plexus-component-annotations - - - org.slf4j - slf4j-jdk14 - - - - - org.codehaus.plexus - plexus-archiver - 4.1.0 - - - org.slf4j - slf4j-jdk14 - - - - - org.codehaus.plexus - plexus-utils - 3.1.0 - - - org.codehaus.plexus - plexus-io - 3.1.1 - - - org.codehaus.plexus - plexus-interactivity-api - 1.0 - - - org.codehaus.plexus - plexus-classworlds - - - - - - ro.isdc.wro4j - wro4j-core - ${wro4j.version} - - - slf4j-api - org.slf4j - - - org.webjars - webjars-locator - - - - - ro.isdc.wro4j - wro4j-extensions - ${wro4j.version} - - - org.slf4j - slf4j-api - - - org.slf4j - slf4j-log4j12 - - - - - joda-time - joda-time - 2.6 - - - org.apache.commons - commons-collections4 - 4.1 - - - org.apache.directory.api - api-all - 1.0.0 - - - slf4j-api - org.slf4j - - - xml-apis - xml-apis - - - - - javax.mail - mail - 1.4.5 - - - javax.mail - javax.mail-api - 1.5.4 - - - org.ocpsoft.prettytime - prettytime - 4.0.0.Final - - - com.github.openjson - openjson - 1.0.10 - - - org.opensaml - opensaml-security-impl - 3.3.0 - - - - - org.webjars.bower - adminlte - 2.3.11 - - - org.webjars - respond - 1.4.2 - - - org.webjars - html5shiv - 3.7.3 - - - org.webjars - font-awesome - 4.7.0 - - - org.webjars.npm - ionicons - 3.0.0 - - - org.webjars - webjars-locator-core - 0.35 - - - org.webjars - less - 2.5.3 - - - org.webjars - swagger-ui - 2.2.5 - - - - com.beust - jcommander - ${jcommander.version} - - - - org.eclipse.jetty - jetty-server - ${jetty.version} - - - org.eclipse.jetty - jetty-http - ${jetty.version} - - - org.eclipse.jetty - jetty-io - ${jetty.version} - - - org.eclipse.jetty - jetty-util - ${jetty.version} - - - org.apache.qpid - qpid-broker-core - ${qpid-broker.version} - - - org.apache.qpid - qpid-broker-plugins-amqp-0-8-protocol - ${qpid-broker.version} - - - org.apache.qpid - qpid-broker-plugins-memory-store - ${qpid-broker.version} - - - - org.jasig.cas.client - cas-client-core - 3.5.1 - - - - - com.codeborne - selenide - 5.3.1 - - - - io.netty - netty-all - - - com.google.guava - guava - - - - - org.seleniumhq.selenium - selenium-java - 3.14.0 - - - - commons-logging - commons-logging - - - - - org.seleniumhq.selenium - selenium-api - ${selenium.version} - - - - com.squareup.okio - okio - 1.14.1 - - - io.netty - netty-all - 4.1.42.Final - - - ch.qos.logback - * - - - - - org.jsoup - jsoup - 1.10.2 - - - dnsjava - dnsjava - 2.1.8 - - - - - org.testng - testng - ${testng.version} - - - com.evolveum.midpoint.tools - test-ng - ${project.version} - - - com.evolveum.midpoint.infra - test-util - ${project.version} - - - - - - - - - evolveum - Evolveum Public Releases - https://nexus.evolveum.com/nexus/content/groups/public/ - - - evolveum-snapshots - Evolveum Snapshots - https://nexus.evolveum.com/nexus/content/repositories/snapshots/ - - - spring-milestone - Spring Milestone Repository - https://repo.spring.io/milestone - - - - - evolveum - Evolveum - https://nexus.evolveum.com/nexus/content/groups/public - - - - - - - org.springframework.boot - spring-boot-maven-plugin - 2.0.1.RELEASE - - true - - - - - org.apache.maven.plugins - maven-source-plugin - 3.1.0 - - - attach-sources - package - - jar - - - - - - com.lukegb.mojo - gitdescribe-maven-plugin - 3.0 - - - - gitdescribe - - git-describe - initialize - - - - - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - true - - - ${project.version} - ${git.describe} - Evolveum - https://www.evolveum.com - https://jira.evolveum.com - dual-licensed under the Apache License 2.0 and European Union Public License - https://www.apache.org/licenses/LICENSE-2.0.txt and https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 - - - - - - org.apache.maven.plugins - maven-war-plugin - 3.2.3 - - - - ${project.version} - ${git.describe} - Evolveum - https://www.evolveum.com - https://jira.evolveum.com - dual-licensed under the Apache License 2.0 and European Union Public License - https://www.apache.org/licenses/LICENSE-2.0.txt and https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 - - - true - false - - - - org.eclipse.jetty - jetty-maven-plugin - ${jetty.version} - - - - org.eclipse.jetty.annotations.maxWait - 240 - - - - /midpoint - - - true - - -Xdebug -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=n - - - - - pl.project13.maven - git-commit-id-plugin - 3.0.1 - - - - org.apache.maven.plugins - maven-shade-plugin - 2.3 - - - org.apache.maven.plugins - maven-enforcer-plugin - 3.0.0-M2 - - - enforce - - - - 3.6 - - - - - - commons-logging:commons-logging - org.springframework:spring-jcl - - - - - - - - enforce - - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.1.1e1 - - - analyze - - analyze-only - - - true - true - - - - - - javax.xml.bind:jaxb-api - com.sun.activation:javax.activation - javax.activation:activation - - - xml-apis:xml-apis - - - jakarta.activation:jakarta.activation-api - jakarta.xml.bind:jakarta.xml.bind-api - org.glassfish.jaxb:xsom - org.glassfish.jaxb:jaxb-runtime - - - org.slf4j:jcl-over-slf4j - org.slf4j:slf4j-api - org.danekja:jdk-serializable-functional - - - - - - - maven-javadoc-plugin - 3.1.1 - - - org.apache.maven.plugins - maven-checkstyle-plugin - ${checkstyle.version} - - ${maven.multiModuleProjectDirectory}/config/checkstyle/checkstyle.xml - ${maven.multiModuleProjectDirectory}/config/checkstyle/checkstyle-suppressions.xml - UTF-8 - true - true - false - **/*.java - - **/*.properties,**/*.xml,**/*.xsd,**/*.wsdl,**/*.json,**/*.yaml,**/*.yml - - - - validate - validate - - check - - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.0 - - ${project.source.version} - ${project.source.version} - - - - org.apache.maven.plugins - maven-resources-plugin - 3.1.0 - - - com.rimerosolutions.maven.plugins - wrapper-maven-plugin - 0.0.4 - - - org.apache.maven.plugins - maven-plugin-plugin - - 3.6.0 - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - - org.eclipse.m2e - lifecycle-mapping - 1.0.0 - - - - - - org.apache.maven.plugins - maven-dependency-plugin - [3.1.1,) - - copy-dependencies - unpack - - - - - - - - - org.apache.cxf - cxf-codegen-plugin - [3.3.1,) - - wsdl2java - - - - - - - - - com.lukegb.mojo - gitdescribe-maven-plugin - [3.0,) - - gitdescribe - - - - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - ${surefire.version} - - - default-test - test - - test - - - - - false - 1 - true - ${redirectTestOutputToFile} - false - - false - - src/test/resources/truststore.jks - target/midpoint-home - ${project.build.directory}/test-classes/logging.properties - - - ${surefire.args} - - - - /opt/jenkins_db_configs/ojdbc7.jar - - c:\midpoint\jdbc-drivers\ojdbc7.jar - - - testng-unit.xml - - - - suitename - Unit - - - listener - - com.evolveum.midpoint.tools.testng.TestListener,com.evolveum.midpoint.tools.testng.RetryListener - - - - - - - org.apache.maven.surefire - surefire-testng - ${surefire.version} - - - - - org.apache.maven.plugins - maven-failsafe-plugin - ${failsafe.version} - - - integration-test - integration-test - - integration-test - verify - - - - - ${redirectTestOutputToFile} - - src/test/resources/truststore.jks - target/midpoint-home - ${project.build.directory}/test-classes/logging.properties - - ${failsafe.args} - - testng-integration.xml - - - - suitename - Integration - - - listener - com.evolveum.midpoint.tools.testng.TestListener,com.evolveum.midpoint.tools.testng.RetryListener - - - - - /opt/jenkins_db_configs/ojdbc7.jar - - c:\midpoint\jdbc-drivers\ojdbc7.jar - - - - - - org.codehaus.mojo - findbugs-maven-plugin - 3.0.5 - - Max - Low - true - com.evolveum.midpoint.* - - - - maven-assembly-plugin - 3.1.1 - - - - - - - - - org.codehaus.mojo - findbugs-maven-plugin - - - org.apache.maven.plugins - maven-checkstyle-plugin - - ${checkstyle.version} - - ${maven.multiModuleProjectDirectory}/build-system/checkstyle-configs/checkstyle.xml - - UTF-8 - true - true - false - - - - - checkstyle - - - - - - - - - - dist - - - !skipDist - - - - dist - - - - - - extratest - - true - - - - - jdk-11 - - 11 - - - 11 - - - - - - xerces - xercesImpl - ${xerces.version} - - - xml-apis - xml-apis - - - - - xalan - serializer - ${xalan.version} - - - xml-apis - xml-apis - - - - - - - - - jdk-8 - - 1.8 - - - 1.8 - - - - + + + + + 4.0.0 + + + + com.evolveum.midpoint + midpoint + 4.1-SNAPSHOT + pom + + midPoint Project + Utility module to compile all of the maven based midPoint projects. + + evolveum + https://www.evolveum.com + + + + Apache License v2.0 + https://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + European Union Public License + https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 + repo + + + + + tools + infra + repo + provisioning + model + custom + gui + icf-connectors + testing + + + + https://github.com/Evolveum/midpoint.git + git@github.com:Evolveum/midpoint.git + https://github.com/Evolveum/midpoint.git + + + Atlassian JIRA + https://jira.evolveum.com/browse/MID + + + + evolveum-nexus + Internal Releases + https://nexus.evolveum.com/nexus/content/repositories/releases/ + + + evolveum-nexus + Internal Snapshots + https://nexus.evolveum.com/nexus/content/repositories/snapshots/ + + + + + + + UTF-8 + 1.8 + en_US + true + false + false + + + ${describe} + ${maven.build.timestamp} + EEE, d MMM yyyy HH:mm:ss Z + + + -Xms1024m -Xmx4096m + -Xms1024m -Xmx4096m -Duser.language=en + + full + + true + + + 2.6 + 2.6 + 3.7 + 1.2 + 3.3.1 + 3.3.0 + 2.2.0 + 2.4.7 + 2.3.1 + 2.3.0.1 + 2.3.0.1 + 2.6.2 + 2.3.0.e3 + 3.141.59 + 1.7.25 + 1.2.3 + 2.1.8.RELEASE + + 5.1.9.RELEASE + 5.1.6.RELEASE + 2.0.0.M30 + 1.2.1.Final + 3.5.0 + 6.14.3 + 1.2 + 2.1.1 + 2.2.3 + 5.2.12.Final + 1.4.193 + 42.2.2 + 6.4.0.jre8 + 2.3.0 + 6.0.6 + 8.6.0 + 2.5.8 + 1.3 + 2.1.4 + 1.5.0.10 + 6.5.0 + 10.11.1.1 + 1.8.0 + 2.10.0 + 1.23 + 3.0.0-M3 + 0.9.11 + 28.1-jre + 1.72 + 3.0.0-M3 + 1.8 + 1.4.0 + 7.1.1 + 2.3.2 + 7.0 + 2.3.1 + 1.1.3 + 1.2.0 + 9.4.20.v20190813 + 3.6.2 + 3.1.0 + 2.7.2 + 2.12.0 + + + + + + + + javax.xml.soap + javax.xml.soap-api + ${javax.xml.soap.version} + + + javax.xml.ws + jaxws-api + ${jaxws-api.version} + + + org.apache.geronimo.specs + geronimo-ws-metadata_2.0_spec + ${geronimo-ws-metadata_2.0_spec.version} + + + com.sun.activation + javax.activation + ${activation.version} + + + + + org.springframework.boot + spring-boot-dependencies + ${spring.boot.version} + pom + import + + + org.springframework.boot + spring-boot-starter-test + ${spring.boot.version} + + + org.ow2.asm + asm + + + + + + + org.reflections + reflections + ${reflections.version} + + + com.google.guava + guava + + + + + + + org.apache.wicket + wicket-core + ${wicket.version} + + + org.apache.wicket + wicket-request + ${wicket.version} + + + org.apache.wicket + wicket-ioc + ${wicket.version} + + + org.ow2.asm + asm + + + org.apache.ant + ant + + + + + org.apache.wicket + wicket-util + ${wicket.version} + + + org.apache.wicket + wicket-devutils + ${wicket.version} + + + org.apache.wicket + wicket-auth-roles + ${wicket.version} + + + org.apache.wicket + wicket-spring + ${wicket.version} + + + org.springframework + * + + + + + org.apache.wicket + wicket-extensions + ${wicket.version} + + + org.apache.wicket + wicket-datetime + 8.0.0-M7 + + + org.ow2.asm + asm + ${asm.version} + + + org.apache.commons + commons-email + ${commons-email.version} + + + javax.activation + activation + + + + + org.codehaus.groovy + groovy-all + ${groovy.version} + pom + + + org.codehaus.groovy + groovy-ant + + + org.codehaus.groovy + groovy-test-junit5 + + + org.codehaus.groovy + groovy-test + + + org.codehaus.groovy + groovy-testng + + + + + org.codehaus.groovy + groovy + ${groovy.version} + + + org.python + jython + 2.5.3 + + + com.h2database + h2 + ${h2.version} + + + org.hibernate + hibernate-core + ${hibernate.version} + + + javax.annotation + jsr250-api + + + + + org.hibernate.javax.persistence + hibernate-jpa-2.1-api + 1.0.0.Final + + + org.javassist + javassist + + 3.25.0-GA + + + com.zaxxer + HikariCP + 3.3.1 + + + org.slf4j + jul-to-slf4j + ${slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + ch.qos.logback + logback-core + ${logback.version} + + + org.codehaus.janino + janino + 3.0.10 + + + com.sleepycat + je + 5.0.103 + + + + xerces + xercesImpl + ${xerces.version} + + + xalan + xalan + ${xalan.version} + + + org.codehaus.staxmate + staxmate + 2.0.1 + + + stax + stax-api + + + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + + + com.sun.xml.bind + jaxb-impl + ${jaxb.version} + + + com.sun.xml.bind + jaxb-core + ${jaxb.version} + + + com.sun.xml.bind + jaxb-xjc + ${jaxb-xjc.version} + + + net.sourceforge.ccxjc + cc-xjc-plugin + 2.0 + + + com.sun.xsom + xsom + 20140925 + + + commons-validator + commons-validator + 1.5.1 + + + + commons-logging + commons-logging + + + commons-digester + commons-digester + + + + + commons-beanutils + commons-beanutils + 1.9.4 + + + + commons-logging + commons-logging + + + + + commons-codec + commons-codec + 1.10 + + + commons-collections + commons-collections + 3.2.2 + + + org.apache.commons + commons-configuration2 + 2.6 + + + + commons-logging + commons-logging + + + + + org.apache.commons + commons-text + 1.8 + + + + com.google.code.findbugs + jsr305 + 3.0.2 + + + commons-io + commons-io + ${commons.io.version} + + + commons-lang + commons-lang + ${commons.lang.version} + + + org.apache.commons + commons-lang3 + ${commons.lang3.version} + + + commons-pool + commons-pool + 1.5.6 + + + commons-javaflow + commons-javaflow + 20060411 + + + org.jetbrains + annotations + 18.0.0 + + + javax.annotation + jsr250-api + 1.0 + + + javax.jws + jsr181-api + 1.0-MR1 + + + javax.inject + javax.inject + 1 + + + javax.persistence + persistence-api + 1.0 + true + + + javax.servlet + servlet-api + 2.5 + provided + + + javax.ws.rs + javax.ws.rs-api + 2.1 + + + + org.apache.httpcomponents + httpclient + 4.5.3.e3 + + + + commons-logging + commons-logging + + + + + + org.apache.httpcomponents + httpcore + 4.4.6 + + + org.apache.cxf + cxf-rt-core + ${cxf.version} + + + + org.apache.geronimo.specs + geronimo-javamail_1.4_spec + + + org.apache.geronimo.specs + geronimo-activation_1.1_spec + + + javax.activation + activation + + + + + org.apache.cxf + cxf-core + ${cxf.version} + + + org.jvnet.staxex + stax-ex + + + javax.xml.soap + javax.xml.soap-api + + + + org.glassfish.jaxb + jaxb-xjc + + + + + org.apache.cxf + cxf-rt-frontend-simple + ${cxf.version} + + + org.apache.cxf + cxf-rt-wsdl + ${cxf.version} + + + javax.activation + activation + + + + + org.apache.cxf + cxf-tools-common + ${cxf.version} + + + org.jvnet.staxex + stax-ex + + + javax.xml.soap + javax.xml.soap-api + + + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${cxf.version} + + + org.apache.cxf + cxf-rt-databinding-aegis + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-local + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http + ${cxf.version} + + + + org.apache.httpcomponents + httpclient + + + + org.apache.httpcomponents + httpcore + + + + + org.apache.cxf + cxf-rt-transports-http-jetty + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-jms + ${cxf.version} + + + org.apache.cxf + cxf-rt-management + ${cxf.version} + + + org.apache.cxf + cxf-rt-bindings-soap + ${cxf.version} + + + org.apache.cxf + cxf-rt-ws-security + ${cxf.version} + + + org.codehaus.woodstox + woodstox-core-asl + + + + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${cxf.version} + + + jakarta.ws.rs + jakarta.ws.rs-api + + + + + org.apache.cxf + cxf-rt-rs-client + ${cxf.version} + + + org.jvnet.staxex + stax-ex + + + javax.xml.soap + javax.xml.soap-api + + + + + org.apache.cxf + cxf-rt-rs-extension-providers + ${cxf.version} + + + org.apache.cxf.xjc-utils + cxf-xjc-runtime + ${cxf-xjc.version} + + + javax.activation + activation + + + + + org.apache.wss4j + wss4j-ws-security-common + ${wss4j.version} + + + org.apache.geronimo.javamail + geronimo-javamail_1.4_mail + + + org.bouncycastle + bcprov-jdk15on + + + com.google.guava + guava + + + + + com.google.guava + guava + ${guava.version} + + + org.apache.wss4j + wss4j-ws-security-dom + ${wss4j.version} + + + org.bouncycastle + bcprov-jdk15on + + + + + + org.codehaus.woodstox + stax2-api + 3.1.4 + + + org.apache.felix + org.osgi.core + 1.4.0 + + + org.forgerock.opendj + opendj + ${opendj.version} + + + + net.tirasa.connid + connector-framework + ${connid.version} + + + net.tirasa.connid + connector-framework-internal + ${connid.version} + + + com.evolveum.polygon + connector-databasetable + 1.4.3.0 + + + com.evolveum.polygon + connector-csv + 2.3 + + + com.evolveum.polygon + connector-ldap + 3.0-SNAPSHOT + + + + org.slf4j + slf4j-jdk14 + + + + + com.evolveum.polygon + connector-powershell + 1.0-M1 + + + + com.evolveum.icf + dummy + 1.1.0.0-e1 + + + org.scannotation + scannotation + 1.0.3 + + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + + + org.slf4j + log4j-over-slf4j + ${slf4j.version} + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.quartz-scheduler + quartz + ${quartz.version} + + + com.mchange + c3p0 + + + com.mchange + mchange-commons-java + + + com.zaxxer + * + + + + + + org.apache.santuario + xmlsec + ${xmlsec.version} + + + javax.xml.stream + stax-api + + + org.codehaus.woodstox + woodstox-core-asl + + + + + org.springframework + spring-core + ${spring.version} + + + + org.springframework + spring-jcl + + + + + org.springframework.security.extensions + spring-security-saml2-core + ${spring.security.saml2.version} + + + commons-logging + commons-logging + + + org.bouncycastle + bcpkix-jdk15on + + + org.bouncycastle + bcprov-jdk15on + + + + + org.cache2k + cache2k-api + ${cache2k.version} + + + org.cache2k + cache2k-core + ${cache2k.version} + + + aopalliance + aopalliance + 1.0 + + + + org.xmlunit + xmlunit-core + ${xmlunit.version} + + + org.xmlunit + xmlunit-legacy + ${xmlunit.version} + + + xml-resolver + xml-resolver + ${xml.resolver.version} + + + mysql + mysql-connector-java + ${jdbc.mysql} + + + org.postgresql + postgresql + ${jdbc.postgres} + + + com.microsoft.sqlserver + mssql-jdbc + ${jdbc.sqlserver} + + + org.mariadb.jdbc + mariadb-java-client + ${jdbc.mariadb} + + + commons-cli + commons-cli + ${commons.cli} + + + org.forgerock.opendj + opendj-ldap-sdk + ${opendj.version} + + + org.apache.velocity + velocity + 1.7 + + + org.apache.derby + derby + ${derby.version} + + + org.apache.derby + derbynet + ${derby.version} + + + org.apache.derby + derbyclient + ${derby.version} + + + + + net.sf.jasperreports + jasperreports + ${jasper.version} + + + xml-apis + xml-apis + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-annotations + + + + commons-logging + commons-logging + + + bouncycastle + bcmail-jdk14 + + + org.bouncycastle + bcmail-jdk14 + + + bouncycastle + bcprov-jdk14 + + + org.bouncycastle + bcprov-jdk14 + + + org.bouncycastle + bctsp-jdk14 + + + + javax.xml.stream + stax-api + + + + + + stax + stax + 1.2.0 + + + stax + stax-api + + + + + + + org.apache.poi + poi + 3.17 + + + com.fasterxml.jackson.core + jackson-core + ${jackson.version} + + + com.fasterxml.jackson.core + jackson-annotations + ${jackson.version} + + + com.fasterxml.jackson.jaxrs + jackson-jaxrs-base + ${jackson.version} + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + com.fasterxml.jackson.module + jackson-module-jaxb-annotations + ${jackson.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson.version} + + + org.apache.ws.xmlschema + xmlschema-core + 2.1.0 + + + org.jvnet.jaxb2_commons + jaxb2-basics-runtime + 0.6.3 + + + + + org.apache.maven + maven-plugin-api + ${maven.api.version} + + + org.codehaus.plexus + plexus-component-annotations + + + org.codehaus.plexus + plexus-classworlds + + + + + org.apache.maven + maven-model + ${maven.api.version} + + + org.apache.maven + maven-artifact + ${maven.api.version} + + + org.apache.maven + maven-core + ${maven.api.version} + + + org.apache.maven + maven-archiver + 3.4.0 + + + org.codehaus.plexus + plexus-container-default + + + org.codehaus.plexus + plexus-component-annotations + + + org.slf4j + slf4j-jdk14 + + + + + org.codehaus.plexus + plexus-archiver + 4.1.0 + + + org.slf4j + slf4j-jdk14 + + + + + org.codehaus.plexus + plexus-utils + 3.1.0 + + + org.codehaus.plexus + plexus-io + 3.1.1 + + + org.codehaus.plexus + plexus-interactivity-api + 1.0 + + + org.codehaus.plexus + plexus-classworlds + + + + + + ro.isdc.wro4j + wro4j-core + ${wro4j.version} + + + slf4j-api + org.slf4j + + + org.webjars + webjars-locator + + + + + ro.isdc.wro4j + wro4j-extensions + ${wro4j.version} + + + org.slf4j + slf4j-api + + + org.slf4j + slf4j-log4j12 + + + + + joda-time + joda-time + 2.6 + + + org.apache.commons + commons-collections4 + 4.1 + + + org.apache.directory.api + api-all + 1.0.0 + + + slf4j-api + org.slf4j + + + xml-apis + xml-apis + + + + + javax.mail + mail + 1.4.5 + + + javax.mail + javax.mail-api + 1.5.4 + + + org.ocpsoft.prettytime + prettytime + 4.0.0.Final + + + com.github.openjson + openjson + 1.0.10 + + + org.opensaml + opensaml-security-impl + 3.3.0 + + + + + org.webjars.bower + adminlte + 2.3.11 + + + org.webjars + respond + 1.4.2 + + + org.webjars + html5shiv + 3.7.3 + + + org.webjars + font-awesome + 4.7.0 + + + org.webjars.npm + ionicons + 3.0.0 + + + org.webjars + webjars-locator-core + 0.35 + + + org.webjars + less + 2.5.3 + + + org.webjars + swagger-ui + 2.2.5 + + + + com.beust + jcommander + ${jcommander.version} + + + + org.eclipse.jetty + jetty-server + ${jetty.version} + + + org.eclipse.jetty + jetty-http + ${jetty.version} + + + org.eclipse.jetty + jetty-io + ${jetty.version} + + + org.eclipse.jetty + jetty-util + ${jetty.version} + + + org.apache.qpid + qpid-broker-core + ${qpid-broker.version} + + + org.apache.qpid + qpid-broker-plugins-amqp-0-8-protocol + ${qpid-broker.version} + + + org.apache.qpid + qpid-broker-plugins-memory-store + ${qpid-broker.version} + + + + org.jasig.cas.client + cas-client-core + 3.5.1 + + + + + com.codeborne + selenide + 5.3.1 + + + + io.netty + netty-all + + + com.google.guava + guava + + + + + org.seleniumhq.selenium + selenium-java + 3.14.0 + + + + commons-logging + commons-logging + + + + + org.seleniumhq.selenium + selenium-api + ${selenium.version} + + + + com.squareup.okio + okio + 1.14.1 + + + io.netty + netty-all + 4.1.42.Final + + + ch.qos.logback + * + + + + + org.jsoup + jsoup + 1.10.2 + + + dnsjava + dnsjava + 2.1.8 + + + + + org.testng + testng + ${testng.version} + + + com.evolveum.midpoint.tools + test-ng + ${project.version} + + + com.evolveum.midpoint.infra + test-util + ${project.version} + + + + + + + + + evolveum + Evolveum Public Releases + https://nexus.evolveum.com/nexus/content/groups/public/ + + + evolveum-snapshots + Evolveum Snapshots + https://nexus.evolveum.com/nexus/content/repositories/snapshots/ + + + spring-milestone + Spring Milestone Repository + https://repo.spring.io/milestone + + + + + evolveum + Evolveum + https://nexus.evolveum.com/nexus/content/groups/public + + + + + + + org.springframework.boot + spring-boot-maven-plugin + 2.0.1.RELEASE + + true + + + + + org.apache.maven.plugins + maven-source-plugin + 3.1.0 + + + attach-sources + package + + jar + + + + + + com.lukegb.mojo + gitdescribe-maven-plugin + 3.0 + + + + gitdescribe + + git-describe + initialize + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + true + + + ${project.version} + ${git.describe} + Evolveum + https://www.evolveum.com + https://jira.evolveum.com + dual-licensed under the Apache License 2.0 and European Union Public License + https://www.apache.org/licenses/LICENSE-2.0.txt and https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 + + + + + + org.apache.maven.plugins + maven-war-plugin + 3.2.3 + + + + ${project.version} + ${git.describe} + Evolveum + https://www.evolveum.com + https://jira.evolveum.com + dual-licensed under the Apache License 2.0 and European Union Public License + https://www.apache.org/licenses/LICENSE-2.0.txt and https://joinup.ec.europa.eu/collection/eupl/eupl-text-11-12 + + + true + false + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty.version} + + + + org.eclipse.jetty.annotations.maxWait + 240 + + + + /midpoint + + + true + + -Xdebug -Xrunjdwp:transport=dt_socket,address=5000,server=y,suspend=n + + + + + pl.project13.maven + git-commit-id-plugin + 3.0.1 + + + + org.apache.maven.plugins + maven-shade-plugin + 2.3 + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.0.0-M2 + + + enforce + + + + 3.6 + + + + + + commons-logging:commons-logging + org.springframework:spring-jcl + + + + + + + + enforce + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1e1 + + + analyze + + analyze-only + + + true + true + + + + + + javax.xml.bind:jaxb-api + com.sun.activation:javax.activation + javax.activation:activation + + + xml-apis:xml-apis + + + jakarta.activation:jakarta.activation-api + jakarta.xml.bind:jakarta.xml.bind-api + org.glassfish.jaxb:xsom + org.glassfish.jaxb:jaxb-runtime + + + org.slf4j:jcl-over-slf4j + org.slf4j:slf4j-api + org.danekja:jdk-serializable-functional + + + + + + + maven-javadoc-plugin + 3.1.1 + + + org.apache.maven.plugins + maven-checkstyle-plugin + ${checkstyle.version} + + ${maven.multiModuleProjectDirectory}/config/checkstyle/checkstyle.xml + ${maven.multiModuleProjectDirectory}/config/checkstyle/checkstyle-suppressions.xml + UTF-8 + true + true + false + **/*.java + + **/*.properties,**/*.xml,**/*.xsd,**/*.wsdl,**/*.json,**/*.yaml,**/*.yml + + + + validate + validate + + check + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${project.source.version} + ${project.source.version} + + + + org.apache.maven.plugins + maven-resources-plugin + 3.1.0 + + + com.rimerosolutions.maven.plugins + wrapper-maven-plugin + 0.0.4 + + + org.apache.maven.plugins + maven-plugin-plugin + + 3.6.0 + + + org.apache.maven.plugins + maven-deploy-plugin + 2.8.2 + + + org.eclipse.m2e + lifecycle-mapping + 1.0.0 + + + + + + org.apache.maven.plugins + maven-dependency-plugin + [3.1.1,) + + copy-dependencies + unpack + + + + + + + + + org.apache.cxf + cxf-codegen-plugin + [3.3.1,) + + wsdl2java + + + + + + + + + com.lukegb.mojo + gitdescribe-maven-plugin + [3.0,) + + gitdescribe + + + + + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + ${surefire.version} + + + default-test + test + + test + + + + + false + 1 + true + ${redirectTestOutputToFile} + false + + false + + src/test/resources/truststore.jks + target/midpoint-home + ${project.build.directory}/test-classes/logging.properties + + + ${surefire.args} + + + + /opt/jenkins_db_configs/ojdbc7.jar + + c:\midpoint\jdbc-drivers\ojdbc7.jar + + + testng-unit.xml + + + + suitename + Unit + + + listener + + com.evolveum.midpoint.tools.testng.TestListener,com.evolveum.midpoint.tools.testng.RetryListener + + + + + + + org.apache.maven.surefire + surefire-testng + ${surefire.version} + + + + + org.apache.maven.plugins + maven-failsafe-plugin + ${failsafe.version} + + + integration-test + integration-test + + integration-test + verify + + + + + ${redirectTestOutputToFile} + + src/test/resources/truststore.jks + target/midpoint-home + ${project.build.directory}/test-classes/logging.properties + + ${failsafe.args} + + testng-integration.xml + + + + suitename + Integration + + + listener + com.evolveum.midpoint.tools.testng.TestListener,com.evolveum.midpoint.tools.testng.RetryListener + + + + + /opt/jenkins_db_configs/ojdbc7.jar + + c:\midpoint\jdbc-drivers\ojdbc7.jar + + + + + + org.codehaus.mojo + findbugs-maven-plugin + 3.0.5 + + Max + Low + true + com.evolveum.midpoint.* + + + + maven-assembly-plugin + 3.1.1 + + + + + + + + + org.codehaus.mojo + findbugs-maven-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + ${checkstyle.version} + + ${maven.multiModuleProjectDirectory}/build-system/checkstyle-configs/checkstyle.xml + + UTF-8 + true + true + false + + + + + checkstyle + + + + + + + + + + dist + + + !skipDist + + + + dist + + + + + + extratest + + true + + + + + jdk-11 + + 11 + + + 11 + + + + + + xerces + xercesImpl + ${xerces.version} + + + xml-apis + xml-apis + + + + + xalan + serializer + ${xalan.version} + + + xml-apis + xml-apis + + + + + + + + + jdk-8 + + 1.8 + + + 1.8 + + + + diff --git a/testing/conntest/pom.xml b/testing/conntest/pom.xml index e4f976f748f..4fb985978d4 100644 --- a/testing/conntest/pom.xml +++ b/testing/conntest/pom.xml @@ -162,6 +162,11 @@ + + com.evolveum.polygon + connector-powershell + test + com.evolveum.polygon connector-databasetable diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapSynchronizationTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapSynchronizationTest.java index 86996c24951..d16461a1f95 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapSynchronizationTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/AbstractLdapSynchronizationTest.java @@ -1,516 +1,511 @@ -package com.evolveum.midpoint.testing.conntest; -/* - * Copyright (c) 2010-2017 Evolveum and contributors - * - * This work is dual-licensed under the Apache License 2.0 - * and European Union Public License. See LICENSE file for details. - */ - -import static org.testng.AssertJUnit.assertNotNull; -import static org.testng.AssertJUnit.assertNull; - -import java.util.List; - -import org.apache.directory.api.ldap.model.entry.DefaultModification; -import org.apache.directory.api.ldap.model.entry.Modification; -import org.apache.directory.api.ldap.model.entry.ModificationOperation; -import org.apache.directory.api.ldap.model.exception.LdapException; -import org.apache.directory.api.ldap.model.message.ModifyDnRequest; -import org.apache.directory.api.ldap.model.message.ModifyDnRequestImpl; -import org.apache.directory.api.ldap.model.message.ModifyDnResponse; -import org.apache.directory.api.ldap.model.name.Dn; -import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.annotation.DirtiesContext.ClassMode; -import org.springframework.test.context.ContextConfiguration; -import org.testng.annotations.Test; - -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; -import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; -import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.LiveSyncCapabilityType; - -/** - * @author Radovan Semancik - */ -@ContextConfiguration(locations = { "classpath:ctx-conntest-test-main.xml" }) -@DirtiesContext(classMode = ClassMode.AFTER_CLASS) -public abstract class AbstractLdapSynchronizationTest extends AbstractLdapTest { - - protected static final String ACCOUNT_HT_UID = "ht"; - protected static final String ACCOUNT_HT_CN = "Herman Toothrot"; - protected static final String ACCOUNT_HT_GIVENNAME = "Herman"; - protected static final String ACCOUNT_HT_SN = "Toothrot"; - protected static final String ACCOUNT_HT_SN_MODIFIED = "Torquemeda Marley"; - - protected static final String ACCOUNT_HTM_UID = "htm"; - protected static final String ACCOUNT_HTM_CN = "Horatio Torquemada Marley"; - - protected static final String GROUP_MONKEYS_CN = "monkeys"; - protected static final String GROUP_MONKEYS_DESCRIPTION = "Monkeys of Monkey Island"; - - protected static final String GROUP_FOOLS_CN = "fools"; - protected static final String GROUP_FOOLS_DESCRIPTION = "not quite the shilling"; - - protected abstract void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) throws ObjectNotFoundException, SchemaException; - - protected boolean syncCanDetectDelete() { - return true; - } - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - } - - @Test - public void test000Sanity() throws Exception { - cleanupDelete(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN)); - cleanupDelete(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); - cleanupDelete(toGroupDn(GROUP_MONKEYS_CN)); - cleanupDelete(toGroupDn(GROUP_FOOLS_CN)); - } - - @Override - protected void assertAdditionalCapabilities(List nativeCapabilities) { - super.assertAdditionalCapabilities(nativeCapabilities); - - assertCapability(nativeCapabilities, LiveSyncCapabilityType.class); - } - - @Test - public void test800ImportSyncTask() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addObject(getSyncTaskFile(), task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - long tsEnd = System.currentTimeMillis(); - - assertStepSyncToken(getSyncTaskOid(), 0, tsStart, tsEnd); - } - - @Test - public void test801SyncAddAccountHt() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - displayUsers(); - - PrismObject user = findUserByUsername(ACCOUNT_HT_UID); - assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); - - assertStepSyncToken(getSyncTaskOid(), 1, tsStart, tsEnd); - } - - /** - * Changing account sn directly. - * Do not change cn here. But even if sn is not changed, this triggers rename in the AD case. - */ - @Test - public void test802ModifyAccountHtSn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - LdapNetworkConnection connection = ldapConnect(); - Modification modSn = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, "sn", ACCOUNT_HT_SN_MODIFIED); - connection.modify(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN), modSn); - ldapDisconnect(connection); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - PrismObject user = findUserByUsername(ACCOUNT_HT_UID); - assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); - - assertStepSyncToken(getSyncTaskOid(), 2, tsStart, tsEnd); - - } - - @Test - public void test810SyncAddGroupMonkeys() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - if (needsGroupFakeMemeberEntry()) { - addLdapGroup(GROUP_MONKEYS_CN, GROUP_MONKEYS_DESCRIPTION, "uid=fake," + getPeopleLdapSuffix()); - } else { - addLdapGroup(GROUP_MONKEYS_CN, GROUP_MONKEYS_DESCRIPTION); - } - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - PrismObject role = findObjectByName(RoleType.class, GROUP_MONKEYS_CN); - display("Role", role); - assertNotNull("no role " + GROUP_MONKEYS_CN, role); - PrismAsserts.assertPropertyValue(role, RoleType.F_DESCRIPTION, GROUP_MONKEYS_DESCRIPTION); - assertNotNull("No role " + GROUP_MONKEYS_CN + " created", role); - - assertStepSyncToken(getSyncTaskOid(), 3, tsStart, tsEnd); - } - - @Test - public void test817RenameAccount() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - LdapNetworkConnection connection = ldapConnect(); - - ModifyDnRequest modDnRequest = new ModifyDnRequestImpl(); - modDnRequest.setName(new Dn(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN))); - modDnRequest.setNewRdn(toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); - modDnRequest.setDeleteOldRdn(true); - ModifyDnResponse modDnResponse = connection.modifyDn(modDnRequest); - display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " -> " + toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN) + ": " + modDnResponse); - - doAdditionalRenameModifications(connection); - - ldapDisconnect(connection); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); - assertNotNull("No user " + ACCOUNT_HTM_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HTM_UID, getAccountHtmCnAfterRename(), ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); - assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); - - assertStepSyncToken(getSyncTaskOid(), 4, tsStart, tsEnd); - - } - - protected String getAccountHtmCnAfterRename() { - return ACCOUNT_HT_CN; - } - - protected void doAdditionalRenameModifications(LdapNetworkConnection connection) throws LdapException { - // Nothing to do here - } - - @Test - public void test818DeleteAccountHtm() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - deleteLdapEntry(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - if (syncCanDetectDelete()) { - assertNull("User " + ACCOUNT_HTM_UID + " still exist", findUserByUsername(ACCOUNT_HTM_UID)); - assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); - } else { - // Just delete the user so we have consistent state for subsequent tests - deleteObject(UserType.class, user.getOid(), task, result); - } - - assertStepSyncToken(getSyncTaskOid(), 5, tsStart, tsEnd); - } - - // TODO: sync with "ALL" object class - - @Test - public void test819DeleteSyncTask() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - deleteObject(TaskType.class, getSyncTaskOid(), task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNoObject(TaskType.class, getSyncTaskOid(), task, result); - } - - @Test - public void test820ImportSyncTaskInetOrgPerson() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addObject(getSyncTaskInetOrgPersonFile(), task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - long tsEnd = System.currentTimeMillis(); - - PrismObject syncTask = getTask(getSyncTaskOid()); - display("Sync task after start", syncTask); - - assertStepSyncToken(getSyncTaskOid(), 5, tsStart, tsEnd); - } - - @Test - public void test821SyncAddAccountHt() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - displayUsers(); - - PrismObject user = findUserByUsername(ACCOUNT_HT_UID); - assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); - - assertStepSyncToken(getSyncTaskOid(), 6, tsStart, tsEnd); - } - - @Test - public void test822ModifyAccountHt() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - LdapNetworkConnection connection = ldapConnect(); - Modification modCn = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, "sn", ACCOUNT_HT_SN_MODIFIED); - connection.modify(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN), modCn); - ldapDisconnect(connection); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - PrismObject user = findUserByUsername(ACCOUNT_HT_UID); - assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); - - assertStepSyncToken(getSyncTaskOid(), 7, tsStart, tsEnd); - } - - /** - * Add a new group. Check that this event is ignored. - */ - @Test - public void test830AddGroupFools() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - addLdapGroup(GROUP_FOOLS_CN, GROUP_FOOLS_DESCRIPTION, toGroupDn("nobody")); - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - PrismObject roleFools = findObjectByName(RoleType.class, GROUP_FOOLS_CN); - assertNull("Unexpected role " + roleFools, roleFools); - - assertStepSyncToken(getSyncTaskOid(), 8, tsStart, tsEnd); - } - - @Test - public void test837RenameAccount() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - LdapNetworkConnection connection = ldapConnect(); - - ModifyDnRequest modDnRequest = new ModifyDnRequestImpl(); - modDnRequest.setName(new Dn(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN))); - modDnRequest.setNewRdn(toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); - modDnRequest.setDeleteOldRdn(true); - ModifyDnResponse modDnResponse = connection.modifyDn(modDnRequest); - display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " -> " + toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN) + ": " + modDnResponse); - - doAdditionalRenameModifications(connection); - - ldapDisconnect(connection); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); - assertNotNull("No user " + ACCOUNT_HTM_UID + " created", user); - assertUser(user, user.getOid(), ACCOUNT_HTM_UID, getAccountHtmCnAfterRename(), ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); - assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); - - assertStepSyncToken(getSyncTaskOid(), 9, tsStart, tsEnd); - - } - - // TODO: create object of a different object class. See that it is ignored by sync. - - @Test - public void test838DeleteAccountHtm() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - deleteLdapEntry(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); - - waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - if (syncCanDetectDelete()) { - assertNull("User " + ACCOUNT_HTM_UID + " still exist", findUserByUsername(ACCOUNT_HTM_UID)); - assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); - } else { - // Just delete the user so we have consistent state for subsequent tests - deleteObject(UserType.class, user.getOid(), task, result); - } - - assertStepSyncToken(getSyncTaskOid(), 10, tsStart, tsEnd); - } - - @Test - public void test839DeleteSyncTask() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - deleteObject(TaskType.class, getSyncTaskOid(), task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoObject(TaskType.class, getSyncTaskOid(), task, result); - } - -} +package com.evolveum.midpoint.testing.conntest; +/* + * Copyright (c) 2010-2020 Evolveum and contributors + * + * This work is dual-licensed under the Apache License 2.0 + * and European Union Public License. See LICENSE file for details. + */ + +import static org.testng.AssertJUnit.assertNotNull; +import static org.testng.AssertJUnit.assertNull; + +import java.util.List; + +import org.apache.directory.api.ldap.model.entry.DefaultModification; +import org.apache.directory.api.ldap.model.entry.Modification; +import org.apache.directory.api.ldap.model.entry.ModificationOperation; +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.apache.directory.api.ldap.model.message.ModifyDnRequest; +import org.apache.directory.api.ldap.model.message.ModifyDnRequestImpl; +import org.apache.directory.api.ldap.model.message.ModifyDnResponse; +import org.apache.directory.api.ldap.model.name.Dn; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.annotation.DirtiesContext.ClassMode; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.RoleType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType; +import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType; +import com.evolveum.midpoint.xml.ns._public.resource.capabilities_3.LiveSyncCapabilityType; + +/** + * @author Radovan Semancik + */ +@ContextConfiguration(locations = { "classpath:ctx-conntest-test-main.xml" }) +@DirtiesContext(classMode = ClassMode.AFTER_CLASS) +public abstract class AbstractLdapSynchronizationTest extends AbstractLdapTest { + + protected static final String ACCOUNT_HT_UID = "ht"; + protected static final String ACCOUNT_HT_CN = "Herman Toothrot"; + protected static final String ACCOUNT_HT_GIVENNAME = "Herman"; + protected static final String ACCOUNT_HT_SN = "Toothrot"; + protected static final String ACCOUNT_HT_SN_MODIFIED = "Torquemeda Marley"; + + protected static final String ACCOUNT_HTM_UID = "htm"; + protected static final String ACCOUNT_HTM_CN = "Horatio Torquemada Marley"; + + protected static final String GROUP_MONKEYS_CN = "monkeys"; + protected static final String GROUP_MONKEYS_DESCRIPTION = "Monkeys of Monkey Island"; + + protected static final String GROUP_FOOLS_CN = "fools"; + protected static final String GROUP_FOOLS_DESCRIPTION = "not quite the shilling"; + + protected abstract void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) throws ObjectNotFoundException, SchemaException; + + protected boolean syncCanDetectDelete() { + return true; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + } + + @Test + public void test000Sanity() throws Exception { + cleanupDelete(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN)); + cleanupDelete(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + cleanupDelete(toGroupDn(GROUP_MONKEYS_CN)); + cleanupDelete(toGroupDn(GROUP_FOOLS_CN)); + } + + @Override + protected void assertAdditionalCapabilities(List nativeCapabilities) { + super.assertAdditionalCapabilities(nativeCapabilities); + + assertCapability(nativeCapabilities, LiveSyncCapabilityType.class); + } + + @Test + public void test800ImportSyncTask() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addObject(getSyncTaskFile(), task, result); + + // THEN + then(); + assertSuccess(result); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + long tsEnd = System.currentTimeMillis(); + + assertStepSyncToken(getSyncTaskOid(), 0, tsStart, tsEnd); + } + + @Test + public void test801SyncAddAccountHt() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + displayUsers(); + + PrismObject user = findUserByUsername(ACCOUNT_HT_UID); + assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + + assertStepSyncToken(getSyncTaskOid(), 1, tsStart, tsEnd); + } + + /** + * Changing account sn directly. + * Do not change cn here. But even if sn is not changed, this triggers rename in the AD case. + */ + @Test + public void test802ModifyAccountHtSn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + LdapNetworkConnection connection = ldapConnect(); + Modification modSn = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, "sn", ACCOUNT_HT_SN_MODIFIED); + connection.modify(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN), modSn); + ldapDisconnect(connection); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + PrismObject user = findUserByUsername(ACCOUNT_HT_UID); + assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); + + assertStepSyncToken(getSyncTaskOid(), 2, tsStart, tsEnd); + + } + + @Test + public void test810SyncAddGroupMonkeys() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + if (needsGroupFakeMemeberEntry()) { + addLdapGroup(GROUP_MONKEYS_CN, GROUP_MONKEYS_DESCRIPTION, "uid=fake," + getPeopleLdapSuffix()); + } else { + addLdapGroup(GROUP_MONKEYS_CN, GROUP_MONKEYS_DESCRIPTION); + } + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + PrismObject role = findObjectByName(RoleType.class, GROUP_MONKEYS_CN); + display("Role", role); + assertNotNull("no role " + GROUP_MONKEYS_CN, role); + PrismAsserts.assertPropertyValue(role, RoleType.F_DESCRIPTION, GROUP_MONKEYS_DESCRIPTION); + assertNotNull("No role " + GROUP_MONKEYS_CN + " created", role); + + assertStepSyncToken(getSyncTaskOid(), 3, tsStart, tsEnd); + } + + @Test + public void test817RenameAccount() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + LdapNetworkConnection connection = ldapConnect(); + + ModifyDnRequest modDnRequest = new ModifyDnRequestImpl(); + modDnRequest.setName(new Dn(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN))); + modDnRequest.setNewRdn(toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + modDnRequest.setDeleteOldRdn(true); + ModifyDnResponse modDnResponse = connection.modifyDn(modDnRequest); + display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " -> " + toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN) + ": " + modDnResponse); + + doAdditionalRenameModifications(connection); + + ldapDisconnect(connection); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); + assertNotNull("No user " + ACCOUNT_HTM_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HTM_UID, getAccountHtmCnAfterRename(), ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); + assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); + + assertStepSyncToken(getSyncTaskOid(), 4, tsStart, tsEnd); + + } + + protected String getAccountHtmCnAfterRename() { + return ACCOUNT_HT_CN; + } + + protected void doAdditionalRenameModifications(LdapNetworkConnection connection) throws LdapException { + // Nothing to do here + } + + @Test + public void test818DeleteAccountHtm() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + deleteLdapEntry(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + if (syncCanDetectDelete()) { + assertNull("User " + ACCOUNT_HTM_UID + " still exist", findUserByUsername(ACCOUNT_HTM_UID)); + assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); + } else { + // Just delete the user so we have consistent state for subsequent tests + deleteObject(UserType.class, user.getOid(), task, result); + } + + assertStepSyncToken(getSyncTaskOid(), 5, tsStart, tsEnd); + } + + // TODO: sync with "ALL" object class + + @Test + public void test819DeleteSyncTask() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + deleteObject(TaskType.class, getSyncTaskOid(), task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoObject(TaskType.class, getSyncTaskOid(), task, result); + } + + @Test + public void test820ImportSyncTaskInetOrgPerson() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addObject(getSyncTaskInetOrgPersonFile(), task, result); + + // THEN + then(); + assertSuccess(result); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + long tsEnd = System.currentTimeMillis(); + + PrismObject syncTask = getTask(getSyncTaskOid()); + display("Sync task after start", syncTask); + + assertStepSyncToken(getSyncTaskOid(), 5, tsStart, tsEnd); + } + + @Test + public void test821SyncAddAccountHt() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + displayUsers(); + + PrismObject user = findUserByUsername(ACCOUNT_HT_UID); + assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + + assertStepSyncToken(getSyncTaskOid(), 6, tsStart, tsEnd); + } + + @Test + public void test822ModifyAccountHt() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + LdapNetworkConnection connection = ldapConnect(); + Modification modCn = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, "sn", ACCOUNT_HT_SN_MODIFIED); + connection.modify(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN), modCn); + ldapDisconnect(connection); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + PrismObject user = findUserByUsername(ACCOUNT_HT_UID); + assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); + + assertStepSyncToken(getSyncTaskOid(), 7, tsStart, tsEnd); + } + + /** + * Add a new group. Check that this event is ignored. + */ + @Test + public void test830AddGroupFools() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addLdapGroup(GROUP_FOOLS_CN, GROUP_FOOLS_DESCRIPTION, toGroupDn("nobody")); + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + PrismObject roleFools = findObjectByName(RoleType.class, GROUP_FOOLS_CN); + assertNull("Unexpected role " + roleFools, roleFools); + + assertStepSyncToken(getSyncTaskOid(), 8, tsStart, tsEnd); + } + + @Test + public void test837RenameAccount() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + LdapNetworkConnection connection = ldapConnect(); + + ModifyDnRequest modDnRequest = new ModifyDnRequestImpl(); + modDnRequest.setName(new Dn(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN))); + modDnRequest.setNewRdn(toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + modDnRequest.setDeleteOldRdn(true); + ModifyDnResponse modDnResponse = connection.modifyDn(modDnRequest); + display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " -> " + toAccountRdn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN) + ": " + modDnResponse); + + doAdditionalRenameModifications(connection); + + ldapDisconnect(connection); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); + assertNotNull("No user " + ACCOUNT_HTM_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HTM_UID, getAccountHtmCnAfterRename(), ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN_MODIFIED); + assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); + + assertStepSyncToken(getSyncTaskOid(), 9, tsStart, tsEnd); + + } + + // TODO: create object of a different object class. See that it is ignored by sync. + + @Test + public void test838DeleteAccountHtm() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject user = findUserByUsername(ACCOUNT_HTM_UID); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + deleteLdapEntry(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + if (syncCanDetectDelete()) { + assertNull("User " + ACCOUNT_HTM_UID + " still exist", findUserByUsername(ACCOUNT_HTM_UID)); + assertNull("User " + ACCOUNT_HT_UID + " still exist", findUserByUsername(ACCOUNT_HT_UID)); + } else { + // Just delete the user so we have consistent state for subsequent tests + deleteObject(UserType.class, user.getOid(), task, result); + } + + assertStepSyncToken(getSyncTaskOid(), 10, tsStart, tsEnd); + } + + @Test + public void test839DeleteSyncTask() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + deleteObject(TaskType.class, getSyncTaskOid(), task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoObject(TaskType.class, getSyncTaskOid(), task, result); + } + +} diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java index 96fdf4fbcc2..0dd0e22f648 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java @@ -1,2308 +1,2385 @@ -/* - * Copyright (c) 2015-2019 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.testing.conntest.ad; - -import static org.testng.AssertJUnit.*; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; - -import java.io.File; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.util.Collection; -import java.util.List; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; - -import org.apache.directory.api.ldap.model.cursor.CursorException; -import org.apache.directory.api.ldap.model.entry.DefaultEntry; -import org.apache.directory.api.ldap.model.entry.Entry; -import org.apache.directory.api.ldap.model.exception.LdapException; -import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; -import org.apache.directory.api.ldap.model.name.Ava; -import org.apache.directory.api.ldap.model.name.Rdn; -import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.testng.AssertJUnit; -import org.testng.annotations.Listeners; -import org.testng.annotations.Test; - -import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.model.api.ModelExecuteOptions; -import com.evolveum.midpoint.prism.PrismObject; -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.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.schema.SearchResultList; -import com.evolveum.midpoint.schema.SearchResultMetadata; -import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.internals.InternalCounters; -import com.evolveum.midpoint.schema.processor.ResourceAttribute; -import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceSchema; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; -import com.evolveum.midpoint.schema.util.ShadowUtil; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.test.IntegrationTestTools; -import com.evolveum.midpoint.test.util.MidPointTestConstants; -import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.testing.conntest.AbstractLdapTest; -import com.evolveum.midpoint.testing.conntest.UserLdapConnectionConfig; -import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.util.exception.SystemException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; - -/** - * @author semancik - */ -@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) -public abstract class AbstractAdLdapMultidomainTest extends AbstractLdapTest - implements AdTestMixin { - - protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap-multidomain"); - - protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); - protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; - - protected static final File ROLE_SUBMISSIVE_FILE = new File(TEST_DIR, "role-submissive.xml"); - protected static final String ROLE_SUBMISSIVE_OID = "0c0c81b2-d0a1-11e5-b51e-0309a826745e"; - - protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); - protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; - - protected static final File ROLE_META_ORG_GROUP_FILE = new File(TEST_DIR, "role-meta-org-group.xml"); - protected static final String ROLE_META_ORG_GROUP_OID = "c5d3294a-0d8e-11e7-bd9d-ff848c2e7e3f"; - - protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; - protected static final String ACCOUNT_JACK_SID = "S-1-5-21-3305462238-3617280118-659738602-4878"; - protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; - protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; - - protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; - - private static final String GROUP_PIRATES_NAME = "pirates"; - private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; - private static final String GROUP_MELEE_ISLAND_ALT_NAME = "Alternative Mêlée Island"; - private static final String GROUP_MELEE_ISLAND_PIRATES_NAME = "Mêlée Island Pirates"; - private static final String GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION = "swashbuckle and loot"; - - protected static final int NUMBER_OF_ACCOUNTS = 18; - private static final String ASSOCIATION_GROUP_NAME = "group"; - - private static final String NS_EXTENSION = "http://whatever.com/my"; - private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); - - protected static final File USER_SUBMAN_FILE = new File(TEST_DIR, "user-subman.xml"); - private static final String USER_SUBMAN_OID = "910ac45a-8bd6-11e6-9122-ef88d95095f0"; - private static final String USER_SUBMAN_USERNAME = "subman"; - private static final String USER_SUBMAN_GIVEN_NAME = "Sub"; - private static final String USER_SUBMAN_FAMILY_NAME = "Man"; - private static final String USER_SUBMAN_FULL_NAME = "Sub Man"; - private static final String USER_SUBMAN_PASSWORD = "sub.123"; - - private static final String USER_SUBDOG_USERNAME = "subdog"; - private static final String USER_SUBDOG_GIVEN_NAME = "Sub"; - private static final String USER_SUBDOG_FAMILY_NAME = "Dog"; - private static final String USER_SUBDOG_FULL_NAME = "Sub Dog"; - - protected static final File USER_SUBMARINE_FILE = new File(TEST_DIR, "user-submarine.xml"); - private static final String USER_SUBMARINE_OID = "c4377f86-8be9-11e6-8ef5-c3c56ff64b09"; - private static final String USER_SUBMARINE_USERNAME = "submarine"; - private static final String USER_SUBMARINE_GIVEN_NAME = "Sub"; - private static final String USER_SUBMARINE_FAMILY_NAME = "Marine"; - private static final String USER_SUBMARINE_FULL_NAME = "Sub Marine"; - - private static final String INTENT_GROUP = "group"; - private static final String INTENT_OU_TOP = "ou-top"; - - private static final String USER_EMPTYHEAD_NAME = "emptyhead"; - - private static final String PROXY_ADDRES_ADDR_UPCASE = "smpt:ADDR"; - private static final String PROXY_ADDRES_ADDR_LOWCASE = "smpt:addr"; - - private static final String OBJECT_CATEGORY_PERSON = "CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; - private static final String OBJECT_CATEGORY_GROUP = "CN=Group,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; - - private static final String USER_GUYBRUSH_PASSWORD_123 = "wanna.be.a.123"; - private static final String USER_GUYBRUSH_PASSWORD_333 = "wanna.be.a.333"; - - private boolean allowDuplicateSearchResults = false; - - protected String jackAccountOid; - protected String groupPiratesOid; - protected long jackLockoutTimestamp; - protected String accountBarbossaOid; - protected String orgMeleeIslandOid; - protected String groupMeleeIslandOid; - protected String ouMeleeIslandOid; - protected String roleMeleeIslandPiratesOid; - protected String groupMeleeIslandPiratesOid; - - private String accountSubmanOid; - - private String accountSubmarineOid; - - @Override - public String getStartSystemCommand() { - return null; - } - - @Override - public String getStopSystemCommand() { - return null; - } - - @Override - protected File getBaseDir() { - return TEST_DIR; - } - - @Override - protected String getSyncTaskOid() { - return "cd1e0ff2-0099-11e5-9e22-001e8c717e5b"; - } - - @Override - protected boolean useSsl() { - return true; - } - - @Override - protected String getLdapSuffix() { - return "DC=ad,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindDn() { - return "CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindPassword() { - return "qwe.123"; - } - - @Override - protected int getSearchSizeLimit() { - return -1; - } - - @Override - public String getPrimaryIdentifierAttributeName() { - return "objectGUID"; - } - - @Override - protected String getPeopleLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - @Override - protected String getGroupsLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - protected String getLdapSubSuffix() { - return "DC=sub,DC=ad,DC=evolveum,DC=com"; - } - - protected String getPeopleLdapSubSuffix() { - return "CN=Users," + getLdapSubSuffix(); - } - - @Override - protected String getLdapAccountObjectClass() { - return "user"; - } - - @Override - protected String getLdapGroupObjectClass() { - return "group"; - } - - @Override - protected String getLdapGroupMemberAttribute() { - return "member"; - } - - private QName getAssociationGroupQName() { - return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); - } - - @Override - protected boolean allowDuplicateSearchResults() { - return allowDuplicateSearchResults; - } - - @Override - protected boolean isGroupMemberMandatory() { - return false; - } - - protected String getOrgsLdapSuffix() { - return "OU=Org," + getLdapSuffix(); - } - - private UserLdapConnectionConfig getSubLdapConnectionConfig() { - UserLdapConnectionConfig config = new UserLdapConnectionConfig(); - config.setLdapHost("hydra.ad.evolveum.com"); - config.setLdapPort(getLdapServerPort()); - config.setBindDn("CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com"); - config.setBindPassword(getLdapBindPassword()); - config.setBaseContext(getLdapSubSuffix()); - return config; - } - - protected abstract File getReconciliationTaskFile(); - - protected abstract String getReconciliationTaskOid(); - - protected String getLdapConnectorClassName() { - return AD_CONNECTOR_TYPE; - } - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); - - // Users - repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); - repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); - repoAddObjectFromFile(USER_SUBMAN_FILE, initResult); - repoAddObjectFromFile(USER_SUBMARINE_FILE, initResult); - - // Roles - repoAddObjectFromFile(ROLE_END_USER_FILE, initResult); - repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); - repoAddObjectFromFile(ROLE_SUBMISSIVE_FILE, initResult); - repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); - repoAddObjectFromFile(ROLE_META_ORG_GROUP_FILE, initResult); - - assignRole(USER_BARBOSSA_OID, ROLE_END_USER_OID); - - } - - @Test - public void test000Sanity() throws Exception { - assertLdapPassword(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); - cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); - cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME)); - cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME)); - cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME)); - cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); - cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_ALT_NAME)); - cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME)); - cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME)); - cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_NAME)); - cleanupDelete("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); - cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); - } - - @Test - @Override - public void test020Schema() throws Exception { - // IntegrationTestTools.displayXml("Resource XML", resource); - accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); - assertAdRefinedSchema(resource, getAccountObjectClass()); - assertExchangeSchema(resource, getAccountObjectClass(), prismContext); - - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - assertEquals("Unexpected number of schema definitions (limited by generation constraints)", 5, resourceSchema.getDefinitions().size()); - - assertLdapConnectorInstances(1); - } - - @Test - public void test100SeachJackBySamAccountName() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = - modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - assertSid(shadow, ACCOUNT_JACK_SID); - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - jackAccountOid = shadow.getOid(); - -// assertConnectorOperationIncrement(2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - /** - * MID-3730 - */ - @Test - public void test101SeachJackByDn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - String jackDn = toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME); - ObjectQuery query = createAccountShadowQueryByAttribute("dn", jackDn, resource); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - assertAccountShadow(shadow, jackDn); - assertSid(shadow, ACCOUNT_JACK_SID); - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - -// assertConnectorOperationIncrement(2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - /** - * Search for non-existent DN should return no results. It should NOT - * throw an error. - *

- * MID-3730 - */ - @Test - public void test102SeachNotExistByDn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - String dn = toAccountDn("idonoexist", "I am a Fiction"); - ObjectQuery query = createAccountShadowQueryByAttribute("dn", dn, resource); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 0, shadows.size()); - -// assertConnectorOperationIncrement(2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - assertLdapConnectorInstances(1); - } - - @Test - public void test105SeachPiratesByCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - then(); - assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - groupPiratesOid = shadow.getOid(); - assertObjectCategory(shadow, OBJECT_CATEGORY_GROUP); - -// assertConnectorOperationIncrement(1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - @Test - public void test110GetJack() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - long startOfTestMsTimestamp = getWin32Filetime(System.currentTimeMillis()); - - // WHEN - when(); - PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); - - // THEN - then(); - assertSuccess(result); - - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - jackAccountOid = shadow.getOid(); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=ad,DC=evolveum,DC=com"); - assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); - assertAttribute(shadow, "sn", "Sparrow"); - assertAttribute(shadow, "description", "The best pirate the world has ever seen"); - assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - List lastLogonValues = ShadowUtil.getAttributeValues(shadow, new QName(getResourceNamespace(), "lastLogon")); - assertEquals("Wrong number of lastLong values: " + lastLogonValues, 1, lastLogonValues.size()); - if (lastLogonValues.get(0) > startOfTestMsTimestamp) { - fail("Wrong lastLogon, expected it to be less than " + startOfTestMsTimestamp + ", but was " + lastLogonValues.get(0)); - } - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - assertLdapConnectorInstances(1); - } - - /** - * No paging. It should return all accounts. - */ - @Test - public void test150SeachAllAccounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - SearchResultList> searchResultList = doSearch(query, - NUMBER_OF_ACCOUNTS, task, result); - - // TODO: Why 14? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 14); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * This is in one block. - */ - @Test - public void test152SeachFirst2Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test154SeachFirst11Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(11); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test162SeachFirst2AccountsOffset0() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setOffset(0); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test172Search2AccountsOffset1() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test174SeachFirst11AccountsOffset2() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); - query.setPaging(paging); - - allowDuplicateSearchResults = true; - - // WHEN - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - // THEN - allowDuplicateSearchResults = false; - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * There is offset, so VLV should be used. - * Explicit sorting. - */ - @Test - public void test182Search2AccountsOffset1SortCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); - query.setPaging(paging); - - SearchResultList> shadows = doSearch(query, 2, task, result); - - assertAccountShadow(shadows.get(0), "CN=Adolf Supperior,CN=Users,DC=ad,DC=evolveum,DC=com"); -// assertAccountShadow(shadows.get(1), "CN=DiscoverySearchMailbox {D919BA05-46A6-415f-80AD-7E09334BB852},CN=Users,DC=ad,DC=evolveum,DC=com"); - - // TODO: Why 2? Why not 1? - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test200AssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", null); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountBarbossaIcfUid); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - - // MID-4624 - ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); - assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); - XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); - long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); - // LDAP server may be on a different host. Allow for some clock offset. - TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); - - assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test210ModifyAccountBarbossaTitle() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_TITLE_NAME); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_TITLE_NAME, "Captain"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * Modify USER, test boolean value mapping. - */ - @Test - public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), - task, result, Boolean.FALSE); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * Just normal modification of proxyAddress, directly on the account. - * As proxyAddress is multivalue, this is ADD and not REPLACE. This is what GUI would do. - * No previous value for proxyAddress is set in the AD account. - * MID-5330 - */ - @Test - public void test214ModifyAccountBarbossaProxyAddressesSimple() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_PROXY_ADDRESSES_NAME); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - assertNotNull("No definition for attribute " + attrQName, attrDef); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationAddProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, PROXY_ADDRES_ADDR_UPCASE); - delta.addModification(attrDelta); - - // WHEN - when(); - executeChanges(delta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_PROXY_ADDRESSES_NAME, PROXY_ADDRES_ADDR_UPCASE); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test220ModifyUserBarbossaPasswordSelfServicePassword1() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD, USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * Try to set the same password again. If this is "admin mode" (no runAs capability) - * the such change should be successful. In "selfservice mode" (runAs capability - in subclass) - * this change should fail. - */ - @Test - public void test222ModifyUserBarbossaPasswordSelfServicePassword1Again() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * Change to different password. This should go well for both admin and self-service. - * MID-5242 - */ - @Test - public void test224ModifyUserBarbossaPasswordSelfServicePassword2() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_2); - } - - /** - * Change password back to the first password. This password was used before. - * In admin mode this should go well. Admin can set password to anything. - * But in self-service mode (in subclass) this should fail due to password history check. - */ - @Test - public void test226ModifyUserBarbossaPasswordSelfServicePassword1AgainAgain() throws Exception { - testModifyUserBarbossaPasswordSelfServiceSuccess( - USER_BARBOSSA_PASSWORD_AD_2, USER_BARBOSSA_PASSWORD_AD_1); - } - - protected void testModifyUserBarbossaPasswordSelfServiceSuccess(String oldPassword, String newPassword) throws Exception { - // GIVEN - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); - - login(USER_BARBOSSA_USERNAME); - - Task task = getTestTask(); - task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, - oldPassword, newPassword); - - // WHEN - when(); - executeChanges(objectDelta, null, task, result); - - // THEN - then(); - login(USER_ADMINISTRATOR_USERNAME); - assertSuccess(result); - - assertBarbossaEnabled(newPassword); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, newPassword); - - assertLdapConnectorInstances(2); - } - - protected void testModifyUserBarbossaPasswordSelfServiceFailure( - String oldPassword, String newPassword) throws Exception { - // GIVEN - login(USER_BARBOSSA_USERNAME); - - Task task = getTestTask(); - task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, - oldPassword, newPassword); - - // WHEN - when(); - executeChanges(objectDelta, null, task, result); - - // THEN - then(); - login(USER_ADMINISTRATOR_USERNAME); - assertPartialError(result); - - assertBarbossaEnabled(newPassword); - assertUserAfter(USER_BARBOSSA_OID) - .assertPassword(newPassword); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); - - assertLdapConnectorInstances(2); - } - - @Test - public void test230DisableUserBarbossa() throws Exception { - // precondition - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.DISABLED); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * MID-4041 - */ - @Test - public void test232ReconcileBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); - } - - /** - * MID-4041 - */ - @Test - public void test236EnableUserBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - /** - * MID-4041 - */ - @Test - public void test237ReconcileBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - /** - * MID-4041 - */ - @Test - public void test238DisableUserBarbossaRawAndReconcile() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.DISABLED); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - /** - * MID-4041 - */ - @Test - public void test239EnableUserBarbossaRawAndReconcile() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.ENABLED); - - // WHEN - when(); - reconcileUser(USER_BARBOSSA_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); - - assertLdapConnectorInstances(2); - } - - protected PrismObject assertBarbossaEnabled(String ldapPassword) throws Exception { - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "FALSE"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, ldapPassword); - - return user; - } - - private void assertBarbossaDisabled(String password) throws Exception { - assertLdapConnectorInstances(2); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - display("disabled Barbossa entry", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "TRUE"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountDisabled(shadow); - - try { - assertLdapPassword(null, entry, password); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected - } - - assertLdapConnectorInstances(2); - } - - /** - * This should create account with a group. And the account shoudl be disabled. - */ - @Test - public void test250AssignGuybrushPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - -// ProtectedStringType userPasswordPs = new ProtectedStringType(); -// userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_333); -// modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - modifyUserReplace(USER_GUYBRUSH_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.DISABLED); - - // WHEN - when(); - assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - display("Entry", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - String shadowOid = getSingleLinkOid(user); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - assertAccountDisabled(shadow); - -// try { -// assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_333); -// AssertJUnit.fail("Password authentication works, but it should fail"); -// } catch (SecurityException e) { -// // this is expected, account is disabled -// } - - assertLdapConnectorInstances(2); - } - - @Test - public void test255ModifyUserGuybrushPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_123); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - display("Guybrush entry after", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - try { - assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_123); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected, account is disabled - } - -// assertLdapConnectorInstances(2); - } - - @Test - public void test260EnableGyubrush() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertLdapPassword(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); - - assertLdapConnectorInstances(2); - } - - /** - * Try to create an account without password. This should end up with an error. - * A reasonable error. - * MID-4046 - */ - @Test - public void test270AssignAccountToEmptyhead() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject userBefore = createUser(USER_EMPTYHEAD_NAME, USER_EMPTYHEAD_NAME, true); - display("User before", userBefore); - addObject(userBefore); - String userEmptyheadOid = userBefore.getOid(); - - // WHEN - when(); - assignAccountToUser(userEmptyheadOid, getResourceOid(), null, task, result); - - // THEN - then(); - assertPartialError(result); - - assertMessageContains(result.getMessage(), "does not meet the length, complexity, or history requirement"); - - assertLdapConnectorInstances(2); - } - - /** - * Just make random test connection between the tests. Make sure that the - * test does not break anything. If it does the next tests will simply fail. - */ - @Test - public void test295TestConnection() throws Exception { - // GIVEN - Task task = getTestTask(); - - // WHEN - when(); - OperationResult testResult = modelService.testResource(getResourceOid(), task); - - // THEN - then(); - display("Test connection result", testResult); - TestUtil.assertSuccess("Test connection result", testResult); - - // Test is disposing connector facade and the entire connector pool. - // Therefore we are back at 1 instance. - assertLdapConnectorInstances(1); - } - - @Test - public void test300AssignBarbossaPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - display("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertLdapConnectorInstances(1); - } - - @Test - public void test390ModifyUserBarbossaRename() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); - objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); - Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); - - // WHEN - when(); - modelService.executeChanges(deltas, null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - display("Shadow after rename (model)", shadow); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); - display("Shadow after rename (repo)", repoShadow); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - -// assertLdapConnectorInstances(2); - } - - // TODO: create account with a group membership - - @Test - public void test395UnAssignBarbossaPirates() throws Exception { - // TODO: do this on another account. There is a bad interference with rename. - - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - display("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test399UnAssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertNoLinkedAccount(user); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test500AddOrgMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject org = instantiateObject(OrgType.class); - OrgType orgType = org.asObjectable(); - orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); - AssignmentType metaroleAssignment = new AssignmentType(); - ObjectReferenceType metaroleRef = new ObjectReferenceType(); - metaroleRef.setOid(ROLE_META_ORG_OID); - metaroleRef.setType(RoleType.COMPLEX_TYPE); - metaroleAssignment.setTargetRef(metaroleRef); - orgType.getAssignment().add(metaroleAssignment); - - // WHEN - when(); - addObject(org, task, result); - - // THEN - then(); - assertSuccess(result); - - orgMeleeIslandOid = org.getOid(); - assertLdapGroup(GROUP_MELEE_ISLAND_NAME); - assertLdapOrg(GROUP_MELEE_ISLAND_NAME); - - org = getObject(OrgType.class, orgMeleeIslandOid); - groupMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); - ouMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); - assertLinks(org, 2); - - PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); - display("Shadow: group (model)", shadowGroup); - - PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); - display("Shadow: ou (model)", shadowOu); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test510AssignGuybrushMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - - assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeIslandOid); - -// assertLdapConnectorInstances(2); - } - - /** - * Create role under the Melee Island org. This creates group in the orgstruct. - */ - @Test - public void test515AddOrgGroupMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject role = instantiateObject(RoleType.class); - RoleType roleType = role.asObjectable(); - roleType.setName(new PolyStringType(GROUP_MELEE_ISLAND_PIRATES_NAME)); - - AssignmentType metaroleAssignment = new AssignmentType(); - ObjectReferenceType metaroleRef = new ObjectReferenceType(); - metaroleRef.setOid(ROLE_META_ORG_GROUP_OID); - metaroleRef.setType(RoleType.COMPLEX_TYPE); - metaroleAssignment.setTargetRef(metaroleRef); - roleType.getAssignment().add(metaroleAssignment); - - AssignmentType orgAssignment = new AssignmentType(); - ObjectReferenceType orgRef = new ObjectReferenceType(); - orgRef.setOid(orgMeleeIslandOid); - orgRef.setType(OrgType.COMPLEX_TYPE); - orgAssignment.setTargetRef(orgRef); - roleType.getAssignment().add(orgAssignment); - - // WHEN - when(); - addObject(role, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - roleMeleeIslandPiratesOid = role.getOid(); - // TODO: assert LDAP object - - assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - - PrismObject roleAfter = getObject(RoleType.class, roleMeleeIslandPiratesOid); - display("Role after", roleAfter); - groupMeleeIslandPiratesOid = getSingleLinkOid(roleAfter); - PrismObject shadow = getShadowModel(groupMeleeIslandPiratesOid); - display("Shadow (model)", shadow); - } - - /** - * Rename org unit. MidPoint should rename OU and ordinary group. - * AD will rename the group in the orgstruct automatically. We need to - * make sure that we can still access that group. - */ - @Test - public void test520RenameMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - renameObject(OrgType.class, orgMeleeIslandOid, GROUP_MELEE_ISLAND_ALT_NAME, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - PrismObject orgAfter = getObject(OrgType.class, orgMeleeIslandOid); - groupMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); - ouMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); - assertLinks(orgAfter, 2); - - PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); - display("Shadow: group (model)", shadowGroup); - - PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); - display("Shadow: ou (model)", shadowOu); - - assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); - - assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); - - assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - - Entry entryGuybrush = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - String shadowAccountOid = getSingleLinkOid(user); - PrismObject shadowAccount = getShadowModel(shadowAccountOid); - display("Shadow: account (model)", shadowAccount); - - assertLdapGroupMember(entryGuybrush, GROUP_MELEE_ISLAND_ALT_NAME); - - IntegrationTestTools.assertAssociation(shadowAccount, getAssociationGroupQName(), groupMeleeIslandOid); - -// assertLdapConnectorInstances(2); - } - - /** - * AD renamed the pirate groups by itself. MidPoint does not know about it. - * The GUID that is stored in the shadow is still OK. But the DN is now out - * of date. Try to update the group. Make sure it works. - * It is expected that the GUI will be used as a primary identifier. - * Note: just reading the group will NOT work. MidPoint is too smart - * for that. It will transparently fix the situation. - */ - @Test - public void test522ModifyMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyObjectReplaceProperty(ShadowType.class, groupMeleeIslandPiratesOid, - ItemPath.create(ShadowType.F_ATTRIBUTES, new QName(MidPointConstants.NS_RI, "description")), - task, result, GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - assertAttribute(entryOrgGroup, "description", GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); - - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test524GetMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - PrismObject shadow = modelService.getObject(ShadowType.class, groupMeleeIslandPiratesOid, null, task, result); - - // THEN - then(); - assertSuccess(result); - - display("Shadow after", shadow); - assertNotNull(shadow); - - assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); - assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); - Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - display("Melee org", entryOrgGroup); - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - } - - @Test - public void test595DeleteOrgGroupMeleeIslandPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - deleteObject(RoleType.class, roleMeleeIslandPiratesOid, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); - - assertNoObject(ShadowType.class, groupMeleeIslandPiratesOid); - -// assertLdapConnectorInstances(2); - } - - /** - * We create "underMelee" org that gets into the way of the delete. - * Melee cannot be deleted in an ordinary way. "tree delete" control must - * be used. This is configured in the connector config. - *

- * MID-5935 - */ - @Test - public void test599DeleteOrgMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - createUnderMeleeEntry(); - - // WHEN - when(); - deleteObject(OrgType.class, orgMeleeIslandOid, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); - assertNoLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); - assertNoLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); - - assertNoObject(ShadowType.class, groupMeleeIslandOid); - assertNoObject(ShadowType.class, ouMeleeIslandOid); - -// assertLdapConnectorInstances(2); - } - - protected void createUnderMeleeEntry() throws LdapException, IOException { - // This OU just gets into the way of the delete. - Entry entry = new DefaultEntry("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME), - "objectclass", "organizationalUnit", - "ou", "underMelee"); - display("underMelee org", entry); - addLdapEntry(entry); - } - - @Test - public void test600AssignAccountSubman() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - assignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - display("Sub entry", entry); - assertAttribute(entry, "title", null); - - PrismObject userAfter = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(userAfter); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountSubmanOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountBarbossaIcfUid); - - assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, USER_SUBMAN_PASSWORD); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - // MID-4624 - ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); - assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); - XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); - long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); - // LDAP server may be on a different host. Allow for some clock offset. - TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test610ModifyUserSubmanTitle() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, UserType.F_TITLE, task, result, - createPolyString("Underdog")); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - display("Sub entry", entry); - assertAttribute(entry, "title", "Underdog"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountSubmanOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test620ModifyUserSubmanPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue("SuB.321"); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertAttribute(entry, "title", "Underdog"); - assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountSubmanOid, shadowOid); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test630DisableUserSubman() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.DISABLED); - - // THEN - then(); - assertSuccess(result); - -// assertLdapConnectorInstances(2); - - PrismObject user = getUser(USER_SUBMAN_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountDisabled(shadow); - - try { - assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected - } - -// assertLdapConnectorInstances(2); - } - - @Test - public void test639EnableUserSubman() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_SUBMAN_OID, - SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, - task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - PrismObject user = getUser(USER_SUBMAN_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test690ModifyUserSubmanRename() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_SUBMAN_OID, UserType.F_NAME, - createPolyString(USER_SUBDOG_USERNAME)); - objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, - createPolyString(USER_SUBDOG_FULL_NAME)); - - // WHEN - when(); - executeChanges(objectDelta, null, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); - assertAttribute(entry, "title", "Underdog"); - - PrismObject user = getUser(USER_SUBMAN_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountSubmanOid, shadowOid); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - display("Shadow after rename (model)", shadow); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); - display("Shadow after rename (repo)", repoShadow); - - assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - -// assertLdapConnectorInstances(2); - } - - @Test - public void test699UnAssignAccountSubdog() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); - assertNoLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); - - PrismObject user = getUser(USER_SUBMAN_OID); - assertNoLinkedAccount(user); - -// assertLdapConnectorInstances(2); - } - - /** - * Create account and modify it in a very quick succession. - * This test is designed to check if we can live with a long - * global catalog update delay. - * MID-2926 - */ - @Test - public void test700AssignAccountSubmarineAndModify() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); - - modifyUserReplace(USER_SUBMARINE_OID, UserType.F_TITLE, task, result, - PrismTestUtil.createPolyString("Underseadog")); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); - display("Sub entry", entry); - assertAttribute(entry, "title", "Underseadog"); - - PrismObject userAfter = getUser(USER_SUBMARINE_OID); - String shadowOid = getSingleLinkOid(userAfter); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountSubmarineOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountIcfUid); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - } - - @Test - public void test809UnAssignAccountSubmarine() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - assertNoLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); - - PrismObject user = getUser(USER_SUBMARINE_OID); - assertNoLinkedAccount(user); - } - - @Test - public void test850ReconcileAccounts() throws Exception { - // GIVEN - assertUsers(6); - - // WHEN - when(); - addTask(getReconciliationTaskFile()); - - waitForTaskFinish(getReconciliationTaskOid(), true); - - // THEN - then(); - - assertUsers(15); - // TODO - -// assertLdapConnectorInstances(2); - } - - @Override - protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { - super.assertAccountShadow(shadow, dn); - ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); - assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); - String primaryId = primaryIdAttr.getRealValue(); - assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); - - ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); - assertNotNull("No SID in " + shadow, objectSidAttr); - display("SID of " + dn + ": " + objectSidAttr); - } - - protected void assertSid(PrismObject shadow, String expectedSid) { - ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); - assertNotNull("No SID in " + shadow, objectSidAttr); - display("SID of " + shadow + ": " + objectSidAttr); - assertEquals("Wrong SID in " + shadow, expectedSid, objectSidAttr.getRealValue()); - } - - private void assertObjectCategory(PrismObject shadow, String expectedObjectCategory) { - ResourceAttribute objectCategoryAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_CATEGORY_NAME)); - assertNotNull("No objectCategory in " + shadow, objectCategoryAttr); - display("objectCategory of " + shadow + ": " + objectCategoryAttr); - assertEquals("Wrong objectCategory in " + shadow, expectedObjectCategory, objectCategoryAttr.getRealValue()); - } - - @Override - protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { - Entry entry = searchLdapAccount("(cn=" + cn + ")"); - assertAttribute(entry, "cn", cn); - assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); - return entry; - } - - protected Entry assertLdapSubAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { - Entry entry = searchLdapAccount(getSubLdapConnectionConfig(), "(cn=" + cn + ")"); - assertAttribute(entry, "cn", cn); - assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); - return entry; - } - - @Override - protected void assertNoLdapAccount(String uid) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { - assertNoLdapAccount(null, uid, cn); - } - - protected void assertNoLdapSubAccount(String uid, String cn) throws LdapException, IOException, CursorException { - assertNoLdapAccount(getSubLdapConnectionConfig(), uid, cn); - } - - protected void assertNoLdapAccount(UserLdapConnectionConfig config, String uid, String cn) throws LdapException, IOException, CursorException { - LdapNetworkConnection connection = ldapConnect(config); - List entriesCn = ldapSearch(config, connection, "(cn=" + cn + ")"); - List entriesSamAccountName = ldapSearch(config, connection, "(sAMAccountName=" + uid + ")"); - ldapDisconnect(connection); - - assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); - assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); - } - - @Override - protected String toAccountDn(String username) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - @Override - protected String toAccountDn(String username, String fullName) { - return ("CN=" + fullName + "," + getPeopleLdapSuffix()); - } - - protected String toAccountSubDn(String username, String fullName) { - return ("CN=" + fullName + "," + getPeopleLdapSubSuffix()); - } - - @Override - protected Rdn toAccountRdn(String username, String fullName) { - try { - return new Rdn(new Ava("CN", fullName)); - } catch (LdapInvalidDnException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - protected String toOrgDn(String cn) { - return "ou=" + cn + "," + getOrgsLdapSuffix(); - } - - protected String toOrgGroupDn(String groupCn, String orgName) { - return "cn=" + groupCn + "," + toOrgDn(orgName); - } - - protected Entry assertLdapOrg(String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgDn(orgName); - Entry entry = getLdapEntry(dn); - assertNotNull("No entry " + dn, entry); - assertAttribute(entry, "ou", orgName); - return entry; - } - - protected Entry assertNoLdapOrg(String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgDn(orgName); - Entry entry = getLdapEntry(dn); - assertNull("Unexpected org entry " + entry, entry); - return entry; - } - - protected Entry assertLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgGroupDn(groupCn, orgName); - Entry entry = getLdapEntry(dn); - assertNotNull("No entry " + dn, entry); - assertAttribute(entry, "cn", groupCn); - return entry; - } - - protected Entry assertNoLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { - String dn = toOrgGroupDn(groupCn, orgName); - Entry entry = getLdapEntry(dn); - assertNull("Unexpected org group entry " + entry, entry); - return entry; - } - - protected void assertLdapPassword(String uid, String fullName, String password) throws LdapException, IOException, CursorException { - assertLdapPassword(null, uid, fullName, password); - } - - protected void assertLdapPassword(UserLdapConnectionConfig config, String uid, String fullName, String password) throws LdapException, IOException, CursorException { - Entry entry = getLdapAccountByCn(config, fullName); - assertLdapPassword(config, entry, password); - } - - protected void assertLdapPassword(String uid, String password) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), - prismContext); - return query; - } - - @Override - protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { - byte[] password = encodePassword("Secret.123"); - Entry entry = new DefaultEntry(toAccountDn(uid, cn), - "objectclass", getLdapAccountObjectClass(), - ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, - "cn", cn, - "givenName", givenName, - "sn", sn, - ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", - ATTRIBUTE_UNICODE_PWD_NAME, password); - return entry; - } - - private byte[] encodePassword(String password) { - String quotedPassword = "\"" + password + "\""; - try { - return quotedPassword.getBytes("UTF-16LE"); - } catch (UnsupportedEncodingException e) { - throw new SystemException(e.getMessage(), e); - } - } - - public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { - assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); - } - - public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { - List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); - PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); - } - - protected abstract void assertAccountDisabled(PrismObject shadow); - - protected abstract void assertAccountEnabled(PrismObject shadow); - -} +/* + * Copyright (c) 2015-2019 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.testing.conntest.ad; + +import static org.testng.AssertJUnit.*; + +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; + +import java.io.File; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.Collection; +import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.prism.PrismProperty; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; + +import org.apache.commons.lang.StringUtils; +import org.apache.directory.api.ldap.model.cursor.CursorException; +import org.apache.directory.api.ldap.model.entry.DefaultEntry; +import org.apache.directory.api.ldap.model.entry.Entry; +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; +import org.apache.directory.api.ldap.model.name.Ava; +import org.apache.directory.api.ldap.model.name.Rdn; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.testng.AssertJUnit; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.model.api.ModelExecuteOptions; +import com.evolveum.midpoint.prism.PrismObject; +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.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.SearchResultMetadata; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.processor.ResourceAttribute; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceSchema; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.testing.conntest.AbstractLdapTest; +import com.evolveum.midpoint.testing.conntest.UserLdapConnectionConfig; +import com.evolveum.midpoint.util.MiscUtil; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.util.exception.SystemException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +/** + * @author semancik + */ +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public abstract class AbstractAdLdapMultidomainTest extends AbstractLdapTest + implements AdTestMixin { + + protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap-multidomain"); + + protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); + protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; + + protected static final File ROLE_SUBMISSIVE_FILE = new File(TEST_DIR, "role-submissive.xml"); + protected static final String ROLE_SUBMISSIVE_OID = "0c0c81b2-d0a1-11e5-b51e-0309a826745e"; + + protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); + protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; + + protected static final File ROLE_META_ORG_GROUP_FILE = new File(TEST_DIR, "role-meta-org-group.xml"); + protected static final String ROLE_META_ORG_GROUP_OID = "c5d3294a-0d8e-11e7-bd9d-ff848c2e7e3f"; + + protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; + protected static final String ACCOUNT_JACK_SID = "S-1-5-21-3305462238-3617280118-659738602-4878"; + protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; + protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; + + protected static final String ACCOUNT_HT_UID = "ht"; + protected static final String ACCOUNT_HT_CN = "Herman Toothrot"; + protected static final String ACCOUNT_HT_GIVENNAME = "Herman"; + protected static final String ACCOUNT_HT_SN = "Toothrot"; + protected static final String ACCOUNT_HT_SN_MODIFIED = "Torquemeda Marley"; + + protected static final String ACCOUNT_HTM_UID = "htm"; + protected static final String ACCOUNT_HTM_CN = "Horatio Torquemada Marley"; + + protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; + + private static final String GROUP_PIRATES_NAME = "pirates"; + private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; + private static final String GROUP_MELEE_ISLAND_ALT_NAME = "Alternative Mêlée Island"; + private static final String GROUP_MELEE_ISLAND_PIRATES_NAME = "Mêlée Island Pirates"; + private static final String GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION = "swashbuckle and loot"; + + protected static final int NUMBER_OF_ACCOUNTS = 18; + private static final String ASSOCIATION_GROUP_NAME = "group"; + + private static final String NS_EXTENSION = "http://whatever.com/my"; + private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); + + protected static final File USER_SUBMAN_FILE = new File(TEST_DIR, "user-subman.xml"); + private static final String USER_SUBMAN_OID = "910ac45a-8bd6-11e6-9122-ef88d95095f0"; + private static final String USER_SUBMAN_USERNAME = "subman"; + private static final String USER_SUBMAN_GIVEN_NAME = "Sub"; + private static final String USER_SUBMAN_FAMILY_NAME = "Man"; + private static final String USER_SUBMAN_FULL_NAME = "Sub Man"; + private static final String USER_SUBMAN_PASSWORD = "sub.123"; + + private static final String USER_SUBDOG_USERNAME = "subdog"; + private static final String USER_SUBDOG_GIVEN_NAME = "Sub"; + private static final String USER_SUBDOG_FAMILY_NAME = "Dog"; + private static final String USER_SUBDOG_FULL_NAME = "Sub Dog"; + + protected static final File USER_SUBMARINE_FILE = new File(TEST_DIR, "user-submarine.xml"); + private static final String USER_SUBMARINE_OID = "c4377f86-8be9-11e6-8ef5-c3c56ff64b09"; + private static final String USER_SUBMARINE_USERNAME = "submarine"; + private static final String USER_SUBMARINE_GIVEN_NAME = "Sub"; + private static final String USER_SUBMARINE_FAMILY_NAME = "Marine"; + private static final String USER_SUBMARINE_FULL_NAME = "Sub Marine"; + + private static final String INTENT_GROUP = "group"; + private static final String INTENT_OU_TOP = "ou-top"; + + private static final String USER_EMPTYHEAD_NAME = "emptyhead"; + + private static final String PROXY_ADDRES_ADDR_UPCASE = "smpt:ADDR"; + private static final String PROXY_ADDRES_ADDR_LOWCASE = "smpt:addr"; + + private static final String OBJECT_CATEGORY_PERSON = "CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; + private static final String OBJECT_CATEGORY_GROUP = "CN=Group,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com"; + + private static final String USER_GUYBRUSH_PASSWORD_123 = "wanna.be.a.123"; + private static final String USER_GUYBRUSH_PASSWORD_333 = "wanna.be.a.333"; + + private boolean allowDuplicateSearchResults = false; + + protected String jackAccountOid; + protected String groupPiratesOid; + protected long jackLockoutTimestamp; + protected String accountBarbossaOid; + protected String orgMeleeIslandOid; + protected String groupMeleeIslandOid; + protected String ouMeleeIslandOid; + protected String roleMeleeIslandPiratesOid; + protected String groupMeleeIslandPiratesOid; + + private String accountSubmanOid; + + private String accountSubmarineOid; + + @Override + public String getStartSystemCommand() { + return null; + } + + @Override + public String getStopSystemCommand() { + return null; + } + + @Override + protected File getBaseDir() { + return TEST_DIR; + } + + @Override + protected String getSyncTaskOid() { + return "0f93d8d4-5fb4-11ea-8571-a3f090bf921f"; + } + + @Override + protected boolean useSsl() { + return true; + } + + @Override + protected String getLdapSuffix() { + return "DC=ad,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindDn() { + return "CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindPassword() { + return "qwe.123"; + } + + @Override + protected int getSearchSizeLimit() { + return -1; + } + + @Override + public String getPrimaryIdentifierAttributeName() { + return "objectGUID"; + } + + @Override + protected String getPeopleLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + @Override + protected String getGroupsLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + protected String getLdapSubSuffix() { + return "DC=sub,DC=ad,DC=evolveum,DC=com"; + } + + protected String getPeopleLdapSubSuffix() { + return "CN=Users," + getLdapSubSuffix(); + } + + @Override + protected String getLdapAccountObjectClass() { + return "user"; + } + + @Override + protected String getLdapGroupObjectClass() { + return "group"; + } + + @Override + protected String getLdapGroupMemberAttribute() { + return "member"; + } + + private QName getAssociationGroupQName() { + return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); + } + + @Override + protected boolean allowDuplicateSearchResults() { + return allowDuplicateSearchResults; + } + + @Override + protected boolean isGroupMemberMandatory() { + return false; + } + + protected String getOrgsLdapSuffix() { + return "OU=Org," + getLdapSuffix(); + } + + private UserLdapConnectionConfig getSubLdapConnectionConfig() { + UserLdapConnectionConfig config = new UserLdapConnectionConfig(); + config.setLdapHost("hydra.ad.evolveum.com"); + config.setLdapPort(getLdapServerPort()); + config.setBindDn("CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com"); + config.setBindPassword(getLdapBindPassword()); + config.setBaseContext(getLdapSubSuffix()); + return config; + } + + protected abstract File getReconciliationTaskFile(); + + protected abstract String getReconciliationTaskOid(); + + protected String getLdapConnectorClassName() { + return AD_CONNECTOR_TYPE; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); + + // Users + repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); + repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); + repoAddObjectFromFile(USER_SUBMAN_FILE, initResult); + repoAddObjectFromFile(USER_SUBMARINE_FILE, initResult); + + // Roles + repoAddObjectFromFile(ROLE_END_USER_FILE, initResult); + repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); + repoAddObjectFromFile(ROLE_SUBMISSIVE_FILE, initResult); + repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); + repoAddObjectFromFile(ROLE_META_ORG_GROUP_FILE, initResult); + + assignRole(USER_BARBOSSA_OID, ROLE_END_USER_OID); + + } + + @Test + public void test000Sanity() throws Exception { + assertLdapPassword(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); + cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME)); + cleanupDelete(getSubLdapConnectionConfig(), toAccountSubDn(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME)); + cleanupDelete(toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN)); + cleanupDelete(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_ALT_NAME)); + cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME)); + cleanupDelete(toOrgGroupDn(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME)); + cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_NAME)); + cleanupDelete("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); + cleanupDelete(toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME)); + } + + @Test + @Override + public void test020Schema() throws Exception { + // IntegrationTestTools.displayXml("Resource XML", resource); + accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); + assertAdRefinedSchema(resource, getAccountObjectClass()); + assertExchangeSchema(resource, getAccountObjectClass(), prismContext); + + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + assertEquals("Unexpected number of schema definitions (limited by generation constraints)", 5, resourceSchema.getDefinitions().size()); + + assertLdapConnectorInstances(1); + } + + @Test + public void test100SeachJackBySamAccountName() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = + modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + assertSid(shadow, ACCOUNT_JACK_SID); + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + jackAccountOid = shadow.getOid(); + +// assertConnectorOperationIncrement(2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + /** + * MID-3730 + */ + @Test + public void test101SeachJackByDn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + String jackDn = toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME); + ObjectQuery query = createAccountShadowQueryByAttribute("dn", jackDn, resource); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, jackDn); + assertSid(shadow, ACCOUNT_JACK_SID); + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + +// assertConnectorOperationIncrement(2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + /** + * Search for non-existent DN should return no results. It should NOT + * throw an error. + *

+ * MID-3730 + */ + @Test + public void test102SeachNotExistByDn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + String dn = toAccountDn("idonoexist", "I am a Fiction"); + ObjectQuery query = createAccountShadowQueryByAttribute("dn", dn, resource); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 0, shadows.size()); + +// assertConnectorOperationIncrement(2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + assertLdapConnectorInstances(1); + } + + @Test + public void test105SeachPiratesByCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + then(); + assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + groupPiratesOid = shadow.getOid(); + assertObjectCategory(shadow, OBJECT_CATEGORY_GROUP); + +// assertConnectorOperationIncrement(1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test110GetJack() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + long startOfTestMsTimestamp = getWin32Filetime(System.currentTimeMillis()); + + // WHEN + when(); + PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); + + // THEN + then(); + assertSuccess(result); + + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=ad,DC=evolveum,DC=com"); + assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); + assertAttribute(shadow, "sn", "Sparrow"); + assertAttribute(shadow, "description", "The best pirate the world has ever seen"); + assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + List lastLogonValues = ShadowUtil.getAttributeValues(shadow, new QName(getResourceNamespace(), "lastLogon")); + assertEquals("Wrong number of lastLong values: " + lastLogonValues, 1, lastLogonValues.size()); + if (lastLogonValues.get(0) > startOfTestMsTimestamp) { + fail("Wrong lastLogon, expected it to be less than " + startOfTestMsTimestamp + ", but was " + lastLogonValues.get(0)); + } + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + assertLdapConnectorInstances(1); + } + + /** + * No paging. It should return all accounts. + */ + @Test + public void test150SeachAllAccounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + SearchResultList> searchResultList = doSearch(query, + NUMBER_OF_ACCOUNTS, task, result); + + // TODO: Why 14? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 14); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * This is in one block. + */ + @Test + public void test152SeachFirst2Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test154SeachFirst11Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(11); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test162SeachFirst2AccountsOffset0() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setOffset(0); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test172Search2AccountsOffset1() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test174SeachFirst11AccountsOffset2() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); + query.setPaging(paging); + + allowDuplicateSearchResults = true; + + // WHEN + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + // THEN + allowDuplicateSearchResults = false; + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * There is offset, so VLV should be used. + * Explicit sorting. + */ + @Test + public void test182Search2AccountsOffset1SortCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); + query.setPaging(paging); + + SearchResultList> shadows = doSearch(query, 2, task, result); + + assertAccountShadow(shadows.get(0), "CN=Adolf Supperior,CN=Users,DC=ad,DC=evolveum,DC=com"); +// assertAccountShadow(shadows.get(1), "CN=DiscoverySearchMailbox {D919BA05-46A6-415f-80AD-7E09334BB852},CN=Users,DC=ad,DC=evolveum,DC=com"); + + // TODO: Why 2? Why not 1? + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test200AssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", null); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountBarbossaOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + + // MID-4624 + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); + XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); + long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); + + assertObjectCategory(shadow, OBJECT_CATEGORY_PERSON); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test210ModifyAccountBarbossaTitle() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_TITLE_NAME); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_TITLE_NAME, "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * Modify USER, test boolean value mapping. + */ + @Test + public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), + task, result, Boolean.FALSE); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * Just normal modification of proxyAddress, directly on the account. + * As proxyAddress is multivalue, this is ADD and not REPLACE. This is what GUI would do. + * No previous value for proxyAddress is set in the AD account. + * MID-5330 + */ + @Test + public void test214ModifyAccountBarbossaProxyAddressesSimple() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_PROXY_ADDRESSES_NAME); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + assertNotNull("No definition for attribute " + attrQName, attrDef); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationAddProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, PROXY_ADDRES_ADDR_UPCASE); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_PROXY_ADDRESSES_NAME, PROXY_ADDRES_ADDR_UPCASE); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test220ModifyUserBarbossaPasswordSelfServicePassword1() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD, USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * Try to set the same password again. If this is "admin mode" (no runAs capability) + * the such change should be successful. In "selfservice mode" (runAs capability - in subclass) + * this change should fail. + */ + @Test + public void test222ModifyUserBarbossaPasswordSelfServicePassword1Again() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * Change to different password. This should go well for both admin and self-service. + * MID-5242 + */ + @Test + public void test224ModifyUserBarbossaPasswordSelfServicePassword2() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD_AD_1, USER_BARBOSSA_PASSWORD_AD_2); + } + + /** + * Change password back to the first password. This password was used before. + * In admin mode this should go well. Admin can set password to anything. + * But in self-service mode (in subclass) this should fail due to password history check. + */ + @Test + public void test226ModifyUserBarbossaPasswordSelfServicePassword1AgainAgain() throws Exception { + testModifyUserBarbossaPasswordSelfServiceSuccess( + USER_BARBOSSA_PASSWORD_AD_2, USER_BARBOSSA_PASSWORD_AD_1); + } + + protected void testModifyUserBarbossaPasswordSelfServiceSuccess(String oldPassword, String newPassword) throws Exception { + // GIVEN + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); + + login(USER_BARBOSSA_USERNAME); + + Task task = getTestTask(); + task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, + oldPassword, newPassword); + + // WHEN + when(); + executeChanges(objectDelta, null, task, result); + + // THEN + then(); + login(USER_ADMINISTRATOR_USERNAME); + assertSuccess(result); + + assertBarbossaEnabled(newPassword); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, newPassword); + + assertLdapConnectorInstances(2); + } + + protected void testModifyUserBarbossaPasswordSelfServiceFailure( + String oldPassword, String newPassword) throws Exception { + // GIVEN + login(USER_BARBOSSA_USERNAME); + + Task task = getTestTask(); + task.setChannel(SchemaConstants.CHANNEL_GUI_SELF_SERVICE_URI); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createOldNewPasswordDelta(USER_BARBOSSA_OID, + oldPassword, newPassword); + + // WHEN + when(); + executeChanges(objectDelta, null, task, result); + + // THEN + then(); + login(USER_ADMINISTRATOR_USERNAME); + assertPartialError(result); + + assertBarbossaEnabled(newPassword); + assertUserAfter(USER_BARBOSSA_OID) + .assertPassword(newPassword); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, oldPassword); + + assertLdapConnectorInstances(2); + } + + @Test + public void test230DisableUserBarbossa() throws Exception { + // precondition + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.DISABLED); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * MID-4041 + */ + @Test + public void test232ReconcileBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); + } + + /** + * MID-4041 + */ + @Test + public void test236EnableUserBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + /** + * MID-4041 + */ + @Test + public void test237ReconcileBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + /** + * MID-4041 + */ + @Test + public void test238DisableUserBarbossaRawAndReconcile() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.DISABLED); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaDisabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + /** + * MID-4041 + */ + @Test + public void test239EnableUserBarbossaRawAndReconcile() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_BARBOSSA_OID, SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + ModelExecuteOptions.createRaw(), task, result, ActivationStatusType.ENABLED); + + // WHEN + when(); + reconcileUser(USER_BARBOSSA_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertBarbossaEnabled(USER_BARBOSSA_PASSWORD_AD_1); + + assertLdapConnectorInstances(2); + } + + protected PrismObject assertBarbossaEnabled(String ldapPassword) throws Exception { + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "FALSE"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, ldapPassword); + + return user; + } + + private void assertBarbossaDisabled(String password) throws Exception { + assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + display("disabled Barbossa entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertAttribute(entry, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME, "TRUE"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPassword(null, entry, password); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + + assertLdapConnectorInstances(2); + } + + /** + * This should create account with a group. And the account shoudl be disabled. + */ + @Test + public void test250AssignGuybrushPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + +// ProtectedStringType userPasswordPs = new ProtectedStringType(); +// userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_333); +// modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + modifyUserReplace(USER_GUYBRUSH_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.DISABLED); + + // WHEN + when(); + assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + String shadowOid = getSingleLinkOid(user); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + assertAccountDisabled(shadow); + +// try { +// assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_333); +// AssertJUnit.fail("Password authentication works, but it should fail"); +// } catch (SecurityException e) { +// // this is expected, account is disabled +// } + + assertLdapConnectorInstances(2); + } + + @Test + public void test255ModifyUserGuybrushPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue(USER_GUYBRUSH_PASSWORD_123); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + display("Guybrush entry after", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + try { + assertLdapPassword(null, entry, USER_GUYBRUSH_PASSWORD_123); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected, account is disabled + } + +// assertLdapConnectorInstances(2); + } + + @Test + public void test260EnableGyubrush() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapPassword(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + + assertLdapConnectorInstances(2); + } + + /** + * Try to create an account without password. This should end up with an error. + * A reasonable error. + * MID-4046 + */ + @Test + public void test270AssignAccountToEmptyhead() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject userBefore = createUser(USER_EMPTYHEAD_NAME, USER_EMPTYHEAD_NAME, true); + display("User before", userBefore); + addObject(userBefore); + String userEmptyheadOid = userBefore.getOid(); + + // WHEN + when(); + assignAccountToUser(userEmptyheadOid, getResourceOid(), null, task, result); + + // THEN + then(); + assertPartialError(result); + + assertMessageContains(result.getMessage(), "does not meet the length, complexity, or history requirement"); + + assertLdapConnectorInstances(2); + } + + /** + * Just make random test connection between the tests. Make sure that the + * test does not break anything. If it does the next tests will simply fail. + */ + @Test + public void test295TestConnection() throws Exception { + // GIVEN + Task task = getTestTask(); + + // WHEN + when(); + OperationResult testResult = modelService.testResource(getResourceOid(), task); + + // THEN + then(); + display("Test connection result", testResult); + TestUtil.assertSuccess("Test connection result", testResult); + + // Test is disposing connector facade and the entire connector pool. + // Therefore we are back at 1 instance. + assertLdapConnectorInstances(1); + } + + @Test + public void test300AssignBarbossaPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertLdapConnectorInstances(1); + } + + @Test + public void test390ModifyUserBarbossaRename() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); + Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); + + // WHEN + when(); + modelService.executeChanges(deltas, null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + +// assertLdapConnectorInstances(2); + } + + // TODO: create account with a group membership + + @Test + public void test395UnAssignBarbossaPirates() throws Exception { + // TODO: do this on another account. There is a bad interference with rename. + + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test399UnAssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertNoLinkedAccount(user); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test500AddOrgMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject org = instantiateObject(OrgType.class); + OrgType orgType = org.asObjectable(); + orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + orgType.getAssignment().add(metaroleAssignment); + + // WHEN + when(); + addObject(org, task, result); + + // THEN + then(); + assertSuccess(result); + + orgMeleeIslandOid = org.getOid(); + assertLdapGroup(GROUP_MELEE_ISLAND_NAME); + assertLdapOrg(GROUP_MELEE_ISLAND_NAME); + + org = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); + ouMeleeIslandOid = getLinkRefOid(org, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); + assertLinks(org, 2); + + PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); + display("Shadow: group (model)", shadowGroup); + + PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); + display("Shadow: ou (model)", shadowOu); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test510AssignGuybrushMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + + assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeIslandOid); + +// assertLdapConnectorInstances(2); + } + + /** + * Create role under the Melee Island org. This creates group in the orgstruct. + */ + @Test + public void test515AddOrgGroupMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject role = instantiateObject(RoleType.class); + RoleType roleType = role.asObjectable(); + roleType.setName(new PolyStringType(GROUP_MELEE_ISLAND_PIRATES_NAME)); + + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_GROUP_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + roleType.getAssignment().add(metaroleAssignment); + + AssignmentType orgAssignment = new AssignmentType(); + ObjectReferenceType orgRef = new ObjectReferenceType(); + orgRef.setOid(orgMeleeIslandOid); + orgRef.setType(OrgType.COMPLEX_TYPE); + orgAssignment.setTargetRef(orgRef); + roleType.getAssignment().add(orgAssignment); + + // WHEN + when(); + addObject(role, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + roleMeleeIslandPiratesOid = role.getOid(); + // TODO: assert LDAP object + + assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + + PrismObject roleAfter = getObject(RoleType.class, roleMeleeIslandPiratesOid); + display("Role after", roleAfter); + groupMeleeIslandPiratesOid = getSingleLinkOid(roleAfter); + PrismObject shadow = getShadowModel(groupMeleeIslandPiratesOid); + display("Shadow (model)", shadow); + } + + /** + * Rename org unit. MidPoint should rename OU and ordinary group. + * AD will rename the group in the orgstruct automatically. We need to + * make sure that we can still access that group. + */ + @Test + public void test520RenameMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + renameObject(OrgType.class, orgMeleeIslandOid, GROUP_MELEE_ISLAND_ALT_NAME, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject orgAfter = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.ENTITLEMENT, INTENT_GROUP); + ouMeleeIslandOid = getLinkRefOid(orgAfter, getResourceOid(), ShadowKindType.GENERIC, INTENT_OU_TOP); + assertLinks(orgAfter, 2); + + PrismObject shadowGroup = getShadowModel(groupMeleeIslandOid); + display("Shadow: group (model)", shadowGroup); + + PrismObject shadowOu = getShadowModel(ouMeleeIslandOid); + display("Shadow: ou (model)", shadowOu); + + assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); + + assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); + + assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + + Entry entryGuybrush = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowAccountOid = getSingleLinkOid(user); + PrismObject shadowAccount = getShadowModel(shadowAccountOid); + display("Shadow: account (model)", shadowAccount); + + assertLdapGroupMember(entryGuybrush, GROUP_MELEE_ISLAND_ALT_NAME); + + IntegrationTestTools.assertAssociation(shadowAccount, getAssociationGroupQName(), groupMeleeIslandOid); + +// assertLdapConnectorInstances(2); + } + + /** + * AD renamed the pirate groups by itself. MidPoint does not know about it. + * The GUID that is stored in the shadow is still OK. But the DN is now out + * of date. Try to update the group. Make sure it works. + * It is expected that the GUI will be used as a primary identifier. + * Note: just reading the group will NOT work. MidPoint is too smart + * for that. It will transparently fix the situation. + */ + @Test + public void test522ModifyMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyObjectReplaceProperty(ShadowType.class, groupMeleeIslandPiratesOid, + ItemPath.create(ShadowType.F_ATTRIBUTES, new QName(MidPointConstants.NS_RI, "description")), + task, result, GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + assertAttribute(entryOrgGroup, "description", GROUP_MELEE_ISLAND_PIRATES_DESCRIPTION); + + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test524GetMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + PrismObject shadow = modelService.getObject(ShadowType.class, groupMeleeIslandPiratesOid, null, task, result); + + // THEN + then(); + assertSuccess(result); + + display("Shadow after", shadow); + assertNotNull(shadow); + + assertLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); + assertLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); + Entry entryOrgGroup = assertLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + display("Melee org", entryOrgGroup); + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + } + + @Test + public void test595DeleteOrgGroupMeleeIslandPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + deleteObject(RoleType.class, roleMeleeIslandPiratesOid, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrgGroup(GROUP_MELEE_ISLAND_PIRATES_NAME, GROUP_MELEE_ISLAND_NAME); + + assertNoObject(ShadowType.class, groupMeleeIslandPiratesOid); + +// assertLdapConnectorInstances(2); + } + + /** + * We create "underMelee" org that gets into the way of the delete. + * Melee cannot be deleted in an ordinary way. "tree delete" control must + * be used. This is configured in the connector config. + *

+ * MID-5935 + */ + @Test + public void test599DeleteOrgMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + createUnderMeleeEntry(); + + // WHEN + when(); + deleteObject(OrgType.class, orgMeleeIslandOid, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapGroup(GROUP_MELEE_ISLAND_NAME); + assertNoLdapGroup(GROUP_MELEE_ISLAND_ALT_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_NAME); + assertNoLdapOrg(GROUP_MELEE_ISLAND_ALT_NAME); + + assertNoObject(ShadowType.class, groupMeleeIslandOid); + assertNoObject(ShadowType.class, ouMeleeIslandOid); + +// assertLdapConnectorInstances(2); + } + + protected void createUnderMeleeEntry() throws LdapException, IOException { + // This OU just gets into the way of the delete. + Entry entry = new DefaultEntry("ou=underMelee," + toOrgDn(GROUP_MELEE_ISLAND_ALT_NAME), + "objectclass", "organizationalUnit", + "ou", "underMelee"); + display("underMelee org", entry); + addLdapEntry(entry); + } + + @Test + public void test600AssignAccountSubman() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + assignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + display("Sub entry", entry); + assertAttribute(entry, "title", null); + + PrismObject userAfter = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(userAfter); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountSubmanOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, USER_SUBMAN_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + // MID-4624 + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); + XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); + long createTimestampMillis = XmlTypeConverter.toMillis(createTimestamp); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, createTimestampMillis); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test610ModifyUserSubmanTitle() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, UserType.F_TITLE, task, result, + createPolyString("Underdog")); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + display("Sub entry", entry); + assertAttribute(entry, "title", "Underdog"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountSubmanOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test620ModifyUserSubmanPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue("SuB.321"); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertAttribute(entry, "title", "Underdog"); + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountSubmanOid, shadowOid); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test630DisableUserSubman() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.DISABLED); + + // THEN + then(); + assertSuccess(result); + +// assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_SUBMAN_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPassword(getSubLdapConnectionConfig(), USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME, "SuB.321"); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + +// assertLdapConnectorInstances(2); + } + + @Test + public void test639EnableUserSubman() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_SUBMAN_OID, + SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS, + task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + PrismObject user = getUser(USER_SUBMAN_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test690ModifyUserSubmanRename() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_SUBMAN_OID, UserType.F_NAME, + createPolyString(USER_SUBDOG_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + createPolyString(USER_SUBDOG_FULL_NAME)); + + // WHEN + when(); + executeChanges(objectDelta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); + assertAttribute(entry, "title", "Underdog"); + + PrismObject user = getUser(USER_SUBMAN_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountSubmanOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + +// assertLdapConnectorInstances(2); + } + + @Test + public void test699UnAssignAccountSubdog() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_SUBMAN_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapSubAccount(USER_SUBMAN_USERNAME, USER_SUBMAN_FULL_NAME); + assertNoLdapSubAccount(USER_SUBDOG_USERNAME, USER_SUBDOG_FULL_NAME); + + PrismObject user = getUser(USER_SUBMAN_OID); + assertNoLinkedAccount(user); + +// assertLdapConnectorInstances(2); + } + + /** + * Create account and modify it in a very quick succession. + * This test is designed to check if we can live with a long + * global catalog update delay. + * MID-2926 + */ + @Test + public void test700AssignAccountSubmarineAndModify() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); + + modifyUserReplace(USER_SUBMARINE_OID, UserType.F_TITLE, task, result, + PrismTestUtil.createPolyString("Underseadog")); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); + display("Sub entry", entry); + assertAttribute(entry, "title", "Underseadog"); + + PrismObject userAfter = getUser(USER_SUBMARINE_OID); + String shadowOid = getSingleLinkOid(userAfter); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountSubmarineOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountIcfUid); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + } + + @Test + public void test809UnAssignAccountSubmarine() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_SUBMARINE_OID, ROLE_SUBMISSIVE_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + assertNoLdapSubAccount(USER_SUBMARINE_USERNAME, USER_SUBMARINE_FULL_NAME); + + PrismObject user = getUser(USER_SUBMARINE_OID); + assertNoLinkedAccount(user); + } + + @Test + public void test850ReconcileAccounts() throws Exception { + // GIVEN + assertUsers(6); + + // WHEN + when(); + addTask(getReconciliationTaskFile()); + + waitForTaskFinish(getReconciliationTaskOid(), true); + + // THEN + then(); + + assertUsers(15); + // TODO + +// assertLdapConnectorInstances(2); + } + + @Test + public void test900ImportSyncTask() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addObject(getSyncTaskFile(), task, result); + + // THEN + then(); + assertSuccess(result); + + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + long tsEnd = System.currentTimeMillis(); + + assertStepSyncToken(getSyncTaskOid(), 0, tsStart, tsEnd); + } + + @Test + public void test901SyncAddAccountHt() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + addLdapAccount(ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + waitForTaskNextRunAssertSuccess(getSyncTaskOid(), true); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + displayUsers(); + + PrismObject user = findUserByUsername(ACCOUNT_HT_UID); + assertNotNull("No user " + ACCOUNT_HT_UID + " created", user); + assertUser(user, user.getOid(), ACCOUNT_HT_UID, ACCOUNT_HT_CN, ACCOUNT_HT_GIVENNAME, ACCOUNT_HT_SN); + + assertStepSyncToken(getSyncTaskOid(), 1, tsStart, tsEnd); + } + + protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) + throws ObjectNotFoundException, SchemaException { + OperationResult result = createOperationResult("assertStepSyncToken"); + Task task = taskManager.getTask(syncTaskOid, result); + PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); + assertNotNull("No sync token", syncTokenProperty); + assertNotNull("No sync token value", syncTokenProperty.getRealValue()); + assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); + assertSuccess(result); + } + + @Override + protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { + super.assertAccountShadow(shadow, dn); + ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); + assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); + String primaryId = primaryIdAttr.getRealValue(); + assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); + + ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); + assertNotNull("No SID in " + shadow, objectSidAttr); + display("SID of " + dn + ": " + objectSidAttr); + } + + protected void assertSid(PrismObject shadow, String expectedSid) { + ResourceAttribute objectSidAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME)); + assertNotNull("No SID in " + shadow, objectSidAttr); + display("SID of " + shadow + ": " + objectSidAttr); + assertEquals("Wrong SID in " + shadow, expectedSid, objectSidAttr.getRealValue()); + } + + private void assertObjectCategory(PrismObject shadow, String expectedObjectCategory) { + ResourceAttribute objectCategoryAttr = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_CATEGORY_NAME)); + assertNotNull("No objectCategory in " + shadow, objectCategoryAttr); + display("objectCategory of " + shadow + ": " + objectCategoryAttr); + assertEquals("Wrong objectCategory in " + shadow, expectedObjectCategory, objectCategoryAttr.getRealValue()); + } + + @Override + protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount("(cn=" + cn + ")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + protected Entry assertLdapSubAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount(getSubLdapConnectionConfig(), "(cn=" + cn + ")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + @Override + protected void assertNoLdapAccount(String uid) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { + assertNoLdapAccount(null, uid, cn); + } + + protected void assertNoLdapSubAccount(String uid, String cn) throws LdapException, IOException, CursorException { + assertNoLdapAccount(getSubLdapConnectionConfig(), uid, cn); + } + + protected void assertNoLdapAccount(UserLdapConnectionConfig config, String uid, String cn) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(config); + List entriesCn = ldapSearch(config, connection, "(cn=" + cn + ")"); + List entriesSamAccountName = ldapSearch(config, connection, "(sAMAccountName=" + uid + ")"); + ldapDisconnect(connection); + + assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); + assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); + } + + @Override + protected String toAccountDn(String username) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + @Override + protected String toAccountDn(String username, String fullName) { + return ("CN=" + fullName + "," + getPeopleLdapSuffix()); + } + + protected String toAccountSubDn(String username, String fullName) { + return ("CN=" + fullName + "," + getPeopleLdapSubSuffix()); + } + + @Override + protected Rdn toAccountRdn(String username, String fullName) { + try { + return new Rdn(new Ava("CN", fullName)); + } catch (LdapInvalidDnException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + protected String toOrgDn(String cn) { + return "ou=" + cn + "," + getOrgsLdapSuffix(); + } + + protected String toOrgGroupDn(String groupCn, String orgName) { + return "cn=" + groupCn + "," + toOrgDn(orgName); + } + + protected Entry assertLdapOrg(String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgDn(orgName); + Entry entry = getLdapEntry(dn); + assertNotNull("No entry " + dn, entry); + assertAttribute(entry, "ou", orgName); + return entry; + } + + protected Entry assertNoLdapOrg(String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgDn(orgName); + Entry entry = getLdapEntry(dn); + assertNull("Unexpected org entry " + entry, entry); + return entry; + } + + protected Entry assertLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgGroupDn(groupCn, orgName); + Entry entry = getLdapEntry(dn); + assertNotNull("No entry " + dn, entry); + assertAttribute(entry, "cn", groupCn); + return entry; + } + + protected Entry assertNoLdapOrgGroup(String groupCn, String orgName) throws LdapException, IOException, CursorException { + String dn = toOrgGroupDn(groupCn, orgName); + Entry entry = getLdapEntry(dn); + assertNull("Unexpected org group entry " + entry, entry); + return entry; + } + + protected void assertLdapPassword(String uid, String fullName, String password) throws LdapException, IOException, CursorException { + assertLdapPassword(null, uid, fullName, password); + } + + protected void assertLdapPassword(UserLdapConnectionConfig config, String uid, String fullName, String password) throws LdapException, IOException, CursorException { + Entry entry = getLdapAccountByCn(config, fullName); + assertLdapPassword(config, entry, password); + } + + protected void assertLdapPassword(String uid, String password) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), + prismContext); + return query; + } + + @Override + protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { + byte[] password = encodePassword("Secret.123"); + Entry entry = new DefaultEntry(toAccountDn(uid, cn), + "objectclass", getLdapAccountObjectClass(), + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, + "cn", cn, + "givenName", givenName, + "sn", sn, + ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", + ATTRIBUTE_UNICODE_PWD_NAME, password); + return entry; + } + + private byte[] encodePassword(String password) { + String quotedPassword = "\"" + password + "\""; + try { + return quotedPassword.getBytes("UTF-16LE"); + } catch (UnsupportedEncodingException e) { + throw new SystemException(e.getMessage(), e); + } + } + + public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { + assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); + } + + public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { + List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); + PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); + } + + protected abstract void assertAccountDisabled(PrismObject shadow); + + protected abstract void assertAccountEnabled(PrismObject shadow); + +} diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java index d99100da1ba..a3fde205e40 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapTest.java @@ -1,1257 +1,1256 @@ -/* - * Copyright (c) 2015-2019 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.testing.conntest.ad; - -import static org.testng.AssertJUnit.*; - -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; -import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.List; -import javax.xml.datatype.XMLGregorianCalendar; -import javax.xml.namespace.QName; - -import org.apache.commons.lang.StringUtils; -import org.apache.directory.api.ldap.model.cursor.CursorException; -import org.apache.directory.api.ldap.model.entry.*; -import org.apache.directory.api.ldap.model.exception.LdapException; -import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; -import org.apache.directory.api.ldap.model.name.Ava; -import org.apache.directory.api.ldap.model.name.Rdn; -import org.apache.directory.ldap.client.api.LdapNetworkConnection; -import org.testng.AssertJUnit; -import org.testng.annotations.Listeners; -import org.testng.annotations.Test; - -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.PrismProperty; -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.query.ObjectPaging; -import com.evolveum.midpoint.prism.query.ObjectQuery; -import com.evolveum.midpoint.prism.query.OrderDirection; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.prism.xml.XmlTypeConverter; -import com.evolveum.midpoint.schema.SearchResultList; -import com.evolveum.midpoint.schema.SearchResultMetadata; -import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.schema.constants.SchemaConstants; -import com.evolveum.midpoint.schema.internals.InternalCounters; -import com.evolveum.midpoint.schema.processor.ResourceAttribute; -import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.result.OperationResult; -import com.evolveum.midpoint.schema.util.MiscSchemaUtil; -import com.evolveum.midpoint.schema.util.ObjectQueryUtil; -import com.evolveum.midpoint.schema.util.ShadowUtil; -import com.evolveum.midpoint.task.api.Task; -import com.evolveum.midpoint.test.AbstractIntegrationTest; -import com.evolveum.midpoint.test.IntegrationTestTools; -import com.evolveum.midpoint.test.util.MidPointTestConstants; -import com.evolveum.midpoint.test.util.TestUtil; -import com.evolveum.midpoint.testing.conntest.AbstractLdapSynchronizationTest; -import com.evolveum.midpoint.util.MiscUtil; -import com.evolveum.midpoint.util.exception.ObjectNotFoundException; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.*; -import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; -import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; - -/** - * @author semancik - */ -@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) -public abstract class AbstractAdLdapTest extends AbstractLdapSynchronizationTest - implements AdTestMixin { - - protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap"); - - protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); - protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; - - protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); - protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; - - protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; - protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; - protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; - - protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; - - private static final String GROUP_PIRATES_NAME = "pirates"; - private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; - - protected static final int NUMBER_OF_ACCOUNTS = 12; - private static final String ASSOCIATION_GROUP_NAME = "group"; - - private static final String NS_EXTENSION = "http://whatever.com/my"; - private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); - - private boolean allowDuplicateSearchResults = false; - - protected String jackAccountOid; - protected String groupPiratesOid; - protected String accountBarbossaOid; - protected String orgMeleeIslandOid; - protected String groupMeleeOid; - - @Override - public String getStartSystemCommand() { - return null; - } - - @Override - public String getStopSystemCommand() { - return null; - } - - @Override - protected File getBaseDir() { - return TEST_DIR; - } - - @Override - protected String getSyncTaskOid() { - return "cd1e0ff2-0099-11e5-9e22-001e8c717e5b"; - } - - @Override - protected boolean useSsl() { - return true; - } - - @Override - protected String getLdapSuffix() { - return "DC=win,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindDn() { - return "CN=midpoint admin1,CN=Users,DC=win,DC=evolveum,DC=com"; - } - - @Override - protected String getLdapBindPassword() { - return "mAZadlo911"; - } - - @Override - protected int getSearchSizeLimit() { - return -1; - } - - @Override - public String getPrimaryIdentifierAttributeName() { - return "objectGUID"; - } - - @Override - protected String getPeopleLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - @Override - protected String getGroupsLdapSuffix() { - return "CN=Users," + getLdapSuffix(); - } - - @Override - protected String getLdapAccountObjectClass() { - return "user"; - } - - @Override - protected String getLdapGroupObjectClass() { - return "group"; - } - - @Override - protected String getLdapGroupMemberAttribute() { - return "member"; - } - - private QName getAssociationGroupQName() { - return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); - } - - @Override - protected boolean allowDuplicateSearchResults() { - return allowDuplicateSearchResults; - } - - @Override - protected File getSyncTaskInetOrgPersonFile() { - return new File(getBaseDir(), "task-sync-user.xml"); - } - - @Override - protected boolean isGroupMemberMandatory() { - return false; - } - - protected String getLdapConnectorClassName() { - return AdTestMixin.AD_CONNECTOR_TYPE; - } - - @Override - public void initSystem(Task initTask, OperationResult initResult) throws Exception { - super.initSystem(initTask, initResult); - - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); - binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); - - // Users - repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); - repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); - - // Roles - repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); - repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); - - } - - @Test - @Override - public void test000Sanity() throws Exception { - super.test000Sanity(); - - assertLdapPasswordByFullName(ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); - cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); - cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); - cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); - cleanupDelete(toGroupDn(GROUP_FOOLS_CN)); - } - - @Test - @Override - public void test020Schema() throws Exception { - accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); - - assertLdapConnectorInstances(1); - } - - // test050 in subclasses - - @Test - public void test100SeachJackBySamAccountName() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - jackAccountOid = shadow.getOid(); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - @Test - public void test105SeachPiratesByCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); - - // THEN - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); - - PrismObject shadow = shadows.get(0); - display("Shadow", shadow); - groupPiratesOid = shadow.getOid(); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(1); - } - - @Test - public void test110GetJack() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - when(); - PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); - - // THEN - result.computeStatus(); - TestUtil.assertSuccess(result); - display("Shadow", shadow); - assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); - jackAccountOid = shadow.getOid(); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=win,DC=evolveum,DC=com"); - assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); - assertAttribute(shadow, "sn", "Sparrow"); - assertAttribute(shadow, "info", "The best pirate the world has ever seen"); - assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); - assertAttribute(shadow, "lastLogon", 0L); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - assertLdapConnectorInstances(1); - } - - /** - * No paging. It should return all accounts. - */ - @Test - public void test150SeachAllAccounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); - rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); - - // WHEN - SearchResultList> searchResultList = doSearch(query, - NUMBER_OF_ACCOUNTS, task, result); - - // TODO: why 11? should be 1 - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 9); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this is in one block. - */ - @Test - public void test152SeachFirst2Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this gets more than two blocks. - */ - @Test - public void test154SeachFirst11Accounts() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setMaxSize(11); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test162SeachFirst2AccountsOffset0() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(); - paging.setOffset(0); - paging.setMaxSize(2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this is in one block. - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test172Search2AccountsOffset1() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - query.setPaging(paging); - - SearchResultList> searchResultList = doSearch(query, 2, task, result); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this gets more than two blocks. - * There is offset, so VLV should be used. - * No explicit sorting. - */ - @Test - public void test174SeachFirst11AccountsOffset2() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); - query.setPaging(paging); - - allowDuplicateSearchResults = true; - - // WHEN - SearchResultList> searchResultList = doSearch(query, 11, task, result); - - // THEN - allowDuplicateSearchResults = false; - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = searchResultList.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - /** - * Blocksize is 5, so this is in one block. - * There is offset, so VLV should be used. - * Explicit sorting. - */ - @Test - public void test182Search2AccountsOffset1SortCn() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - - ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); - paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); - query.setPaging(paging); - - SearchResultList> shadows = doSearch(query, 2, task, result); - - assertAccountShadow(shadows.get(0), "CN=Administrator,CN=Users,DC=win,DC=evolveum,DC=com"); - assertAccountShadow(shadows.get(1), "CN=Chuck LeChuck,CN=Users,DC=win,DC=evolveum,DC=com"); - - assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); - assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); - - SearchResultMetadata metadata = shadows.getMetadata(); - if (metadata != null) { - assertFalse(metadata.isPartialResults()); - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test200AssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - long tsStart = System.currentTimeMillis(); - - // WHEN - when(); - assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - assertSuccess(result); - - long tsEnd = System.currentTimeMillis(); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", null); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - accountBarbossaOid = shadow.getOid(); - Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); - String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); - assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); - - assertEquals("Wrong ICFS UID", - formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), - accountBarbossaIcfUid); - - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); - - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); - assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); - XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); - // LDAP server may be on a different host. Allow for some clock offset. - TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, XmlTypeConverter.toMillis(createTimestamp)); - - assertLdapConnectorInstances(2); - } - - @Test - public void test210ModifyAccountBarbossaTitle() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "title"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); - delta.addModification(attrDelta); - - // WHEN - when(); - modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * Modify USER, test boolean value mapping. - */ - @Test - public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta delta = prismContext.deltaFactory().object() - .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); - QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); - ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); - PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( - ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); - delta.addModification(attrDelta); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), - task, result, Boolean.FALSE); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test220ModifyUserBarbossaPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_2); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_2); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - /** - * MID-5242 - */ - @Test - public void test222ModifyUserBarbossaPasswordNational() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_AD_1); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test230DisableUserBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // precondition - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); - - // THEN - then(); - assertSuccess(result); - - assertLdapConnectorInstances(2); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountDisabled(shadow); - - try { - assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test239EnableUserBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - assertSuccess(result); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertLdapConnectorInstances(2); - } - - /** - * This should create account with a group. And disabled. - */ - @Test - public void test250AssignGuybrushPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); - - // WHEN - when(); - assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - display("Entry", entry); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.DISABLED); - String shadowOid = getSingleLinkOid(user); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - assertAccountDisabled(shadow); - - assertLdapConnectorInstances(2); - } - - @Test - public void test255ModifyUserGuybrushPassword() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ProtectedStringType userPasswordPs = new ProtectedStringType(); - userPasswordPs.setClearValue("wanna.be.a.123"); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); - - try { - assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); - AssertJUnit.fail("Password authentication works, but it should fail"); - } catch (SecurityException e) { - // this is expected, account is disabled - } - - assertLdapConnectorInstances(2); - } - - @Test - public void test260EnableGyubrush() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - assertAdministrativeStatus(user, ActivationStatusType.ENABLED); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); - - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - assertAccountEnabled(shadow); - - assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); - - assertLdapConnectorInstances(2); - } - - @Test - public void test300AssignBarbossaPirates() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - display("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test390ModifyUserBarbossaRename() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); - objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, - PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); - Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); - - // WHEN - when(); - modelService.executeChanges(deltas, null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - assertAttribute(entry, "title", "Captain"); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - PrismObject shadow = getObject(ShadowType.class, shadowOid); - display("Shadow after rename (model)", shadow); - - PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); - display("Shadow after rename (repo)", repoShadow); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - - assertLdapConnectorInstances(2); - } - - // TODO: create account with a group membership - - @Test - public void test395UnAssignBarbossaPirates() throws Exception { - // TODO: do this on another account. There is a bad interference with rename. - - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - display("Entry", entry); - assertAttribute(entry, "title", "Captain"); - - assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - String shadowOid = getSingleLinkOid(user); - assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); - - PrismObject shadow = getObject(ShadowType.class, shadowOid); - IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); - - assertLdapConnectorInstances(2); - } - - @Test - public void test399UnAssignAccountBarbossa() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); - assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); - - PrismObject user = getUser(USER_BARBOSSA_OID); - assertNoLinkedAccount(user); - - assertLdapConnectorInstances(2); - } - - @Test - public void test500AddOrgMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - PrismObject org = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(OrgType.class).instantiate(); - OrgType orgType = org.asObjectable(); - orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); - AssignmentType metaroleAssignment = new AssignmentType(); - ObjectReferenceType metaroleRef = new ObjectReferenceType(); - metaroleRef.setOid(ROLE_META_ORG_OID); - metaroleRef.setType(RoleType.COMPLEX_TYPE); - metaroleAssignment.setTargetRef(metaroleRef); - orgType.getAssignment().add(metaroleAssignment); - - // WHEN - when(); - addObject(org, task, result); - - // THEN - then(); - result.computeStatus(); - TestUtil.assertSuccess(result); - - orgMeleeIslandOid = org.getOid(); - assertLdapGroup(GROUP_MELEE_ISLAND_NAME); - - org = getObject(OrgType.class, orgMeleeIslandOid); - groupMeleeOid = getSingleLinkOid(org); - PrismObject shadow = getShadowModel(groupMeleeOid); - display("Shadow (model)", shadow); - - assertLdapConnectorInstances(2); - } - - @Test - public void test510AssignGuybrushMeleeIsland() throws Exception { - // GIVEN - Task task = getTestTask(); - OperationResult result = task.getResult(); - - // WHEN - when(); - assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); - - // THEN - then(); - assertSuccess(result); - - Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); - - PrismObject user = getUser(USER_GUYBRUSH_OID); - String shadowOid = getSingleLinkOid(user); - PrismObject shadow = getShadowModel(shadowOid); - display("Shadow (model)", shadow); - - assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); - - IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeOid); - - assertLdapConnectorInstances(2); - } - - @Override - protected void doAdditionalRenameModifications(LdapNetworkConnection connection) throws LdapException { - Modification mod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, - ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, ACCOUNT_HTM_UID); - connection.modify(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN), mod); - display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " " + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME + - " -> " + ACCOUNT_HTM_UID + ": " + mod); - } - - @Override - protected String getAccountHtmCnAfterRename() { - return ACCOUNT_HTM_CN; - } - - @Override - protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { - super.assertAccountShadow(shadow, dn); - ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); - assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); - String primaryId = primaryIdAttr.getRealValue(); - assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); - } - - @Override - protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { - Entry entry = searchLdapAccount("(cn=" + cn + ")"); - assertAttribute(entry, "cn", cn); - assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); - return entry; - } - - @Override - protected void assertNoLdapAccount(String uid) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { - LdapNetworkConnection connection = ldapConnect(); - List entriesCn = ldapSearch(connection, "(cn=" + cn + ")"); - List entriesSamAccountName = ldapSearch(connection, "(sAMAccountName=" + uid + ")"); - ldapDisconnect(connection); - - assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); - assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); - } - - @Override - protected String toAccountDn(String username) { - throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - @Override - protected String toAccountDn(String username, String fullName) { - return "CN=" + fullName + "," + getPeopleLdapSuffix(); - } - - @Override - protected Rdn toAccountRdn(String username, String fullName) { - try { - return new Rdn(new Ava("CN", fullName)); - } catch (LdapInvalidDnException e) { - throw new IllegalStateException(e.getMessage(), e); - } - } - - protected void assertLdapPasswordByFullName(String fullName, String password) - throws LdapException, IOException, CursorException { - Entry entry = getLdapAccountByCn(fullName); - assertLdapPassword(entry, password); - } - - protected void assertLdapPassword(String uid, String password) { - throw new UnsupportedOperationException( - "Boom! Cannot do this here. This is bloody AD! We need full name!"); - } - - protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { - ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); - ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), - prismContext); - return query; - } - - @Override - protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { - byte[] password = encodePassword("Secret.123"); - Entry entry = new DefaultEntry(toAccountDn(uid, cn), - "objectclass", getLdapAccountObjectClass(), - ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, - "cn", cn, - "givenName", givenName, - "sn", sn, - ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", - ATTRIBUTE_UNICODE_PWD_NAME, password); - return entry; - } - - private byte[] encodePassword(String password) { - String quotedPassword = "\"" + password + "\""; - return quotedPassword.getBytes(StandardCharsets.UTF_16LE); - } - - @Override - protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) - throws ObjectNotFoundException, SchemaException { - OperationResult result = createOperationResult("assertStepSyncToken"); - Task task = taskManager.getTask(syncTaskOid, result); - PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); - assertNotNull("No sync token", syncTokenProperty); - assertNotNull("No sync token value", syncTokenProperty.getRealValue()); - assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); - result.computeStatus(); - TestUtil.assertSuccess(result); - } - - public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { - assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); - } - - public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { - List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); - PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); - } - - protected abstract void assertAccountDisabled(PrismObject shadow); - - protected abstract void assertAccountEnabled(PrismObject shadow); -} +/* + * Copyright (c) 2015-2019 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.testing.conntest.ad; + +import static org.testng.AssertJUnit.*; + +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_ACTIVATION_ADMINISTRATIVE_STATUS; +import static com.evolveum.midpoint.schema.constants.SchemaConstants.PATH_CREDENTIALS_PASSWORD_VALUE; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.List; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import org.apache.commons.lang.StringUtils; +import org.apache.directory.api.ldap.model.cursor.CursorException; +import org.apache.directory.api.ldap.model.entry.*; +import org.apache.directory.api.ldap.model.exception.LdapException; +import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; +import org.apache.directory.api.ldap.model.name.Ava; +import org.apache.directory.api.ldap.model.name.Rdn; +import org.apache.directory.ldap.client.api.LdapNetworkConnection; +import org.testng.AssertJUnit; +import org.testng.annotations.Listeners; +import org.testng.annotations.Test; + +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.PrismProperty; +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.query.ObjectPaging; +import com.evolveum.midpoint.prism.query.ObjectQuery; +import com.evolveum.midpoint.prism.query.OrderDirection; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.prism.xml.XmlTypeConverter; +import com.evolveum.midpoint.schema.SearchResultList; +import com.evolveum.midpoint.schema.SearchResultMetadata; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.constants.SchemaConstants; +import com.evolveum.midpoint.schema.internals.InternalCounters; +import com.evolveum.midpoint.schema.processor.ResourceAttribute; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.result.OperationResult; +import com.evolveum.midpoint.schema.util.MiscSchemaUtil; +import com.evolveum.midpoint.schema.util.ObjectQueryUtil; +import com.evolveum.midpoint.schema.util.ShadowUtil; +import com.evolveum.midpoint.task.api.Task; +import com.evolveum.midpoint.test.AbstractIntegrationTest; +import com.evolveum.midpoint.test.IntegrationTestTools; +import com.evolveum.midpoint.test.util.MidPointTestConstants; +import com.evolveum.midpoint.test.util.TestUtil; +import com.evolveum.midpoint.testing.conntest.AbstractLdapSynchronizationTest; +import com.evolveum.midpoint.util.MiscUtil; +import com.evolveum.midpoint.util.exception.ObjectNotFoundException; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.*; +import com.evolveum.prism.xml.ns._public.types_3.PolyStringType; +import com.evolveum.prism.xml.ns._public.types_3.ProtectedStringType; + +/** + * @author semancik + */ +@Listeners({ com.evolveum.midpoint.tools.testng.AlphabeticalMethodInterceptor.class }) +public abstract class AbstractAdLdapTest extends AbstractLdapSynchronizationTest + implements AdTestMixin { + + protected static final File TEST_DIR = new File(MidPointTestConstants.TEST_RESOURCES_DIR, "ad-ldap"); + + protected static final File ROLE_PIRATES_FILE = new File(TEST_DIR, "role-pirate.xml"); + protected static final String ROLE_PIRATES_OID = "5dd034e8-41d2-11e5-a123-001e8c717e5b"; + + protected static final File ROLE_META_ORG_FILE = new File(TEST_DIR, "role-meta-org.xml"); + protected static final String ROLE_META_ORG_OID = "f2ad0ace-45d7-11e5-af54-001e8c717e5b"; + + protected static final String ACCOUNT_JACK_SAM_ACCOUNT_NAME = "jack"; + protected static final String ACCOUNT_JACK_FULL_NAME = "Jack Sparrow"; + protected static final String ACCOUNT_JACK_PASSWORD = "qwe.123"; + + protected static final String USER_CPTBARBOSSA_FULL_NAME = "Captain Hector Barbossa"; + + private static final String GROUP_PIRATES_NAME = "pirates"; + private static final String GROUP_MELEE_ISLAND_NAME = "Mêlée Island"; + + protected static final int NUMBER_OF_ACCOUNTS = 12; + private static final String ASSOCIATION_GROUP_NAME = "group"; + + private static final String NS_EXTENSION = "http://whatever.com/my"; + private static final QName EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME = new QName(NS_EXTENSION, "showInAdvancedViewOnly"); + + private boolean allowDuplicateSearchResults = false; + + protected String jackAccountOid; + protected String groupPiratesOid; + protected String accountBarbossaOid; + protected String orgMeleeIslandOid; + protected String groupMeleeOid; + + @Override + public String getStartSystemCommand() { + return null; + } + + @Override + public String getStopSystemCommand() { + return null; + } + + @Override + protected File getBaseDir() { + return TEST_DIR; + } + + @Override + protected String getSyncTaskOid() { + return "cd1e0ff2-0099-11e5-9e22-001e8c717e5b"; + } + + @Override + protected boolean useSsl() { + return true; + } + + @Override + protected String getLdapSuffix() { + return "DC=win,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindDn() { + return "CN=midpoint admin1,CN=Users,DC=win,DC=evolveum,DC=com"; + } + + @Override + protected String getLdapBindPassword() { + return "mAZadlo911"; + } + + @Override + protected int getSearchSizeLimit() { + return -1; + } + + @Override + public String getPrimaryIdentifierAttributeName() { + return "objectGUID"; + } + + @Override + protected String getPeopleLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + @Override + protected String getGroupsLdapSuffix() { + return "CN=Users," + getLdapSuffix(); + } + + @Override + protected String getLdapAccountObjectClass() { + return "user"; + } + + @Override + protected String getLdapGroupObjectClass() { + return "group"; + } + + @Override + protected String getLdapGroupMemberAttribute() { + return "member"; + } + + private QName getAssociationGroupQName() { + return new QName(MidPointConstants.NS_RI, ASSOCIATION_GROUP_NAME); + } + + @Override + protected boolean allowDuplicateSearchResults() { + return allowDuplicateSearchResults; + } + + @Override + protected File getSyncTaskInetOrgPersonFile() { + return new File(getBaseDir(), "task-sync-user.xml"); + } + + @Override + protected boolean isGroupMemberMandatory() { + return false; + } + + protected String getLdapConnectorClassName() { + return AdTestMixin.AD_CONNECTOR_TYPE; + } + + @Override + public void initSystem(Task initTask, OperationResult initResult) throws Exception { + super.initSystem(initTask, initResult); + + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_OBJECT_GUID_NAME); + binaryAttributeDetector.addBinaryAttribute(ATTRIBUTE_UNICODE_PWD_NAME); + + // Users + repoAddObjectFromFile(USER_BARBOSSA_FILE, initResult); + repoAddObjectFromFile(USER_GUYBRUSH_FILE, initResult); + + // Roles + repoAddObjectFromFile(ROLE_PIRATES_FILE, initResult); + repoAddObjectFromFile(ROLE_META_ORG_FILE, initResult); + + } + + @Test + @Override + public void test000Sanity() throws Exception { + super.test000Sanity(); + + assertLdapPasswordByFullName(ACCOUNT_JACK_FULL_NAME, ACCOUNT_JACK_PASSWORD); + cleanupDelete(toAccountDn(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME)); + cleanupDelete(toAccountDn(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME)); + cleanupDelete(toGroupDn(GROUP_MELEE_ISLAND_NAME)); + cleanupDelete(toGroupDn(GROUP_FOOLS_CN)); + } + + @Test + @Override + public void test020Schema() throws Exception { + accountObjectClassDefinition = assertAdResourceSchema(resource, getAccountObjectClass(), prismContext); + + assertLdapConnectorInstances(1); + } + + // test050 in subclasses + + @Test + public void test100SeachJackBySamAccountName() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = createSamAccountNameQuery(ACCOUNT_JACK_SAM_ACCOUNT_NAME); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 2); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test105SeachPiratesByCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getGroupObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter("cn", GROUP_PIRATES_NAME), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + SearchResultList> shadows = modelService.searchObjects(ShadowType.class, query, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertEquals("Unexpected search result: " + shadows, 1, shadows.size()); + + PrismObject shadow = shadows.get(0); + display("Shadow", shadow); + groupPiratesOid = shadow.getOid(); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(1); + } + + @Test + public void test110GetJack() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + when(); + PrismObject shadow = modelService.getObject(ShadowType.class, jackAccountOid, null, task, result); + + // THEN + result.computeStatus(); + TestUtil.assertSuccess(result); + display("Shadow", shadow); + assertAccountShadow(shadow, toAccountDn(ACCOUNT_JACK_SAM_ACCOUNT_NAME, ACCOUNT_JACK_FULL_NAME)); + jackAccountOid = shadow.getOid(); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertAttribute(shadow, "dn", "CN=Jack Sparrow,CN=Users,DC=win,DC=evolveum,DC=com"); + assertAttribute(shadow, "cn", ACCOUNT_JACK_FULL_NAME); + assertAttribute(shadow, "sn", "Sparrow"); + assertAttribute(shadow, "info", "The best pirate the world has ever seen"); + assertAttribute(shadow, "sAMAccountName", ACCOUNT_JACK_SAM_ACCOUNT_NAME); + assertAttribute(shadow, "lastLogon", 0L); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + assertLdapConnectorInstances(1); + } + + /** + * No paging. It should return all accounts. + */ + @Test + public void test150SeachAllAccounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + rememberCounter(InternalCounters.CONNECTOR_OPERATION_COUNT); + rememberCounter(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT); + + // WHEN + SearchResultList> searchResultList = doSearch(query, + NUMBER_OF_ACCOUNTS, task, result); + + // TODO: why 11? should be 1 + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 9); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this is in one block. + */ + @Test + public void test152SeachFirst2Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this gets more than two blocks. + */ + @Test + public void test154SeachFirst11Accounts() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setMaxSize(11); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test162SeachFirst2AccountsOffset0() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(); + paging.setOffset(0); + paging.setMaxSize(2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this is in one block. + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test172Search2AccountsOffset1() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + query.setPaging(paging); + + SearchResultList> searchResultList = doSearch(query, 2, task, result); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this gets more than two blocks. + * There is offset, so VLV should be used. + * No explicit sorting. + */ + @Test + public void test174SeachFirst11AccountsOffset2() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(2, 11); + query.setPaging(paging); + + allowDuplicateSearchResults = true; + + // WHEN + SearchResultList> searchResultList = doSearch(query, 11, task, result); + + // THEN + allowDuplicateSearchResults = false; + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = searchResultList.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + /** + * Blocksize is 5, so this is in one block. + * There is offset, so VLV should be used. + * Explicit sorting. + */ + @Test + public void test182Search2AccountsOffset1SortCn() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + + ObjectPaging paging = prismContext.queryFactory().createPaging(1, 2); + paging.setOrdering(getAttributePath(resource, "cn"), OrderDirection.ASCENDING); + query.setPaging(paging); + + SearchResultList> shadows = doSearch(query, 2, task, result); + + assertAccountShadow(shadows.get(0), "CN=Administrator,CN=Users,DC=win,DC=evolveum,DC=com"); + assertAccountShadow(shadows.get(1), "CN=Chuck LeChuck,CN=Users,DC=win,DC=evolveum,DC=com"); + + assertCounterIncrement(InternalCounters.CONNECTOR_OPERATION_COUNT, 1); + assertCounterIncrement(InternalCounters.CONNECTOR_SIMULATED_PAGING_SEARCH_COUNT, 0); + + SearchResultMetadata metadata = shadows.getMetadata(); + if (metadata != null) { + assertFalse(metadata.isPartialResults()); + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test200AssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + long tsStart = System.currentTimeMillis(); + + // WHEN + when(); + assignAccountToUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + assertSuccess(result); + + long tsEnd = System.currentTimeMillis(); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", null); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + accountBarbossaOid = shadow.getOid(); + Collection> identifiers = ShadowUtil.getPrimaryIdentifiers(shadow); + String accountBarbossaIcfUid = (String) identifiers.iterator().next().getRealValue(); + assertNotNull("No identifier in " + shadow, accountBarbossaIcfUid); + + assertEquals("Wrong ICFS UID", + formatGuidToDashedNotation(MiscUtil.binaryToHex(entry.get(getPrimaryIdentifierAttributeName()).getBytes())), + accountBarbossaIcfUid); + + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + ResourceAttribute createTimestampAttribute = ShadowUtil.getAttribute(shadow, new QName(MidPointConstants.NS_RI, "createTimeStamp")); + assertNotNull("No createTimestamp in " + shadow, createTimestampAttribute); + XMLGregorianCalendar createTimestamp = createTimestampAttribute.getRealValue(); + // LDAP server may be on a different host. Allow for some clock offset. + TestUtil.assertBetween("Wrong createTimestamp in " + shadow, roundTsDown(tsStart) - 120000, roundTsUp(tsEnd) + 120000, XmlTypeConverter.toMillis(createTimestamp)); + + assertLdapConnectorInstances(2); + } + + @Test + public void test210ModifyAccountBarbossaTitle() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "title"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, "Captain"); + delta.addModification(attrDelta); + + // WHEN + when(); + modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test212ModifyAccountBarbossaShowInAdvancedViewOnlyTrue() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + modelService.executeChanges(MiscSchemaUtil.createCollection(delta), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "TRUE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * Modify USER, test boolean value mapping. + */ + @Test + public void test213ModifyUserBarbossaShowInAdvancedViewOnlyFalse() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, "showInAdvancedViewOnly"); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, Boolean.TRUE); + delta.addModification(attrDelta); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, ItemPath.create(UserType.F_EXTENSION, EXTENSION_SHOW_IN_ADVANCED_VIEW_ONLY_QNAME), + task, result, Boolean.FALSE); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "showInAdvancedViewOnly", "FALSE"); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test220ModifyUserBarbossaPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_2); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_2); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + /** + * MID-5242 + */ + @Test + public void test222ModifyUserBarbossaPasswordNational() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue(USER_BARBOSSA_PASSWORD_AD_1); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test230DisableUserBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // precondition + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); + + // THEN + then(); + assertSuccess(result); + + assertLdapConnectorInstances(2); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountDisabled(shadow); + + try { + assertLdapPasswordByFullName(USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD_AD_1); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test239EnableUserBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_BARBOSSA_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + assertSuccess(result); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapConnectorInstances(2); + } + + /** + * This should create account with a group. And disabled. + */ + @Test + public void test250AssignGuybrushPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.DISABLED); + + // WHEN + when(); + assignRole(USER_GUYBRUSH_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.DISABLED); + String shadowOid = getSingleLinkOid(user); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + assertAccountDisabled(shadow); + + assertLdapConnectorInstances(2); + } + + @Test + public void test255ModifyUserGuybrushPassword() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ProtectedStringType userPasswordPs = new ProtectedStringType(); + userPasswordPs.setClearValue("wanna.be.a.123"); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, PATH_CREDENTIALS_PASSWORD_VALUE, task, result, userPasswordPs); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "514"); + + try { + assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + AssertJUnit.fail("Password authentication works, but it should fail"); + } catch (SecurityException e) { + // this is expected, account is disabled + } + + assertLdapConnectorInstances(2); + } + + @Test + public void test260EnableGyubrush() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + modifyUserReplace(USER_GUYBRUSH_OID, PATH_ACTIVATION_ADMINISTRATIVE_STATUS, task, result, ActivationStatusType.ENABLED); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + assertAdministrativeStatus(user, ActivationStatusType.ENABLED); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + assertAccountEnabled(shadow); + + assertLdapPasswordByFullName(USER_GUYBRUSH_FULL_NAME, "wanna.be.a.123"); + + assertLdapConnectorInstances(2); + } + + @Test + public void test300AssignBarbossaPirates() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test390ModifyUserBarbossaRename() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta objectDelta = createModifyUserReplaceDelta(USER_BARBOSSA_OID, UserType.F_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_USERNAME)); + objectDelta.addModificationReplaceProperty(UserType.F_FULL_NAME, + PrismTestUtil.createPolyString(USER_CPTBARBOSSA_FULL_NAME)); + Collection> deltas = MiscSchemaUtil.createCollection(objectDelta); + + // WHEN + when(); + modelService.executeChanges(deltas, null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + assertAttribute(entry, "title", "Captain"); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + PrismObject shadow = getObject(ShadowType.class, shadowOid); + display("Shadow after rename (model)", shadow); + + PrismObject repoShadow = repositoryService.getObject(ShadowType.class, shadowOid, null, result); + display("Shadow after rename (repo)", repoShadow); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + + assertLdapConnectorInstances(2); + } + + // TODO: create account with a group membership + + @Test + public void test395UnAssignBarbossaPirates() throws Exception { + // TODO: do this on another account. There is a bad interference with rename. + + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignRole(USER_BARBOSSA_OID, ROLE_PIRATES_OID, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + Entry entry = assertLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + display("Entry", entry); + assertAttribute(entry, "title", "Captain"); + + assertLdapNoGroupMember(entry, GROUP_PIRATES_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + PrismObject shadow = getObject(ShadowType.class, shadowOid); + IntegrationTestTools.assertNoAssociation(shadow, getAssociationGroupQName(), groupPiratesOid); + + assertLdapConnectorInstances(2); + } + + @Test + public void test399UnAssignAccountBarbossa() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + unassignAccountFromUser(USER_BARBOSSA_OID, getResourceOid(), null, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + assertNoLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertNoLdapAccount(USER_CPTBARBOSSA_USERNAME, USER_CPTBARBOSSA_FULL_NAME); + + PrismObject user = getUser(USER_BARBOSSA_OID); + assertNoLinkedAccount(user); + + assertLdapConnectorInstances(2); + } + + @Test + public void test500AddOrgMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + PrismObject org = prismContext.getSchemaRegistry().findObjectDefinitionByCompileTimeClass(OrgType.class).instantiate(); + OrgType orgType = org.asObjectable(); + orgType.setName(new PolyStringType(GROUP_MELEE_ISLAND_NAME)); + AssignmentType metaroleAssignment = new AssignmentType(); + ObjectReferenceType metaroleRef = new ObjectReferenceType(); + metaroleRef.setOid(ROLE_META_ORG_OID); + metaroleRef.setType(RoleType.COMPLEX_TYPE); + metaroleAssignment.setTargetRef(metaroleRef); + orgType.getAssignment().add(metaroleAssignment); + + // WHEN + when(); + addObject(org, task, result); + + // THEN + then(); + result.computeStatus(); + TestUtil.assertSuccess(result); + + orgMeleeIslandOid = org.getOid(); + assertLdapGroup(GROUP_MELEE_ISLAND_NAME); + + org = getObject(OrgType.class, orgMeleeIslandOid); + groupMeleeOid = getSingleLinkOid(org); + PrismObject shadow = getShadowModel(groupMeleeOid); + display("Shadow (model)", shadow); + + assertLdapConnectorInstances(2); + } + + @Test + public void test510AssignGuybrushMeleeIsland() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + // WHEN + when(); + assignOrg(USER_GUYBRUSH_OID, orgMeleeIslandOid, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_GUYBRUSH_USERNAME, USER_GUYBRUSH_FULL_NAME); + + PrismObject user = getUser(USER_GUYBRUSH_OID); + String shadowOid = getSingleLinkOid(user); + PrismObject shadow = getShadowModel(shadowOid); + display("Shadow (model)", shadow); + + assertLdapGroupMember(entry, GROUP_MELEE_ISLAND_NAME); + + IntegrationTestTools.assertAssociation(shadow, getAssociationGroupQName(), groupMeleeOid); + + assertLdapConnectorInstances(2); + } + + @Override + protected void doAdditionalRenameModifications(LdapNetworkConnection connection) throws LdapException { + Modification mod = new DefaultModification(ModificationOperation.REPLACE_ATTRIBUTE, + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, ACCOUNT_HTM_UID); + connection.modify(toAccountDn(ACCOUNT_HTM_UID, ACCOUNT_HTM_CN), mod); + display("Modified " + toAccountDn(ACCOUNT_HT_UID, ACCOUNT_HT_CN) + " " + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME + + " -> " + ACCOUNT_HTM_UID + ": " + mod); + } + + @Override + protected String getAccountHtmCnAfterRename() { + return ACCOUNT_HTM_CN; + } + + @Override + protected void assertAccountShadow(PrismObject shadow, String dn) throws SchemaException { + super.assertAccountShadow(shadow, dn); + ResourceAttribute primaryIdAttr = ShadowUtil.getAttribute(shadow, getPrimaryIdentifierAttributeQName()); + assertNotNull("No primary identifier (" + getPrimaryIdentifierAttributeQName() + " in " + shadow, primaryIdAttr); + String primaryId = primaryIdAttr.getRealValue(); + assertTrue("Unexpected chars in primary ID: '" + primaryId + "'", primaryId.matches("[a-z0-9\\-]+")); + } + + @Override + protected Entry assertLdapAccount(String samAccountName, String cn) throws LdapException, IOException, CursorException { + Entry entry = searchLdapAccount("(cn=" + cn + ")"); + assertAttribute(entry, "cn", cn); + assertAttribute(entry, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName); + return entry; + } + + @Override + protected void assertNoLdapAccount(String uid) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected void assertNoLdapAccount(String uid, String cn) throws LdapException, IOException, CursorException { + LdapNetworkConnection connection = ldapConnect(); + List entriesCn = ldapSearch(connection, "(cn=" + cn + ")"); + List entriesSamAccountName = ldapSearch(connection, "(sAMAccountName=" + uid + ")"); + ldapDisconnect(connection); + + assertEquals("Unexpected number of entries for cn=" + cn + ": " + entriesCn, 0, entriesCn.size()); + assertEquals("Unexpected number of entries for sAMAccountName=" + uid + ": " + entriesSamAccountName, 0, entriesSamAccountName.size()); + } + + @Override + protected String toAccountDn(String username) { + throw new UnsupportedOperationException("Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + @Override + protected String toAccountDn(String username, String fullName) { + return "CN=" + fullName + "," + getPeopleLdapSuffix(); + } + + @Override + protected Rdn toAccountRdn(String username, String fullName) { + try { + return new Rdn(new Ava("CN", fullName)); + } catch (LdapInvalidDnException e) { + throw new IllegalStateException(e.getMessage(), e); + } + } + + protected void assertLdapPasswordByFullName(String fullName, String password) + throws LdapException, IOException, CursorException { + Entry entry = getLdapAccountByCn(fullName); + assertLdapPassword(entry, password); + } + + protected void assertLdapPassword(String uid, String password) { + throw new UnsupportedOperationException( + "Boom! Cannot do this here. This is bloody AD! We need full name!"); + } + + protected ObjectQuery createSamAccountNameQuery(String samAccountName) throws SchemaException { + ObjectQuery query = ObjectQueryUtil.createResourceAndObjectClassQuery(getResourceOid(), getAccountObjectClass(), prismContext); + ObjectQueryUtil.filterAnd(query.getFilter(), createAttributeFilter(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, samAccountName), + prismContext); + return query; + } + + @Override + protected Entry createAccountEntry(String uid, String cn, String givenName, String sn) throws LdapException { + byte[] password = encodePassword("Secret.123"); + Entry entry = new DefaultEntry(toAccountDn(uid, cn), + "objectclass", getLdapAccountObjectClass(), + ATTRIBUTE_SAM_ACCOUNT_NAME_NAME, uid, + "cn", cn, + "givenName", givenName, + "sn", sn, + ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512", + ATTRIBUTE_UNICODE_PWD_NAME, password); + return entry; + } + + private byte[] encodePassword(String password) { + String quotedPassword = "\"" + password + "\""; + return quotedPassword.getBytes(StandardCharsets.UTF_16LE); + } + + @Override + protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) + throws ObjectNotFoundException, SchemaException { + OperationResult result = createOperationResult("assertStepSyncToken"); + Task task = taskManager.getTask(syncTaskOid, result); + PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); + assertNotNull("No sync token", syncTokenProperty); + assertNotNull("No sync token value", syncTokenProperty.getRealValue()); + assertNotNull("Empty sync token value", StringUtils.isBlank(syncTokenProperty.getRealValue())); + assertSuccess(result); + } + + public void assertAttribute(PrismObject shadow, String attrName, T... expectedValues) { + assertAttribute(shadow, new QName(getResourceNamespace(), attrName), expectedValues); + } + + public void assertAttribute(PrismObject shadow, QName attrQname, T... expectedValues) { + List actualValues = ShadowUtil.getAttributeValues(shadow, attrQname); + PrismAsserts.assertSets("attribute " + attrQname + " in " + shadow, actualValues, expectedValues); + } + + protected abstract void assertAccountDisabled(PrismObject shadow); + + protected abstract void assertAccountEnabled(PrismObject shadow); +} diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml index 7d17493139a..2b43b0addf6 100644 --- a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml @@ -1,855 +1,856 @@ - - - - Active Directory Chimera (LDAP) - - - - - c:connectorType - com.evolveum.polygon.connector.ldap.ad.AdLdapConnector - - - - - - - chimera.ad.evolveum.com - 636 - adBaseDn - CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com - ssl - - qwe.123 - - host=hydra.ad.evolveum.com; baseContext=DC=sub,DC=ad,DC=evolveum,DC=com; bindDn=CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com - ignore - resolve - msExchHideFromAddressLists - true - false - always - - - false - false - false - - - - - powershell - - - - c:connectorType - com.evolveum.polygon.connector.powershell.PowerShellConnector - - - - - - chimera.ad.evolveum.com - midpoint - - qwe.123 - - midpoint - credssp - 5986 - true - variables - - - false - false - false - - - - - - - ri:user - ri:group - ri:organizationalUnit - ri:domain - ri:msExchBaseClass - - - - - - - - account - Default Account - true - ri:user - - ri:organizationalUnit - - - attributes/dn - adUsersDn - - - - - ri:dn - Distinguished Name - mr:distinguishedName - - - fullName - - - - - - - - - ri:sAMAccountName - Login name - true - - - name - - - - - name - - - - - - ri:cn - - 0 - - - - fullName - - - - - fullName - - - - - - ri:sn - - 0 - - - - familyName - - - - - familyName - - - - - - ri:givenName - - - givenName - - - - - givenName - - - - - - ri:title - - - title - - - - - - ri:userPrincipalName - - - name - - - - - - - - - ri:pwdLastSet - - - -1 - - - - - - ri:createTimeStamp - explicit - - - - ri:objectCategory - - - CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com - - - - - - ri:showInAdvancedViewOnly - - - extension/showInAdvancedViewOnly - - - - - - ri:msExchHideFromAddressLists - MID-4041 - - strong - - activation/effectiveStatus - - - - - - - - - ri:group - AD Group Membership - entitlement - group - objectToSubject - ri:member - ri:dn - ri:memberOf - ri:dn - false - - - - ri:org-group - AD Org Group Membership - entitlement - org-group - objectToSubject - ri:member - ri:dn - ri:memberOf - ri:dn - false - - - - - - attributes/dn - cn=midpoint,cn=users,dc=ad,dc=evolveum,dc=com - - - - - - - attributes/dn - CN=SUB$,CN=Users,DC=ad,DC=evolveum,DC=com - - - - - - - attributes/dn - CN=DiscoverySearchMailbox - true - - - - - - - attributes/dn - CN=SystemMailbox - true - - - - - - - - - - - - - - - - - - - - generic - ou-top - Top Org - true - ri:organizationalUnit - - ri:organizationalUnit - - - attributes/dn - OU=Org,DC=ad,DC=evolveum,DC=com - - - - - ri:dn - Distinguished Name - mr:distinguishedName - - - name - - - - - - - - - ri:ou - - 0 - - - - name - - - - - - - ri:objectCategory - - - CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com - - - - - - - - - account - sub - Sub Account - false - ri:user - - ri:organizationalUnit - - - attributes/dn - CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com - - - - - ri:dn - Distinguished Name - mr:distinguishedName - - - $user/fullName - - - - - - - - - ri:sAMAccountName - Login name - - - $user/name - - - - - name - - - - - - ri:cn - - 0 - - - - fullName - - - - - fullName - - - - - - ri:sn - - 0 - - - - familyName - - - - - familyName - - - - - - ri:givenName - - - givenName - - - - - givenName - - - - - - ri:title - - - title - - - - - - ri:userPrincipalName - - - $user/name - - - - - - - - - ri:pwdLastSet - - - -1 - - - - - - ri:createTimeStamp - explicit - - - - ri:nTSecurityDescriptor - - - 0 - - - - - ri:instanceType - - - 0 - - - - - ri:objectCategory - - - 0 - - - - CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com - - - - - - - ri:group - AD Group Membership - entitlement - group - objectToSubject - ri:member - ri:dn - ri:memberOf - ri:dn - false - - - - - - - - - - - - - - - - - - generic - ou-sub - Sub Org - ri:organizationalUnit - - ri:domain - - - attributes/dn - DC=sub,DC=ad,DC=evolveum,DC=com - - - - - ri:dn - Distinguished Name - mr:distinguishedName - - - name - - - - - - - - - ri:ou - - 0 - - - - name - - - - - - - ri:objectCategory - - - CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com - - - - - - - - - entitlement - group - AD Group - Groups in the parent (top) domain - true - ri:group - - ri:organizationalUnit - - - attributes/dn - CN=Users,DC=ad,DC=evolveum,DC=com - - - - - dn - mr:distinguishedName - - - $focus/name - - - - - - - - ri:cn - mr:stringIgnoreCase - - - $focus/name - - - - - name - - - - - ri:description - - strong - - description - - - - - description - - - - - - - entitlement - org-group - Organizational Group - Groups in the parent (top) domain that are part of organizational units - false - ri:group - - ri:organizationalUnit - - - attributes/dn - OU=Org,DC=ad,DC=evolveum,DC=com - - - - - dn - mr:distinguishedName - - - $focus/name - - - - - - - - ri:cn - mr:stringIgnoreCase - - - $focus/name - - - - - name - - - - - ri:description - - strong - - description - - - - - description - - - - - - - - - - - - - - - true - true - - - - - - Account sync - ri:user - account - default - UserType - true - - - c:name - - $shadow/attributes/sAMAccountName - - - - - - linked - true - - - deleted - http://midpoint.evolveum.com/xml/ns/public/model/action-3#deleteFocus - - - unlinked - http://midpoint.evolveum.com/xml/ns/public/model/action-3#link - - - unmatched - http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus - - - - - - - + + + + Active Directory Chimera (LDAP) + + + + + c:connectorType + com.evolveum.polygon.connector.ldap.ad.AdLdapConnector + + + + + + + chimera.ad.evolveum.com + 636 + adBaseDn + CN=midpoint,CN=Users,DC=ad,DC=evolveum,DC=com + ssl + + qwe.123 + + host=hydra.ad.evolveum.com; baseContext=DC=sub,DC=ad,DC=evolveum,DC=com; bindDn=CN=midpoint,CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com + ignore + resolve + msExchHideFromAddressLists + true + false + always + CN=Users,DC=ad,DC=evolveum,DC=com + + + false + false + false + + + + + powershell + + + + c:connectorType + com.evolveum.polygon.connector.powershell.PowerShellConnector + + + + + + chimera.ad.evolveum.com + midpoint + + qwe.123 + + midpoint + credssp + 5986 + true + variables + + + false + false + false + + + + + + + ri:user + ri:group + ri:organizationalUnit + ri:domain + ri:msExchBaseClass + + + + + + + + account + Default Account + true + ri:user + + ri:organizationalUnit + + + attributes/dn + adUsersDn + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + fullName + + + + + + + + + ri:sAMAccountName + Login name + true + + + name + + + + + name + + + + + + ri:cn + + 0 + + + + fullName + + + + + fullName + + + + + + ri:sn + + 0 + + + + familyName + + + + + familyName + + + + + + ri:givenName + + + givenName + + + + + givenName + + + + + + ri:title + + + title + + + + + + ri:userPrincipalName + + + name + + + + + + + + + ri:pwdLastSet + + + -1 + + + + + + ri:createTimeStamp + explicit + + + + ri:objectCategory + + + CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + ri:showInAdvancedViewOnly + + + extension/showInAdvancedViewOnly + + + + + + ri:msExchHideFromAddressLists + MID-4041 + + strong + + activation/effectiveStatus + + + + + + + + + ri:group + AD Group Membership + entitlement + group + objectToSubject + ri:member + ri:dn + ri:memberOf + ri:dn + false + + + + ri:org-group + AD Org Group Membership + entitlement + org-group + objectToSubject + ri:member + ri:dn + ri:memberOf + ri:dn + false + + + + + + attributes/dn + cn=midpoint,cn=users,dc=ad,dc=evolveum,dc=com + + + + + + + attributes/dn + CN=SUB$,CN=Users,DC=ad,DC=evolveum,DC=com + + + + + + + attributes/dn + CN=DiscoverySearchMailbox + true + + + + + + + attributes/dn + CN=SystemMailbox + true + + + + + + + + + + + + + + + + + + + + generic + ou-top + Top Org + true + ri:organizationalUnit + + ri:organizationalUnit + + + attributes/dn + OU=Org,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + name + + + + + + + + + ri:ou + + 0 + + + + name + + + + + + + ri:objectCategory + + + CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + + + + account + sub + Sub Account + false + ri:user + + ri:organizationalUnit + + + attributes/dn + CN=Users,DC=sub,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + $user/fullName + + + + + + + + + ri:sAMAccountName + Login name + + + $user/name + + + + + name + + + + + + ri:cn + + 0 + + + + fullName + + + + + fullName + + + + + + ri:sn + + 0 + + + + familyName + + + + + familyName + + + + + + ri:givenName + + + givenName + + + + + givenName + + + + + + ri:title + + + title + + + + + + ri:userPrincipalName + + + $user/name + + + + + + + + + ri:pwdLastSet + + + -1 + + + + + + ri:createTimeStamp + explicit + + + + ri:nTSecurityDescriptor + + + 0 + + + + + ri:instanceType + + + 0 + + + + + ri:objectCategory + + + 0 + + + + CN=Person,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + + ri:group + AD Group Membership + entitlement + group + objectToSubject + ri:member + ri:dn + ri:memberOf + ri:dn + false + + + + + + + + + + + + + + + + + + generic + ou-sub + Sub Org + ri:organizationalUnit + + ri:domain + + + attributes/dn + DC=sub,DC=ad,DC=evolveum,DC=com + + + + + ri:dn + Distinguished Name + mr:distinguishedName + + + name + + + + + + + + + ri:ou + + 0 + + + + name + + + + + + + ri:objectCategory + + + CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=ad,DC=evolveum,DC=com + + + + + + + + + entitlement + group + AD Group + Groups in the parent (top) domain + true + ri:group + + ri:organizationalUnit + + + attributes/dn + CN=Users,DC=ad,DC=evolveum,DC=com + + + + + dn + mr:distinguishedName + + + $focus/name + + + + + + + + ri:cn + mr:stringIgnoreCase + + + $focus/name + + + + + name + + + + + ri:description + + strong + + description + + + + + description + + + + + + + entitlement + org-group + Organizational Group + Groups in the parent (top) domain that are part of organizational units + false + ri:group + + ri:organizationalUnit + + + attributes/dn + OU=Org,DC=ad,DC=evolveum,DC=com + + + + + dn + mr:distinguishedName + + + $focus/name + + + + + + + + ri:cn + mr:stringIgnoreCase + + + $focus/name + + + + + name + + + + + ri:description + + strong + + description + + + + + description + + + + + + + + + + + + + + + true + true + + + + + + Account sync + ri:user + account + default + UserType + true + + + c:name + + $shadow/attributes/sAMAccountName + + + + + + linked + true + + + deleted + http://midpoint.evolveum.com/xml/ns/public/model/action-3#deleteFocus + + + unlinked + http://midpoint.evolveum.com/xml/ns/public/model/action-3#link + + + unmatched + http://midpoint.evolveum.com/xml/ns/public/model/action-3#addFocus + + + + + + + diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/task-sync.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/task-sync.xml new file mode 100644 index 00000000000..f6a92fda7fb --- /dev/null +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/task-sync.xml @@ -0,0 +1,28 @@ + + + + + + Synchronization: Active Directory Chimera (LDAP) + + 0f93d8d4-5fb4-11ea-8571-a3f090bf921f + + runnable + + http://midpoint.evolveum.com/xml/ns/public/model/synchronization/task/live-sync/handler-3 + + recurring + + 3 + + + diff --git a/testing/conntest/src/test/resources/logback-test.xml b/testing/conntest/src/test/resources/logback-test.xml index 69f46a4eb5a..fc529df964b 100644 --- a/testing/conntest/src/test/resources/logback-test.xml +++ b/testing/conntest/src/test/resources/logback-test.xml @@ -1,68 +1,73 @@ - - - - - - - - - ./target/test.log - - - %date [%thread] %-5level [%X{subsystem}]\(%logger{46}\): %message%n - - - - - %date [%thread] %-5level \(%logger{46}\): %message%n - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + ./target/test.log + + + %date [%thread] %-5level [%X{subsystem}]\(%logger{46}\): %message%n + + + + + %date [%thread] %-5level \(%logger{46}\): %message%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From ffaf79e8f9f7b714807ab146e4ce04a940e84a6d Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 9 Mar 2020 13:56:26 +0100 Subject: [PATCH 2/5] baseContextsToSynchronize -> baseContextToSynchronize (MID-5942) --- pom.xml | 2 +- .../conntest/ad/AbstractAdLdapMultidomainTest.java | 8 ++++++-- .../resources/ad-ldap-multidomain/resource-chimera.xml | 2 +- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index bd49a078ecd..b9064b88a29 100644 --- a/pom.xml +++ b/pom.xml @@ -892,7 +892,7 @@ com.evolveum.polygon connector-ldap - 3.0-M1 + 3.0-SNAPSHOT diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java index 0dd0e22f648..ad3fa327405 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java @@ -2138,7 +2138,9 @@ public void test850ReconcileAccounts() throws Exception { // assertLdapConnectorInstances(2); } - @Test + // DISABLED because we do not know how to properly configure sync privileges in a AD forrest. + // More experiments are needed, but only after we migrate our old AD servers. + @Test(enabled=false) public void test900ImportSyncTask() throws Exception { // GIVEN Task task = getTestTask(); @@ -2161,7 +2163,9 @@ public void test900ImportSyncTask() throws Exception { assertStepSyncToken(getSyncTaskOid(), 0, tsStart, tsEnd); } - @Test + // DISABLED because we do not know how to properly configure sync privileges in a AD forrest. + // More experiments are needed, but only after we migrate our old AD servers. + @Test(enabled=false) public void test901SyncAddAccountHt() throws Exception { // GIVEN Task task = getTestTask(); diff --git a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml index 2b43b0addf6..742e93e16da 100644 --- a/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml +++ b/testing/conntest/src/test/resources/ad-ldap-multidomain/resource-chimera.xml @@ -41,7 +41,7 @@ true false always - CN=Users,DC=ad,DC=evolveum,DC=com + CN=Users,DC=ad,DC=evolveum,DC=com false From 2bf522bcb19e6ff44219b9ec6d3ff3db760374d2 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Mon, 9 Mar 2020 15:20:14 +0100 Subject: [PATCH 3/5] Test to reproduce MID-4385: can't reproduce --- .../ad/AbstractAdLdapMultidomainTest.java | 46 ++ .../testing/conntest/ad/AdTestMixin.java | 505 +++++++++--------- 2 files changed, 299 insertions(+), 252 deletions(-) diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java index ad3fa327405..537362e9d1d 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java @@ -154,6 +154,8 @@ public abstract class AbstractAdLdapMultidomainTest extends AbstractLdapTest private static final String USER_GUYBRUSH_PASSWORD_123 = "wanna.be.a.123"; private static final String USER_GUYBRUSH_PASSWORD_333 = "wanna.be.a.333"; + private static final String VERY_STRANGE_PARAMETER = "This iš a véry stándže p§räméteř!"; + private boolean allowDuplicateSearchResults = false; protected String jackAccountOid; @@ -951,6 +953,50 @@ public void test214ModifyAccountBarbossaProxyAddressesSimple() throws Exception String shadowOid = getSingleLinkOid(user); assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); +// assertLdapConnectorInstances(2); + } + + /** + * MID-4385 + */ + @Test + public void test216ModifyAccountBarbossaUserParameters() throws Exception { + // GIVEN + Task task = getTestTask(); + OperationResult result = task.getResult(); + + ObjectDelta delta = prismContext.deltaFactory().object() + .createEmptyModifyDelta(ShadowType.class, accountBarbossaOid); + QName attrQName = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_PARAMETERS_NAME); + ResourceAttributeDefinition attrDef = accountObjectClassDefinition.findAttributeDefinition(attrQName); + assertNotNull("No definition for attribute " + attrQName, attrDef); + PropertyDelta attrDelta = prismContext.deltaFactory().property().createModificationReplaceProperty( + ItemPath.create(ShadowType.F_ATTRIBUTES, attrQName), attrDef, VERY_STRANGE_PARAMETER); + delta.addModification(attrDelta); + + // WHEN + when(); + executeChanges(delta, null, task, result); + + // THEN + then(); + assertSuccess(result); + + Entry entry = assertLdapAccount(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME); + assertAttribute(entry, ATTRIBUTE_USER_PARAMETERS_NAME, VERY_STRANGE_PARAMETER); + assertAttribute(entry, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME, "512"); + assertAttribute(entry, ATTRIBUTE_OBJECT_CATEGORY_NAME, OBJECT_CATEGORY_PERSON); + assertLdapPassword(USER_BARBOSSA_USERNAME, USER_BARBOSSA_FULL_NAME, USER_BARBOSSA_PASSWORD); + + PrismObject user = getUser(USER_BARBOSSA_OID); + String shadowOid = getSingleLinkOid(user); + assertEquals("Shadows have moved", accountBarbossaOid, shadowOid); + + assertModelShadow(shadowOid) + .attributes() + .attribute(ATTRIBUTE_USER_PARAMETERS_NAME) + .assertRealValues(VERY_STRANGE_PARAMETER); + // assertLdapConnectorInstances(2); } diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AdTestMixin.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AdTestMixin.java index 514bf27c05c..e787b5dd63c 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AdTestMixin.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AdTestMixin.java @@ -1,252 +1,253 @@ -/* - * Copyright (c) 2016 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.testing.conntest.ad; - -import static org.testng.AssertJUnit.*; - -import javax.xml.namespace.QName; - -import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; -import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; -import com.evolveum.midpoint.prism.PrimitiveType; -import com.evolveum.midpoint.prism.PrismContext; -import com.evolveum.midpoint.prism.PrismObject; -import com.evolveum.midpoint.prism.util.PrismAsserts; -import com.evolveum.midpoint.prism.util.PrismTestUtil; -import com.evolveum.midpoint.schema.constants.MidPointConstants; -import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; -import com.evolveum.midpoint.schema.processor.ResourceSchema; -import com.evolveum.midpoint.schema.util.ResourceTypeUtil; -import com.evolveum.midpoint.tools.testng.MidpointTestMixin; -import com.evolveum.midpoint.util.DOMUtil; -import com.evolveum.midpoint.util.DebugDumpable; -import com.evolveum.midpoint.util.exception.SchemaException; -import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; - -/** - * Mixin providing common methods/utilities for Active Directory (AD) related tests. - */ -public interface AdTestMixin extends MidpointTestMixin { - - String ATTRIBUTE_OBJECT_GUID_NAME = "objectGUID"; - String ATTRIBUTE_OBJECT_SID_NAME = "objectSid"; - String ATTRIBUTE_OBJECT_CATEGORY_NAME = "objectCategory"; - String ATTRIBUTE_SAM_ACCOUNT_NAME_NAME = "sAMAccountName"; - String ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME = "userAccountControl"; - QName ATTRIBUTE_USER_ACCOUNT_CONTROL_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME); - String ATTRIBUTE_UNICODE_PWD_NAME = "unicodePwd"; - String ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME = "msExchHideFromAddressLists"; - QName ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); - String ATTRIBUTE_TITLE_NAME = "title"; - String ATTRIBUTE_PROXY_ADDRESSES_NAME = "proxyAddresses"; - - QName OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME = new QName(MidPointConstants.NS_RI, "msExchBaseClass"); - - String AD_CONNECTOR_TYPE = "com.evolveum.polygon.connector.ldap.ad.AdLdapConnector"; - - /** - * Returns dashed GUID notation formatted from simple hex-encoded binary. - *

- * E.g. "2f01c06bb1d0414e9a69dd3841a13506" -> "6bc0012f-d0b1-4e41-9a69-dd3841a13506" - */ - default String formatGuidToDashedNotation(String hexValue) { - if (hexValue == null) { - return null; - } - return hexValue.substring(6, 8) - + hexValue.substring(4, 6) - + hexValue.substring(2, 4) - + hexValue.substring(0, 2) - + '-' - + hexValue.substring(10, 12) - + hexValue.substring(8, 10) - + '-' - + hexValue.substring(14, 16) - + hexValue.substring(12, 14) - + '-' - + hexValue.substring(16, 20) - + '-' - + hexValue.substring(20, 32); - } - - default ObjectClassComplexTypeDefinition assertAdResourceSchema( - PrismObject resource, QName accountObjectClass, PrismContext prismContext) - throws SchemaException { - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - display("Resource schema", resourceSchema); - ResourceTypeUtil.validateSchema(resourceSchema, resource); - return assertAdSchema(resource, accountObjectClass); - } - - default ObjectClassComplexTypeDefinition assertAdResourceSchemaLongTimestamp( - PrismObject resource, QName accountObjectClass, PrismContext prismContext) - throws SchemaException { - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - display("Resource schema", resourceSchema); - ResourceTypeUtil.validateSchema(resourceSchema, resource); - return assertAdSchemaLongTimestamp(resource, accountObjectClass); - } - - default ObjectClassComplexTypeDefinition assertAdRefinedSchema( - PrismObject resource, QName accountObjectClass) throws SchemaException { - RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); - display("Refined schema", refinedSchema); - RefinedResourceSchemaImpl.validateRefinedSchema(refinedSchema, resource); - return assertAdSchema(resource, accountObjectClass); - } - - // Assumes string timestamp - default ObjectClassComplexTypeDefinition assertAdSchema( - PrismObject resource, QName accountObjectClass) throws SchemaException { - ObjectClassComplexTypeDefinition accountObjectClassDefinition = assertAdSchemaBase(resource, accountObjectClass); - - ResourceAttributeDefinition createTimestampDef = - accountObjectClassDefinition.findAttributeDefinition("createTimeStamp"); - PrismAsserts.assertDefinition(createTimestampDef, - new QName(MidPointConstants.NS_RI, "createTimeStamp"), DOMUtil.XSD_DATETIME, 0, 1); - assertTrue("createTimeStampDef read", createTimestampDef.canRead()); - assertFalse("createTimeStampDef modify", createTimestampDef.canModify()); - assertFalse("createTimeStampDef add", createTimestampDef.canAdd()); - - ResourceAttributeDefinition whenChangedDef = - accountObjectClassDefinition.findAttributeDefinition("whenChanged"); - PrismAsserts.assertDefinition(whenChangedDef, - new QName(MidPointConstants.NS_RI, "createTimeStamp"), DOMUtil.XSD_DATETIME, 0, 1); - assertTrue("whenChanged read", whenChangedDef.canRead()); - assertFalse("whenChanged modify", whenChangedDef.canModify()); - assertFalse("whenChanged add", whenChangedDef.canAdd()); - - return accountObjectClassDefinition; - } - - // Assumes string timestamp - default ObjectClassComplexTypeDefinition assertAdSchemaLongTimestamp( - PrismObject resource, QName accountObjectClass) throws SchemaException { - ObjectClassComplexTypeDefinition accountObjectClassDefinition = assertAdSchemaBase(resource, accountObjectClass); - - ResourceAttributeDefinition createTimestampDef = accountObjectClassDefinition.findAttributeDefinition("createTimeStamp"); - PrismAsserts.assertDefinition(createTimestampDef, new QName(MidPointConstants.NS_RI, "createTimeStamp"), - DOMUtil.XSD_LONG, 0, 1); - assertTrue("createTimeStampDef read", createTimestampDef.canRead()); - assertFalse("createTimeStampDef modify", createTimestampDef.canModify()); - assertFalse("createTimeStampDef add", createTimestampDef.canAdd()); - - return accountObjectClassDefinition; - } - - // TODO after ditching JDK 8 - /*private*/ default ObjectClassComplexTypeDefinition assertAdSchemaBase( - PrismObject resource, QName accountObjectClass) throws SchemaException { - - RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); - display("Refined schema", refinedSchema); - ObjectClassComplexTypeDefinition accountObjectClassDefinition = refinedSchema.findObjectClassDefinition(accountObjectClass); - assertNotNull("No definition for object class " + accountObjectClass, accountObjectClassDefinition); - display("Account object class def", accountObjectClassDefinition); - - ResourceAttributeDefinition cnDef = accountObjectClassDefinition.findAttributeDefinition("cn"); - PrismAsserts.assertDefinition(cnDef, new QName(MidPointConstants.NS_RI, "cn"), DOMUtil.XSD_STRING, 0, 1); - assertTrue("cn read", cnDef.canRead()); - assertTrue("cn modify", cnDef.canModify()); - assertTrue("cn add", cnDef.canAdd()); - - ResourceAttributeDefinition samAccountNameDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME); - PrismAsserts.assertDefinition(samAccountNameDef, - new QName(MidPointConstants.NS_RI, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME), DOMUtil.XSD_STRING, 0, 1); - assertTrue("samAccountNameDef read", samAccountNameDef.canRead()); - assertTrue("samAccountNameDef modify", samAccountNameDef.canModify()); - assertTrue("samAccountNameDef add", samAccountNameDef.canAdd()); - - ResourceAttributeDefinition oDef = accountObjectClassDefinition.findAttributeDefinition("o"); - PrismAsserts.assertDefinition(oDef, new QName(MidPointConstants.NS_RI, "o"), DOMUtil.XSD_STRING, 0, -1); - assertTrue("o read", oDef.canRead()); - assertTrue("o modify", oDef.canModify()); - assertTrue("o add", oDef.canAdd()); - - ResourceAttributeDefinition isCriticalSystemObjectDef = accountObjectClassDefinition.findAttributeDefinition("isCriticalSystemObject"); - PrismAsserts.assertDefinition(isCriticalSystemObjectDef, new QName(MidPointConstants.NS_RI, "isCriticalSystemObject"), - PrimitiveType.XSD_BOOLEAN, 0, 1); - assertTrue("isCriticalSystemObject read", isCriticalSystemObjectDef.canRead()); - assertTrue("isCriticalSystemObject modify", isCriticalSystemObjectDef.canModify()); - assertTrue("isCriticalSystemObject add", isCriticalSystemObjectDef.canAdd()); - - ResourceAttributeDefinition nTSecurityDescriptorDef = accountObjectClassDefinition.findAttributeDefinition("nTSecurityDescriptor"); - PrismAsserts.assertDefinition(nTSecurityDescriptorDef, new QName(MidPointConstants.NS_RI, "nTSecurityDescriptor"), - PrimitiveType.XSD_BASE64BINARY, 0, 1); - assertTrue("nTSecurityDescriptor read", nTSecurityDescriptorDef.canRead()); - assertTrue("nTSecurityDescriptor modify", nTSecurityDescriptorDef.canModify()); - assertTrue("nTSecurityDescriptor add", nTSecurityDescriptorDef.canAdd()); - - ResourceAttributeDefinition objectSidDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_OBJECT_SID_NAME); - PrismAsserts.assertDefinition(objectSidDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME), - PrimitiveType.XSD_STRING, 0, 1); - assertTrue("objectSid read", objectSidDef.canRead()); - assertFalse("objectSid modify", objectSidDef.canModify()); - assertFalse("objectSid add", objectSidDef.canAdd()); - - ResourceAttributeDefinition lastLogonDef = accountObjectClassDefinition.findAttributeDefinition("lastLogon"); - PrismAsserts.assertDefinition(lastLogonDef, new QName(MidPointConstants.NS_RI, "lastLogon"), - PrimitiveType.XSD_LONG, 0, 1); - assertTrue("lastLogonDef read", lastLogonDef.canRead()); - assertTrue("lastLogonDef modify", lastLogonDef.canModify()); - assertTrue("lastLogonDef add", lastLogonDef.canAdd()); - - ResourceAttributeDefinition proxyAddressesDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_PROXY_ADDRESSES_NAME); - PrismAsserts.assertDefinition(proxyAddressesDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_PROXY_ADDRESSES_NAME), - PrimitiveType.XSD_STRING, 0, -1); - assertTrue("proxyAddressesDef read", proxyAddressesDef.canRead()); - assertTrue("proxyAddressesDef modify", proxyAddressesDef.canModify()); - assertTrue("proxyAddressesDef add", proxyAddressesDef.canAdd()); - // TODO: proxyAddressesDef.getMatchingRuleQName() - - return accountObjectClassDefinition; - } - - default void assertExchangeSchema(PrismObject resource, QName accountObjectClassQName, PrismContext prismContext) throws SchemaException { - - ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); - assertExchangeSchema(resourceSchema, accountObjectClassQName); - - RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); - assertExchangeSchema(refinedSchema, accountObjectClassQName); - } - - default void assertExchangeSchema(ResourceSchema resourceSchema, QName accountObjectClassQName) { - ObjectClassComplexTypeDefinition msExchBaseClassObjectClassDefinition = resourceSchema.findObjectClassDefinition(OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME); - assertNotNull("No definition for object class " + OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME, msExchBaseClassObjectClassDefinition); - display("Object class " + OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME + " def", msExchBaseClassObjectClassDefinition); - - ResourceAttributeDefinition msExchHideFromAddressListsDef = msExchBaseClassObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); - PrismAsserts.assertDefinition(msExchHideFromAddressListsDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME), DOMUtil.XSD_BOOLEAN, 0, 1); - assertTrue("msExchHideFromAddressLists read", msExchHideFromAddressListsDef.canRead()); - assertTrue("msExchHideFromAddressLists modify", msExchHideFromAddressListsDef.canModify()); - assertTrue("msExchHideFromAddressLists add", msExchHideFromAddressListsDef.canAdd()); - - ObjectClassComplexTypeDefinition accountObjectClassDef = resourceSchema.findObjectClassDefinition(accountObjectClassQName); - assertNotNull("No definition for object class " + accountObjectClassQName, accountObjectClassDef); - display("Object class " + accountObjectClassQName + " def", accountObjectClassDef); - - ResourceAttributeDefinition accountMsExchHideFromAddressListsDef = accountObjectClassDef.findAttributeDefinition(ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); - PrismAsserts.assertDefinition(accountMsExchHideFromAddressListsDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME), DOMUtil.XSD_BOOLEAN, 0, 1); - assertTrue("msExchHideFromAddressLists read", accountMsExchHideFromAddressListsDef.canRead()); - assertTrue("msExchHideFromAddressLists modify", accountMsExchHideFromAddressListsDef.canModify()); - assertTrue("msExchHideFromAddressLists add", accountMsExchHideFromAddressListsDef.canAdd()); - } - - default long getWin32Filetime(long millis) { - return (millis + 11644473600000L) * 10000L; - } - - default void display(String title, DebugDumpable value) { - PrismTestUtil.display(title, value); - } - - default void display(String title, Object value) { - PrismTestUtil.display(title, value); - } -} +/* + * Copyright (c) 2016 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.testing.conntest.ad; + +import static org.testng.AssertJUnit.*; + +import javax.xml.namespace.QName; + +import com.evolveum.midpoint.common.refinery.RefinedResourceSchema; +import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl; +import com.evolveum.midpoint.prism.PrimitiveType; +import com.evolveum.midpoint.prism.PrismContext; +import com.evolveum.midpoint.prism.PrismObject; +import com.evolveum.midpoint.prism.util.PrismAsserts; +import com.evolveum.midpoint.prism.util.PrismTestUtil; +import com.evolveum.midpoint.schema.constants.MidPointConstants; +import com.evolveum.midpoint.schema.processor.ObjectClassComplexTypeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceAttributeDefinition; +import com.evolveum.midpoint.schema.processor.ResourceSchema; +import com.evolveum.midpoint.schema.util.ResourceTypeUtil; +import com.evolveum.midpoint.tools.testng.MidpointTestMixin; +import com.evolveum.midpoint.util.DOMUtil; +import com.evolveum.midpoint.util.DebugDumpable; +import com.evolveum.midpoint.util.exception.SchemaException; +import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType; + +/** + * Mixin providing common methods/utilities for Active Directory (AD) related tests. + */ +public interface AdTestMixin extends MidpointTestMixin { + + String ATTRIBUTE_OBJECT_GUID_NAME = "objectGUID"; + String ATTRIBUTE_OBJECT_SID_NAME = "objectSid"; + String ATTRIBUTE_OBJECT_CATEGORY_NAME = "objectCategory"; + String ATTRIBUTE_SAM_ACCOUNT_NAME_NAME = "sAMAccountName"; + String ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME = "userAccountControl"; + QName ATTRIBUTE_USER_ACCOUNT_CONTROL_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_USER_ACCOUNT_CONTROL_NAME); + String ATTRIBUTE_UNICODE_PWD_NAME = "unicodePwd"; + String ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME = "msExchHideFromAddressLists"; + QName ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_QNAME = new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); + String ATTRIBUTE_TITLE_NAME = "title"; + String ATTRIBUTE_PROXY_ADDRESSES_NAME = "proxyAddresses"; + String ATTRIBUTE_USER_PARAMETERS_NAME = "userParameters"; + + QName OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME = new QName(MidPointConstants.NS_RI, "msExchBaseClass"); + + String AD_CONNECTOR_TYPE = "com.evolveum.polygon.connector.ldap.ad.AdLdapConnector"; + + /** + * Returns dashed GUID notation formatted from simple hex-encoded binary. + *

+ * E.g. "2f01c06bb1d0414e9a69dd3841a13506" -> "6bc0012f-d0b1-4e41-9a69-dd3841a13506" + */ + default String formatGuidToDashedNotation(String hexValue) { + if (hexValue == null) { + return null; + } + return hexValue.substring(6, 8) + + hexValue.substring(4, 6) + + hexValue.substring(2, 4) + + hexValue.substring(0, 2) + + '-' + + hexValue.substring(10, 12) + + hexValue.substring(8, 10) + + '-' + + hexValue.substring(14, 16) + + hexValue.substring(12, 14) + + '-' + + hexValue.substring(16, 20) + + '-' + + hexValue.substring(20, 32); + } + + default ObjectClassComplexTypeDefinition assertAdResourceSchema( + PrismObject resource, QName accountObjectClass, PrismContext prismContext) + throws SchemaException { + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + display("Resource schema", resourceSchema); + ResourceTypeUtil.validateSchema(resourceSchema, resource); + return assertAdSchema(resource, accountObjectClass); + } + + default ObjectClassComplexTypeDefinition assertAdResourceSchemaLongTimestamp( + PrismObject resource, QName accountObjectClass, PrismContext prismContext) + throws SchemaException { + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + display("Resource schema", resourceSchema); + ResourceTypeUtil.validateSchema(resourceSchema, resource); + return assertAdSchemaLongTimestamp(resource, accountObjectClass); + } + + default ObjectClassComplexTypeDefinition assertAdRefinedSchema( + PrismObject resource, QName accountObjectClass) throws SchemaException { + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + display("Refined schema", refinedSchema); + RefinedResourceSchemaImpl.validateRefinedSchema(refinedSchema, resource); + return assertAdSchema(resource, accountObjectClass); + } + + // Assumes string timestamp + default ObjectClassComplexTypeDefinition assertAdSchema( + PrismObject resource, QName accountObjectClass) throws SchemaException { + ObjectClassComplexTypeDefinition accountObjectClassDefinition = assertAdSchemaBase(resource, accountObjectClass); + + ResourceAttributeDefinition createTimestampDef = + accountObjectClassDefinition.findAttributeDefinition("createTimeStamp"); + PrismAsserts.assertDefinition(createTimestampDef, + new QName(MidPointConstants.NS_RI, "createTimeStamp"), DOMUtil.XSD_DATETIME, 0, 1); + assertTrue("createTimeStampDef read", createTimestampDef.canRead()); + assertFalse("createTimeStampDef modify", createTimestampDef.canModify()); + assertFalse("createTimeStampDef add", createTimestampDef.canAdd()); + + ResourceAttributeDefinition whenChangedDef = + accountObjectClassDefinition.findAttributeDefinition("whenChanged"); + PrismAsserts.assertDefinition(whenChangedDef, + new QName(MidPointConstants.NS_RI, "createTimeStamp"), DOMUtil.XSD_DATETIME, 0, 1); + assertTrue("whenChanged read", whenChangedDef.canRead()); + assertFalse("whenChanged modify", whenChangedDef.canModify()); + assertFalse("whenChanged add", whenChangedDef.canAdd()); + + return accountObjectClassDefinition; + } + + // Assumes string timestamp + default ObjectClassComplexTypeDefinition assertAdSchemaLongTimestamp( + PrismObject resource, QName accountObjectClass) throws SchemaException { + ObjectClassComplexTypeDefinition accountObjectClassDefinition = assertAdSchemaBase(resource, accountObjectClass); + + ResourceAttributeDefinition createTimestampDef = accountObjectClassDefinition.findAttributeDefinition("createTimeStamp"); + PrismAsserts.assertDefinition(createTimestampDef, new QName(MidPointConstants.NS_RI, "createTimeStamp"), + DOMUtil.XSD_LONG, 0, 1); + assertTrue("createTimeStampDef read", createTimestampDef.canRead()); + assertFalse("createTimeStampDef modify", createTimestampDef.canModify()); + assertFalse("createTimeStampDef add", createTimestampDef.canAdd()); + + return accountObjectClassDefinition; + } + + // TODO after ditching JDK 8 + /*private*/ default ObjectClassComplexTypeDefinition assertAdSchemaBase( + PrismObject resource, QName accountObjectClass) throws SchemaException { + + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + display("Refined schema", refinedSchema); + ObjectClassComplexTypeDefinition accountObjectClassDefinition = refinedSchema.findObjectClassDefinition(accountObjectClass); + assertNotNull("No definition for object class " + accountObjectClass, accountObjectClassDefinition); + display("Account object class def", accountObjectClassDefinition); + + ResourceAttributeDefinition cnDef = accountObjectClassDefinition.findAttributeDefinition("cn"); + PrismAsserts.assertDefinition(cnDef, new QName(MidPointConstants.NS_RI, "cn"), DOMUtil.XSD_STRING, 0, 1); + assertTrue("cn read", cnDef.canRead()); + assertTrue("cn modify", cnDef.canModify()); + assertTrue("cn add", cnDef.canAdd()); + + ResourceAttributeDefinition samAccountNameDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_SAM_ACCOUNT_NAME_NAME); + PrismAsserts.assertDefinition(samAccountNameDef, + new QName(MidPointConstants.NS_RI, ATTRIBUTE_SAM_ACCOUNT_NAME_NAME), DOMUtil.XSD_STRING, 0, 1); + assertTrue("samAccountNameDef read", samAccountNameDef.canRead()); + assertTrue("samAccountNameDef modify", samAccountNameDef.canModify()); + assertTrue("samAccountNameDef add", samAccountNameDef.canAdd()); + + ResourceAttributeDefinition oDef = accountObjectClassDefinition.findAttributeDefinition("o"); + PrismAsserts.assertDefinition(oDef, new QName(MidPointConstants.NS_RI, "o"), DOMUtil.XSD_STRING, 0, -1); + assertTrue("o read", oDef.canRead()); + assertTrue("o modify", oDef.canModify()); + assertTrue("o add", oDef.canAdd()); + + ResourceAttributeDefinition isCriticalSystemObjectDef = accountObjectClassDefinition.findAttributeDefinition("isCriticalSystemObject"); + PrismAsserts.assertDefinition(isCriticalSystemObjectDef, new QName(MidPointConstants.NS_RI, "isCriticalSystemObject"), + PrimitiveType.XSD_BOOLEAN, 0, 1); + assertTrue("isCriticalSystemObject read", isCriticalSystemObjectDef.canRead()); + assertTrue("isCriticalSystemObject modify", isCriticalSystemObjectDef.canModify()); + assertTrue("isCriticalSystemObject add", isCriticalSystemObjectDef.canAdd()); + + ResourceAttributeDefinition nTSecurityDescriptorDef = accountObjectClassDefinition.findAttributeDefinition("nTSecurityDescriptor"); + PrismAsserts.assertDefinition(nTSecurityDescriptorDef, new QName(MidPointConstants.NS_RI, "nTSecurityDescriptor"), + PrimitiveType.XSD_BASE64BINARY, 0, 1); + assertTrue("nTSecurityDescriptor read", nTSecurityDescriptorDef.canRead()); + assertTrue("nTSecurityDescriptor modify", nTSecurityDescriptorDef.canModify()); + assertTrue("nTSecurityDescriptor add", nTSecurityDescriptorDef.canAdd()); + + ResourceAttributeDefinition objectSidDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_OBJECT_SID_NAME); + PrismAsserts.assertDefinition(objectSidDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_OBJECT_SID_NAME), + PrimitiveType.XSD_STRING, 0, 1); + assertTrue("objectSid read", objectSidDef.canRead()); + assertFalse("objectSid modify", objectSidDef.canModify()); + assertFalse("objectSid add", objectSidDef.canAdd()); + + ResourceAttributeDefinition lastLogonDef = accountObjectClassDefinition.findAttributeDefinition("lastLogon"); + PrismAsserts.assertDefinition(lastLogonDef, new QName(MidPointConstants.NS_RI, "lastLogon"), + PrimitiveType.XSD_LONG, 0, 1); + assertTrue("lastLogonDef read", lastLogonDef.canRead()); + assertTrue("lastLogonDef modify", lastLogonDef.canModify()); + assertTrue("lastLogonDef add", lastLogonDef.canAdd()); + + ResourceAttributeDefinition proxyAddressesDef = accountObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_PROXY_ADDRESSES_NAME); + PrismAsserts.assertDefinition(proxyAddressesDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_PROXY_ADDRESSES_NAME), + PrimitiveType.XSD_STRING, 0, -1); + assertTrue("proxyAddressesDef read", proxyAddressesDef.canRead()); + assertTrue("proxyAddressesDef modify", proxyAddressesDef.canModify()); + assertTrue("proxyAddressesDef add", proxyAddressesDef.canAdd()); + // TODO: proxyAddressesDef.getMatchingRuleQName() + + return accountObjectClassDefinition; + } + + default void assertExchangeSchema(PrismObject resource, QName accountObjectClassQName, PrismContext prismContext) throws SchemaException { + + ResourceSchema resourceSchema = RefinedResourceSchema.getResourceSchema(resource, prismContext); + assertExchangeSchema(resourceSchema, accountObjectClassQName); + + RefinedResourceSchema refinedSchema = RefinedResourceSchema.getRefinedSchema(resource); + assertExchangeSchema(refinedSchema, accountObjectClassQName); + } + + default void assertExchangeSchema(ResourceSchema resourceSchema, QName accountObjectClassQName) { + ObjectClassComplexTypeDefinition msExchBaseClassObjectClassDefinition = resourceSchema.findObjectClassDefinition(OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME); + assertNotNull("No definition for object class " + OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME, msExchBaseClassObjectClassDefinition); + display("Object class " + OBJECT_CLASS_MS_EXCH_BASE_CLASS_QNAME + " def", msExchBaseClassObjectClassDefinition); + + ResourceAttributeDefinition msExchHideFromAddressListsDef = msExchBaseClassObjectClassDefinition.findAttributeDefinition(ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); + PrismAsserts.assertDefinition(msExchHideFromAddressListsDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME), DOMUtil.XSD_BOOLEAN, 0, 1); + assertTrue("msExchHideFromAddressLists read", msExchHideFromAddressListsDef.canRead()); + assertTrue("msExchHideFromAddressLists modify", msExchHideFromAddressListsDef.canModify()); + assertTrue("msExchHideFromAddressLists add", msExchHideFromAddressListsDef.canAdd()); + + ObjectClassComplexTypeDefinition accountObjectClassDef = resourceSchema.findObjectClassDefinition(accountObjectClassQName); + assertNotNull("No definition for object class " + accountObjectClassQName, accountObjectClassDef); + display("Object class " + accountObjectClassQName + " def", accountObjectClassDef); + + ResourceAttributeDefinition accountMsExchHideFromAddressListsDef = accountObjectClassDef.findAttributeDefinition(ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME); + PrismAsserts.assertDefinition(accountMsExchHideFromAddressListsDef, new QName(MidPointConstants.NS_RI, ATTRIBUTE_MS_EXCH_HIDE_FROM_ADDRESS_LISTS_NAME), DOMUtil.XSD_BOOLEAN, 0, 1); + assertTrue("msExchHideFromAddressLists read", accountMsExchHideFromAddressListsDef.canRead()); + assertTrue("msExchHideFromAddressLists modify", accountMsExchHideFromAddressListsDef.canModify()); + assertTrue("msExchHideFromAddressLists add", accountMsExchHideFromAddressListsDef.canAdd()); + } + + default long getWin32Filetime(long millis) { + return (millis + 11644473600000L) * 10000L; + } + + default void display(String title, DebugDumpable value) { + PrismTestUtil.display(title, value); + } + + default void display(String title, Object value) { + PrismTestUtil.display(title, value); + } +} From 6f9572188931f3528d8c279515728276191f1bd1 Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 10 Mar 2020 10:20:23 +0100 Subject: [PATCH 4/5] LDAP connector 3.0-M2 --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index b9064b88a29..b83d517acb6 100644 --- a/pom.xml +++ b/pom.xml @@ -892,7 +892,7 @@ com.evolveum.polygon connector-ldap - 3.0-SNAPSHOT + 3.0-M2 From 1ca953b6168978d116801e455800680e87e0fb2a Mon Sep 17 00:00:00 2001 From: Radovan Semancik Date: Tue, 10 Mar 2020 10:39:05 +0100 Subject: [PATCH 5/5] Post-merge fix --- .../testing/conntest/ad/AbstractAdLdapMultidomainTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java index 537362e9d1d..4bd9b09a60d 100644 --- a/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java +++ b/testing/conntest/src/test/java/com/evolveum/midpoint/testing/conntest/ad/AbstractAdLdapMultidomainTest.java @@ -2242,7 +2242,7 @@ public void test901SyncAddAccountHt() throws Exception { protected void assertStepSyncToken(String syncTaskOid, int step, long tsStart, long tsEnd) throws ObjectNotFoundException, SchemaException { OperationResult result = createOperationResult("assertStepSyncToken"); - Task task = taskManager.getTask(syncTaskOid, result); + Task task = taskManager.getTaskPlain(syncTaskOid, result); PrismProperty syncTokenProperty = task.getExtensionPropertyOrClone(SchemaConstants.SYNC_TOKEN); assertNotNull("No sync token", syncTokenProperty); assertNotNull("No sync token value", syncTokenProperty.getRealValue());