diff --git a/.gitignore b/.gitignore index 0848cc3ed..b298de799 100644 --- a/.gitignore +++ b/.gitignore @@ -412,3 +412,6 @@ beacon/spring/out # macOS jenv .java-version +/a.xml +/application.yml +/backend/src/test/resources/conf/deletem.xml diff --git a/Jenkinsfile b/Jenkinsfile index 3ae5f4595..60f82aca1 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -16,32 +16,6 @@ pipeline { } } } - - stage('Build Docker images') { - when { - expression { - return GIT_BRANCH in ['master'] - } - } - steps { - sh '''./gradlew docker -x test - ''' - } - } - - stage('Deploy') { - when { - expression { - return GIT_BRANCH in ['master'] - } - } - steps { - sh ''' - docker stop shibui || true && docker rm shibui || true - docker run -d --restart always --name shibui -p 8080:8080 -v /etc/shibui:/conf -v /etc/shibui/application.yml:/application.yml -m 2GB --memory-swap=4GB --entrypoint /usr/bin/java unicon/shibui:latest -Xmx1G -jar app.war - ''' - } - } } post { failure { @@ -54,4 +28,4 @@ pipeline { cleanWs() } } -} +} \ No newline at end of file diff --git a/README.md b/README.md index bb1ede559..c34cf18bc 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ ## Requirements_ -* Java 8 (note that ONLY Java 8 is supported at this time; other later versions might work) +* Java 11 (note that ONLY Java 11 is supported at this time; other later versions might work) ## Running There are currently 2 ways to run the application: -1. As an executable -1. deployed in a Java Servlet 3.0 container +1. As an executable WAR using Java +1. deployed in a Java Servlet 3.0 container such as Tomcat or Jetty Note that some features require encoded slashes in the URL. In tomcat (which is embedded in the war), this can be allowed with: @@ -57,6 +57,7 @@ beginning with `#` are commented out. # Server Configuration #server.port=8080 + # Logging Configuration #logging.config=classpath:log4j2.xml #logging.level.org.springframework.web=ERROR @@ -110,4 +111,10 @@ spring.profiles.active=default # Password for the default user. If not set, a password will be generated at startup #shibui.default-password= -``` + +springdoc.use-management-port=true +springdoc.pathsToMatch=/entities, /api/** +# This property enables the openapi and swagger-ui endpoints to be exposed beneath the actuator base path. +management.endpoints.web.exposure.include=openapi, swagger-ui +management.server.port=9090 +``` \ No newline at end of file diff --git a/backend/build.gradle b/backend/build.gradle index f41778d28..71ab2c763 100644 --- a/backend/build.gradle +++ b/backend/build.gradle @@ -1,11 +1,11 @@ plugins { - id 'groovy' - id 'war' - id 'org.springframework.boot' version '2.4.2' - id 'com.gorylenko.gradle-git-properties' version '1.4.21' - id 'io.freefair.lombok' version '5.3.0' - id 'com.palantir.docker' version '0.28.0' - id 'com.palantir.docker-run' version '0.28.0' + id "groovy" + id "war" + id "org.springframework.boot" + id "io.freefair.lombok" + id "com.gorylenko.gradle-git-properties" version "1.4.21" + id "com.palantir.docker" version "0.28.0" + id "com.palantir.docker-run" version "0.28.0" } apply plugin: 'io.spring.dependency-management' @@ -14,18 +14,26 @@ apply plugin: 'jacoco' sourceCompatibility = 11 targetCompatibility = 11 +test { + useJUnitPlatform() // Needed by spock to find specification tests +} + repositories { jcenter() maven { url 'https://build.shibboleth.net/nexus/content/groups/public' artifactUrls = ['https://build.shibboleth.net/nexus/content/repositories/thirdparty-snapshots'] } + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } mavenLocal() + mavenCentral() } configurations.all { resolutionStrategy { - force 'org.cryptacular:cryptacular:1.1.3' + force "org.cryptacular:cryptacular:${project.'cryptacularVersion'}" eachDependency { details -> if (details.requested.group == 'org.seleniumhq.selenium' && details.requested.name != 'htmlunit-driver') { @@ -105,7 +113,7 @@ bootWar { } springBoot { - mainClassName = 'edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication' + mainClass = 'edu.internet2.tier.shibboleth.admin.ui.ShibbolethUiApplication' buildInfo() } @@ -114,24 +122,22 @@ generateLombokConfig.enabled = false dependencies { // opensaml deps ['opensaml-saml-api', 'opensaml-saml-impl', 'opensaml-xmlsec-api', 'opensaml-xmlsec-impl'].each { - compile "org.opensaml:${it}:${project.'opensaml.version'}" + compile "org.opensaml:${it}:${project.'opensamlVersion'}" } -// Left here to save time later - when pac4j is/was updated, I needed all of these to get the runtime right with the SAML2 client -// runtimeOnly "org.bouncycastle:bcprov-jdk15on:1.69" -// runtimeOnly "org.bouncycastle:bcprov-ext-jdk15on:1.69" -// runtimeOnly "org.bouncycastle:bcutil-jdk15on:1.69" -// runtimeOnly "org.bouncycastle:bcpkix-jdk15on:1.69" - + runtimeOnly "org.bouncycastle:bcprov-jdk15on:1.70" + runtimeOnly "org.bouncycastle:bcprov-ext-jdk15on:1.70" + runtimeOnly "org.bouncycastle:bcutil-jdk15on:1.70" + runtimeOnly "org.bouncycastle:bcpkix-jdk15on:1.70" // shibboleth idp deps ['idp-profile-spring', 'idp-profile-api'].each { - compile "net.shibboleth.idp:${it}:${project.'shibboleth.version'}" + compile "net.shibboleth.idp:${it}:${project.'shibbolethVersion'}" } // hibernate deps ['hibernate-core'].each { - compile "org.hibernate:${it}:${project.'hibernate.version'}" + compile "org.hibernate:${it}:${project.'hibernateVersion'}" } // spring boot auto-config starters @@ -139,27 +145,25 @@ dependencies { compile "org.springframework.boot:spring-boot-${it}" } // To override older version with security issue - https://www.lunasec.io/docs/blog/log4j-zero-day/ - implementation 'org.apache.logging.log4j:log4j-to-slf4j:2.15.0' - implementation 'org.apache.logging.log4j:log4j-api:2.15.0' + implementation "org.apache.logging.log4j:log4j-to-slf4j:${project.'log4JVersion'}" + implementation "org.apache.logging.log4j:log4j-api:${project.'log4JVersion'}" // TODO: figure out what this should really be - runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat' + runtimeOnly "org.springframework.boot:spring-boot-starter-tomcat:${project.'springbootVersion'}" //Spring Configuration Annotation Processor - makes IntelliJ happy about @ConfigurationProperties - compileOnly "org.springframework.boot:spring-boot-configuration-processor" + compileOnly "org.springframework.boot:spring-boot-configuration-processor:${project.'springbootVersion'}" // lucene deps ['core', 'analyzers-common', 'queryparser'].each { - compile "org.apache.lucene:lucene-${it}:${project.'lucene.version'}" + compile "org.apache.lucene:lucene-${it}:${project.'luceneVersion'}" } compile "org.liquibase:liquibase-core" compile group: 'org.jadira.usertype', name: 'usertype.core', version: '6.0.1.GA' //For easy data mocking capabilities - compile 'net.andreinc.mockneat:mockneat:0.1.4' - - compile 'org.codehaus.groovy:groovy-all:3.0.7' + compile 'net.andreinc:mockneat:0.4.7' //So it works on Java 9 without explicitly requiring to load that module (needed by Hibernate) runtimeOnly 'javax.xml.bind:jaxb-api:2.3.0' @@ -167,22 +171,26 @@ dependencies { runtimeOnly 'org.glassfish.jaxb:jaxb-runtime:2.3.0' compile "com.h2database:h2" - runtimeOnly "org.postgresql:postgresql:42.2.20" - runtimeOnly 'org.mariadb.jdbc:mariadb-java-client:2.2.0' - runtimeOnly 'mysql:mysql-connector-java:5.1.48' - - //Swagger - compile 'io.springfox:springfox-swagger2:2.9.2' - compile 'io.springfox:springfox-swagger-ui:2.9.2' - - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.springframework.security:spring-security-test" - testCompile "org.spockframework:spock-core:1.3-groovy-2.5" - testCompile "org.spockframework:spock-spring:1.3-groovy-2.5" + runtimeOnly "org.postgresql:postgresql:${project.'postgresVersion'}" + runtimeOnly "org.mariadb.jdbc:mariadb-java-client:${project.'mariadbVersion'}" + runtimeOnly "mysql:mysql-connector-java:${project.'mysqlVersion'}" + runtimeOnly "com.microsoft.sqlserver:mssql-jdbc:${project.'sqlserverVersion'}" + + //Swagger 3 + implementation 'org.springdoc:springdoc-openapi-ui:1.6.8' + + compile 'org.codehaus.groovy:groovy-all:3.0.10' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" + testImplementation "org.spockframework:spock-spring" + + testCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + testCompile "org.springframework.security:spring-security-test:${project.'springSecurityVersion'}" + testCompile 'org.skyscreamer:jsonassert:1.5.0' testCompile "org.xmlunit:xmlunit-core:2.5.1" testRuntime 'cglib:cglib-nodep:3.2.5' - compile "net.shibboleth.ext:spring-extensions:5.4.0" + compile "net.shibboleth.ext:spring-extensions:6.2.0" //JSON schema generator testCompile 'com.kjetland:mbknor-jackson-jsonschema_2.12:1.0.29' @@ -196,18 +204,21 @@ dependencies { integrationTestCompile configurations.compile integrationTestCompile 'com.saucelabs:sebuilder-interpreter:1.0.6' integrationTestCompile 'jp.vmi:selenese-runner-java:3.20.0' - integrationTestCompile "org.springframework.boot:spring-boot-starter-test" - integrationTestCompile "org.springframework.security:spring-security-test" - integrationTestCompile "org.spockframework:spock-core:1.3-groovy-2.5" - integrationTestCompile "org.spockframework:spock-spring:1.3-groovy-2.5" + integrationTestCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + integrationTestCompile "org.springframework.security:spring-security-test:${project.'springSecurityVersion'}" + integrationTestCompile platform("org.spockframework:spock-bom:2.1-groovy-3.0") + integrationTestCompile "org.spockframework:spock-core" + integrationTestCompile "org.spockframework:spock-spring" // CSV file support - compile 'com.opencsv:opencsv:4.4' + compile 'com.opencsv:opencsv:4.4', { + exclude group: 'commons-collections' + } - testCompile 'org.skyscreamer:jsonassert:1.5.0' + compile "org.apache.commons:commons-collections4:${project.'commonsCollections4Version'}" // Envers for persistent entities versioning - compile 'org.hibernate:hibernate-envers' + compile "org.hibernate:hibernate-envers:${project.'hibernateVersion'}" //Pacj4 sub-project runtimeOnly project(':pac4j-module') @@ -219,7 +230,9 @@ dependencies { enversTestCompile sourceSets.test.output enversTestCompile configurations.compile enversTestCompile configurations.testCompile + enversTestCompile configurations.testImplementation + enversTestRuntime configurations.testImplementation enversTestRuntime configurations.runtime enversTestRuntime configurations.testRuntime } @@ -230,6 +243,7 @@ task copyUI(type: Copy) { } task integrationTest(type: Test) { + useJUnitPlatform() group = 'verification' description = 'Run various integration tests' dependsOn 'copyUI' @@ -241,12 +255,14 @@ task integrationTest(type: Test) { } task enversTest(type: Test) { + useJUnitPlatform() group = 'verification' description = 'Run tests pertaing to envers versioning engine' testClassesDirs = sourceSets.enversTest.output.classesDirs classpath = sourceSets.enversTest.runtimeClasspath systemProperties = System.properties systemProperties['user.dir'] = workingDir + useJUnitPlatform() } check { diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEnversVersioningTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEnversVersioningTests.groovy index b468a2ffa..6d976a033 100644 --- a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEnversVersioningTests.groovy +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/envers/MetadataResolverEnversVersioningTests.groovy @@ -14,7 +14,6 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetad import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.TemplateScheme -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.autoconfigure.domain.EntityScan @@ -269,7 +268,7 @@ class MetadataResolverEnversVersioningTests extends Specification { when: ResourceBackedMetadataResolver resolver = new ResourceBackedMetadataResolver(name: 'rbmr').with { it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes(taskTimerRef: 'taskTimerRef') - it.classpathMetadataResource = new ClasspathMetadataResource(file: 'metadata.xml') + it.classpathMetadataResource = new ClasspathMetadataResource(fileResource: 'metadata.xml') it } @@ -283,7 +282,7 @@ class MetadataResolverEnversVersioningTests extends Specification { resolverHistory.size() == 1 getTargetEntityForRevisionIndex(resolverHistory, 0).name == 'rbmr' getTargetEntityForRevisionIndex(resolverHistory, 0).reloadableMetadataResolverAttributes.taskTimerRef == 'taskTimerRef' - getTargetEntityForRevisionIndex(resolverHistory, 0).classpathMetadataResource.file == 'metadata.xml' + getTargetEntityForRevisionIndex(resolverHistory, 0).classpathMetadataResource.fileResource == 'metadata.xml' getRevisionEntityForRevisionIndex(resolverHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(resolverHistory, 0).timestamp > 0L getModifiedEntityNames(resolverHistory, 0).sort() == expectedModifiedPersistentEntities.sort() @@ -291,7 +290,7 @@ class MetadataResolverEnversVersioningTests extends Specification { when: resolver.name = 'rbmrUPDATED' resolver.reloadableMetadataResolverAttributes.taskTimerRef = 'taskTimerRefUPDATED' - resolver.classpathMetadataResource.file = 'metadataUPDATED.xml' + resolver.classpathMetadataResource.fileResource = 'metadataUPDATED.xml' resolverHistory = updateAndGetRevisionHistoryOfMetadataResolver(resolver, metadataResolverRepository, @@ -303,7 +302,7 @@ class MetadataResolverEnversVersioningTests extends Specification { resolverHistory.size() == 2 getTargetEntityForRevisionIndex(resolverHistory, 1).name == 'rbmrUPDATED' getTargetEntityForRevisionIndex(resolverHistory, 1).reloadableMetadataResolverAttributes.taskTimerRef == 'taskTimerRefUPDATED' - getTargetEntityForRevisionIndex(resolverHistory, 1).classpathMetadataResource.file == 'metadataUPDATED.xml' + getTargetEntityForRevisionIndex(resolverHistory, 1).classpathMetadataResource.fileResource == 'metadataUPDATED.xml' getRevisionEntityForRevisionIndex(resolverHistory, 1).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(resolverHistory, 1).timestamp > 0L getModifiedEntityNames(resolverHistory, 1).sort() == expectedModifiedPersistentEntities.sort() @@ -311,8 +310,8 @@ class MetadataResolverEnversVersioningTests extends Specification { //Check the original revision is intact getTargetEntityForRevisionIndex(resolverHistory, 0).name == 'rbmr' getTargetEntityForRevisionIndex(resolverHistory, 0).reloadableMetadataResolverAttributes.taskTimerRef == 'taskTimerRef' - getTargetEntityForRevisionIndex(resolverHistory, 0).classpathMetadataResource.file == 'metadata.xml' + getTargetEntityForRevisionIndex(resolverHistory, 0).classpathMetadataResource.fileResource == 'metadata.xml' getRevisionEntityForRevisionIndex(resolverHistory, 0).principalUserName == 'anonymousUser' getRevisionEntityForRevisionIndex(resolverHistory, 0).timestamp > 0L } -} +} \ No newline at end of file diff --git a/backend/src/integration/groovy/edu/internet2/tier/shibboleth/admin/ui/SeleniumSIDETest.groovy b/backend/src/integration/groovy/edu/internet2/tier/shibboleth/admin/ui/SeleniumSIDETest.groovy index f60242089..14a65b52b 100644 --- a/backend/src/integration/groovy/edu/internet2/tier/shibboleth/admin/ui/SeleniumSIDETest.groovy +++ b/backend/src/integration/groovy/edu/internet2/tier/shibboleth/admin/ui/SeleniumSIDETest.groovy @@ -37,6 +37,9 @@ class SeleniumSIDETest extends Specification { it.remoteUrl = 'http://selenium-hub:4444/wd/hub' it.remoteBrowser = 'firefox' } + if (System.properties.getProperty('selenium.port')) { + this.setRandomPort("${System.properties.getProperty('selenium.port')}" as int) + } if (System.properties.getProperty('selenium.host')) { it.baseurl = "http://${System.properties.getProperty('selenium.host')}:${this.randomPort}" } else { @@ -74,6 +77,9 @@ class SeleniumSIDETest extends Specification { it.remoteUrl = 'http://selenium-hub:4444/wd/hub' it.remoteBrowser = 'firefox' } + if (System.properties.getProperty('selenium.port')) { + this.setRandomPort("${System.properties.getProperty('selenium.port')}" as int) + } if (System.properties.getProperty('selenium.host')) { it.baseurl = "http://${System.properties.getProperty('selenium.host')}:${this.randomPort}" } else { @@ -117,7 +123,7 @@ class SeleniumSIDETest extends Specification { 'SHIBUI-1335: Verify Filesystem Metadata Provider' | '/SHIBUI-1335-2.side' 'SHIBUI-1335: Verify Local Dynamic Metadata Provider' | '/SHIBUI-1335-3.side' 'SHIBUI-1335: Verify Dynamic HTTP Metadata Provider Filters' | '/SHIBUI-1335-4.side' - 'SHIBUI-1361: Verify dates display in proper format' | '/SHIBUI-1361.side' + 'SHIBUI-1361: Verify dates display in proper format' | '/SHIBUI-1361.side' // Note that this script WILL NOT PASS in the Selenium IDE due to it thinking there is a syntax error where there is none. 'SHIBUI-1385: Restore a metadata source version' | '/SHIBUI-1385-1.side' 'SHIBUI-1385: Restore a metadata provider version' | '/SHIBUI-1385-2.side' 'SHIBUI-1391: Regex Validation' | '/SHIBUI-1391.side' @@ -126,7 +132,14 @@ class SeleniumSIDETest extends Specification { 'SHIBUI-1503: Non-admin can create metadata source' | '/SHIBUI-1503-1.side' 'SHIBUI-1503: User can be deleted' | '/SHIBUI-1503-2.side' 'SHIBUI-1503: User can be enabled' | '/SHIBUI-1503-3.side' - 'SHIBUI-2052: Logged in user & role appear on dashboard' | '/SHIBUI-2052.side' + 'SHIBUI-1732: Create, use, and delete CEA String' | '/SHIBUI-1732-1.side' + 'SHIBUI-1732: Create, use, and delete CEA Boolean' | '/SHIBUI-1732-2.side' + 'SHIBUI-1732: Create, use, and delete CEA List' | '/SHIBUI-1732-3.side' + 'SHIBUI-1732: Create, use, and delete CEA Long' | '/SHIBUI-1732-4.side' + 'SHIBUI-1732: Create, use, and delete CEA Double' | '/SHIBUI-1732-5.side' + 'SHIBUI-1732: Create, use, and delete CEA Duration' | '/SHIBUI-1732-6.side' + 'SHIBUI-1732: Create, use, and delete CEA Spring Bean' | '/SHIBUI-1732-7.side' + 'SHIBUI-1392: Verify provider with script filter is persistable' | '/SHIBUI-1392.side' 'SHIBUI-1740: Group can be created, edited, deleted' | '/SHIBUI-1740-1.side' 'SHIBUI-1740: Verify dev profile group membership' | '/SHIBUI-1740-2.side' 'SHIBUI-1740: Verify admin-owned resource not visible to nonadmins' | '/SHIBUI-1740-3.side' @@ -138,14 +151,8 @@ class SeleniumSIDETest extends Specification { 'SHIBUI-1744: Verify attribute bundle CRUD operations' | '/SHIBUI-1744-1.side' 'SHIBUI-1744: Verify attribute bundles in metadata sources' | '/SHIBUI-1744-2.side' 'SHIBUI-1744: Verify attribute bundles in entity attribute filters' | '/SHIBUI-1744-3.side' + 'SHIBUI-2052: Logged in user & role appear on dashboard' | '/SHIBUI-2052.side' 'SHIBUI-2116: Verify entity attribute bundle highlights' | '/SHIBUI-2116.side' // Note that this script WILL NOT PASS in the Selenium IDE due to ${driver} not being set (it is provided by this groovy script). - 'SHIBUI-1732: Create, use, and delete CEA String' | '/SHIBUI-1732-1.side' - 'SHIBUI-1732: Create, use, and delete CEA Boolean' | '/SHIBUI-1732-2.side' - 'SHIBUI-1732: Create, use, and delete CEA List' | '/SHIBUI-1732-3.side' - 'SHIBUI-1732: Create, use, and delete CEA Long' | '/SHIBUI-1732-4.side' - 'SHIBUI-1732: Create, use, and delete CEA Double' | '/SHIBUI-1732-5.side' - 'SHIBUI-1732: Create, use, and delete CEA Duration' | '/SHIBUI-1732-6.side' - 'SHIBUI-1732: Create, use, and delete CEA Spring Bean' | '/SHIBUI-1732-7.side' - 'SHIBUI-1392: Verify provider with script filter is persistable' | '/SHIBUI-1392.side' // Something about this test breaks all the other ones after it + 'SHIBUI-2269: Verify XML generation of external filters' | '/SHIBUI-2269.side' } } diff --git a/backend/src/integration/resources/SHIBUI-1281.side b/backend/src/integration/resources/SHIBUI-1281.side index ce3222850..06e730ecd 100644 --- a/backend/src/integration/resources/SHIBUI-1281.side +++ b/backend/src/integration/resources/SHIBUI-1281.side @@ -626,9 +626,12 @@ "id": "c1534880-c4e5-4fbd-b200-c28f9f556ab9", "comment": "", "command": "click", - "target": "css=div.p-0.m-0.container-fluid > div:nth-child(2) > div > div.mr-2.flex-grow-1.undefined > div > div:nth-child(1) > div > div > button", + "target": "css=.is-invalid > .toggle-button", "targets": [ - ["css=.is-invalid .svg-inline--fa", "css:finder"] + ["css=.is-invalid > .toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div[2]/div/div/div/div/div/div/button", "xpath:position"] ], "value": "" }, { @@ -678,12 +681,12 @@ "id": "97a98737-862d-4567-8b20-c5c991444ed0", "comment": "", "command": "click", - "target": "css=div.p-0.m-0.container-fluid > div:nth-child(3) > div > div.mr-2.flex-grow-1.undefined > div > div:nth-child(1) > div > div > button", + "target": "css=.is-invalid > .toggle-button", "targets": [ - ["css=#\\/serviceProviderSsoDescriptor\\/nameIdFormats\\/2-container .btn", "css:finder"], - ["xpath=(//button[@type='button'])[4]", "xpath:attributes"], - ["xpath=//div[@id='/serviceProviderSsoDescriptor/nameIdFormats/2-container']/div/div/button", "xpath:idRelative"], - ["xpath=//li[3]/div/sf-form-element/div/sf-widget-chooser/datalist-component/div/auto-complete/div/div/div/button", "xpath:position"] + ["css=.is-invalid > .toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[14]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div[2]/div/div/div/div/div/div[2]/div[3]/div/div/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[3]/div/div/div/div/div/div/button", "xpath:position"] ], "value": "" }, { @@ -731,12 +734,12 @@ "id": "e2e8d5d4-8b6a-42d5-9fe7-abb8a84216e3", "comment": "", "command": "click", - "target": "css=div.p-0.m-0.container-fluid > div:nth-child(4) > div > div.mr-2.flex-grow-1.undefined > div > div:nth-child(1) > div > div > button", + "target": "css=.is-invalid > .toggle-button", "targets": [ - ["css=#\\/serviceProviderSsoDescriptor\\/nameIdFormats\\/3-container .btn", "css:finder"], - ["xpath=(//button[@type='button'])[5]", "xpath:attributes"], - ["xpath=//div[@id='/serviceProviderSsoDescriptor/nameIdFormats/3-container']/div/div/button", "xpath:idRelative"], - ["xpath=//li[4]/div/sf-form-element/div/sf-widget-chooser/datalist-component/div/auto-complete/div/div/div/button", "xpath:position"] + ["css=.is-invalid > .toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[16]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div[2]/div/div/div/div/div/div[2]/div[4]/div/div/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[4]/div/div/div/div/div/div/button", "xpath:position"] ], "value": "" }, { @@ -778,10 +781,11 @@ "id": "23fd8856-32df-48ed-a198-a74e8ca71b10", "comment": "", "command": "type", - "target": "css=div.p-0.m-0.container-fluid > div:nth-child(5) > div > div.mr-2.flex-grow-1.undefined > div > div:nth-child(1) > div > div > div:nth-child(1) > input.rbt-input-main.form-control.rbt-input", + "target": "id=option-selector-root_serviceProviderSsoDescriptor_nameIdFormats_4", "targets": [ - ["css=.focus", "css:finder"], - ["xpath=(//input[@value=''])[5]", "xpath:attributes"], + ["id=option-selector-root_serviceProviderSsoDescriptor_nameIdFormats_4", "id"], + ["css=#option-selector-root_serviceProviderSsoDescriptor_nameIdFormats_4", "css:finder"], + ["xpath=//input[@id='option-selector-root_serviceProviderSsoDescriptor_nameIdFormats_4']", "xpath:attributes"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div[2]/div/div/div/div/div/div[2]/div[5]/div/div/div/div/div/div/div/input", "xpath:idRelative"], ["xpath=//div[5]/div/div/div/div/div/div/div/input", "xpath:position"] ], @@ -1970,7 +1974,7 @@ ["xpath=//metadata-configuration[@id='configuration']/div/section[9]/div/div[2]/object-property/array-property/div/div[5]/div/span", "xpath:idRelative"], ["xpath=//div/div[5]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "1406d7e4-907d-4359-8de8-a40206f0993e", "comment": "", @@ -1985,11 +1989,12 @@ "id": "4e0fa4f5-817f-41fb-9885-60f37b699436", "comment": "", "command": "waitForElementVisible", - "target": "css=tr > .text-right", + "target": "css=td:nth-child(1)", "targets": [ - ["css=tr > .text-right", "css:finder"], - ["xpath=//td[5]", "xpath:position"], - ["xpath=//td[contains(.,'Enabled')]", "xpath:innerText"] + ["css=.lead", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div/span", "xpath:idRelative"], + ["xpath=//section/div/div/span", "xpath:position"], + ["xpath=//span[contains(.,'Current Metadata Sources')]", "xpath:innerText"] ], "value": "10000" }, { @@ -2106,7 +2111,21 @@ "target": "css=td:nth-child(2)", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "d2caeac4-7520-4e3c-96b1-840610b6983c", diff --git a/backend/src/integration/resources/SHIBUI-1311.side b/backend/src/integration/resources/SHIBUI-1311.side index 01edf7f02..1004e1bb6 100644 --- a/backend/src/integration/resources/SHIBUI-1311.side +++ b/backend/src/integration/resources/SHIBUI-1311.side @@ -461,42 +461,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "232da257-962f-4a4b-8213-038ef90c96c3", - "comment": "", - "command": "click", - "target": "css=.btn-outline-secondary", - "targets": [ - ["css=.btn-outline-secondary", "css:finder"], - ["xpath=(//button[@type='button'])[2]", "xpath:attributes"], - ["xpath=//div[@id='/metadataFilters/RequiredValidUntil/maxValidityInterval-container']/div/div/button", "xpath:idRelative"], - ["xpath=//div/button", "xpath:position"], - ["xpath=//button[contains(.,'Toggle Dropdown')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "236d7114-a227-4087-8aa0-2851acfe19ac", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b8d999f1-0c59-4a9a-9991-91d222f52b8e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_metadataFilters_0_maxValidityInterval", "id"], + ["css=#root_metadataFilters_0_maxValidityInterval", "css:finder"], + ["xpath=//input[@id='root_metadataFilters_0_maxValidityInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] ], - "value": "" + "value": "PT1H" }, { "id": "8af1abb5-2c7a-4a4c-a8f7-0eb287100dde", "comment": "", @@ -1032,17 +1009,19 @@ "id": "b799fede-c85b-4bd3-8e03-347f8a7d188a", "comment": "", "command": "click", - "target": "css=tr:nth-child(2) .fa-chevron-circle-up", + "target": "css=tr:nth-child(2) .px-1:nth-child(3)", "targets": [ - ["css=tr:nth-child(2) .fa-chevron-circle-up", "css:finder"], - ["xpath=//tr[2]/td/div/button[2]/i", "xpath:position"] + ["css=tr:nth-child(2) .px-1:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/div/div/table/tbody/tr[2]/td/div/button[2]", "xpath:idRelative"], + ["xpath=//tr[2]/td/div/button[2]", "xpath:position"] ], "value": "" }, { "id": "dc866249-3245-4baa-af0e-55af28d270cf", "comment": "", "command": "pause", - "target": "5000", + "target": "7000", "targets": [], "value": "" }, { @@ -1061,10 +1040,12 @@ "id": "664aafa3-9f6f-4eab-9eb6-a4d1a8344c5c", "comment": "", "command": "click", - "target": "css=tr:nth-child(2) .fa-chevron-circle-up", + "target": "css=tr:nth-child(2) .px-1:nth-child(3)", "targets": [ - ["css=tr:nth-child(2) .fa-chevron-circle-up", "css:finder"], - ["xpath=//tr[2]/td/div/button[2]/i", "xpath:position"] + ["css=tr:nth-child(2) .px-1:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/div/div/table/tbody/tr[2]/td/div/button[2]", "xpath:idRelative"], + ["xpath=//tr[2]/td/div/button[2]", "xpath:position"] ], "value": "" }, { @@ -1079,6 +1060,20 @@ ["xpath=//td[contains(.,'Disabled')]", "xpath:innerText"] ], "value": "" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1333.side b/backend/src/integration/resources/SHIBUI-1333.side index bdc73b6ce..4a61515ff 100644 --- a/backend/src/integration/resources/SHIBUI-1333.side +++ b/backend/src/integration/resources/SHIBUI-1333.side @@ -1956,7 +1956,7 @@ ["xpath=//metadata-configuration[@id='configuration']/div/section[9]/div/div[2]/object-property/array-property/div/div[5]/div/span", "xpath:idRelative"], ["xpath=//div/div[5]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "1406d7e4-907d-4359-8de8-a40206f0993e", "comment": "", @@ -2253,8 +2253,22 @@ ["xpath=//metadata-configuration[@id='configuration']/div/section[8]/div/div[2]/object-property/array-property/div/div/div[3]/div/span", "xpath:idRelative"], ["xpath=//section[8]/div/div[2]/object-property/array-property/div/div/div[3]/div/span", "xpath:position"] ], - "value": "True" - }] + "value": "true" + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "d2caeac4-7520-4e3c-96b1-840610b6983c", diff --git a/backend/src/integration/resources/SHIBUI-1334-1.side b/backend/src/integration/resources/SHIBUI-1334-1.side index 9187fd0bd..f0491037d 100644 --- a/backend/src/integration/resources/SHIBUI-1334-1.side +++ b/backend/src/integration/resources/SHIBUI-1334-1.side @@ -1966,7 +1966,7 @@ ["xpath=//metadata-configuration[@id='configuration']/div/section[9]/div/div[2]/object-property/array-property/div/div[5]/div/span", "xpath:idRelative"], ["xpath=//div/div[5]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "a1050ebe-55c5-4eac-8d12-615f3ff1cd72", "comment": "", @@ -2005,11 +2005,15 @@ "id": "4e0fa4f5-817f-41fb-9885-60f37b699436", "comment": "", "command": "waitForElementVisible", - "target": "css=tr > .text-right", + "target": "linkText=Test Provider", "targets": [ - ["css=tr > .text-right", "css:finder"], - ["xpath=//td[5]", "xpath:position"], - ["xpath=//td[contains(.,'Enabled')]", "xpath:innerText"] + ["linkText=Test Provider", "linkText"], + ["css=.align-middle > a", "css:finder"], + ["xpath=//a[contains(text(),'Test Provider')]", "xpath:link"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/div/div/table/tbody/tr/td/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/source/bb384f9e-a87d-4e46-aa68-81d46b7c43e1/configuration/options')]", "xpath:href"], + ["xpath=//td/a", "xpath:position"], + ["xpath=//a[contains(.,'Test Provider')]", "xpath:innerText"] ], "value": "10000" }, { @@ -2277,7 +2281,7 @@ ["xpath=//metadata-configuration[@id='configuration']/div/section[8]/div/div[2]/object-property/array-property/div/div/div[3]/div/span", "xpath:idRelative"], ["xpath=//section[8]/div/div[2]/object-property/array-property/div/div/div[3]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "2c46cdcd-d5a5-47fe-aa7b-0120fd2fcfc9", "comment": "", @@ -2713,7 +2717,21 @@ ["xpath=//section[2]/div/div[2]/div[2]/div/div/div/span[3]", "xpath:position"] ], "value": "Display Name" - }] + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "d2caeac4-7520-4e3c-96b1-840610b6983c", diff --git a/backend/src/integration/resources/SHIBUI-1334-2.side b/backend/src/integration/resources/SHIBUI-1334-2.side index 37a6992a0..325fd6166 100644 --- a/backend/src/integration/resources/SHIBUI-1334-2.side +++ b/backend/src/integration/resources/SHIBUI-1334-2.side @@ -448,41 +448,13 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "232da257-962f-4a4b-8213-038ef90c96c3", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "d30605a0-013c-403d-86ab-780f471fe159", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b8d999f1-0c59-4a9a-9991-91d222f52b8e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", - "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", + "targets": [], + "value": "PT1H" }, { "id": "8af1abb5-2c7a-4a4c-a8f7-0eb287100dde", "comment": "", @@ -966,60 +938,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "78967fb5-8f61-46ce-9c14-9b6ceb12b03a", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(2) .toggle-button", - "targets": [ - ["css=.form-group:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[13]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "5febc53d-9179-4a5e-81a2-6d00495e0953", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "8ba62572-354d-47f4-bb72-f9309c1cb201", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "753d2e1d-54cd-4edd-9718-3f875e617bc1", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "d7406190-0bb0-4df8-9c0b-7e393952b6a2", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(3) .toggle-button", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_connectionRequestTimeout", "targets": [ - ["css=.form-group:nth-child(3) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div[2]/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div[2]/div/div/div/button", "xpath:position"] + ["id=root_httpMetadataResolverAttributes_connectionRequestTimeout", "id"], + ["css=#root_httpMetadataResolverAttributes_connectionRequestTimeout", "css:finder"], + ["xpath=//input[@id='root_httpMetadataResolverAttributes_connectionRequestTimeout']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "0fd359bb-a5d0-47f8-aa99-2cf2f32eae3d", "comment": "", @@ -1030,38 +961,16 @@ }, { "id": "337ac160-7990-425f-83da-2788d8a0985e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "bebea55c-1ac2-4556-ac7f-7e666731e569", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "19182110-0f86-4601-ae12-0b90967ef68a", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(4) .toggle-button", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_connectionTimeout", "targets": [ - ["css=.form-group:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[17]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div[3]/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/button", "xpath:position"] + ["id=root_httpMetadataResolverAttributes_connectionTimeout", "id"], + ["css=#root_httpMetadataResolverAttributes_connectionTimeout", "css:finder"], + ["xpath=//input[@id='root_httpMetadataResolverAttributes_connectionTimeout']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div[2]/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT1M" }, { "id": "c38b8d8d-e108-4895-bf2e-4cfc1fc28e5e", "comment": "", @@ -1072,19 +981,16 @@ }, { "id": "34693225-4754-4b27-92ee-3e37304a8cd7", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_socketTimeout", "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_socketTimeout']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] + ["id=root_httpMetadataResolverAttributes_socketTimeout", "id"], + ["css=#root_httpMetadataResolverAttributes_socketTimeout", "css:finder"], + ["xpath=//input[@id='root_httpMetadataResolverAttributes_socketTimeout']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div[3]/div/div/input", "xpath:idRelative"], + ["xpath=//div[3]/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT10M" }, { "id": "d9a9dcb4-bac1-4f5a-a822-047bd2941df0", "comment": "", @@ -1209,6 +1115,20 @@ ["xpath=//div[2]/div[2]/div/div[5]/div/span[2]", "xpath:position"] ], "value": "PT10M" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1335-1.side b/backend/src/integration/resources/SHIBUI-1335-1.side index 2ed4eda91..da5bd33c5 100644 --- a/backend/src/integration/resources/SHIBUI-1335-1.side +++ b/backend/src/integration/resources/SHIBUI-1335-1.side @@ -348,13 +348,13 @@ "target": "id=option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0", "targets": [ ["id=option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0", "id"], - ["linkText=PT0S", "linkText"], + ["linkText=PT1M", "linkText"], ["css=#option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0", "css:finder"], ["xpath=//a[@id='option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay']/a", "xpath:idRelative"], ["xpath=//a[contains(@href, '#')]", "xpath:href"], ["xpath=//div[2]/a", "xpath:position"], - ["xpath=//a[contains(.,'PT0S')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] ], "value": "" }, { @@ -390,13 +390,13 @@ "target": "id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "targets": [ ["id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "id"], - ["linkText=PT1M", "linkText"], + ["linkText=PT10M", "linkText"], ["css=#option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "css:finder"], ["xpath=//a[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay']/a[3]", "xpath:idRelative"], ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] ], "value": "" }, { @@ -442,41 +442,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "363af92e-0327-47b9-918c-1560adab40cc", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "a14576bb-2d15-4e51-89c6-b8289311e58a", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "a4470d6f-04a7-4c4b-8c1e-70cff2f35e8a", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_metadataFilters_0_maxValidityInterval", "id"], + ["css=#root_metadataFilters_0_maxValidityInterval", "css:finder"], + ["xpath=//input[@id='root_metadataFilters_0_maxValidityInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] ], - "value": "" + "value": "PT15M" }, { "id": "4530c1b4-8f27-4272-9633-c792a3a54f90", "comment": "", @@ -1304,10 +1282,10 @@ "id": "e16e4888-e311-4719-9f87-590ddb124dc4", "comment": "", "command": "click", - "target": "css=.text-left:nth-child(3)", + "target": "xpath=(//button[@type='button'])[11]", "targets": [ - ["css=.text-left:nth-child(3)", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], + ["css=.nav-link:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[11]", "xpath:attributes"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div/nav/button[3]", "xpath:idRelative"], ["xpath=//button[3]", "xpath:position"], ["xpath=//button[contains(.,'Attributes')]", "xpath:innerText"] @@ -1794,6 +1772,20 @@ ["xpath=//button[contains(.,'Entity Attributes Filter')]", "xpath:innerText"] ], "value": "Entity Attributes Filter" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1335-2.side b/backend/src/integration/resources/SHIBUI-1335-2.side index f3719c173..9fa874572 100644 --- a/backend/src/integration/resources/SHIBUI-1335-2.side +++ b/backend/src/integration/resources/SHIBUI-1335-2.side @@ -414,7 +414,21 @@ ["xpath=//span[contains(.,'FilesystemMetadataResolver')]", "xpath:innerText"] ], "value": "FilesystemMetadataResolver" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "248ba015-77cd-430f-b973-d14fd4f39a27", diff --git a/backend/src/integration/resources/SHIBUI-1335-3.side b/backend/src/integration/resources/SHIBUI-1335-3.side index f10c8d687..562653b3f 100644 --- a/backend/src/integration/resources/SHIBUI-1335-3.side +++ b/backend/src/integration/resources/SHIBUI-1335-3.side @@ -233,60 +233,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "1a8a9dcf-9c6b-4802-8483-981d14131346", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(2) .toggle-button", - "targets": [ - ["css=.row:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "2d40e408-16c8-4eba-ae11-bc836c534c58", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "443a9cfc-17c8-49da-9d87-bfabda8fd0b6", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0", "id"], - ["linkText=PT0S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration']/a", "xpath:idRelative"], - ["xpath=//a[contains(@href, '#')]", "xpath:href"], - ["xpath=//div[2]/a", "xpath:position"], - ["xpath=//a[contains(.,'PT0S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "0b259df7-d713-4d4a-b9c3-ffe0b1c0ecf5", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "84f35d35-ea9c-4a06-aaec-bee1c1922aec", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_minCacheDuration", "targets": [ - ["css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[3]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/div/div/button", "xpath:position"] + ["id=root_dynamicMetadataResolverAttributes_minCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_minCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_minCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "032f1b9b-640c-4f77-a61a-3bc2127b447e", "comment": "", @@ -297,40 +256,12 @@ }, { "id": "c03be15d-ee34-4cd1-bac9-c52e3baa70a3", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "508576b2-18ca-4360-ab90-fc0bf4b83cab", - "comment": "", - "command": "pause", - "target": "500", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "targets": [], - "value": "" + "value": "PT5M" }, { - "id": "f0cdfbcf-46e2-4013-b085-0730b0127842", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(4) .toggle-button", - "targets": [ - ["css=.row:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[4]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[4]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "6ac213ff-c86b-4724-9f80-a50989f00369", + "id": "508576b2-18ca-4360-ab90-fc0bf4b83cab", "comment": "", "command": "pause", "target": "500", @@ -339,19 +270,10 @@ }, { "id": "dd663319-7eef-4301-a0d4-24d9583eab7f", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", + "targets": [], + "value": "PT10M" }, { "id": "25ed1d75-be93-4e20-88ba-57d8ae7bf053", "comment": "", @@ -372,41 +294,13 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "54df6d88-1a85-407f-935a-a016f5952a93", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(6) .toggle-button", - "targets": [ - ["css=.row:nth-child(6) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[6]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[6]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "9a756ef8-7633-43c2-ac27-48f2bd41ad15", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "e7f2439a-e9a1-4b23-b0b9-d992f5b477d4", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", + "targets": [], + "value": "PT5M" }, { "id": "64af203b-565c-4e35-b7da-4646423a3279", "comment": "", @@ -485,6 +379,20 @@ ["xpath=//span[contains(.,'LocalDynamicMetadataResolver')]", "xpath:innerText"] ], "value": "LocalDynamicMetadataResolver" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1335-4.side b/backend/src/integration/resources/SHIBUI-1335-4.side index 5fa6b3dd9..93b6bfcfd 100644 --- a/backend/src/integration/resources/SHIBUI-1335-4.side +++ b/backend/src/integration/resources/SHIBUI-1335-4.side @@ -298,60 +298,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "a51172e3-792f-4881-8083-efcb34c63e56", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(2) .toggle-button", - "targets": [ - ["css=.row:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "07e1ade9-022c-4458-ba65-b7eecb4f8c0b", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b1ec3405-0d75-45d6-8986-51c2f09c4dc4", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "c64e2180-1b40-4bb9-8910-25a51438f27c", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "2793bf1b-177b-461f-b06c-0a584ab6eaf0", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_minCacheDuration", "targets": [ - ["css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[3]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/div/div/button", "xpath:position"] + ["id=root_dynamicMetadataResolverAttributes_minCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_minCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_minCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "dc45395b-a584-4b7d-8c12-b6d0e669031a", "comment": "", @@ -362,40 +321,12 @@ }, { "id": "87084a6a-8e89-4c00-a3d9-c104107a3ba2", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "239001d8-35ff-41d0-95cf-7e81917a9e19", - "comment": "", - "command": "pause", - "target": "500", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "targets": [], - "value": "" - }, { - "id": "4c017bde-e242-4d2f-838e-a2a026e4292b", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(4) .toggle-button", - "targets": [ - ["css=.row:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[4]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[4]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" + "value": "PT5M" }, { - "id": "57ea5bd7-1ee0-41d9-b39e-56aeddeec7a0", + "id": "239001d8-35ff-41d0-95cf-7e81917a9e19", "comment": "", "command": "pause", "target": "500", @@ -404,40 +335,12 @@ }, { "id": "d477fd6a-2c15-4fb6-a199-d49aa495ef94", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "0783a0de-0a8d-4cc2-adc4-6ed94f277298", - "comment": "", - "command": "pause", - "target": "500", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", "targets": [], - "value": "" - }, { - "id": "62f7ce3c-5cff-43c6-8ce6-a0e6bf2b2257", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(6) .toggle-button", - "targets": [ - ["css=.row:nth-child(6) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[6]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[6]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" + "value": "PT10M" }, { - "id": "a155f0af-2dd4-4906-a783-19a99d23a6a8", + "id": "0783a0de-0a8d-4cc2-adc4-6ed94f277298", "comment": "", "command": "pause", "target": "500", @@ -446,19 +349,16 @@ }, { "id": "bf855df4-326e-484e-9022-d2c84e09e6f3", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] + ["id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", "id"], + ["css=#root_dynamicMetadataResolverAttributes_cleanupTaskInterval", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_cleanupTaskInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[6]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[6]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT15M" }, { "id": "44e50478-4b65-420f-8f29-7ecb6c70c856", "comment": "", @@ -530,41 +430,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "b777b343-71a0-4056-a85e-d8d548b993b2", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "7a7f2f9c-0f95-4a5c-89c3-299a212f2fb9", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "22f7bf37-718c-4126-867b-67a383eefff5", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2", + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["id=root_metadataFilters_0_maxValidityInterval", "id"], + ["css=#root_metadataFilters_0_maxValidityInterval", "css:finder"], + ["xpath=//input[@id='root_metadataFilters_0_maxValidityInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] ], - "value": "" + "value": "PT15M" }, { "id": "5320f384-0881-4e7a-b89f-33a57efb22ba", "comment": "", @@ -912,10 +790,10 @@ "id": "f82f3d61-f057-4c8e-96c8-321cc7bb134c", "comment": "", "command": "click", - "target": "css=.text-left:nth-child(3)", + "target": "css=.nav-link:nth-child(3)", "targets": [ - ["css=.text-left:nth-child(3)", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], + ["css=.nav-link:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[11]", "xpath:attributes"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div/nav/button[3]", "xpath:idRelative"], ["xpath=//button[3]", "xpath:position"], ["xpath=//button[contains(.,'Attributes')]", "xpath:innerText"] @@ -1203,6 +1081,20 @@ ["xpath=//td[contains(.,'EntityAttributes')]", "xpath:innerText"] ], "value": "EntityAttributes" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1352-1.side b/backend/src/integration/resources/SHIBUI-1352-1.side index ab74cc9cc..3b4f07eff 100644 --- a/backend/src/integration/resources/SHIBUI-1352-1.side +++ b/backend/src/integration/resources/SHIBUI-1352-1.side @@ -259,41 +259,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "59ca3a2c-b9da-4ac6-9b44-d44271355659", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(2) .toggle-button", - "targets": [ - ["css=.row:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "bf63096b-b796-4a70-bc98-96a18dc0531e", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "8db04a8f-565a-4fa9-b5c0-8ce4b200b11c", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_minCacheDuration", "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_dynamicMetadataResolverAttributes_minCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_minCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_minCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "33586d4c-c18b-4081-add7-43ef4d6d8ef8", "comment": "", @@ -301,60 +279,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "a5274853-084e-438f-8cea-9a74e55fd0b9", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", - "targets": [ - ["css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[3]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "e5c5f95e-79df-4782-82d1-11c96bec4651", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "bf7f5914-5aad-485a-8af0-aa510605e1dc", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "3e4b2db4-f2b8-4d4e-ae6b-17741831dc84", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "b2bd8d25-4f3c-47b2-a070-53a364840916", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(4) .toggle-button", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "targets": [ - ["css=.row:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[4]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[4]/div/div/div/div/div/button", "xpath:position"] + ["id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_maxCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_maxCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[3]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[3]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT5M" }, { "id": "2f6feb3c-fc51-410b-abe0-97a4c1a5aa6a", "comment": "", @@ -365,19 +302,16 @@ }, { "id": "9a411cfc-479d-4951-aab2-e8d09ba64b4e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-5", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-5", "id"], - ["linkText=PT1H", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-5", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-5']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData']/a[6]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[6]", "xpath:href"], - ["xpath=//a[6]", "xpath:position"], - ["xpath=//a[contains(.,'PT1H')]", "xpath:innerText"] + ["id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", "id"], + ["css=#root_dynamicMetadataResolverAttributes_maxIdleEntityData", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_maxIdleEntityData']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[4]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[4]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT10M" }, { "id": "1176d384-4b0c-4a67-8e43-6cc3cbbcff73", "comment": "", @@ -398,41 +332,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "ae32fb25-67b1-469b-9f23-3cbca895b956", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(6) .toggle-button", - "targets": [ - ["css=.row:nth-child(6) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[6]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[6]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "b874867f-a32d-43f8-998b-e99488257fe6", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "c30bf781-4d5d-46ad-9bbc-4a5165788870", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-1", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", "id"], + ["css=#root_dynamicMetadataResolverAttributes_cleanupTaskInterval", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_cleanupTaskInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[6]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[6]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT5M" }, { "id": "1202602e-9311-4c3c-b836-9a433cbbcd8c", "comment": "", @@ -495,6 +407,20 @@ ["xpath=//td[contains(.,'LocalDynamicMetadataResolver')]", "xpath:innerText"] ], "value": "LocalDynamicMetadataResolver" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1352-2.side b/backend/src/integration/resources/SHIBUI-1352-2.side index fe4538846..4663a24e7 100644 --- a/backend/src/integration/resources/SHIBUI-1352-2.side +++ b/backend/src/integration/resources/SHIBUI-1352-2.side @@ -414,7 +414,21 @@ ["xpath=//td[contains(.,'FilesystemMetadataResolver')]", "xpath:innerText"] ], "value": "FilesystemMetadataResolver" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "cb217b7c-b7f0-47a4-9860-8731876d2b1a", diff --git a/backend/src/integration/resources/SHIBUI-1361.side b/backend/src/integration/resources/SHIBUI-1361.side index ee3ed5e8f..7e05b232e 100644 --- a/backend/src/integration/resources/SHIBUI-1361.side +++ b/backend/src/integration/resources/SHIBUI-1361.side @@ -462,41 +462,13 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "bb542739-db7f-4386-8d46-3438f7afd4e1", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "763ce787-9ee8-4c78-bff0-d4ad94dff963", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b8d999f1-0c59-4a9a-9991-91d222f52b8e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", - "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", + "targets": [], + "value": "PT15M" }, { "id": "8af1abb5-2c7a-4a4c-a8f7-0eb287100dde", "comment": "", @@ -1026,62 +998,15 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "d00ecf98-7425-467c-acbb-3b39918e3462", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(2) .toggle-button", - "targets": [ - ["css=.form-group:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[13]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "7379d277-790e-47ca-b74c-fc73cc2d8a42", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "8ba62572-354d-47f4-bb72-f9309c1cb201", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "8497a440-4e0c-4589-aaf8-f530dbefb3c7", - "comment": "", - "command": "pause", - "target": "500", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_connectionRequestTimeout", "targets": [], - "value": "" - }, { - "id": "d7406190-0bb0-4df8-9c0b-7e393952b6a2", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(3) .toggle-button", - "targets": [ - ["css=.form-group:nth-child(3) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div[2]/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div[2]/div/div/div/button", "xpath:position"] - ], - "value": "" + "value": "PT30S" }, { - "id": "655375ab-b3e4-449e-acfa-577b0ab4957e", + "id": "8497a440-4e0c-4589-aaf8-f530dbefb3c7", "comment": "", "command": "pause", "target": "500", @@ -1090,38 +1015,10 @@ }, { "id": "337ac160-7990-425f-83da-2788d8a0985e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "855e85a8-d8c3-4b72-ae8a-763f2d86869a", - "comment": "", - "command": "pause", - "target": "500", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_connectionTimeout", "targets": [], - "value": "" - }, { - "id": "19182110-0f86-4601-ae12-0b90967ef68a", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(4) .toggle-button", - "targets": [ - ["css=.form-group:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[17]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div[3]/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/button", "xpath:position"] - ], - "value": "" + "value": "PT1M" }, { "id": "d0befeb0-e5e2-4233-803e-8c417ca570a0", "comment": "", @@ -1132,19 +1029,16 @@ }, { "id": "34693225-4754-4b27-92ee-3e37304a8cd7", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_socketTimeout", "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_socketTimeout']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] + ["id=root_httpMetadataResolverAttributes_socketTimeout", "id"], + ["css=#root_httpMetadataResolverAttributes_socketTimeout", "css:finder"], + ["xpath=//input[@id='root_httpMetadataResolverAttributes_socketTimeout']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div[3]/div/div/input", "xpath:idRelative"], + ["xpath=//div[3]/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT10M" }, { "id": "d9a9dcb4-bac1-4f5a-a822-047bd2941df0", "comment": "", @@ -1410,6 +1304,20 @@ "target": "rightDateIsDate", "targets": [], "value": "true" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1364-1.side b/backend/src/integration/resources/SHIBUI-1364-1.side index ffd426504..8fe9da05e 100644 --- a/backend/src/integration/resources/SHIBUI-1364-1.side +++ b/backend/src/integration/resources/SHIBUI-1364-1.side @@ -412,13 +412,13 @@ "target": "id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "targets": [ ["id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "id"], - ["linkText=PT1M", "linkText"], + ["linkText=PT10M", "linkText"], ["css=#option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "css:finder"], ["xpath=//a[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay']/a[3]", "xpath:idRelative"], ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] ], "value": "" }, { @@ -464,34 +464,13 @@ "target": "1500", "targets": [], "value": "" - }, { - "id": "a4ff078a-48ec-47c6-a67f-f562f7a2b02c", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" }, { "id": "a4470d6f-04a7-4c4b-8c1e-70cff2f35e8a", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", - "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", + "targets": [], + "value": "PT30M" }, { "id": "4530c1b4-8f27-4272-9633-c792a3a54f90", "comment": "", @@ -1932,13 +1911,13 @@ "target": "id=option-selector-items-root_backupFileInitNextRefreshDelay-item-2", "targets": [ ["id=option-selector-items-root_backupFileInitNextRefreshDelay-item-2", "id"], - ["linkText=PT1M", "linkText"], + ["linkText=PT30S", "linkText"], ["css=#option-selector-items-root_backupFileInitNextRefreshDelay-item-2", "css:finder"], ["xpath=//a[@id='option-selector-items-root_backupFileInitNextRefreshDelay-item-2']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_backupFileInitNextRefreshDelay']/a[3]", "xpath:idRelative"], ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] ], "value": "" }, { @@ -2055,7 +2034,7 @@ ["xpath=//div[8]/div/span[2]", "xpath:position"], ["xpath=//span[contains(.,'PT1M')]", "xpath:innerText"] ], - "value": "PT1M" + "value": "PT30S" }, { "id": "1f3e3d25-ea44-4110-913c-c6dc9a7ec215", "comment": "", @@ -2099,7 +2078,7 @@ ["xpath=//div[2]/div/span[2]", "xpath:position"], ["xpath=//span[contains(.,'PT1M')]", "xpath:innerText"] ], - "value": "PT1M" + "value": "PT30S" }, { "id": "0b097967-1b4e-40cc-b8d7-bd0529fd46d2", "comment": "", @@ -2351,13 +2330,22 @@ ["xpath=//button[contains(.,'Compare Selected(2)')]", "xpath:innerText"] ], "value": "" + }, { + "id": "9ddfc4d9-0fbd-44f2-8584-4d7fcb6d0c6b", + "comment": "", + "command": "waitForElementEditable", + "target": "css=#filters > div:nth-child(3) > div:nth-child(2) > div > button", + "targets": [ + ["css=.d-flex:nth-child(3) > .border-primary:nth-child(2) .svg-inline--fa", "css:finder"] + ], + "value": "30000" }, { "id": "2ff5a597-9fe0-46b4-9ca5-63123ddb3cef", "comment": "", "command": "click", - "target": "css=.border-primary:nth-child(2) .fa-square", + "target": "css=#filters > div:nth-child(3) > div:nth-child(2) > div > button", "targets": [ - ["css=.border-primary:nth-child(2) .fa-square", "css:finder"] + ["css=.d-flex:nth-child(3) > .border-primary:nth-child(2) .svg-inline--fa", "css:finder"] ], "value": "" }, { @@ -2377,25 +2365,39 @@ "id": "d7b5550d-1db8-4fa5-800f-fde753413c13", "comment": "", "command": "assertText", - "target": "css=.mb-4:nth-child(8) .p-2 > div > div:nth-child(1) .d-block:nth-child(2)", + "target": "css=.bg-diff > .d-block:nth-child(2)", "targets": [ - ["css=.mb-4:nth-child(8) .p-2 > div > div:nth-child(1) .d-block:nth-child(2)", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div/div/section[5]/div/div[2]/div[2]/div/div/span[2]", "xpath:idRelative"], - ["xpath=//section[5]/div/div[2]/div[2]/div/div/span[2]", "xpath:position"], - ["xpath=//span[contains(.,'Entity Attributes Filter')]", "xpath:innerText"] + ["css=.bg-diff > .d-block:nth-child(2)", "css:finder"], + ["xpath=//div[@id='filters']/section/div/div[2]/div[2]/div/div/span[2]", "xpath:idRelative"], + ["xpath=//div[2]/section/div/div[2]/div[2]/div/div/span[2]", "xpath:position"], + ["xpath=//span[contains(.,'Entity Attributes Filter Version 2')]", "xpath:innerText"] ], "value": "Entity Attributes Filter Version 2" }, { "id": "ad797f09-746e-4778-954e-6f92ac5934ea", "comment": "", "command": "assertText", - "target": "css=.mb-4:nth-child(8) .p-2 > div > div:nth-child(1) .d-block:nth-child(3)", + "target": "css=.bg-diff > .d-block:nth-child(3)", "targets": [ - ["css=.mb-4:nth-child(8) .p-2 > div > div:nth-child(1) .d-block:nth-child(3)", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div/div/section[5]/div/div[2]/div[2]/div/div/span[3]", "xpath:idRelative"], - ["xpath=//section[5]/div/div[2]/div[2]/div/div/span[3]", "xpath:position"] + ["css=.bg-diff > .d-block:nth-child(3)", "css:finder"], + ["xpath=//div[@id='filters']/section/div/div[2]/div[2]/div/div/span[3]", "xpath:idRelative"], + ["xpath=//div[2]/section/div/div[2]/div[2]/div/div/span[3]", "xpath:position"] ], "value": "Entity Attributes Filter" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1364-2.side b/backend/src/integration/resources/SHIBUI-1364-2.side index 784151a04..b3e061afa 100644 --- a/backend/src/integration/resources/SHIBUI-1364-2.side +++ b/backend/src/integration/resources/SHIBUI-1364-2.side @@ -295,13 +295,13 @@ "target": "id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "targets": [ ["id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "id"], - ["linkText=PT1M", "linkText"], + ["linkText=PT10M", "linkText"], ["css=#option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "css:finder"], ["xpath=//a[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay']/a[3]", "xpath:idRelative"], ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] ], "value": "" }, { @@ -681,7 +681,21 @@ ["xpath=//div[2]/div/span[3]", "xpath:position"] ], "value": "12345" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "248ba015-77cd-430f-b973-d14fd4f39a27", diff --git a/backend/src/integration/resources/SHIBUI-1364-3.side b/backend/src/integration/resources/SHIBUI-1364-3.side index af7d0bb84..48116451c 100644 --- a/backend/src/integration/resources/SHIBUI-1364-3.side +++ b/backend/src/integration/resources/SHIBUI-1364-3.side @@ -226,60 +226,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "1a8a9dcf-9c6b-4802-8483-981d14131346", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(2) .toggle-button", - "targets": [ - ["css=.row:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "2d40e408-16c8-4eba-ae11-bc836c534c58", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "443a9cfc-17c8-49da-9d87-bfabda8fd0b6", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0", "id"], - ["linkText=PT0S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-0']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration']/a", "xpath:idRelative"], - ["xpath=//a[contains(@href, '#')]", "xpath:href"], - ["xpath=//div[2]/a", "xpath:position"], - ["xpath=//a[contains(.,'PT0S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "0b259df7-d713-4d4a-b9c3-ffe0b1c0ecf5", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "84f35d35-ea9c-4a06-aaec-bee1c1922aec", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_minCacheDuration", "targets": [ - ["css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[3]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/div/div/button", "xpath:position"] + ["id=root_dynamicMetadataResolverAttributes_minCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_minCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_minCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "032f1b9b-640c-4f77-a61a-3bc2127b447e", "comment": "", @@ -290,19 +249,16 @@ }, { "id": "c03be15d-ee34-4cd1-bac9-c52e3baa70a3", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_maxCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_maxCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[3]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[3]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT1M" }, { "id": "508576b2-18ca-4360-ab90-fc0bf4b83cab", "comment": "", @@ -310,41 +266,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "f0cdfbcf-46e2-4013-b085-0730b0127842", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(4) .toggle-button", - "targets": [ - ["css=.row:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[4]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[4]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "6ac213ff-c86b-4724-9f80-a50989f00369", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "dd663319-7eef-4301-a0d4-24d9583eab7f", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", "id"], + ["css=#root_dynamicMetadataResolverAttributes_maxIdleEntityData", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_maxIdleEntityData']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[3]/div/div/div/div[4]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[4]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT5M" }, { "id": "25ed1d75-be93-4e20-88ba-57d8ae7bf053", "comment": "", @@ -365,41 +299,13 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "54df6d88-1a85-407f-935a-a016f5952a93", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(6) .toggle-button", - "targets": [ - ["css=.row:nth-child(6) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[6]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[6]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "9a756ef8-7633-43c2-ac27-48f2bd41ad15", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "e7f2439a-e9a1-4b23-b0b9-d992f5b477d4", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", + "targets": [], + "value": "PT15M" }, { "id": "64af203b-565c-4e35-b7da-4646423a3279", "comment": "", @@ -694,6 +600,20 @@ ["xpath=//div[3]/div/span[3]", "xpath:position"] ], "value": "12345" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1364-4.side b/backend/src/integration/resources/SHIBUI-1364-4.side index 6096a62ac..3384d27ea 100644 --- a/backend/src/integration/resources/SHIBUI-1364-4.side +++ b/backend/src/integration/resources/SHIBUI-1364-4.side @@ -282,60 +282,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "a51172e3-792f-4881-8083-efcb34c63e56", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(2) .toggle-button", - "targets": [ - ["css=.row:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "07e1ade9-022c-4458-ba65-b7eecb4f8c0b", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b1ec3405-0d75-45d6-8986-51c2f09c4dc4", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_minCacheDuration']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "c64e2180-1b40-4bb9-8910-25a51438f27c", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "2793bf1b-177b-461f-b06c-0a584ab6eaf0", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_minCacheDuration", "targets": [ - ["css=.row:nth-child(3) > .col-12 > .form-group .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[3]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/div/div/button", "xpath:position"] + ["id=root_dynamicMetadataResolverAttributes_minCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_minCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_minCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "dc45395b-a584-4b7d-8c12-b6d0e669031a", "comment": "", @@ -346,38 +305,16 @@ }, { "id": "87084a6a-8e89-4c00-a3d9-c104107a3ba2", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxCacheDuration']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "239001d8-35ff-41d0-95cf-7e81917a9e19", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "4c017bde-e242-4d2f-838e-a2a026e4292b", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(4) .toggle-button", + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "targets": [ - ["css=.row:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[4]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[4]/div/div/div/div/div/button", "xpath:position"] + ["id=root_dynamicMetadataResolverAttributes_maxCacheDuration", "id"], + ["css=#root_dynamicMetadataResolverAttributes_maxCacheDuration", "css:finder"], + ["xpath=//input[@id='root_dynamicMetadataResolverAttributes_maxCacheDuration']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[3]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[3]/div/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT5M" }, { "id": "57ea5bd7-1ee0-41d9-b39e-56aeddeec7a0", "comment": "", @@ -388,19 +325,10 @@ }, { "id": "d477fd6a-2c15-4fb6-a199-d49aa495ef94", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_maxIdleEntityData']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_maxIdleEntityData", + "targets": [], + "value": "PT15M" }, { "id": "0783a0de-0a8d-4cc2-adc4-6ed94f277298", "comment": "", @@ -421,41 +349,13 @@ ["xpath=//div[2]/input", "xpath:position"] ], "value": "" - }, { - "id": "62f7ce3c-5cff-43c6-8ce6-a0e6bf2b2257", - "comment": "", - "command": "click", - "target": "css=.row:nth-child(6) .toggle-button", - "targets": [ - ["css=.row:nth-child(6) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div[6]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[6]/div/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "a155f0af-2dd4-4906-a783-19a99d23a6a8", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "bf855df4-326e-484e-9022-d2c84e09e6f3", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", - "targets": [ - ["id=option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_dynamicMetadataResolverAttributes_cleanupTaskInterval']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_dynamicMetadataResolverAttributes_cleanupTaskInterval", + "targets": [], + "value": "PT30M" }, { "id": "df2a3e70-d7d3-487b-a205-218e9987b060", "comment": "", @@ -512,42 +412,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "b777b343-71a0-4056-a85e-d8d548b993b2", - "comment": "", - "command": "click", - "target": "css=.btn-outline-secondary", - "targets": [ - ["css=.btn-outline-secondary", "css:finder"], - ["xpath=(//button[@type='button'])[2]", "xpath:attributes"], - ["xpath=//div[@id='/metadataFilters/RequiredValidUntil/maxValidityInterval-container']/div/div/button", "xpath:idRelative"], - ["xpath=//div/button", "xpath:position"], - ["xpath=//button[contains(.,'Toggle Dropdown')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "7a7f2f9c-0f95-4a5c-89c3-299a212f2fb9", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "22f7bf37-718c-4126-867b-67a383eefff5", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2", + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["id=root_metadataFilters_0_maxValidityInterval", "id"], + ["css=#root_metadataFilters_0_maxValidityInterval", "css:finder"], + ["xpath=//input[@id='root_metadataFilters_0_maxValidityInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] ], - "value": "" + "value": "PT20M" }, { "id": "5320f384-0881-4e7a-b89f-33a57efb22ba", "comment": "", @@ -874,10 +751,10 @@ "id": "6895180e-e563-4199-acda-f20823f58a03", "comment": "", "command": "click", - "target": "css=.text-left:nth-child(3)", + "target": "css=.nav-link:nth-child(3)", "targets": [ - ["css=.text-left:nth-child(3)", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], + ["css=.nav-link:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[11]", "xpath:attributes"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div/nav/button[3]", "xpath:idRelative"], ["xpath=//button[3]", "xpath:position"], ["xpath=//button[contains(.,'Attributes')]", "xpath:innerText"] @@ -1540,23 +1417,14 @@ ["xpath=//input", "xpath:position"] ], "value": "" - }, { - "id": "e83dc2da-ad95-4e50-b969-57721eb8f1dc", - "comment": "", - "command": "click", - "target": "css=.d-flex:nth-child(5) > .border-primary:nth-child(2) .svg-inline--fa", - "targets": [ - ["css=.d-flex:nth-child(5) > .border-primary:nth-child(2) .svg-inline--fa", "css:finder"] - ], - "value": "" }, { "id": "c2102a31-6e18-4d6c-8146-e23459403b65", "comment": "", "command": "assertText", - "target": "css=.border-primary:nth-child(2) > .bg-primary-light .mb-0:nth-child(1)", + "target": "css=.d-flex:nth-child(3) > .border-primary:nth-child(2) .mb-0:nth-child(1)", "targets": [ - ["css=.border-primary:nth-child(2) > .bg-primary-light .mb-0:nth-child(1)", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div/div/div[4]/div[2]/div/div/p", "xpath:idRelative"], + ["css=.d-flex:nth-child(3) > .border-primary:nth-child(2) .mb-0:nth-child(1)", "css:finder"], + ["xpath=//div[@id='filters']/div[3]/div[2]/div/div/p", "xpath:idRelative"], ["xpath=//p", "xpath:position"], ["xpath=//p[contains(.,'Entity Attributes Filter V2')]", "xpath:innerText"] ], @@ -1565,13 +1433,27 @@ "id": "cac6c125-c81b-40af-ae21-2b717df9511e", "comment": "", "command": "assertText", - "target": "css=.border-primary:nth-child(3) > .bg-primary-light .mb-0:nth-child(1)", + "target": "css=.d-flex:nth-child(3) .bg-lighter .mb-0:nth-child(1)", "targets": [ - ["css=.border-primary:nth-child(3) > .bg-primary-light .mb-0:nth-child(1)", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div/div/div[4]/div[3]/div/div/p", "xpath:idRelative"], + ["css=.d-flex:nth-child(3) .bg-lighter .mb-0:nth-child(1)", "css:finder"], + ["xpath=//div[@id='filters']/div[3]/div[3]/div/div/p", "xpath:idRelative"], ["xpath=//div[3]/div/div/p", "xpath:position"] ], "value": "Entity Attributes Filter" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1385-1.side b/backend/src/integration/resources/SHIBUI-1385-1.side index 8c2dcc5cb..801580133 100644 --- a/backend/src/integration/resources/SHIBUI-1385-1.side +++ b/backend/src/integration/resources/SHIBUI-1385-1.side @@ -1995,9 +1995,9 @@ ["css=.d-flex:nth-child(1) > .py-2 > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[3]/div/section[9]/div/div[2]/div[2]/div/div/span", "xpath:idRelative"], ["xpath=//section[9]/div/div[2]/div[2]/div/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] ], - "value": "True" + "value": "true" }, { "id": "1406d7e4-907d-4359-8de8-a40206f0993e", "comment": "", @@ -2291,9 +2291,9 @@ ["css=.d-flex:nth-child(1) > .py-2 > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div/div/section[8]/div/div[2]/div[2]/div/div/span", "xpath:idRelative"], ["xpath=//section[8]/div/div[2]/div[2]/div/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] ], - "value": "True" + "value": "true" }, { "id": "2c46cdcd-d5a5-47fe-aa7b-0120fd2fcfc9", "comment": "", @@ -2878,7 +2878,21 @@ ["xpath=//section[2]/div/div[2]/div[2]/div/div/div/span[3]", "xpath:position"] ], "value": "Display Name" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "d2caeac4-7520-4e3c-96b1-840610b6983c", diff --git a/backend/src/integration/resources/SHIBUI-1385-2.side b/backend/src/integration/resources/SHIBUI-1385-2.side index 57e73890b..2381964f9 100644 --- a/backend/src/integration/resources/SHIBUI-1385-2.side +++ b/backend/src/integration/resources/SHIBUI-1385-2.side @@ -461,41 +461,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "232da257-962f-4a4b-8213-038ef90c96c3", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "293cf806-cec0-4b31-a7be-c77e938ac435", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b8d999f1-0c59-4a9a-9991-91d222f52b8e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_metadataFilters_0_maxValidityInterval", "id"], + ["css=#root_metadataFilters_0_maxValidityInterval", "css:finder"], + ["xpath=//input[@id='root_metadataFilters_0_maxValidityInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] ], - "value": "" + "value": "PT5M" }, { "id": "8af1abb5-2c7a-4a4c-a8f7-0eb287100dde", "comment": "", @@ -999,60 +977,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "78967fb5-8f61-46ce-9c14-9b6ceb12b03a", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(2) .toggle-button", - "targets": [ - ["css=.form-group:nth-child(2) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[13]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "aa3ed5b0-cd6e-4e8d-9c35-57524db80ca7", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "8ba62572-354d-47f4-bb72-f9309c1cb201", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionRequestTimeout']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "31d15a76-ef02-42ed-87a0-56543de45b0d", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "d7406190-0bb0-4df8-9c0b-7e393952b6a2", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(3) .toggle-button", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_connectionRequestTimeout", "targets": [ - ["css=.form-group:nth-child(3) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div[2]/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div[2]/div/div/div/button", "xpath:position"] + ["id=root_httpMetadataResolverAttributes_connectionRequestTimeout", "id"], + ["css=#root_httpMetadataResolverAttributes_connectionRequestTimeout", "css:finder"], + ["xpath=//input[@id='root_httpMetadataResolverAttributes_connectionRequestTimeout']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT30S" }, { "id": "bf37da0d-3a16-4944-b7ae-f116c898040b", "comment": "", @@ -1063,38 +1000,16 @@ }, { "id": "337ac160-7990-425f-83da-2788d8a0985e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", "id"], - ["linkText=PT1M", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout-item-2']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_connectionTimeout']/a[3]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], - ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "603e9774-e7cb-4c31-9e53-43c4262ba58d", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" - }, { - "id": "19182110-0f86-4601-ae12-0b90967ef68a", - "comment": "", - "command": "click", - "target": "css=.form-group:nth-child(4) .toggle-button", + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_connectionTimeout", "targets": [ - ["css=.form-group:nth-child(4) .toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[17]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[6]/div/div/div/div/div[2]/div[3]/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[3]/div/div/div/button", "xpath:position"] + ["id=root_httpMetadataResolverAttributes_connectionTimeout", "id"], + ["css=#root_httpMetadataResolverAttributes_connectionTimeout", "css:finder"], + ["xpath=//input[@id='root_httpMetadataResolverAttributes_connectionTimeout']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div[2]/div[2]/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div[2]/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/input", "xpath:position"] ], - "value": "" + "value": "PT1M" }, { "id": "70ca5b38-22a6-4c61-b645-9b67b2e88178", "comment": "", @@ -1105,19 +1020,10 @@ }, { "id": "34693225-4754-4b27-92ee-3e37304a8cd7", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", - "targets": [ - ["id=option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", "id"], - ["linkText=PT10M", "linkText"], - ["css=#option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_httpMetadataResolverAttributes_socketTimeout-item-3']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_httpMetadataResolverAttributes_socketTimeout']/a[4]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[4]", "xpath:href"], - ["xpath=//a[4]", "xpath:position"], - ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_httpMetadataResolverAttributes_socketTimeout", + "targets": [], + "value": "PT10M" }, { "id": "d9a9dcb4-bac1-4f5a-a822-047bd2941df0", "comment": "", @@ -1480,6 +1386,20 @@ ["xpath=//span[3]", "xpath:position"] ], "value": "Test Metadata Provider" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1391.side b/backend/src/integration/resources/SHIBUI-1391.side index aae00f2ab..67267b429 100644 --- a/backend/src/integration/resources/SHIBUI-1391.side +++ b/backend/src/integration/resources/SHIBUI-1391.side @@ -334,13 +334,13 @@ "target": "id=option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0", "targets": [ ["id=option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0", "id"], - ["linkText=PT0S", "linkText"], + ["linkText=PT1M", "linkText"], ["css=#option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0", "css:finder"], ["xpath=//a[@id='option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay-item-0']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_reloadableMetadataResolverAttributes_minRefreshDelay']/a", "xpath:idRelative"], ["xpath=//a[contains(@href, '#')]", "xpath:href"], ["xpath=//div[2]/a", "xpath:position"], - ["xpath=//a[contains(.,'PT0S')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] ], "value": "" }, { @@ -376,13 +376,13 @@ "target": "id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "targets": [ ["id=option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "id"], - ["linkText=PT1M", "linkText"], + ["linkText=PT10M", "linkText"], ["css=#option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2", "css:finder"], ["xpath=//a[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay-item-2']", "xpath:attributes"], ["xpath=//div[@id='option-selector-items-root_reloadableMetadataResolverAttributes_maxRefreshDelay']/a[3]", "xpath:idRelative"], ["xpath=(//a[contains(@href, '#')])[3]", "xpath:href"], ["xpath=//a[3]", "xpath:position"], - ["xpath=//a[contains(.,'PT1M')]", "xpath:innerText"] + ["xpath=//a[contains(.,'PT10M')]", "xpath:innerText"] ], "value": "" }, { @@ -421,34 +421,13 @@ ["xpath=//li[3]/button", "xpath:position"] ], "value": "" - }, { - "id": "363af92e-0327-47b9-918c-1560adab40cc", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" }, { "id": "a4470d6f-04a7-4c4b-8c1e-70cff2f35e8a", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", - "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] - ], - "value": "" + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", + "targets": [], + "value": "PT15M" }, { "id": "4530c1b4-8f27-4272-9633-c792a3a54f90", "comment": "", @@ -728,7 +707,7 @@ ["xpath=//div/small", "xpath:position"], ["xpath=//small[contains(.,'Invalid Regular Expression')]", "xpath:innerText"] ], - "value": "Invalid Regular Expression" + "value": "Invalid regular expression" }, { "id": "0280c7b8-5714-43b8-89cc-f1260037bd44", "comment": "", @@ -743,6 +722,20 @@ ["xpath=//div[2]/div/div/input", "xpath:position"] ], "value": ".*" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1392.side b/backend/src/integration/resources/SHIBUI-1392.side index 70e057548..1dc727268 100644 --- a/backend/src/integration/resources/SHIBUI-1392.side +++ b/backend/src/integration/resources/SHIBUI-1392.side @@ -507,7 +507,21 @@ ["xpath=//p[contains(.,'eval(true)')]", "xpath:innerText"] ], "value": "eval(true);" - }] + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "4f69a686-bcaa-4963-84af-2e592e8c8842", diff --git a/backend/src/integration/resources/SHIBUI-1407-1.side b/backend/src/integration/resources/SHIBUI-1407-1.side index 2a587d5ce..2a6525167 100644 --- a/backend/src/integration/resources/SHIBUI-1407-1.side +++ b/backend/src/integration/resources/SHIBUI-1407-1.side @@ -1497,9 +1497,12 @@ "id": "fd33610c-dbca-410d-b2a4-117a1b2b6a79", "comment": "", "command": "click", - "target": "css=.mt-2:nth-child(2) .mr-2 .svg-inline--fa", + "target": "css=.is-invalid > .toggle-button", "targets": [ - ["css=.mt-2:nth-child(2) .mr-2 .svg-inline--fa", "css:finder"] + ["css=.is-invalid > .toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[9]/div/div/div/div[2]/div/div/div/div/div/div[2]/div[2]/div/div/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div[2]/div/div/div/div/div/div/button", "xpath:position"] ], "value": "" }, { @@ -2010,7 +2013,7 @@ ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[3]/div/section[9]/div/div[2]/div[2]/div[2]/div", "xpath:idRelative"], ["xpath=//section[9]/div/div[2]/div[2]/div[2]/div", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "1406d7e4-907d-4359-8de8-a40206f0993e", "comment": "", @@ -2286,7 +2289,7 @@ ["xpath=//div[@id='root']/div/main/div/section/div/div/section[8]/div/div[2]/div[2]/div[3]/div", "xpath:idRelative"], ["xpath=//section[8]/div/div[2]/div[2]/div[3]/div", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "2c46cdcd-d5a5-47fe-aa7b-0120fd2fcfc9", "comment": "", @@ -2605,7 +2608,21 @@ "target": "isPresent", "targets": [], "value": "true" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "d2caeac4-7520-4e3c-96b1-840610b6983c", diff --git a/backend/src/integration/resources/SHIBUI-1407-2.side b/backend/src/integration/resources/SHIBUI-1407-2.side index 5ddb62a47..73381ad90 100644 --- a/backend/src/integration/resources/SHIBUI-1407-2.side +++ b/backend/src/integration/resources/SHIBUI-1407-2.side @@ -468,41 +468,19 @@ "target": "500", "targets": [], "value": "" - }, { - "id": "232da257-962f-4a4b-8213-038ef90c96c3", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[5]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div/div/div/div/button", "xpath:position"] - ], - "value": "" - }, { - "id": "293cf806-cec0-4b31-a7be-c77e938ac435", - "comment": "", - "command": "pause", - "target": "500", - "targets": [], - "value": "" }, { "id": "b8d999f1-0c59-4a9a-9991-91d222f52b8e", "comment": "", - "command": "click", - "target": "id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", + "command": "type", + "target": "id=root_metadataFilters_0_maxValidityInterval", "targets": [ - ["id=option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "id"], - ["linkText=PT30S", "linkText"], - ["css=#option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1", "css:finder"], - ["xpath=//a[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval-item-1']", "xpath:attributes"], - ["xpath=//div[@id='option-selector-items-root_metadataFilters_0_maxValidityInterval']/a[2]", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], - ["xpath=//div[2]/a[2]", "xpath:position"], - ["xpath=//a[contains(.,'PT30S')]", "xpath:innerText"] + ["id=root_metadataFilters_0_maxValidityInterval", "id"], + ["css=#root_metadataFilters_0_maxValidityInterval", "css:finder"], + ["xpath=//input[@id='root_metadataFilters_0_maxValidityInterval']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[4]/div/div/div/div/div[2]/div/div/div/div/div/div/div[2]/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] ], - "value": "" + "value": "PT15M" }, { "id": "8af1abb5-2c7a-4a4c-a8f7-0eb287100dde", "comment": "", @@ -1032,6 +1010,20 @@ "target": "isDiff", "targets": [], "value": "true" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1503-1.side b/backend/src/integration/resources/SHIBUI-1503-1.side index e70c277bf..e8c611e9e 100644 --- a/backend/src/integration/resources/SHIBUI-1503-1.side +++ b/backend/src/integration/resources/SHIBUI-1503-1.side @@ -458,8 +458,13 @@ "id": "990aff50-4646-4258-a9f0-ef5f39b8dc83", "comment": "", "command": "waitForElementVisible", - "target": "css=.badge-pill", - "targets": [], + "target": "css=.rounded-pill", + "targets": [ + ["css=.ms-1", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/div/div[4]/a/span", "xpath:idRelative"], + ["xpath=//div[4]/a/span", "xpath:position"], + ["xpath=//span[contains(.,'3')]", "xpath:innerText"] + ], "value": "30000" }, { "id": "d77d51d9-fbf7-4358-a995-41fcf0f6885f", @@ -472,7 +477,7 @@ "id": "9fd2f2ad-6315-48be-b1e5-b958956c20be", "comment": "", "command": "assertText", - "target": "css=.badge-pill", + "target": "css=.rounded-pill", "targets": [ ["css=.badge-pill", "css:finder"], ["xpath=//li[4]/a/span", "xpath:position"], diff --git a/backend/src/integration/resources/SHIBUI-1503-3.side b/backend/src/integration/resources/SHIBUI-1503-3.side index 25a91828f..60250abbd 100644 --- a/backend/src/integration/resources/SHIBUI-1503-3.side +++ b/backend/src/integration/resources/SHIBUI-1503-3.side @@ -214,7 +214,21 @@ ["xpath=//a[contains(.,'Metadata Sources')]", "xpath:innerText"] ], "value": "Metadata Sources" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "173aaf44-c763-416e-ab3c-d5afd5ffcd29", diff --git a/backend/src/integration/resources/SHIBUI-1521.side b/backend/src/integration/resources/SHIBUI-1521.side index f49fef4c4..b1ec76f6d 100644 --- a/backend/src/integration/resources/SHIBUI-1521.side +++ b/backend/src/integration/resources/SHIBUI-1521.side @@ -1808,7 +1808,7 @@ ["xpath=//metadata-configuration[@id='configuration']/div/section[9]/div/div[2]/object-property/array-property/div/div[5]/div/span", "xpath:idRelative"], ["xpath=//div/div[5]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "1406d7e4-907d-4359-8de8-a40206f0993e", "comment": "", diff --git a/backend/src/integration/resources/SHIBUI-1732-1.side b/backend/src/integration/resources/SHIBUI-1732-1.side index b898f8bf9..38720ef67 100644 --- a/backend/src/integration/resources/SHIBUI-1732-1.side +++ b/backend/src/integration/resources/SHIBUI-1732-1.side @@ -862,9 +862,9 @@ "id": "62aae077-0f97-48ec-97cb-2111ea9e3400", "comment": "", "command": "assertText", - "target": "css=.row:nth-child(7) > .col-12 > .form-group > div > .mb-0 span", + "target": "css=.row:nth-child(7) > .col-12 > .mb-3 > div > div > .form-label > span", "targets": [ - ["css=.row:nth-child(7) > .col-12 > .form-group > div > .mb-0 span", "css:finder"], + ["css=.row:nth-child(7) > .col-12 > .mb-3 > div > div > .form-label > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[7]/div/div/div/div/div[7]/div/div/div/div/label/span", "xpath:idRelative"], ["xpath=//div[7]/div/div/div/div/label/span", "xpath:position"], ["xpath=//span[contains(.,'Custom String Display')]", "xpath:innerText"] @@ -1031,7 +1031,21 @@ "target": "css=table > tbody > tr", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "a9b788f1-5f67-4d2c-82a5-30dc53eb75e9", diff --git a/backend/src/integration/resources/SHIBUI-1732-2.side b/backend/src/integration/resources/SHIBUI-1732-2.side index 3b3777779..39b05afb3 100644 --- a/backend/src/integration/resources/SHIBUI-1732-2.side +++ b/backend/src/integration/resources/SHIBUI-1732-2.side @@ -967,7 +967,21 @@ ["xpath=//div[3]/div/div/div[3]/button", "xpath:position"] ], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "4c985215-babb-4f22-8422-505980ce939b", diff --git a/backend/src/integration/resources/SHIBUI-1732-3.side b/backend/src/integration/resources/SHIBUI-1732-3.side index 5a794676b..54573d88b 100644 --- a/backend/src/integration/resources/SHIBUI-1732-3.side +++ b/backend/src/integration/resources/SHIBUI-1732-3.side @@ -834,13 +834,6 @@ ["xpath=//input", "xpath:position"] ], "value": "Test" - }, { - "id": "f21989e9-8b54-4e55-a6f7-c699939f0992", - "comment": "", - "command": "select", - "target": "name=type", - "targets": [], - "value": "label=FileBackedHttpMetadataResolver" }, { "id": "3c298664-b8c4-40de-986e-a955c760ba3e", "comment": "", @@ -1130,9 +1123,13 @@ "id": "1690cd2a-caae-4e79-80e1-6c558683bdf2", "comment": "", "command": "click", - "target": "css=.fa-save > path", + "target": "css=.btn-info", "targets": [ - ["css=.fa-save > path", "css:finder"] + ["css=.btn-info", "css:finder"], + ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div/div[2]/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/button", "xpath:position"], + ["xpath=//button[contains(.,' Save')]", "xpath:innerText"] ], "value": "" }, { @@ -1328,7 +1325,7 @@ "id": "2dd7992f-ee99-45a3-ad85-20488c4bd4b1", "comment": "", "command": "click", - "target": "css=.border-primary:nth-child(2) .svg-inline--fa", + "target": "css=#filters > div:nth-child(3) > div:nth-child(2) > div > button", "targets": [ ["css=.border-primary:nth-child(2) .svg-inline--fa", "css:finder"] ], @@ -1552,6 +1549,20 @@ ["xpath=//ul[2]/li[2]/span", "xpath:position"] ], "value": "bar" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1732-4.side b/backend/src/integration/resources/SHIBUI-1732-4.side index 5c7260a30..214a49cbd 100644 --- a/backend/src/integration/resources/SHIBUI-1732-4.side +++ b/backend/src/integration/resources/SHIBUI-1732-4.side @@ -830,9 +830,9 @@ "id": "af84ef03-8d0a-4201-b217-40926b723582", "comment": "", "command": "assertText", - "target": "css=.row:nth-child(7) > .col-12 > .form-group > div > .mb-0 span", + "target": "css=.row:nth-child(7) > .col-12 > .mb-3 > div > div > .form-label > span", "targets": [ - ["css=.row:nth-child(7) > .col-12 > .form-group > div > .mb-0 span", "css:finder"], + ["css=.row:nth-child(7) > .col-12 > .mb-3 > div > div > .form-label > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[7]/div/div/div/div/div[7]/div/div/div/div/label/span", "xpath:idRelative"], ["xpath=//div[7]/div/div/div/div/label/span", "xpath:position"], ["xpath=//span[contains(.,'Custom Long Display')]", "xpath:innerText"] @@ -992,6 +992,13 @@ ["xpath=//div[3]/div/div/div[3]/button", "xpath:position"] ], "value": "" + }, { + "id": "14c486b1-bdff-4474-94e3-b4286303a8fd", + "comment": "", + "command": "pause", + "target": "5000", + "targets": [], + "value": "" }, { "id": "e3892564-1a1b-4ee6-bbab-49d3cb3079d7", "comment": "", @@ -999,6 +1006,20 @@ "target": "css=table > tbody > tr", "targets": [], "value": "" + }, { + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" }] }], "suites": [{ diff --git a/backend/src/integration/resources/SHIBUI-1732-5.side b/backend/src/integration/resources/SHIBUI-1732-5.side index a74508f17..f9886d3f5 100644 --- a/backend/src/integration/resources/SHIBUI-1732-5.side +++ b/backend/src/integration/resources/SHIBUI-1732-5.side @@ -1006,7 +1006,21 @@ "target": "css=table > tbody > tr", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "575d414c-556d-45f7-b2f2-c9971ad51348", diff --git a/backend/src/integration/resources/SHIBUI-1732-6.side b/backend/src/integration/resources/SHIBUI-1732-6.side index e90e128f2..68a329d37 100644 --- a/backend/src/integration/resources/SHIBUI-1732-6.side +++ b/backend/src/integration/resources/SHIBUI-1732-6.side @@ -1017,7 +1017,21 @@ "target": "css=table > tbody > tr", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "575d414c-556d-45f7-b2f2-c9971ad51348", diff --git a/backend/src/integration/resources/SHIBUI-1732-7.side b/backend/src/integration/resources/SHIBUI-1732-7.side index fd55d0449..1403a1b68 100644 --- a/backend/src/integration/resources/SHIBUI-1732-7.side +++ b/backend/src/integration/resources/SHIBUI-1732-7.side @@ -982,7 +982,21 @@ "target": "css=table > tbody > tr", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "575d414c-556d-45f7-b2f2-c9971ad51348", diff --git a/backend/src/integration/resources/SHIBUI-1740-1.side b/backend/src/integration/resources/SHIBUI-1740-1.side index c3cc756ff..f2b1ed457 100644 --- a/backend/src/integration/resources/SHIBUI-1740-1.side +++ b/backend/src/integration/resources/SHIBUI-1740-1.side @@ -142,9 +142,13 @@ "id": "fa3bb65e-b526-4813-ad6f-c528f527a5a5", "comment": "", "command": "click", - "target": "css=.fa-save", + "target": "css=.btn-info", "targets": [ - ["css=.fa-save", "css:finder"] + ["css=.btn-info", "css:finder"], + ["xpath=(//button[@type='button'])[5]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,' Save')]", "xpath:innerText"] ], "value": "" }, { @@ -298,7 +302,21 @@ "target": "xpath=//li[contains(.,'Deleted group successfully.')]", "targets": [], "value": "Deleted group successfully." - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "bb170239-568b-4e90-991e-1a5882465aaa", diff --git a/backend/src/integration/resources/SHIBUI-1740-2.side b/backend/src/integration/resources/SHIBUI-1740-2.side index ce06fa931..c1a7fedd5 100644 --- a/backend/src/integration/resources/SHIBUI-1740-2.side +++ b/backend/src/integration/resources/SHIBUI-1740-2.side @@ -298,7 +298,21 @@ ["xpath=//tr[4]/td[4]/span/select", "xpath:position"] ], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "16a0d393-c257-46c4-9a0f-dc2a84dfc23b", diff --git a/backend/src/integration/resources/SHIBUI-1740-3.side b/backend/src/integration/resources/SHIBUI-1740-3.side index 9c53b80e5..60c7669d9 100644 --- a/backend/src/integration/resources/SHIBUI-1740-3.side +++ b/backend/src/integration/resources/SHIBUI-1740-3.side @@ -381,7 +381,21 @@ ["xpath=//div[2]/div/div/div", "xpath:position"] ], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "9c39a96d-d969-4bd7-bba4-074f847f14d0", diff --git a/backend/src/integration/resources/SHIBUI-1740-4.side b/backend/src/integration/resources/SHIBUI-1740-4.side index 77631079b..0e72fa643 100644 --- a/backend/src/integration/resources/SHIBUI-1740-4.side +++ b/backend/src/integration/resources/SHIBUI-1740-4.side @@ -619,7 +619,21 @@ ["xpath=//div[2]/div/div/div", "xpath:position"] ], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "13b2104f-1386-474b-8478-566db394923b", diff --git a/backend/src/integration/resources/SHIBUI-1742-1.side b/backend/src/integration/resources/SHIBUI-1742-1.side index 3e60ce581..09985e641 100644 --- a/backend/src/integration/resources/SHIBUI-1742-1.side +++ b/backend/src/integration/resources/SHIBUI-1742-1.side @@ -605,7 +605,21 @@ ["xpath=//span/div/label", "xpath:position"] ], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "8a97286b-5660-452c-9f23-4c5f5bf8de3b", diff --git a/backend/src/integration/resources/SHIBUI-1742-2.side b/backend/src/integration/resources/SHIBUI-1742-2.side index ba40df4c0..db099d957 100644 --- a/backend/src/integration/resources/SHIBUI-1742-2.side +++ b/backend/src/integration/resources/SHIBUI-1742-2.side @@ -112,9 +112,13 @@ "id": "548d864c-87ba-4889-823e-3e9729d596db", "comment": "", "command": "click", - "target": "css=.fa-save", + "target": "css=.btn-info", "targets": [ - ["css=.fa-save", "css:finder"] + ["css=.btn-info", "css:finder"], + ["xpath=(//button[@type='button'])[5]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,' Save')]", "xpath:innerText"] ], "value": "" }, { @@ -270,7 +274,7 @@ "id": "a378e628-4227-451b-9fb6-ef9edb7fc4fa", "comment": "", "command": "click", - "target": "css=table > tbody > tr:nth-child(5) > td.text-right > button", + "target": "css=tr:nth-child(5) .text-danger", "targets": [ ["css=tr:nth-child(5) .text-danger path", "css:finder"] ], @@ -377,7 +381,7 @@ "id": "f4201d01-e582-4071-921b-ede543ce181a", "comment": "", "command": "click", - "target": "css=table > tbody > tr:nth-child(5) > td.text-right > button", + "target": "css=tr:nth-child(5) .text-danger", "targets": [ ["css=tr:nth-child(5) .text-danger", "css:finder"], ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], @@ -403,7 +407,21 @@ "target": "xpath=//div[@role=\"alert\" and contains(., \"Deleted role successfully.\")]", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "2feb47ff-b645-47f5-9128-6b3a51eca540", diff --git a/backend/src/integration/resources/SHIBUI-1743-1.side b/backend/src/integration/resources/SHIBUI-1743-1.side index 76a1a3a75..526df3bf4 100644 --- a/backend/src/integration/resources/SHIBUI-1743-1.side +++ b/backend/src/integration/resources/SHIBUI-1743-1.side @@ -142,9 +142,13 @@ "id": "e207cc31-d81c-4128-b029-88c8539d914f", "comment": "", "command": "click", - "target": "css=.fa-save > path", + "target": "css=.btn-info", "targets": [ - ["css=.fa-save > path", "css:finder"] + ["css=.btn-info", "css:finder"], + ["xpath=(//button[@type='button'])[5]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,' Save')]", "xpath:innerText"] ], "value": "" }, { @@ -255,7 +259,21 @@ ["xpath=//div[3]/div/div/div/div/input", "xpath:position"] ], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "c5aa01a8-f302-4538-85f8-2f57971ea640", diff --git a/backend/src/integration/resources/SHIBUI-1743-2.side b/backend/src/integration/resources/SHIBUI-1743-2.side index 3908e652d..e2984ae63 100644 --- a/backend/src/integration/resources/SHIBUI-1743-2.side +++ b/backend/src/integration/resources/SHIBUI-1743-2.side @@ -451,9 +451,9 @@ "id": "2627de6e-206f-4825-9918-dc8df830b17a", "comment": "", "command": "assertText", - "target": "css=.mb-0 .border-0 > .m-0", + "target": "css=.border-0 > .m-0", "targets": [ - ["css=.mb-0 .border-0 > .m-0", "css:finder"], + ["css=.border-0 > .m-0", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[8]/div/div/div/div/div[2]/div/div/div/div[2]/div/div/div/div/div/div/div/div/div/ul/li/small", "xpath:idRelative"], ["xpath=//small", "xpath:position"], ["xpath=//small[contains(.,'Pattern must match group url validation pattern: foo.*')]", "xpath:innerText"] @@ -597,7 +597,21 @@ ["xpath=//section[6]/div/div[2]/div[2]/div/div[2]/div/span", "xpath:position"] ], "value": "foobar" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "c1770d48-99b6-4866-af1c-d4e485b851ab", diff --git a/backend/src/integration/resources/SHIBUI-1744-1.side b/backend/src/integration/resources/SHIBUI-1744-1.side index bbf69eeab..ea21809ae 100644 --- a/backend/src/integration/resources/SHIBUI-1744-1.side +++ b/backend/src/integration/resources/SHIBUI-1744-1.side @@ -239,9 +239,14 @@ "id": "a7cd7ab2-3309-4ca2-ae1b-0b566c161582", "comment": "", "command": "click", - "target": "css=.fa-edit", + "target": "linkText=Edit", "targets": [ - ["css=.fa-edit", "css:finder"] + ["linkText=Edit", "linkText"], + ["css=.text-end > .text-primary", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/attributes/bundles/60fd84d7-9284-49d4-8ef7-ee06cb1652a0/edit')]", "xpath:href"], + ["xpath=//td[3]/a", "xpath:position"], + ["xpath=//a[contains(.,'Edit')]", "xpath:innerText"] ], "value": "" }, { @@ -395,9 +400,14 @@ "id": "8ea152c6-4509-4969-b499-95272cb6b92e", "comment": "", "command": "click", - "target": "css=.fa-edit", + "target": "linkText=Edit", "targets": [ - ["css=.fa-edit", "css:finder"] + ["linkText=Edit", "linkText"], + ["css=.text-end > .text-primary", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/attributes/bundles/60fd84d7-9284-49d4-8ef7-ee06cb1652a0/edit')]", "xpath:href"], + ["xpath=//td[3]/a", "xpath:position"], + ["xpath=//a[contains(.,'Edit')]", "xpath:innerText"] ], "value": "" }, { @@ -469,7 +479,21 @@ "target": "xpath=//div[@role=\"alert\" and contains(., \"Bundle has been deleted.\")]", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "f081803d-04c9-4aea-bd5b-765885cb4739", diff --git a/backend/src/integration/resources/SHIBUI-1744-2.side b/backend/src/integration/resources/SHIBUI-1744-2.side index 2bc9dc4e1..40e268775 100644 --- a/backend/src/integration/resources/SHIBUI-1744-2.side +++ b/backend/src/integration/resources/SHIBUI-1744-2.side @@ -547,9 +547,9 @@ ["css=.d-flex:nth-child(3) > .py-2 > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[3]/div/section[9]/div/div[2]/div[2]/div[3]/div/span", "xpath:idRelative"], ["xpath=//div[2]/div[3]/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] ], - "value": "True" + "value": "true" }, { "id": "bfc6ef5f-aaf7-4945-bbc1-d89e95b8d3ac", "comment": "", @@ -560,7 +560,7 @@ ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[3]/div/section[9]/div/div[2]/div[2]/div[4]/div/span", "xpath:idRelative"], ["xpath=//div[2]/div[4]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "5225f1db-7bdc-432e-a422-c6684b9e8416", "comment": "", @@ -571,7 +571,7 @@ ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[3]/div/section[9]/div/div[2]/div[2]/div[5]/div/span", "xpath:idRelative"], ["xpath=//div[2]/div[5]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "2a14e2d4-31f1-4ae8-b977-b6edd94de02c", "comment": "", @@ -614,9 +614,9 @@ ["css=.d-flex:nth-child(4) > .py-2 > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div/div/section[8]/div/div[2]/div[2]/div[4]/div/span", "xpath:idRelative"], ["xpath=//div[2]/div[4]/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] ], - "value": "True" + "value": "true" }, { "id": "09fa0157-7e1a-4886-969e-fe9519974923", "comment": "", @@ -626,9 +626,9 @@ ["css=.d-flex:nth-child(4) > .py-2 > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div/div/section[8]/div/div[2]/div[2]/div[4]/div/span", "xpath:idRelative"], ["xpath=//div[2]/div[4]/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] ], - "value": "True" + "value": "true" }, { "id": "95dd6769-d8b6-4c1e-a799-fb4c083a1b43", "comment": "", @@ -638,10 +638,24 @@ ["css=.d-flex:nth-child(4) > .py-2 > span", "css:finder"], ["xpath=//div[@id='root']/div/main/div/section/div/div/section[8]/div/div[2]/div[2]/div[4]/div/span", "xpath:idRelative"], ["xpath=//div[2]/div[4]/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] - ], - "value": "True" - }] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] + ], + "value": "true" + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "56040c8b-b45c-454e-b2ba-2a06056b397f", diff --git a/backend/src/integration/resources/SHIBUI-1744-3.side b/backend/src/integration/resources/SHIBUI-1744-3.side index 96d28a5c4..67e45e747 100644 --- a/backend/src/integration/resources/SHIBUI-1744-3.side +++ b/backend/src/integration/resources/SHIBUI-1744-3.side @@ -652,9 +652,9 @@ ["css=.d-flex:nth-child(3) > .py-2 > span", "css:finder"], ["xpath=//div[@id='filters']/ul/li/div[2]/section[3]/div/div[2]/div[2]/div[3]/div/span", "xpath:idRelative"], ["xpath=//section[3]/div/div[2]/div[2]/div[3]/div/span", "xpath:position"], - ["xpath=//span[contains(.,'True')]", "xpath:innerText"] + ["xpath=//span[contains(.,'true')]", "xpath:innerText"] ], - "value": "True" + "value": "true" }, { "id": "64723648-aef5-4c50-8605-74c5992ac628", "comment": "", @@ -665,7 +665,7 @@ ["xpath=//div[@id='filters']/ul/li/div[2]/section[3]/div/div[2]/div[2]/div[4]/div/span", "xpath:idRelative"], ["xpath=//section[3]/div/div[2]/div[2]/div[4]/div/span", "xpath:position"] ], - "value": "True" + "value": "true" }, { "id": "509ee76e-7d39-453e-a5cc-cf7b3975b476", "comment": "", @@ -676,8 +676,22 @@ ["xpath=//div[@id='filters']/ul/li/div[2]/section[3]/div/div[2]/div[2]/div[5]/div/span", "xpath:idRelative"], ["xpath=//section[3]/div/div[2]/div[2]/div[5]/div/span", "xpath:position"] ], - "value": "True" - }] + "value": "true" + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "56040c8b-b45c-454e-b2ba-2a06056b397f", diff --git a/backend/src/integration/resources/SHIBUI-2052.side b/backend/src/integration/resources/SHIBUI-2052.side index f034b03bf..6ae8a91a6 100644 --- a/backend/src/integration/resources/SHIBUI-2052.side +++ b/backend/src/integration/resources/SHIBUI-2052.side @@ -206,7 +206,21 @@ ["xpath=//span[contains(.,'nonadmin')]", "xpath:innerText"] ], "value": "nonadmin" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "c28e825e-e76e-4ff3-b9a8-1a7beacce942", diff --git a/backend/src/integration/resources/SHIBUI-2116.side b/backend/src/integration/resources/SHIBUI-2116.side index b1a7bb553..907704b91 100644 --- a/backend/src/integration/resources/SHIBUI-2116.side +++ b/backend/src/integration/resources/SHIBUI-2116.side @@ -508,18 +508,6 @@ ["xpath=//a[contains(.,'Add a new metadata provider')]", "xpath:innerText"] ], "value": "" - }, { - "id": "ab3f0a46-c48d-4521-b14a-c69bb30d781a", - "comment": "", - "command": "click", - "target": "css=.justify-content-start > .btn-primary", - "targets": [ - ["css=.justify-content-start > .btn-primary", "css:finder"], - ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], - ["xpath=//div[5]/div/div/div[3]/button", "xpath:position"], - ["xpath=//button[contains(.,'Discard Changes')]", "xpath:innerText"] - ], - "value": "" }, { "id": "f098bb58-cc06-401a-b231-1eeb73d13e76", "comment": "", @@ -829,7 +817,21 @@ "target": "xpath=//tr[contains(., 'employeeNumber') and contains(@class, 'text-light bg-info')]", "targets": [], "value": "" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "a8b8a626-3d99-42d2-9cd7-c801006ce420", diff --git a/backend/src/integration/resources/SHIBUI-2269.side b/backend/src/integration/resources/SHIBUI-2269.side new file mode 100644 index 000000000..f2848dddb --- /dev/null +++ b/backend/src/integration/resources/SHIBUI-2269.side @@ -0,0 +1,545 @@ +{ + "id": "1b31a551-eb09-4bd4-8db9-694bf1539a46", + "version": "2.0", + "name": "SHIBUI-2269", + "url": "http://localhost:10101", + "tests": [{ + "id": "841ade0e-83bd-4a4b-94f2-de6bd5c536b2", + "name": "SHIBUI-2269", + "commands": [{ + "id": "d6b23986-6d14-4b10-be7b-a7e6f576e3b2", + "comment": "", + "command": "open", + "target": "/login", + "targets": [], + "value": "" + }, { + "id": "f77ecd77-01c2-4463-944e-1a69600f5297", + "comment": "", + "command": "type", + "target": "name=username", + "targets": [ + ["name=username", "name"], + ["css=tr:nth-child(1) input", "css:finder"], + ["xpath=//input[@name='username']", "xpath:attributes"], + ["xpath=//input", "xpath:position"] + ], + "value": "admin" + }, { + "id": "c9bf0a22-faa9-494c-b2ed-6c9653248551", + "comment": "", + "command": "type", + "target": "name=password", + "targets": [ + ["name=password", "name"], + ["css=tr:nth-child(2) input", "css:finder"], + ["xpath=//input[@name='password']", "xpath:attributes"], + ["xpath=//tr[2]/td[2]/input", "xpath:position"] + ], + "value": "adminpass" + }, { + "id": "7ab1d854-3582-4101-bd19-f94b8f438090", + "comment": "", + "command": "sendKeys", + "target": "name=password", + "targets": [ + ["name=password", "name"], + ["css=tr:nth-child(2) input", "css:finder"], + ["xpath=//input[@name='password']", "xpath:attributes"], + ["xpath=//tr[2]/td[2]/input", "xpath:position"] + ], + "value": "${KEY_ENTER}" + }, { + "id": "4059cae7-b9f9-49d0-a213-343bcaba66d1", + "comment": "", + "command": "waitForElementVisible", + "target": "id=metadata-nav-dropdown-toggle", + "targets": [], + "value": "30000" + }, { + "id": "f03af8d5-5875-4a2c-b93a-c3ddcbd4b16a", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "081f495b-4d84-4758-824c-1e85b6311e7f", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }, { + "id": "9e912dd5-6ace-45be-bafd-2d1655906575", + "comment": "", + "command": "open", + "target": "/", + "targets": [], + "value": "" + }, { + "id": "3bb52950-667c-4852-a98f-6a6fb5632ba5", + "comment": "", + "command": "waitForElementEditable", + "target": "id=metadata-nav-dropdown-toggle", + "targets": [], + "value": "30000" + }, { + "id": "6af18279-b5ed-47d0-932b-cba97881b9bb", + "comment": "", + "command": "click", + "target": "id=metadata-nav-dropdown-toggle", + "targets": [ + ["id=metadata-nav-dropdown-toggle", "id"], + ["css=#metadata-nav-dropdown-toggle", "css:finder"], + ["xpath=//button[@id='metadata-nav-dropdown-toggle']", "xpath:attributes"], + ["xpath=//div[@id='metadata-nav-dropdown']/button", "xpath:idRelative"], + ["xpath=//div[2]/button", "xpath:position"], + ["xpath=//button[contains(.,'Add New')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "b07230f3-c268-4680-943f-5f8f81414002", + "comment": "", + "command": "click", + "target": "id=metadata-nav-dropdown-provider", + "targets": [ + ["id=metadata-nav-dropdown-provider", "id"], + ["linkText=Add a new metadata provider", "linkText"], + ["css=#metadata-nav-dropdown-provider", "css:finder"], + ["xpath=//a[contains(text(),'Add a new metadata provider')]", "xpath:link"], + ["xpath=//a[@id='metadata-nav-dropdown-provider']", "xpath:attributes"], + ["xpath=//div[@id='metadata-nav-dropdown']/div/a[2]", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/provider/new')]", "xpath:href"], + ["xpath=//a[2]", "xpath:position"], + ["xpath=//a[contains(.,'Add a new metadata provider')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "004dbab9-263e-4f90-9c5f-9d2948d80ab5", + "comment": "", + "command": "waitForElementEditable", + "target": "name=type", + "targets": [], + "value": "30000" + }, { + "id": "d77381c8-2164-499d-91fa-e762792644ec", + "comment": "", + "command": "select", + "target": "name=type", + "targets": [], + "value": "label=ExternalMetadataResolver" + }, { + "id": "8edf9e5e-188e-435d-acbd-a0ee770df39d", + "comment": "", + "command": "type", + "target": "name=name", + "targets": [ + ["name=name", "name"], + ["css=.form-control", "css:finder"], + ["xpath=//input[@name='name']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div/div/form/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "ExternalTest" + }, { + "id": "d652c1d5-44d2-448a-8dae-85d266b51638", + "comment": "", + "command": "click", + "target": "css=.direction", + "targets": [ + ["css=.direction", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/nav/ul/li[2]/button/span[2]", "xpath:idRelative"], + ["xpath=//span[2]", "xpath:position"], + ["xpath=//span[contains(.,'Next')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "d1294ac3-d91c-495a-ab0b-cc3183cc08d5", + "comment": "", + "command": "pause", + "target": "5000", + "targets": [], + "value": "" + }, { + "id": "b15dcd2a-9360-4831-a95c-8797eb235972", + "comment": "", + "command": "type", + "target": "id=root_xmlId", + "targets": [ + ["id=root_xmlId", "id"], + ["css=#root_xmlId", "css:finder"], + ["xpath=//input[@id='root_xmlId']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[2]/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "1" + }, { + "id": "657ee88c-4777-485b-b3de-a467657e6fe4", + "comment": "", + "command": "type", + "target": "id=root_description", + "targets": [ + ["id=root_description", "id"], + ["css=#root_description", "css:finder"], + ["xpath=//textarea[@id='root_description']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div[2]/div/div/form/div/div/div/div/div[2]/div[2]/div/div/textarea", "xpath:idRelative"], + ["xpath=//textarea", "xpath:position"] + ], + "value": "External Test" + }, { + "id": "5548997c-2f3a-4376-89a9-606b5b948ef1", + "comment": "", + "command": "click", + "target": "css=.label:nth-child(1)", + "targets": [ + ["css=.label:nth-child(1)", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div/nav/ul/li[3]/button/span", "xpath:idRelative"], + ["xpath=//li[3]/button/span", "xpath:position"], + ["xpath=//span[contains(.,'2. Finished!')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "826e7804-88f0-436e-9951-11e8065671ed", + "comment": "", + "command": "click", + "target": "css=.save", + "targets": [ + ["css=.save", "css:finder"], + ["xpath=(//button[@type='button'])[6]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div/nav/ul/li[3]/button", "xpath:idRelative"], + ["xpath=//li[3]/button", "xpath:position"] + ], + "value": "" + }, { + "id": "ab15e915-02b9-4616-9f92-ffcb0386918c", + "comment": "", + "command": "click", + "target": "linkText=ExternalTest", + "targets": [ + ["linkText=ExternalTest", "linkText"], + ["css=.align-middle > a", "css:finder"], + ["xpath=//a[contains(text(),'ExternalTest')]", "xpath:link"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/div/div/table/tbody/tr/td[2]/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/provider/0e237f9c-3ffe-49da-a60d-289733126d92/configuration/options')]", "xpath:href"], + ["xpath=//td[2]/a", "xpath:position"], + ["xpath=//a[contains(.,'ExternalTest')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "3ece6089-c462-437e-9384-62cede8afc7d", + "comment": "", + "command": "click", + "target": "linkText=Add Filter", + "targets": [ + ["linkText=Add Filter", "linkText"], + ["css=#filters .btn", "css:finder"], + ["xpath=//div[@id='filters']/div/div/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/provider/0e237f9c-3ffe-49da-a60d-289733126d92/filter/new')]", "xpath:href"], + ["xpath=//div[3]/div/div/a", "xpath:position"], + ["xpath=//a[contains(.,' Add Filter')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "b409c3ea-3066-4d06-a660-4702cdace6ec", + "comment": "", + "command": "waitForElementEditable", + "target": "name=type", + "targets": [], + "value": "30000" + }, { + "id": "84111b1d-6927-4536-b883-0b057f13d898", + "comment": "", + "command": "select", + "target": "name=type", + "targets": [], + "value": "label=EntityAttributes" + }, { + "id": "ec27be24-7951-4d76-9457-4a5dbe5866ef", + "comment": "", + "command": "waitForElementEditable", + "target": "id=root_name", + "targets": [], + "value": "30000" + }, { + "id": "bea341ae-4cdf-432e-8032-c827e9c8a7b8", + "comment": "", + "command": "type", + "target": "id=root_name", + "targets": [ + ["id=root_name", "id"], + ["css=#root_name", "css:finder"], + ["xpath=//input[@id='root_name']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "1" + }, { + "id": "79f5b0a9-57e9-4f6b-8980-4af6258a5aa4", + "comment": "", + "command": "click", + "target": "id=dropdown-label.filter-target-type", + "targets": [ + ["id=dropdown-label.filter-target-type", "id"], + ["css=#dropdown-label\\.filter-target-type", "css:finder"], + ["xpath=//button[@id='dropdown-label.filter-target-type']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[6]/div/div/div/fieldset/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//fieldset/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Entity ID ')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "d01e44ab-802b-4d85-ac2e-e2e03a00c1c0", + "comment": "", + "command": "click", + "target": "css=.dropdown-item:nth-child(3)", + "targets": [ + ["css=.dropdown-item:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[17]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[6]/div/div/div/fieldset/div/div/div/div/div/button[3]", "xpath:idRelative"], + ["xpath=//div/button[3]", "xpath:position"], + ["xpath=//button[contains(.,'Script')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f401438a-0154-4610-be40-580829ba76a9", + "comment": "", + "command": "type", + "target": "css=.npm__react-simple-code-editor__textarea", + "targets": [ + ["css=.npm__react-simple-code-editor__textarea", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[6]/div/div/div/fieldset/div/div/div[2]/div/div/div/div/textarea", "xpath:idRelative"], + ["xpath=//textarea", "xpath:position"] + ], + "value": "true;" + }, { + "id": "75563d4f-487d-4c08-81d9-26a8ef989711", + "comment": "", + "command": "click", + "target": "css=.btn-info", + "targets": [ + ["css=.btn-info", "css:finder"], + ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div/div[2]/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/button", "xpath:position"], + ["xpath=//button[contains(.,' Save')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "21f5c73b-0aa2-41cd-a97c-35c05a892275", + "comment": "", + "command": "click", + "target": "linkText=Add Filter", + "targets": [ + ["linkText=Add Filter", "linkText"], + ["css=#filters > .numbered-header .btn", "css:finder"], + ["xpath=//div[@id='filters']/div/div/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/metadata/provider/0e237f9c-3ffe-49da-a60d-289733126d92/filter/new')]", "xpath:href"], + ["xpath=//div[3]/div/div/a", "xpath:position"], + ["xpath=//a[contains(.,' Add Filter')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "6eb76a2f-370a-4547-b05e-f0dc8bdb60ba", + "comment": "", + "command": "select", + "target": "name=type", + "targets": [], + "value": "label=NameIDFormat" + }, { + "id": "fcacadd8-7b9e-4878-b1cc-3d5da56e6660", + "comment": "", + "command": "click", + "target": "css=.col-12 > .mb-3 > div > div", + "targets": [ + ["css=.col-12 > .mb-3 > div > div", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div/div/div/div/div", "xpath:idRelative"], + ["xpath=//div/div/div/div/div/div/div/div", "xpath:position"] + ], + "value": "" + }, { + "id": "4d206821-ace7-483e-876e-99c7a0490144", + "comment": "", + "command": "waitForElementEditable", + "target": "id=root_name", + "targets": [], + "value": "30000" + }, { + "id": "62afd5f1-e565-4bb8-a142-9eda83e98a1c", + "comment": "", + "command": "type", + "target": "id=root_name", + "targets": [ + ["id=root_name", "id"], + ["css=#root_name", "css:finder"], + ["xpath=//input[@id='root_name']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "2" + }, { + "id": "da90db0c-c7e6-4dc5-b643-13a3c2029f05", + "comment": "", + "command": "click", + "target": "id=dropdown-label.filter-target-type", + "targets": [ + ["id=dropdown-label.filter-target-type", "id"], + ["css=#dropdown-label\\.filter-target-type", "css:finder"], + ["xpath=//button[@id='dropdown-label.filter-target-type']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[3]/div/div/div/fieldset/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//fieldset/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Entity ID ')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "bce0cd29-246e-4f6e-a860-0eade5c73850", + "comment": "", + "command": "click", + "target": "css=.dropdown-item:nth-child(3)", + "targets": [ + ["css=.dropdown-item:nth-child(3)", "css:finder"], + ["xpath=(//button[@type='button'])[16]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[3]/div/div/div/fieldset/div/div/div/div/div/button[3]", "xpath:idRelative"], + ["xpath=//button[3]", "xpath:position"], + ["xpath=//button[contains(.,'Script')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "2923ab38-d8ff-4d3f-b247-1d977d06a0dd", + "comment": "", + "command": "click", + "target": "id=dropdown-label.filter-target-type", + "targets": [ + ["id=dropdown-label.filter-target-type", "id"], + ["css=#dropdown-label\\.filter-target-type", "css:finder"], + ["xpath=//button[@id='dropdown-label.filter-target-type']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[3]/div/div/div/fieldset/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//fieldset/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Script ')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "7141ca97-429a-4d1f-9efb-68a23fc92748", + "comment": "", + "command": "click", + "target": "css=.show > .dropdown-item:nth-child(2)", + "targets": [ + ["css=.show > .dropdown-item:nth-child(2)", "css:finder"], + ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[3]/div/div/div/fieldset/div/div/div/div/div/button[2]", "xpath:idRelative"], + ["xpath=//fieldset/div/div/div/div/div/button[2]", "xpath:position"], + ["xpath=//button[contains(.,'Regex')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "e15eab26-07bd-45e9-ba8e-ee2a400baee9", + "comment": "", + "command": "type", + "target": "id=targetInput", + "targets": [ + ["id=targetInput", "id"], + ["name=script", "name"], + ["css=#targetInput", "css:finder"], + ["xpath=//input[@id='targetInput']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/div[2]/div[2]/div[2]/div/form/div/div/div/div[3]/div/div/div/fieldset/div/div/div[2]/div/div/input", "xpath:idRelative"], + ["xpath=//div[2]/div/div/input", "xpath:position"] + ], + "value": ".*unicon.*" + }, { + "id": "55cc5ef6-1b05-48a9-bc9d-58551b751feb", + "comment": "", + "command": "click", + "target": "css=.fa-floppy-disk > path", + "targets": [ + ["css=.fa-floppy-disk > path", "css:finder"] + ], + "value": "" + }, { + "id": "802be014-0d04-4bda-93d1-ca7a5d7f802d", + "comment": "", + "command": "waitForElementVisible", + "target": "css=.text:nth-child(2)", + "targets": [ + ["css=.text:nth-child(2)", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div/section/div/div/h2/span[2]", "xpath:idRelative"], + ["xpath=//h2/span[2]", "xpath:position"], + ["xpath=//span[contains(.,'Common Attributes')]", "xpath:innerText"] + ], + "value": "30000" + }, { + "id": "7e3e7d65-e0ff-4a2d-a0e9-5080bfefd4df", + "comment": "", + "command": "click", + "target": "css=.btn-outline-secondary", + "targets": [ + ["css=.btn-outline-secondary", "css:finder"], + ["xpath=(//button[@type='button'])[5]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div/div/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Enable')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "42929ec9-7860-467a-a52b-946df9965de5", + "comment": "", + "command": "click", + "target": "xpath=//div[@id='filters']/ul/li/div/span[3]/div/input", + "targets": [ + ["id=customSwitch-df84f9b7-6cbe-4727-b71e-733eb9b46ca0", "id"], + ["css=#customSwitch-df84f9b7-6cbe-4727-b71e-733eb9b46ca0", "css:finder"], + ["xpath=//input[@id='customSwitch-df84f9b7-6cbe-4727-b71e-733eb9b46ca0']", "xpath:attributes"], + ["xpath=//div[@id='filters']/ul/li/div/span[3]/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "" + }, { + "id": "3bb95cdd-23aa-425d-af75-e4d69b819235", + "comment": "", + "command": "click", + "target": "xpath=//div[@id='filters']/ul/li[2]/div/span[3]/div/input", + "targets": [ + ["id=customSwitch-be9ce5a5-1242-4884-882a-7a977cd7bbd5", "id"], + ["css=#customSwitch-be9ce5a5-1242-4884-882a-7a977cd7bbd5", "css:finder"], + ["xpath=//input[@id='customSwitch-be9ce5a5-1242-4884-882a-7a977cd7bbd5']", "xpath:attributes"], + ["xpath=//div[@id='filters']/ul/li[2]/div/span[3]/div/input", "xpath:idRelative"], + ["xpath=//li[2]/div/span[3]/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "038ab74e-cab9-486e-bbfc-25a7c1cfad82", + "comment": "", + "command": "open", + "target": "/api/MetadataResolvers/External", + "targets": [], + "value": "" + }, { + "id": "9e6390c9-3122-4038-8dce-61ae0c157e4a", + "comment": "", + "command": "assertText", + "target": "css=#folder4 > .opened > .line > span", + "targets": [ + ["css=#folder4 > .opened > .line > span", "css:finder"] + ], + "value": "" + }, { + "id": "8c32b412-dc63-4be5-98fb-8c3cd67895af", + "comment": "", + "command": "assertText", + "target": "css=#folder7 > .opened > .line > span", + "targets": [ + ["css=#folder7 > .opened > .line > span", "css:finder"] + ], + "value": "" + }] + }], + "suites": [{ + "id": "d2caeac4-7520-4e3c-96b1-840610b6983c", + "name": "Default Suite", + "persistSession": false, + "parallel": false, + "timeout": 300, + "tests": ["841ade0e-83bd-4a4b-94f2-de6bd5c536b2"] + }], + "urls": ["http://localhost:10101/"], + "plugins": [] +} \ No newline at end of file diff --git a/backend/src/integration/resources/SHIBUI-950.side b/backend/src/integration/resources/SHIBUI-950.side index afe6b423e..dc7e5fd1b 100644 --- a/backend/src/integration/resources/SHIBUI-950.side +++ b/backend/src/integration/resources/SHIBUI-950.side @@ -220,7 +220,21 @@ ["xpath=//td[contains(.,'https://wiki.shibboleth.net/shibboleth')]", "xpath:innerText"] ], "value": "https://wiki.shibboleth.net/shibboleth" - }] + },{ + "id": "4ec2c493-85e4-403b-9b09-031c5728f498", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "e074980a-8f21-4c22-8412-c4b6fcdcd1a4", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] }], "suites": [{ "id": "9199306b-76bb-4caa-8493-4915a82d53f6", diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy index 556adb962..5ae31882c 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityAttributesFiltersUiDefinitionController.groovy @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry import edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService +import io.swagger.v3.oas.annotations.tags.Tag +import io.swagger.v3.oas.annotations.tags.Tags import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping @@ -24,6 +26,7 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR */ @RestController @RequestMapping('/api/ui/EntityAttributesFilters') +@Tags(value = [@Tag(name = "ui")]) class EntityAttributesFiltersUiDefinitionController { @Autowired @@ -58,4 +61,4 @@ class EntityAttributesFiltersUiDefinitionController { void init() { this.jsonSchemaLocation = entityAttributesFiltersSchema(this.jsonSchemaResourceLocationRegistry); } -} +} \ No newline at end of file diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy index e6c878b0b..fe4a54434 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolverUiDefinitionController.groovy @@ -3,6 +3,8 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry +import io.swagger.v3.oas.annotations.tags.Tag +import io.swagger.v3.oas.annotations.tags.Tags import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping @@ -10,12 +12,12 @@ import org.springframework.web.bind.annotation.PathVariable import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.dynamicHttpMetadataProviderSchema +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.externalMetadataProviderSchema import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.filesystemMetadataProviderSchema import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.localDynamicMetadataProviderSchema -import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaLocationLookup.dynamicHttpMetadataProviderSchema -import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType - +import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR /** * Controller implementing REST resource responsible for exposing structure definition for metadata resolvers user * interface in terms of JSON schema. @@ -25,6 +27,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResour */ @RestController @RequestMapping('/api/ui/MetadataResolver') +@Tags(value = [@Tag(name = "ui")]) class MetadataResolverUiDefinitionController { @Autowired @@ -47,6 +50,9 @@ class MetadataResolverUiDefinitionController { case SchemaType.DYNAMIC_HTTP_METADATA_RESOLVER: jsonSchemaLocation = dynamicHttpMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry) break + case SchemaType.EXTERNAL_METADATA_RESOLVER: + jsonSchemaLocation = externalMetadataProviderSchema(this.jsonSchemaResourceLocationRegistry) + break default: throw new UnsupportedOperationException("Json schema for an unsupported metadata resolver (" + resolverType + ") was requested") } @@ -66,4 +72,4 @@ class MetadataResolverUiDefinitionController { ResponseEntity getResolverTypes() { return ResponseEntity.ok(SchemaType.getResolverTypes()) } -} +} \ No newline at end of file diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy index bf685db05..db00c31d3 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataSourcesUiDefinitionController.groovy @@ -4,6 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry import edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService +import io.swagger.v3.oas.annotations.tags.Tag +import io.swagger.v3.oas.annotations.tags.Tags import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired @@ -26,6 +28,7 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR */ @RestController @RequestMapping('/api/ui/MetadataSources') +@Tags(value = [@Tag(name = "ui")]) class MetadataSourcesUiDefinitionController { private static final Logger logger = LoggerFactory.getLogger(MetadataSourcesUiDefinitionController.class); @@ -63,4 +66,4 @@ class MetadataSourcesUiDefinitionController { void init() { this.jsonSchemaLocation = metadataSourcesSchema(this.jsonSchemaResourceLocationRegistry); } -} +} \ No newline at end of file diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/NameIdFormatFilterUiDefinitionController.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/NameIdFormatFilterUiDefinitionController.groovy index 3dcfcaffe..2283183be 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/NameIdFormatFilterUiDefinitionController.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/NameIdFormatFilterUiDefinitionController.groovy @@ -5,6 +5,8 @@ import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocat import edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocationRegistry import edu.internet2.tier.shibboleth.admin.ui.service.JsonSchemaBuilderService import groovy.util.logging.Slf4j +import io.swagger.v3.oas.annotations.tags.Tag +import io.swagger.v3.oas.annotations.tags.Tags import org.springframework.beans.factory.annotation.Autowired import org.springframework.http.ResponseEntity import org.springframework.web.bind.annotation.GetMapping @@ -25,6 +27,7 @@ import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR @RestController @RequestMapping('/api/ui/NameIdFormatFilter') @Slf4j +@Tags(value = [@Tag(name = "ui")]) class NameIdFormatFilterUiDefinitionController { @Autowired @@ -57,4 +60,4 @@ class NameIdFormatFilterUiDefinitionController { void init() { this.jsonSchemaLocation = nameIdFormatFilterSchema(this.jsonSchemaResourceLocationRegistry) } -} +} \ No newline at end of file diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy index 79420f6d0..170a45fa8 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImpl.groovy @@ -11,6 +11,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilF import edu.internet2.tier.shibboleth.admin.ui.domain.filters.SignatureValidationFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.opensaml.OpenSamlNameIdFormatFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FilesystemMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver @@ -32,7 +33,7 @@ import groovy.util.logging.Slf4j import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder import net.shibboleth.utilities.java.support.scripting.EvaluableScript -import org.apache.commons.collections.CollectionUtils +import org.apache.commons.collections4.CollectionUtils import org.opensaml.saml.common.profile.logic.EntityIdPredicate import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilter @@ -286,6 +287,12 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } + void constructXmlNodeForResolver(ExternalMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) { + markupBuilderDelegate.MetadataFilters(providerRef: resolver.getXmlId()) { + childNodes() + } + } + void constructXmlNodeForResolver(FileBackedHttpMetadataResolver resolver, def markupBuilderDelegate, Closure childNodes) { markupBuilderDelegate.MetadataProvider(id: resolver.xmlId, 'xsi:type': 'FileBackedHTTPMetadataProvider', @@ -419,7 +426,7 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { MetadataResource( 'xmlns:resource': 'urn:mace:shibboleth:2.0:resource', 'xsi:type': 'resource:ClasspathResource', - 'file': resolver.classpathMetadataResource.file) + 'file': resolver.classpathMetadataResource.fileResource) } childNodes() @@ -449,11 +456,11 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { 'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:resource http://shibboleth.net/schema/idp/shibboleth-resource.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd' ) { - resolversPositionOrderContainerService.allMetadataResolversInDefinedOrderOrUnordered.each { edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr -> - //TODO: We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type) - if ((mr.type != 'BaseMetadataResolver') && (mr.enabled)) { + // We do not currently marshall the internal incommon chaining resolver (with BaseMetadataResolver type) + // We do not want to include the custom type: ExternalMetadataResolver + if ((mr.type != 'BaseMetadataResolver') && (mr.type != 'ExternalMetadataResolver') && (mr.enabled)) { constructXmlNodeForResolver(mr, delegate) { //TODO: enhance def didNamespaceProtectionFilter = !(shibUIConfiguration.protectedAttributeNamespaces && shibUIConfiguration.protectedAttributeNamespaces.size() > 0) @@ -478,6 +485,42 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } + @Override + Document generateExternalMetadataFilterConfiguration() { + // TODO: this can probably be a better writer + new StringWriter().withCloseable { writer -> + def xml = new MarkupBuilder(writer) + xml.omitEmptyAttributes = true + xml.omitNullAttributes = true + + // https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1279033515/ByReferenceFilter + xml.MetadataFilter( + 'xsi:type': 'ByReference', + 'xmlns:xsi': 'http://www.w3.org/2001/XMLSchema-instance', + 'xsi:schemaLocation': 'urn:mace:shibboleth:2.0:metadata http://shibboleth.net/schema/idp/shibboleth-metadata.xsd urn:mace:shibboleth:2.0:security http://shibboleth.net/schema/idp/shibboleth-security.xsd urn:oasis:names:tc:SAML:2.0:assertion http://docs.oasis-open.org/security/saml/v2.0/saml-schema-assertion-2.0.xsd urn:oasis:names:tc:SAML:2.0:metadata http://docs.oasis-open.org/security/saml/v2.0/saml-schema-metadata-2.0.xsd', + 'xmlns:md': 'urn:oasis:names:tc:SAML:2.0:metadata', + 'xmlns': 'urn:mace:shibboleth:2.0:metadata', + 'xmlns:security': 'urn:mace:shibboleth:2.0:security', + 'xmlns:saml2': 'urn:oasis:names:tc:SAML:2.0:assertion' + ) { + resolversPositionOrderContainerService.allMetadataResolversInDefinedOrderOrUnordered.each { + edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver mr -> + // Only include the custom type: ExternalMetadataResolver + if ((mr.type == 'ExternalMetadataResolver') && (mr.enabled)) { + constructXmlNodeForResolver(mr, delegate) { + mr.metadataFilters.each { edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter filter -> + if (filter.isFilterEnabled()) { + constructXmlNodeForFilter(filter, delegate) + } + } + } + } + } + } + return DOMBuilder.newInstance().parseText(writer.toString()) + } + } + private String generateJavaScriptRegexScript(String regex) { return """ "use strict"; diff --git a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy index dd8bf8954..5109ee46c 100644 --- a/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy +++ b/backend/src/main/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JsonSchemaBuilderService.groovy @@ -33,6 +33,9 @@ class JsonSchemaBuilderService { result.addAll(customPropertiesConfiguration.getAttributes().collect { it['name'] }) + resultNames.addAll(customPropertiesConfiguration.getAttributes().collect { + it['displayName'] + }) json['enum'] = result json['enumNames'] = resultNames diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java index d539ad025..41393a625 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/ShibbolethUiApplication.java @@ -2,6 +2,8 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService; +import io.swagger.v3.oas.annotations.OpenAPIDefinition; +import io.swagger.v3.oas.annotations.info.Info; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -31,6 +33,7 @@ @EnableScheduling @EnableWebSecurity @EnableAsync +@OpenAPIDefinition(info=@Info(description = "The Shibboleth UI is specifically designed to help manage and edit metadata-driven configuration support for Shibboleth", title = "Shibboleth UI API", version = "1.0")) public class ShibbolethUiApplication extends SpringBootServletInitializer { private static final Logger logger = LoggerFactory.getLogger(ShibbolethUiApplication.class); @@ -86,4 +89,4 @@ public void initializeResolvers(ApplicationStartedEvent e) { }); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java index c897a31b5..fdc85e20f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/CoreShibUiConfiguration.java @@ -6,6 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolversPositionOrderContainerRepository; import edu.internet2.tier.shibboleth.admin.ui.scheduled.EntityDescriptorFilesScheduledTasks; +import edu.internet2.tier.shibboleth.admin.ui.scheduled.ExternalMetadataProvidersScheduledTasks; import edu.internet2.tier.shibboleth.admin.ui.scheduled.MetadataProvidersScheduledTasks; import edu.internet2.tier.shibboleth.admin.ui.security.model.listener.GroupUpdatedEntityListener; import edu.internet2.tier.shibboleth.admin.ui.security.model.listener.UserUpdatedEntityListener; @@ -88,6 +89,14 @@ public MetadataProvidersScheduledTasks metadataProvidersScheduledTasks( return new MetadataProvidersScheduledTasks(resource, metadataResolverService, fileWritingService()); } + @Bean + @ConditionalOnProperty(name = "shibui.external.metadataProviders.target") + public ExternalMetadataProvidersScheduledTasks externalMetadataProvidersScheduledTasks( + @Value("${shibui.external.metadataProviders.target}") final Resource resource, + final MetadataResolverService metadataResolverService) { + return new ExternalMetadataProvidersScheduledTasks(resource, metadataResolverService, fileWritingService()); + } + @Bean public EntityIdsSearchService entityIdsSearchService(LuceneUtility luceneUtility, Analyzer fullTokenAnalyzer) { return new EntityIdsSearchServiceImpl(luceneUtility, fullTokenAnalyzer); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java index d483319f3..34c5c1eaf 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/JsonSchemaComponentsConfiguration.java @@ -14,6 +14,7 @@ import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.*; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.EXTERNAL_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; @@ -57,6 +58,8 @@ public class JsonSchemaComponentsConfiguration { @Setter private String nameIdFormatFilterUiSchemaLocation = "classpath:nameid-filter.schema.json"; + private String externalMetadataResolverUiSchemaLocation = "classpath:external.schema.json"; + @Bean public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(ResourceLoader resourceLoader, ObjectMapper jacksonMapper) { return JsonSchemaResourceLocationRegistry.inMemory() @@ -90,6 +93,12 @@ public JsonSchemaResourceLocationRegistry jsonSchemaResourceLocationRegistry(Res .jacksonMapper(jacksonMapper) .detectMalformedJson(true) .build()) + .register(EXTERNAL_METADATA_RESOLVER, JsonSchemaLocationBuilder.with() + .jsonSchemaLocation(externalMetadataResolverUiSchemaLocation) + .resourceLoader(resourceLoader) + .jacksonMapper(jacksonMapper) + .detectMalformedJson(true) + .build()) .register(NAME_ID_FORMAT_FILTER, JsonSchemaLocationBuilder.with() .jsonSchemaLocation(nameIdFormatFilterUiSchemaLocation) .resourceLoader(resourceLoader) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java index 1c8a86907..43539d77d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/StaticResourcesConfiguration.java @@ -1,7 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.web.ResourceProperties; +import org.springframework.boot.autoconfigure.web.WebProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.Resource; @@ -17,7 +17,7 @@ */ @Configuration -@EnableConfigurationProperties({ResourceProperties.class}) +@EnableConfigurationProperties({WebProperties.class}) public class StaticResourcesConfiguration implements WebMvcConfigurer { static final String[] STATIC_RESOURCES = new String[]{ "/**/*.css", @@ -36,16 +36,17 @@ public class StaticResourcesConfiguration implements WebMvcConfigurer { }; @Autowired - private ResourceProperties resourceProperties = new ResourceProperties(); + private WebProperties resourceProperties = new WebProperties(); @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler(STATIC_RESOURCES) - .addResourceLocations(resourceProperties.getStaticLocations()) + .addResourceLocations(resourceProperties.getResources().getStaticLocations()) .setCachePeriod(10); registry.addResourceHandler("/**") .addResourceLocations( - Arrays.stream(resourceProperties.getStaticLocations()) + Arrays.stream(resourceProperties.getResources().getStaticLocations()) .map(l -> l + "index.html") .toArray(String[]::new) ) @@ -59,4 +60,4 @@ protected Resource getResource(String resourcePath, Resource location) throws IO } ); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/SwaggerConfig.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/SwaggerConfig.java deleted file mode 100644 index 1f48b6e2f..000000000 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/SwaggerConfig.java +++ /dev/null @@ -1,23 +0,0 @@ -package edu.internet2.tier.shibboleth.admin.ui.configuration; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.PathSelectors; -import springfox.documentation.builders.RequestHandlerSelectors; -import springfox.documentation.spi.DocumentationType; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.swagger2.annotations.EnableSwagger2; - -@Configuration -@EnableSwagger2 -public class SwaggerConfig { - - @Bean - public Docket api() { - return new Docket(DocumentationType.SWAGGER_2) - .select() - .apis(RequestHandlerSelectors.any()) - .paths(PathSelectors.regex("/api/.*")) - .build(); - } -} diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java index 8584ff303..f04f2f716 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/WebSecurityConfig.java @@ -135,6 +135,7 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception { public void configure(WebSecurity web) throws Exception { super.configure(web); web.httpFirewall(allowUrlEncodedSlashHttpFirewall()); + web.ignoring().antMatchers("/actuator/**"); } }; } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateController.java index 60705cd15..c9e0f20f5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateController.java @@ -2,6 +2,8 @@ import javax.script.ScriptException; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -25,6 +27,7 @@ @RestController @RequestMapping("/api/activate") +@Tags(value = {@Tag(name = "activate")}) public class ActivateController { @Autowired @@ -62,4 +65,4 @@ public ResponseEntity enableProvider(@PathVariable String resourceId, @PathVa return ResponseEntity.ok(existingResolver); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java index 1dbe5e026..92c498781 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleController.java @@ -7,6 +7,8 @@ import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupExistsConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.model.Group; import edu.internet2.tier.shibboleth.admin.ui.service.AttributeBundleService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -25,6 +27,7 @@ @RestController @RequestMapping("/api/custom/entity/bundles") @Slf4j +@Tags(value = {@Tag(name = "bundles")}) public class AttributeBundleController { @Autowired AttributeBundleService attributeBundleService; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ConfigurationController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ConfigurationController.java index fa458816a..b9c58d60f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ConfigurationController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ConfigurationController.java @@ -3,19 +3,20 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration; import edu.internet2.tier.shibboleth.admin.ui.security.model.Role; import edu.internet2.tier.shibboleth.admin.ui.security.repository.RoleRepository; -import edu.internet2.tier.shibboleth.admin.ui.service.EmailService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.stream.Collectors; /** * @author Bill Smith (wsmith@unicon.net) */ -@Controller +@RestController @RequestMapping(value = "/api") public class ConfigurationController { @@ -26,12 +27,14 @@ public class ConfigurationController { RoleRepository roleRepository; @GetMapping(value = "/customAttributes") + @Tags(value = {@Tag(name = "attributes")}) public ResponseEntity getCustomAttributes() { return ResponseEntity.ok(customPropertiesConfiguration.getAttributes()); } @GetMapping(value = "/supportedRoles") + @Tags(value = {@Tag(name = "admin")}) public ResponseEntity getSupportedRoles() { return ResponseEntity.ok(roleRepository.findAll().stream().map(Role::getName).collect(Collectors.toList())); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java index bd683de22..517be9958 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/CustomEntityAttributesDefinitionsController.java @@ -1,10 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; +import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition; +import edu.internet2.tier.shibboleth.admin.ui.service.CustomEntityAttributesDefinitionService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -13,13 +16,12 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.support.ServletUriComponentsBuilder; -import edu.internet2.tier.shibboleth.admin.ui.domain.CustomEntityAttributeDefinition; -import edu.internet2.tier.shibboleth.admin.ui.service.CustomEntityAttributesDefinitionService; - -@Controller +@RestController @RequestMapping(value = "/api/custom/entity") +@Tags(value = {@Tag(name = "attributes")}) public class CustomEntityAttributesDefinitionsController { @Autowired private CustomEntityAttributesDefinitionService caService; @@ -102,4 +104,4 @@ public ResponseEntity delete(@PathVariable String resourceId) { caService.deleteDefinition(cad); return ResponseEntity.noContent().build(); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesController.java index 6adc4c95b..9e0425d00 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesController.java @@ -1,15 +1,14 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.text.SimpleDateFormat; -import java.time.Instant; -import java.time.ZoneOffset; -import java.time.format.DateTimeFormatter; -import java.util.Date; - -import javax.servlet.http.HttpServletRequest; - +import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; +import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; +import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; +import lombok.extern.slf4j.Slf4j; +import net.shibboleth.utilities.java.support.resolver.ResolverException; import org.apache.http.client.utils.DateUtils; import org.opensaml.core.xml.io.MarshallingException; import org.opensaml.saml.saml2.metadata.EntityDescriptor; @@ -17,28 +16,29 @@ import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; -import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; -import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; -import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; -import lombok.extern.slf4j.Slf4j; -import net.shibboleth.utilities.java.support.resolver.ResolverException; +import javax.servlet.http.HttpServletRequest; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.time.Instant; +import java.time.ZoneOffset; +import java.util.Date; -@Controller +/** + * EntitiesController is here to meet the requirements for this project being an MDQ. Despite similar logic to the + * EntitiesDescriptorController, the required endpoints that make this project an MDQ server are served by this controller. + */ +@RestController @RequestMapping(value = { "/entities", // per protocol - https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol "/api/entities" }, // existing - included to break no existing code method = RequestMethod.GET) @Slf4j -/** -* EntitiesController is here to meet the requirements for this project being an MDQ. Despite similar logic to the -* EntitiesDescriptorController, the required endpoints that make this project an MDQ server are served by this controller. -*/ +@Tags(value = {@Tag(name = "MDQ")}) public class EntitiesController { @Autowired private EntityDescriptorService entityDescriptorService; @@ -50,6 +50,8 @@ public class EntitiesController { private EntityDescriptorRepository entityDescriptorRepository; @RequestMapping(value = "/{entityId:.*}") + @Operation(description = "Endpoint based on the MDQ spec to return a single entity's information. see: https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol", + summary = "Return a single entity from the entity's id", method = "GET") @Transactional(readOnly = true) public ResponseEntity getOne(final @PathVariable String entityId, HttpServletRequest request) throws UnsupportedEncodingException, ResolverException { EntityDescriptor entityDescriptor = this.getEntityDescriptor(entityId); @@ -69,6 +71,8 @@ private String formatModifiedDate(EntityDescriptorRepresentation entityDescripto } @RequestMapping(value = "/{entityId:.*}", produces = "application/xml") + @Operation(description = "Endpoint based on the MDQ spec to return a single entity's information. see: https://spaces.at.internet2.edu/display/MDQ/Metadata+Query+Protocol", + summary = "Return a single entity from the entity's id", method = "GET") @Transactional(readOnly = true) public ResponseEntity getOneXml(final @PathVariable String entityId) throws MarshallingException, ResolverException, UnsupportedEncodingException { EntityDescriptor entityDescriptor = this.getEntityDescriptor(entityId); @@ -91,4 +95,4 @@ private EntityDescriptor getEntityDescriptor(final String entityId) throws Resol } return entityDescriptor; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java index 3122eb90e..c2d9b81a0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorController.java @@ -9,6 +9,8 @@ import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorVersionService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import lombok.extern.slf4j.Slf4j; import org.opensaml.core.xml.io.MarshallingException; import org.springframework.beans.factory.annotation.Autowired; @@ -35,6 +37,7 @@ @RestController @RequestMapping("/api") @Slf4j +@Tags(value = {@Tag(name = "entity")}) public class EntityDescriptorController { static URI getResourceUriFor(String resourceId) { return ServletUriComponentsBuilder diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java index 034556c92..13db0fd22 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityIdsSearchController.java @@ -1,6 +1,8 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; import edu.internet2.tier.shibboleth.admin.ui.service.EntityIdsSearchService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @@ -10,6 +12,7 @@ @RestController @RequestMapping("/api/EntityIds/search") +@Tags(value = {@Tag(name = "entity")}) public class EntityIdsSearchController { EntityIdsSearchService entityIdsSearchService; @@ -26,4 +29,4 @@ ResponseEntity search(@RequestParam(required = false) String resourceId, final int resultLimit = (limit != null ? limit : 10); return ResponseEntity.ok(this.entityIdsSearchService.findBySearchTermAndOptionalLimit(resourceId, term, resultLimit)); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/InternationalizationMessagesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/InternationalizationMessagesController.java index c5ec89f6c..288533290 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/InternationalizationMessagesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/InternationalizationMessagesController.java @@ -1,11 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; import edu.internet2.tier.shibboleth.admin.ui.i18n.MappedResourceBundleMessageSource; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.Collections; import java.util.HashSet; @@ -18,8 +20,9 @@ /** * @author Bill Smith (wsmith@unicon.net) */ -@Controller +@RestController @RequestMapping(value = "/api/messages") +@Tags(value = {@Tag(name = "messages")}) public class InternationalizationMessagesController { @Autowired MappedResourceBundleMessageSource messageSource; @@ -57,4 +60,4 @@ private Set getResourceBundles() { return Collections.unmodifiableSet(resourceBundles); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java index a9191dffc..a70fc2f9b 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersController.java @@ -9,6 +9,9 @@ import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService; import static java.util.stream.Collectors.toList; + +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import static org.springframework.http.HttpStatus.BAD_REQUEST; @@ -38,6 +41,7 @@ @RestController @RequestMapping("/api/MetadataResolvers/{metadataResolverId}") +@Tags(value = {@Tag(name = "metadata filters")}) public class MetadataFiltersController { private static final Supplier HTTP_400_BAD_REQUEST_EXCEPTION = () -> new HttpClientErrorException(BAD_REQUEST); private static final Supplier HTTP_404_CLIENT_ERROR_EXCEPTION = () -> new HttpClientErrorException(NOT_FOUND); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersPositionOrderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersPositionOrderController.java index 4c7d70ec0..fc44c188c 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersPositionOrderController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersPositionOrderController.java @@ -4,6 +4,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; @@ -26,6 +28,7 @@ */ @RestController @RequestMapping("/api/MetadataResolvers/{metadataResolverId}/FiltersPositionOrder") +@Tags(value = {@Tag(name = "metadata filters")}) public class MetadataFiltersPositionOrderController { @Autowired @@ -80,4 +83,4 @@ public ResponseEntity getFiltersPositionOrder(@PathVariable String metadataRe return ResponseEntity.ok(resourceIds); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java index d8e09ff56..6a11f07a2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversController.java @@ -13,6 +13,8 @@ import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverVersionService; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolversPositionOrderContainerService; import edu.internet2.tier.shibboleth.admin.util.OpenSamlChainingMetadataResolverUtil; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import lombok.extern.slf4j.Slf4j; import net.shibboleth.utilities.java.support.component.ComponentInitializationException; import net.shibboleth.utilities.java.support.resolver.ResolverException; @@ -48,6 +50,7 @@ @RestController @RequestMapping("/api") @Slf4j +@Tags(value = {@Tag(name = "metadata resolvers")}) public class MetadataResolversController { @Autowired @@ -79,7 +82,7 @@ public ResponseEntity unableToParseJson(Exception ex) { return ResponseEntity.badRequest().body(new ErrorResponse(HttpStatus.BAD_REQUEST.toString(), ex.getMessage(), ex.getCause().getMessage())); } - @GetMapping("/MetadataResolvers") + @GetMapping(value = "/MetadataResolvers", produces = "application/json") @Transactional(readOnly = true) public ResponseEntity getAll() { List resolvers = positionOrderContainerService.getAllMetadataResolversInDefinedOrderOrUnordered(); @@ -89,7 +92,6 @@ public ResponseEntity getAll() { @GetMapping(value = "/MetadataResolvers", produces = "application/xml") @Transactional(readOnly = true) public ResponseEntity getXml() throws IOException, TransformerException { - // TODO: externalize try (StringWriter writer = new StringWriter()) { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); @@ -100,6 +102,19 @@ public ResponseEntity getXml() throws IOException, TransformerException { } } + @GetMapping(value = "/MetadataResolvers/External", produces = "application/xml") + @Transactional(readOnly = true) + public ResponseEntity getExternalXml() throws IOException, TransformerException { + try (StringWriter writer = new StringWriter()) { + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + transformer.transform(new DOMSource(metadataResolverService.generateExternalMetadataFilterConfiguration()), new StreamResult(writer)); + return ResponseEntity.ok(writer.toString()); + } + } + @GetMapping("/MetadataResolvers/{resourceId}") @Transactional(readOnly = true) public ResponseEntity getOne(@PathVariable String resourceId) { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversPositionOrderController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversPositionOrderController.java index ab78e4a52..e498f5113 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversPositionOrderController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversPositionOrderController.java @@ -3,6 +3,8 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolversPositionOrderContainer; import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolversPositionOrderContainerService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -16,6 +18,7 @@ */ @RestController @RequestMapping("/api/MetadataResolversPositionOrder") +@Tags(value = {@Tag(name = "metadata resolvers")}) public class MetadataResolversPositionOrderController { @Autowired @@ -31,4 +34,4 @@ public ResponseEntity createOrUpdate(@RequestBody MetadataResolversPositionOr public ResponseEntity getPositionOrderContainer() { return ResponseEntity.ok(positionOrderContainerService.retrieveExistingOrEmpty()); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java index 5aef3d9e2..0af16ada6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/RootUiViewController.java @@ -1,12 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; -import com.google.common.io.ByteStreams; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.core.io.Resource; import org.springframework.stereotype.Controller; -import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -15,7 +10,6 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.net.URISyntaxException; -import java.nio.charset.Charset; import java.util.stream.Collectors; @Controller @@ -41,4 +35,4 @@ public void indexHtml(HttpServletRequest request, HttpServletResponse response) writer.write(content.getBytes()); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java index 6600307af..cf4962c15 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractAuditable.java @@ -1,20 +1,9 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZoneOffset; -import java.time.ZonedDateTime; -import java.time.temporal.ChronoUnit; - -import javax.persistence.Column; -import javax.persistence.EntityListeners; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; -import javax.persistence.Transient; -import javax.validation.constraints.NotNull; - +import com.fasterxml.jackson.annotation.JsonFormat; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.Hidden; +import lombok.EqualsAndHashCode; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; import org.hibernate.envers.Audited; @@ -24,10 +13,19 @@ import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; -import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonProperty; - -import lombok.EqualsAndHashCode; +import javax.persistence.Column; +import javax.persistence.EntityListeners; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.MappedSuperclass; +import javax.persistence.Transient; +import javax.validation.constraints.NotNull; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; @MappedSuperclass @@ -38,38 +36,46 @@ public abstract class AbstractAuditable implements Auditable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) + @Hidden protected Long id; @CreationTimestamp @CreatedDate - @Column(nullable = false, updatable = false, columnDefinition = "DATETIME(6)") + @Column(nullable = false, updatable = false) @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS") + @Hidden private LocalDateTime createdDate; @UpdateTimestamp @LastModifiedDate - @Column(nullable = false, columnDefinition = "DATETIME(6)") + @Column(nullable = false) @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS") + @Hidden private LocalDateTime modifiedDate; @Column(name = "created_by") @CreatedBy + @Hidden private String createdBy; @Column(name = "modified_by") @LastModifiedBy + @Hidden private String modifiedBy; @Transient @JsonProperty + @Hidden private boolean current; @Override + @Hidden public Long getAudId() { return id; } @Override + @Hidden public void setAudId(@NotNull Long id) { this.id = id; } @@ -81,7 +87,7 @@ public LocalDateTime getCreatedDate() { @Override public void setCreatedDate(LocalDateTime createdDate) { - this.createdDate = createdDate; + this.createdDate = createdDate == null ? null : createdDate.truncatedTo(ChronoUnit.NANOS); } @Override @@ -91,7 +97,7 @@ public LocalDateTime getModifiedDate() { @Override public void setModifiedDate(LocalDateTime modifiedDate) { - this.modifiedDate = modifiedDate; + this.modifiedDate = modifiedDate == null ? null : modifiedDate.truncatedTo(ChronoUnit.NANOS); } public String getCreatedBy() { @@ -134,4 +140,4 @@ private static ZonedDateTime toZonedDateTime(LocalDateTime localDateTime) { .toZonedDateTime() .truncatedTo(ChronoUnit.MILLIS); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java index 449cda701..ee9747bd9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AbstractDescriptor.java @@ -7,16 +7,17 @@ import org.opensaml.core.xml.XMLObject; import org.opensaml.saml.saml2.common.CacheableSAMLObject; import org.opensaml.saml.saml2.common.TimeBoundSAMLObject; -import org.opensaml.xmlsec.signature.Signature; import org.opensaml.xmlsec.signature.SignableXMLObject; +import org.opensaml.xmlsec.signature.Signature; import javax.annotation.Nullable; import javax.persistence.CascadeType; import javax.persistence.MappedSuperclass; import javax.persistence.OneToOne; +import java.time.Duration; +import java.time.Instant; import java.util.List; - @MappedSuperclass @EqualsAndHashCode(callSuper = true) @Audited @@ -42,23 +43,27 @@ public boolean isValid() { } @Override - public Long getCacheDuration() { - return cacheDuration; + public Duration getCacheDuration() { + return null == cacheDuration ? null : Duration.ofMillis(cacheDuration); } @Override - public void setCacheDuration(Long cacheDuration) { - this.cacheDuration = cacheDuration; + public void setCacheDuration(@Nullable final Duration duration) { + if (duration == null) { + cacheDuration = null; + } else { + cacheDuration = duration.toMillis(); + } } @Override - public DateTime getValidUntil() { - return validUntil; + public Instant getValidUntil() { + return null == validUntil ? null : Instant.ofEpochMilli(validUntil.getMillis()); } @Override - public void setValidUntil(DateTime validUntil) { - this.validUntil = validUntil; + public void setValidUntil(Instant validUntilInstant) { + this.validUntil = new DateTime(validUntilInstant.toEpochMilli()); } @Override @@ -102,4 +107,4 @@ public List getOrderedChildren() { return null; //TODO ? } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java index c5f33b7b1..396278587 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AdditionalMetadataLocation.java @@ -2,24 +2,24 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) -public class AdditionalMetadataLocation extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AdditionalMetadataLocation { - - private String locationURI; +public class AdditionalMetadataLocation extends AbstractXMLObject + implements org.opensaml.saml.saml2.metadata.AdditionalMetadataLocation { + @Column(name = "locationuri", nullable = true) private String locationURI; private String namespaceURI; @Override - public String getLocationURI() { + public String getURI() { return locationURI; } @Override - public void setLocationURI(String locationURI) { + public void setURI(String locationURI) { this.locationURI = locationURI; } @@ -32,4 +32,4 @@ public String getNamespaceURI() { public void setNamespaceURI(String namespaceURI) { this.namespaceURI = namespaceURI; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java index e5dba9a06..7370003d8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AffiliateMember.java @@ -2,22 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) public class AffiliateMember extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AffiliateMember { - - private String localId; + @Column(name = "local_id") + private String uri; @Override - public String getID() { - return this.localId; + public String getURI() { + return this.uri; } @Override - public void setID(String id) { - this.localId = id; + public void setURI(String uri) { + this.uri = uri; } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java index a1dba47fa..632bcb888 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeConsumingService.java @@ -86,11 +86,11 @@ public void setServiceDescriptions(List serviceDescriptions) } @Override - public List getRequestAttributes() { + public List getRequestedAttributes() { return (List) (List) this.requestedAttributes; } public void setRequestedAttributes(List requestedAttributes) { this.requestedAttributes = requestedAttributes; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java index 21aea9486..51b753c1d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeProfile.java @@ -2,22 +2,21 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) public class AttributeProfile extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AttributeProfile { - - private String profileURI; + @Column(name = "profileuri") private String uri; @Override - public String getProfileURI() { - return profileURI; + public String getURI() { + return uri; } @Override - public void setProfileURI(String profileURI) { - this.profileURI = profileURI; + public void setURI(String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java index 11296d558..d4aa76b91 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/AttributeValue.java @@ -1,10 +1,54 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.opensaml.core.xml.util.AttributeMap; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import javax.persistence.ElementCollection; import javax.persistence.Entity; +import javax.persistence.PostLoad; +import javax.persistence.PrePersist; +import javax.persistence.Transient; +import javax.xml.namespace.QName; +import java.util.HashMap; +import java.util.Map; +/** + * Since Java doesn't support multiple inheritance, this is based on a copy of previously written code - AbstractAttributeExtensibleXMLObject + */ @Entity @EqualsAndHashCode(callSuper = true) -public class AttributeValue extends AbstractXMLObject implements org.opensaml.saml.saml2.core.AttributeValue { -} +public class AttributeValue extends AbstractElementExtensibleXMLObject implements org.opensaml.saml.saml2.core.AttributeValue { + private transient final AttributeMap unknownAttributes = new AttributeMap(this); + private String textContent; + @ElementCollection private Map storageAttributeMap = new HashMap<>(); + + @Nullable + @Override + public String getTextContent() { + return null; + } + + @Override + public void setTextContent(@Nullable String newContent) { + this.textContent = newContent; + } + + @Nonnull + @Override + @Transient + public AttributeMap getUnknownAttributes() { + return this.unknownAttributes; + } + + @PrePersist + void prePersist() { + this.storageAttributeMap = this.unknownAttributes; + } + + @PostLoad + void postLoad() { + this.unknownAttributes.putAll(this.storageAttributeMap); + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java index 54748b91c..1e9d564bb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Company.java @@ -2,22 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; - @Entity @EqualsAndHashCode(callSuper = true) public class Company extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.Company { - - private String name; + @Column(name = "name") + private String value; @Override - public String getName() { - return name; + public String getValue() { + return value; } @Override - public void setName(String name) { - this.name = name; + public void setValue(String value) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java index f1d14911a..6e7ced3e2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/CustomEntityAttributeDefinition.java @@ -35,7 +35,7 @@ public class CustomEntityAttributeDefinition implements IRelyingPartyOverridePro @ElementCollection @CollectionTable(name = "custom_entity_attr_list_items", joinColumns = @JoinColumn(name = "name")) @Fetch(FetchMode.JOIN) - @Column(name = "value", nullable = false) + @Column(name = "item_value", nullable = false) Set customAttrListDefinitions = new HashSet<>(); @Column(name = "default_value", nullable = true) @@ -114,4 +114,4 @@ public void setName(String name) { public void updateExamplesList() { examples = customAttrListDefinitions; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java index 2cf346579..53f24b720 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EmailAddress.java @@ -1,25 +1,25 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; -import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) @Audited public class EmailAddress extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.EmailAddress { - - private String address; + @Column(name = "address") + private String uri; @Override - public String getAddress() { - return address; + public String getURI() { + return uri; } @Override - public void setAddress(String address) { - this.address = address; + public void setURI(String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java index d48a3ea6f..effdd6be7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/EntityAttributes.java @@ -3,6 +3,8 @@ import lombok.EqualsAndHashCode; import org.hibernate.envers.Audited; import org.opensaml.core.xml.XMLObject; +import org.opensaml.saml.common.SAMLObject; +import org.opensaml.saml.ext.saml2mdattr.impl.EntityAttributesImpl; import org.opensaml.saml.saml2.core.Assertion; import javax.annotation.Nullable; @@ -55,4 +57,17 @@ public List getOrderedChildren() { return Collections.unmodifiableList(children); } -} + + @Override + public List getEntityAttributesChildren() { + ArrayList children = new ArrayList<>(); + + if (this.getAssertions().size() == 0 && this.getAttributes().size() == 0) { + return null; + } + + children.addAll(this.getAttributes()); + children.addAll(this.getAssertions()); + return children; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java index 612733fc4..e450ae623 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/GivenName.java @@ -1,9 +1,9 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; -import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @@ -11,15 +11,16 @@ @Audited public class GivenName extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.GivenName { - private String name; + @Column(name = "name") + private String value; @Override - public String getName() { - return name; + public String getValue() { + return value; } @Override - public void setName(String name) { - this.name = name; + public void setValue(String value) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java index e0a54d494..3f7dcb48e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/LocalizedName.java @@ -3,6 +3,7 @@ import org.hibernate.envers.Audited; import javax.annotation.Nullable; +import javax.persistence.Column; import javax.persistence.MappedSuperclass; @MappedSuperclass @@ -11,6 +12,7 @@ public class LocalizedName extends AbstractXMLObject implements org.opensaml.sam private String xMLLang; + @Column(name = "name_value") private String value; @Nullable @@ -34,4 +36,4 @@ public String getValue() { public void setValue(@Nullable String value) { this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java index 13453438a..ba93d33be 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Logo.java @@ -12,7 +12,7 @@ @Audited public class Logo extends AbstractXMLObject implements org.opensaml.saml.ext.saml2mdui.Logo { @Column(name = "logUrl") - private String url; + private String uri; @Column(name = "logoHieght") private int height; @@ -24,13 +24,13 @@ public class Logo extends AbstractXMLObject implements org.opensaml.saml.ext.sam private String xmlLang; @Override - public String getURL() { - return this.url; + public String getURI() { + return this.uri; } @Override - public void setURL(String url) { - this.url = url; + public void setURI(String uri) { + this.uri = uri; } @Override @@ -63,4 +63,4 @@ public String getXMLLang() { public void setXMLLang(@Nullable String xmlLang) { this.xmlLang = xmlLang; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java index 148ec91e7..8c6a9ed27 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/NameIDFormat.java @@ -3,6 +3,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @@ -10,16 +11,16 @@ @Audited public class NameIDFormat extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.NameIDFormat { - private String format; - + @Column(name = "format") + private String uri; @Override - public String getFormat() { - return format; + public String getURI() { + return uri; } @Override - public void setFormat(String format) { - this.format = format; + public void setURI(String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java index 1cf739ece..625e96379 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/OrganizationURL.java @@ -4,6 +4,7 @@ import org.hibernate.envers.Audited; import javax.annotation.Nullable; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @@ -13,7 +14,8 @@ public class OrganizationURL extends AbstractXMLObject implements org.opensaml.s private String xMLLang; - private String value; + @Column(name="uri_value") + private String uri; @Nullable @Override @@ -28,12 +30,12 @@ public void setXMLLang(@Nullable String xmlLang) { @Nullable @Override - public String getValue() { - return value; + public String getURI() { + return uri; } @Override - public void setValue(@Nullable String value) { - this.value = value; + public void setURI(@Nullable String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java index a62cdeaa6..b6be50f64 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java @@ -2,21 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) public class SurName extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.SurName { - - private String name; + @Column(name = "name") + private String value; @Override - public String getName() { - return name; + public String getValue() { + return value; } @Override - public void setName(String name) { - this.name = name; + public void setValue(String name) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java index 729d5d40f..7aa111b07 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/TelephoneNumber.java @@ -2,21 +2,22 @@ import lombok.EqualsAndHashCode; +import javax.persistence.Column; import javax.persistence.Entity; @Entity @EqualsAndHashCode(callSuper = true) public class TelephoneNumber extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.TelephoneNumber { - - private String number; + @Column(name = "number") + private String value; @Override - public String getNumber() { - return number; + public String getValue() { + return value; } @Override - public void setNumber(String number) { - this.number = number; + public void setValue(String value) { + this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java index b1db21b72..cff1a3c9d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Certificate.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.domain; import lombok.EqualsAndHashCode; +import org.hibernate.annotations.Type; import org.hibernate.envers.Audited; import javax.annotation.Nullable; @@ -14,6 +15,7 @@ public class X509Certificate extends AbstractXMLObject implements org.opensaml.xmlsec.signature.X509Certificate { @Column(name = "x509CertificateValue") @Lob + @Type(type = "org.hibernate.type.TextType") private String value; @Nullable @@ -26,4 +28,4 @@ public String getValue() { public void setValue(@Nullable String value) { this.value = value; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java index e875932cd..7afd88814 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/X509Data.java @@ -19,6 +19,7 @@ import javax.xml.namespace.QName; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -74,10 +75,11 @@ public void addX509Certificate(edu.internet2.tier.shibboleth.admin.ui.domain.X50 this.xmlObjects.add(x509Certificate); } + // TODO: might need to really implement this @Nonnull @Override public List getX509CRLs() { - return null; + return Collections.EMPTY_LIST; } @Nonnull diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java index 1b13a3cd4..e1a7646ac 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSDateTime.java @@ -11,6 +11,7 @@ import javax.annotation.Nullable; import javax.persistence.Entity; import javax.persistence.Transient; +import java.time.Instant; @Entity @EqualsAndHashCode(callSuper = true) @@ -29,23 +30,21 @@ protected XSDateTime() { @Nullable @Override //TODO: find good way to persist - public DateTime getValue() { - return this.dateTime; + public Instant getValue() { + return Instant.ofEpochMilli(this.dateTime.getMillis()); } @Override - public void setValue(@Nullable DateTime newValue) { - this.dateTime = newValue; + public void setValue(@Nullable Instant newValue) { + this.dateTime = new DateTime(newValue.toEpochMilli()); } @Nonnull - @Override public DateTimeFormatter getDateTimeFormatter() { return this.dateTimeFormatter; } - @Override public void setDateTimeFormatter(@Nonnull DateTimeFormatter newFormatter) { this.dateTimeFormatter = newFormatter; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java index 8663bf818..336bb8cd7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/XSURI.java @@ -12,16 +12,16 @@ @Audited public class XSURI extends AbstractXMLObject implements org.opensaml.core.xml.schema.XSURI { @Column(name = "xsuriValue") - private String value; + private String uri; @Nullable @Override - public String getValue() { - return this.value; + public String getURI() { + return this.uri; } @Override - public void setValue(@Nullable String value) { - this.value = value; + public void setURI(@Nullable String uri) { + this.uri = uri; } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java index a7959dbbf..e2ed028a0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/EntityAttributesFilterTarget.java @@ -26,7 +26,7 @@ public class EntityAttributesFilterTarget extends AbstractAuditable implements I @ElementCollection (fetch = FetchType.EAGER) @OrderColumn - @Column(length = 760) + @Column(length = 760, name="target_value") private List value; public EntityAttributesFilterTargetType getEntityAttributesFilterTargetType() { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java index 90445ff75..3a5bfe9da 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/NameIdFormatFilterTarget.java @@ -8,6 +8,7 @@ import org.hibernate.envers.AuditOverride; import org.hibernate.envers.Audited; +import javax.persistence.Column; import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.OrderColumn; @@ -27,6 +28,7 @@ public class NameIdFormatFilterTarget extends AbstractAuditable implements IFilt @ElementCollection @OrderColumn + @Column(name="target_value") private List value; public NameIdFormatFilterTargetType getNameIdFormatFilterTargetType() { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java index 90a5f6c18..d9c1fc636 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/filters/opensaml/OpenSamlNameIdFormatFilter.java @@ -6,6 +6,7 @@ import org.opensaml.core.xml.config.XMLObjectProviderRegistrySupport; import org.opensaml.saml.common.SAMLObjectBuilder; import org.opensaml.saml.metadata.resolver.filter.FilterException; +import org.opensaml.saml.metadata.resolver.filter.MetadataFilterContext; import org.opensaml.saml.metadata.resolver.filter.impl.NameIDFormatFilter; import org.opensaml.saml.saml2.metadata.AttributeAuthorityDescriptor; import org.opensaml.saml.saml2.metadata.EntitiesDescriptor; @@ -45,7 +46,7 @@ public void setRemoveExistingFormats(final boolean flag) { @Nullable @Override - public XMLObject filter(@Nullable XMLObject metadata) throws FilterException { + public XMLObject filter(@Nullable XMLObject metadata, @Nonnull final MetadataFilterContext context) throws FilterException { if (metadata == null) { return null; } @@ -84,8 +85,8 @@ protected void filterRoleDescriptor(@Nonnull final RoleDescriptor role, for (final String format : formats) { final NameIDFormat nif = formatBuilder.buildObject(); - nif.setFormat(format); + nif.setURI(format); roleFormats.add(nif); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ClasspathMetadataResource.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ClasspathMetadataResource.java index a3dc076ab..a76943378 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ClasspathMetadataResource.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ClasspathMetadataResource.java @@ -15,6 +15,6 @@ @Setter @EqualsAndHashCode public class ClasspathMetadataResource { - - private String file; -} + // renamed from "file" to work with SQLServer + private String fileResource; +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ExternalMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ExternalMetadataResolver.java new file mode 100644 index 000000000..cf488be82 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/ExternalMetadataResolver.java @@ -0,0 +1,28 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.resolvers; + +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import lombok.ToString; +import org.hibernate.envers.Audited; + +import javax.persistence.Column; +import javax.persistence.Entity; + +@Entity +@EqualsAndHashCode(callSuper = true) +@Getter +@Setter +@ToString +@Audited +public class ExternalMetadataResolver extends MetadataResolver { + @Column + private String description; + + @Column + String name; + + public ExternalMetadataResolver() { + type = "ExternalMetadataResolver"; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java index 63a04d764..19c96e753 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/MetadataResolver.java @@ -43,7 +43,8 @@ @JsonSubTypes.Type(value = FileBackedHttpMetadataResolver.class, name = "FileBackedHttpMetadataResolver"), @JsonSubTypes.Type(value = DynamicHttpMetadataResolver.class, name = "DynamicHttpMetadataResolver"), @JsonSubTypes.Type(value = FilesystemMetadataResolver.class, name = "FilesystemMetadataResolver"), - @JsonSubTypes.Type(value = ResourceBackedMetadataResolver.class, name = "ResourceBackedMetadataResolver")}) + @JsonSubTypes.Type(value = ResourceBackedMetadataResolver.class, name = "ResourceBackedMetadataResolver"), + @JsonSubTypes.Type(value = ExternalMetadataResolver.class, name = "ExternalMetadataResolver")}) @Audited @AuditOverride(forClass = AbstractAuditable.class) public class MetadataResolver extends AbstractAuditable implements IActivatable { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java index 6a54c409b..4b642e52a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFileBackedHTTPMetadataResolver.java @@ -7,8 +7,6 @@ import org.apache.http.HttpResponse; import org.apache.http.impl.client.HttpClients; import org.apache.lucene.index.IndexWriter; -import org.joda.time.DateTime; -import org.joda.time.chrono.ISOChronology; import org.opensaml.saml.metadata.resolver.filter.FilterException; import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain; import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver; @@ -17,8 +15,12 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.io.File; +import java.time.Duration; +import java.time.Instant; -import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toPositiveNonZeroDuration; +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toTimeDuration; import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; /** @@ -49,8 +51,9 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, sourceResolver.getReloadableMetadataResolverAttributes(), parserPool); this.setBackupFile(placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackingFile())); - this.setBackupFileInitNextRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()))); + this.setBackupFileInitNextRefreshDelay(toPositiveNonZeroDuration( + placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(sourceResolver.getBackupFileInitNextRefreshDelay()), + Duration.ofSeconds(5))); if (sourceResolver.getInitializeFromBackupFile() != null) { this.setInitializeFromBackupFile(sourceResolver.getInitializeFromBackupFile()); } @@ -64,7 +67,7 @@ public OpenSamlFileBackedHTTPMetadataResolver(ParserPool parserPool, // TODO: this is still probably not the best way to do this? @Nullable @Override - public DateTime getLastRefresh() { + public Instant getLastRefresh() { return null; } @@ -115,14 +118,14 @@ public synchronized void refresh() throws ResolverException { try { - DateTime now = new DateTime(ISOChronology.getInstanceUTC()); + Instant nowInstant = Instant.ofEpochMilli(System.currentTimeMillis()); String mdId = getMetadataIdentifier(); final byte[] mdBytes = fetchMetadata(); if (mdBytes == null) { - processCachedMetadata(mdId, now); + processCachedMetadata(mdId, nowInstant); } else { - processNewMetadata(mdId, now, mdBytes); + processNewMetadata(mdId, nowInstant, mdBytes); } } catch (final Throwable t) { if (t instanceof Exception) { @@ -133,4 +136,16 @@ public synchronized void refresh() throws ResolverException { } } } -} + + @Override + public void validateBackupFile(final File backupFile) throws ResolverException { + // NOPE, not going to validate this because the file reference is likely not to exist on the shibui server nor even be a + // valid path on the running server. The file is needed for the XML, but we shouldn't be validating it. + } + + @Override + protected byte[] fetchMetadata() throws ResolverException { + // NOPE, we don't need to try and fetch the metadata from either the URI nor the file + return null; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java index cfd3bdf2c..f8b9a856f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlFilesystemMetadataResolver.java @@ -14,6 +14,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; +import java.time.Instant; /** * @author Bill Smith (wsmith@unicon.net) @@ -46,7 +47,7 @@ public OpenSamlFilesystemMetadataResolver(ParserPool parserPool, // TODO: this is still probably not the best way to do this? @Nullable @Override - public DateTime getLastRefresh() { + public Instant getLastRefresh() { return null; } @@ -87,4 +88,16 @@ public void refilter() { logger.error("An error occurred while attempting to filter metadata!", e); } } -} + + @Override + public void validateMetadataFile(@Nonnull final File file) throws ResolverException { + // NOPE, not going to validate this because the file reference is likely not to exist on the shibui server nor even be a + // valid path on the running server. The file is needed for the XML, but we shouldn't be validating it. + } + + @Override + protected byte[] fetchMetadata() throws ResolverException { + // NOPE, we don't need to try and fetch the metadata + return null; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java index cd7c564c7..548c14eb6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlMetadataResolverConstructorHelper.java @@ -8,7 +8,10 @@ import org.opensaml.saml.metadata.resolver.impl.AbstractDynamicMetadataResolver; import org.opensaml.saml.metadata.resolver.impl.AbstractReloadingMetadataResolver; -import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toMillis; +import java.time.Duration; + +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toPositiveNonZeroDuration; +import static edu.internet2.tier.shibboleth.admin.util.DurationUtility.toTimeDuration; import static edu.internet2.tier.shibboleth.admin.util.TokenPlaceholderResolvers.placeholderResolverService; /** @@ -24,12 +27,12 @@ public static void updateOpenSamlMetadataResolverFromDynamicMetadataResolverAttr if (attributes != null) { if (attributes.getBackgroundInitializationFromCacheDelay() != null) { dynamicMetadataResolver - .setBackgroundInitializationFromCacheDelay(toMillis(placeholderResolverService() + .setBackgroundInitializationFromCacheDelay(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getBackgroundInitializationFromCacheDelay()))); } if (attributes.getCleanupTaskInterval() != null) { - dynamicMetadataResolver.setCleanupTaskInterval(toMillis(placeholderResolverService() + dynamicMetadataResolver.setCleanupTaskInterval(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getCleanupTaskInterval()))); } @@ -38,22 +41,22 @@ public static void updateOpenSamlMetadataResolverFromDynamicMetadataResolverAttr } if (attributes.getMaxCacheDuration() != null) { - dynamicMetadataResolver.setMaxCacheDuration(toMillis(placeholderResolverService() + dynamicMetadataResolver.setMaxCacheDuration(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxCacheDuration()))); } if (attributes.getMaxIdleEntityData() != null) { - dynamicMetadataResolver.setMaxIdleEntityData(toMillis(placeholderResolverService() + dynamicMetadataResolver.setMaxIdleEntityData(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxIdleEntityData()))); } if (attributes.getMinCacheDuration() != null) { - dynamicMetadataResolver.setMinCacheDuration(toMillis(placeholderResolverService() + dynamicMetadataResolver.setMinCacheDuration(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getMinCacheDuration()))); } if (attributes.getBackgroundInitializationFromCacheDelay() != null) { - dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toMillis(placeholderResolverService() + dynamicMetadataResolver.setBackgroundInitializationFromCacheDelay(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getBackgroundInitializationFromCacheDelay()))); } @@ -98,17 +101,17 @@ public static void updateOpenSamlMetadataResolverFromReloadableMetadataResolverA if (attributes != null) { if (attributes.getExpirationWarningThreshold() != null) { reloadingMetadataResolver - .setExpirationWarningThreshold(toMillis(placeholderResolverService() + .setExpirationWarningThreshold(toTimeDuration(placeholderResolverService() .resolveValueFromPossibleTokenPlaceholder(attributes.getExpirationWarningThreshold()))); } - if (attributes.getMaxRefreshDelay() != null) { - reloadingMetadataResolver.setMaxRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(attributes.getMaxRefreshDelay()))); - } - if (attributes.getMinRefreshDelay() != null) { - reloadingMetadataResolver.setMinRefreshDelay(toMillis(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(attributes.getMinRefreshDelay()))); - } + + // Open SAML 4.x libarry requires values non-null, greater than zero for min and max refresh rates + reloadingMetadataResolver.setMaxRefreshDelay(toPositiveNonZeroDuration( + placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(attributes.getMaxRefreshDelay()), + Duration.ofHours(4))); + reloadingMetadataResolver.setMinRefreshDelay(toPositiveNonZeroDuration( + placeholderResolverService().resolveValueFromPossibleTokenPlaceholder(attributes.getMinRefreshDelay()), + Duration.ofMinutes(5))); if (attributes.getResolveViaPredicatesOnly() != null) { reloadingMetadataResolver.setResolveViaPredicatesOnly(attributes.getResolveViaPredicatesOnly()); @@ -125,4 +128,4 @@ public static void updateOpenSamlMetadataResolverFromReloadableMetadataResolverA // attributes.getTaskTimerRef(); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java index 62bdb37d8..1c02099f6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/opensaml/OpenSamlResourceBackedMetadataResolver.java @@ -14,6 +14,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.IOException; +import java.time.Instant; /** * @author Bill Smith (wsmith@unicon.net) @@ -47,7 +48,7 @@ public OpenSamlResourceBackedMetadataResolver(ParserPool parserPool, // TODO: this is still probably not the best way to do this? @Nullable @Override - public DateTime getLastRefresh() { + public Instant getLastRefresh() { return null; } @@ -79,4 +80,4 @@ public void refilter() { logger.error("An error occurred while attempting to filter metadata!", e); } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java index 71986eea7..b44e4e7ce 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaLocationLookup.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.jsonschema; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.ENTITY_ATTRIBUTES_FILTERS; +import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.EXTERNAL_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.METADATA_SOURCES; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.FILESYSTEM_METADATA_RESOLVER; import static edu.internet2.tier.shibboleth.admin.ui.jsonschema.JsonSchemaResourceLocation.SchemaType.LOCAL_DYNAMIC_METADATA_RESOLVER; @@ -66,6 +67,19 @@ public static JsonSchemaResourceLocation localDynamicMetadataProviderSchema(Json .orElseThrow(() -> new IllegalStateException("JSON schema resource location for local dynamic metadata resolver is not registered.")); } + /** + * Searches external metadata resolver JSON schema resource location object in the given location registry. + * + * @param resourceLocationRegistry + * @return external metadata resolver JSON schema resource location object + * @throws IllegalStateException if schema is not found in the given registry + */ + public static JsonSchemaResourceLocation externalMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { + return resourceLocationRegistry + .lookup(EXTERNAL_METADATA_RESOLVER) + .orElseThrow(() -> new IllegalStateException("JSON schema resource location for external metadata resolver is not registered.")); + } + /** * Searches dynamic http metadata resolver JSON schema resource location object in the given location registry. * @@ -75,8 +89,8 @@ public static JsonSchemaResourceLocation localDynamicMetadataProviderSchema(Json */ public static JsonSchemaResourceLocation dynamicHttpMetadataProviderSchema(JsonSchemaResourceLocationRegistry resourceLocationRegistry) { return resourceLocationRegistry - .lookup(DYNAMIC_HTTP_METADATA_RESOLVER) - .orElseThrow(() -> new IllegalStateException("JSON schema resource location for dynamic http metadata resolver is not registered.")); + .lookup(DYNAMIC_HTTP_METADATA_RESOLVER) + .orElseThrow(() -> new IllegalStateException("JSON schema resource location for dynamic http metadata resolver is not registered.")); } /** @@ -91,4 +105,4 @@ public static JsonSchemaResourceLocation nameIdFormatFilterSchema(JsonSchemaReso .lookup(NAME_ID_FORMAT_FILTER) .orElseThrow(() -> new IllegalStateException("JSON schema resource location for name id format filter is not registered.")); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java index 2d25fac0b..1b9054cd3 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/jsonschema/JsonSchemaResourceLocation.java @@ -104,7 +104,8 @@ public enum SchemaType { FILE_BACKED_HTTP_METADATA_RESOLVER("FileBackedHttpMetadataResolver"), FILESYSTEM_METADATA_RESOLVER("FilesystemMetadataResolver"), LOCAL_DYNAMIC_METADATA_RESOLVER("LocalDynamicMetadataResolver"), - DYNAMIC_HTTP_METADATA_RESOLVER("DynamicHttpMetadataResolver"); + DYNAMIC_HTTP_METADATA_RESOLVER("DynamicHttpMetadataResolver"), + EXTERNAL_METADATA_RESOLVER("ExternalMetadataResolver"); String jsonType; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/scheduled/ExternalMetadataProvidersScheduledTasks.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/scheduled/ExternalMetadataProvidersScheduledTasks.java new file mode 100644 index 000000000..b2e3c7d37 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/scheduled/ExternalMetadataProvidersScheduledTasks.java @@ -0,0 +1,53 @@ +package edu.internet2.tier.shibboleth.admin.ui.scheduled; + +import edu.internet2.tier.shibboleth.admin.ui.service.FileWritingService; +import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.Resource; +import org.springframework.core.io.WritableResource; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.transaction.annotation.Transactional; + +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.StringWriter; + +@Configuration +@ConditionalOnProperty("shibui.external.metadataProviders.target") +public class ExternalMetadataProvidersScheduledTasks { + private static final Logger logger = LoggerFactory.getLogger(ExternalMetadataProvidersScheduledTasks.class); + + private final Resource target; + private final MetadataResolverService metadataResolverService; + private final FileWritingService fileWritingService; + + public ExternalMetadataProvidersScheduledTasks(Resource target, MetadataResolverService metadataResolverService, FileWritingService fileWritingService) { + this.target = target; + this.metadataResolverService = metadataResolverService; + this.fileWritingService = fileWritingService; + } + + @Scheduled(fixedRateString = "${shibui.external.metadataProviders.taskRunRate:30000}") + @Transactional(readOnly = true) + public void generateMetadataProvidersFile() { + try (StringWriter os = new StringWriter()) { + Transformer transformer = TransformerFactory.newInstance().newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + + + transformer.transform(new DOMSource(metadataResolverService.generateExternalMetadataFilterConfiguration()), new StreamResult(os)); + this.fileWritingService.write((WritableResource)this.target, os.toString()); + } catch (IOException | TransformerException e) { + logger.error(e.getLocalizedMessage(), e); + } + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupController.java index bcb1b047c..c287a14a7 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupController.java @@ -1,12 +1,17 @@ package edu.internet2.tier.shibboleth.admin.ui.security.controller; +import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupDeleteException; +import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupExistsConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.InvalidGroupRegexException; +import edu.internet2.tier.shibboleth.admin.ui.security.model.Group; +import edu.internet2.tier.shibboleth.admin.ui.security.service.IGroupService; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.annotation.Secured; -import org.springframework.stereotype.Controller; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; @@ -15,17 +20,11 @@ import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.servlet.support.ServletUriComponentsBuilder; - -import edu.internet2.tier.shibboleth.admin.ui.controller.ErrorResponse; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; -import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupDeleteException; -import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupExistsConflictException; -import edu.internet2.tier.shibboleth.admin.ui.security.model.Group; -import edu.internet2.tier.shibboleth.admin.ui.security.service.IGroupService; +import org.springframework.web.bind.annotation.RestController; -@Controller +@RestController @RequestMapping(value = "/api/admin/groups") +@Tags(value = {@Tag(name = "admin")}) public class GroupController { @Autowired private IGroupService groupService; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesController.java index d576e0630..539dc3195 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesController.java @@ -2,6 +2,8 @@ import java.util.Optional; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -24,6 +26,7 @@ @RestController @RequestMapping("/api/admin/roles") +@Tags(value = {@Tag(name = "admin")}) public class RolesController { @Autowired private IRolesService rolesService; @@ -71,4 +74,4 @@ public ResponseEntity update(@RequestBody Role incomingRoleDetail, @PathVaria Role result = rolesService.updateRole(updateRole); return ResponseEntity.ok(result); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java index 93fec88aa..a281adc10 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/UsersController.java @@ -6,6 +6,9 @@ import java.util.List; import java.util.Optional; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; +import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -28,8 +31,7 @@ import edu.internet2.tier.shibboleth.admin.ui.security.model.User; import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; -import groovy.util.logging.Slf4j; -import jline.internal.Log; + /** * Implementation of the REST resource endpoints exposing system users. @@ -37,6 +39,7 @@ @RestController @RequestMapping("/api/admin/users") @Slf4j +@Tags(value = {@Tag(name = "admin")}) public class UsersController { private UserRepository userRepository; private UserService userService; @@ -76,7 +79,7 @@ public List getAll() { return results; } catch (Exception e) { - Log.error("Unable to fetch users because: {}", e.getMessage()); + log.error("Unable to fetch users because: {}", e.getMessage()); throw e; } } @@ -149,4 +152,4 @@ ResponseEntity updateOne(@PathVariable(value = "username") String username, @ User savedUser = userService.save(persistedUser); return ResponseEntity.ok(savedUser); } - } + } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java index d1f1f0ccc..f6c419b31 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAEntityDescriptorServiceImpl.java @@ -156,7 +156,7 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope if (ed.getSPSSODescriptor("") != null && ed.getSPSSODescriptor("").getNameIDFormats().size() > 0) { ServiceProviderSsoDescriptorRepresentation serviceProviderSsoDescriptorRepresentation = representation.getServiceProviderSsoDescriptor(true); serviceProviderSsoDescriptorRepresentation.setNameIdFormats( - ed.getSPSSODescriptor("").getNameIDFormats().stream().map(p -> p.getFormat()).collect(Collectors.toList()) + ed.getSPSSODescriptor("").getNameIDFormats().stream().map(p -> p.getURI()).collect(Collectors.toList()) ); } @@ -165,7 +165,7 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope OrganizationRepresentation organizationRepresentation = new OrganizationRepresentation(); organizationRepresentation.setName(ed.getOrganization().getOrganizationNames().get(0).getValue()); organizationRepresentation.setDisplayName(ed.getOrganization().getDisplayNames().get(0).getValue()); - organizationRepresentation.setUrl(ed.getOrganization().getURLs().get(0).getValue()); + organizationRepresentation.setUrl(ed.getOrganization().getURLs().get(0).getURI()); representation.setOrganization(organizationRepresentation); } @@ -179,10 +179,10 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope contactRepresentation.setType(contactPerson.getType().toString()); } if (contactPerson.getGivenName() != null) { - contactRepresentation.setName(contactPerson.getGivenName().getName()); + contactRepresentation.setName(contactPerson.getGivenName().getValue()); } if (contactPerson.getEmailAddresses() != null && contactPerson.getEmailAddresses().size() > 0) { - contactRepresentation.setEmailAddress(contactPerson.getEmailAddresses().get(0).getAddress()); + contactRepresentation.setEmailAddress(contactPerson.getEmailAddresses().get(0).getURI()); } contactRepresentations.add(contactRepresentation); @@ -200,17 +200,17 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope mduiRepresentation.setDisplayName(uiInfo.getDisplayNames().get(0).getValue()); } if (uiInfo.getInformationURLs().size() > 0) { - mduiRepresentation.setInformationUrl(uiInfo.getInformationURLs().get(0).getValue()); + mduiRepresentation.setInformationUrl(uiInfo.getInformationURLs().get(0).getURI()); } if (uiInfo.getPrivacyStatementURLs().size() > 0) { - mduiRepresentation.setPrivacyStatementUrl(uiInfo.getPrivacyStatementURLs().get(0).getValue()); + mduiRepresentation.setPrivacyStatementUrl(uiInfo.getPrivacyStatementURLs().get(0).getURI()); } if (uiInfo.getDescriptions().size() > 0) { mduiRepresentation.setDescription(uiInfo.getDescriptions().get(0).getValue()); } if (uiInfo.getLogos().size() > 0) { org.opensaml.saml.ext.saml2mdui.Logo logo = uiInfo.getLogos().get(0); - mduiRepresentation.setLogoUrl(logo.getURL()); + mduiRepresentation.setLogoUrl(logo.getURI()); mduiRepresentation.setLogoHeight(logo.getHeight()); mduiRepresentation.setLogoWidth(logo.getWidth()); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java index 2343206a7..d0d20bd61 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverConverterServiceImpl.java @@ -99,7 +99,7 @@ private OpenSamlResourceBackedMetadataResolver convertToOpenSamlRepresentation(R break; case CLASSPATH: resource = ResourceHelper.of(new ClassPathResource(placeholderResolverService() - .resolveValueFromPossibleTokenPlaceholder(resolver.getClasspathMetadataResource().getFile()))); + .resolveValueFromPossibleTokenPlaceholder(resolver.getClasspathMetadataResource().getFileResource()))); break; default: throw new RuntimeException("Unsupported resource type!"); @@ -153,4 +153,4 @@ public boolean isDirectory() { return true; } } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverService.java index 5fd205c20..d851cd021 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/MetadataResolverService.java @@ -7,6 +7,7 @@ import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InitializationException; +import org.w3c.dom.Node; public interface MetadataResolverService { public MetadataResolver findByResourceId(String resourceId) throws EntityNotFoundException; @@ -16,4 +17,6 @@ public interface MetadataResolverService { public void reloadFilters(String metadataResolverName); public MetadataResolver updateMetadataResolverEnabledStatus(MetadataResolver existingResolver) throws ForbiddenException, MetadataFileNotFoundException, InitializationException; -} + + public Document generateExternalMetadataFilterConfiguration(); +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java index b19328e27..0d531321a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/DurationUtility.java @@ -36,4 +36,14 @@ public static Long toMillis(String xmlDuration) { duration.addTo(zero); // potentially can return undesired results for large xmlDurations return zero.getTime(); } -} + + public static java.time.Duration toTimeDuration(String xmlDuration) { + long value = toMillis(xmlDuration); + return java.time.Duration.ofMillis(value); + } + + public static java.time.Duration toPositiveNonZeroDuration (String xmlDuration, java.time.Duration defaultDuration) { + long value = toMillis(xmlDuration); + return value > 0 ? java.time.Duration.ofMillis(value) : defaultDuration; + } +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java index 8b4e7a71a..5fd444344 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/util/EntityDescriptorConversionUtils.java @@ -185,11 +185,11 @@ public static void setupContacts(EntityDescriptor ed, EntityDescriptorRepresenta contactPerson.setType(contactRepresentation.getType()); GivenName givenName = openSamlObjects.buildDefaultInstanceOfType(GivenName.class); - givenName.setName(contactRepresentation.getName()); + givenName.setValue(contactRepresentation.getName()); contactPerson.setGivenName(givenName); EmailAddress emailAddress = openSamlObjects.buildDefaultInstanceOfType(EmailAddress.class); - emailAddress.setAddress(contactRepresentation.getEmailAddress()); + emailAddress.setURI(contactRepresentation.getEmailAddress()); contactPerson.addEmailAddress(emailAddress); ed.addContactPerson(contactPerson); @@ -233,7 +233,7 @@ public static void setupOrganization(EntityDescriptor ed, EntityDescriptorRepres OrganizationURL organizationURL = openSamlObjects.buildDefaultInstanceOfType(OrganizationURL.class); organizationURL.setXMLLang("en"); - organizationURL.setValue(organizationRepresentation.getUrl()); + organizationURL.setURI(organizationRepresentation.getUrl()); organization.getURLs().add(organizationURL); ed.setOrganization(organization); @@ -296,7 +296,7 @@ public static void setupSPSSODescriptor(EntityDescriptor ed, EntityDescriptorRep for (String nameidFormat : representation.getServiceProviderSsoDescriptor().getNameIdFormats()) { NameIDFormat nameIDFormat = openSamlObjects.buildDefaultInstanceOfType(NameIDFormat.class); - nameIDFormat.setFormat(nameidFormat); + nameIDFormat.setURI(nameidFormat); spssoDescriptor.getNameIDFormats().add(nameIDFormat); } @@ -327,7 +327,7 @@ public static void setupUIInfo(EntityDescriptor ed, EntityDescriptorRepresentati if (!Strings.isNullOrEmpty(mduiRepresentation.getInformationUrl())) { InformationURL informationURL = openSamlObjects.buildDefaultInstanceOfType(InformationURL.class); getUIInfo(ed).addInformationURL(informationURL); - informationURL.setValue(mduiRepresentation.getInformationUrl()); + informationURL.setURI(mduiRepresentation.getInformationUrl()); informationURL.setXMLLang("en"); } else { ed.getOptionalSPSSODescriptor() @@ -339,7 +339,7 @@ public static void setupUIInfo(EntityDescriptor ed, EntityDescriptorRepresentati if (!Strings.isNullOrEmpty(mduiRepresentation.getPrivacyStatementUrl())) { PrivacyStatementURL privacyStatementURL = openSamlObjects.buildDefaultInstanceOfType(PrivacyStatementURL.class); getUIInfo(ed).addPrivacyStatementURL(privacyStatementURL); - privacyStatementURL.setValue(mduiRepresentation.getPrivacyStatementUrl()); + privacyStatementURL.setURI(mduiRepresentation.getPrivacyStatementUrl()); privacyStatementURL.setXMLLang("en"); } else { ed.getOptionalSPSSODescriptor() @@ -363,7 +363,7 @@ public static void setupUIInfo(EntityDescriptor ed, EntityDescriptorRepresentati if (!Strings.isNullOrEmpty(mduiRepresentation.getLogoUrl())) { Logo logo = openSamlObjects.buildDefaultInstanceOfType(Logo.class); getUIInfo(ed).addLogo(logo); - logo.setURL(mduiRepresentation.getLogoUrl()); + logo.setURI(mduiRepresentation.getLogoUrl()); logo.setHeight(mduiRepresentation.getLogoHeight()); logo.setWidth(mduiRepresentation.getLogoWidth()); logo.setXMLLang("en"); diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 0556e5b45..109e7c30f 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -9,6 +9,9 @@ logging.level.org.springframework=INFO logging.level.edu.internet2.tier.shibboleth.admin.ui=INFO spring.main.allow-bean-definition-overriding=true +# "In Spring MVC, the path was previously analyzed by AntPathMatcher, but it was changed to use PathPatternParser introduced in WebFlux from Spring 5.3.0." +# we still have the option to use ant path matcher thus keeping existing configuration from having to change +spring.mvc.pathmatch.matching-strategy=ant_path_matcher # Database Credentials spring.datasource.username=shibui @@ -16,7 +19,7 @@ spring.datasource.password=shibui # Database Configuration H2 spring.datasource.url=jdbc:h2:mem:shibui;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE -spring.datasource.platform=h2 +spring.sql.init.platform=h2 spring.datasource.driverClassName=org.h2.Driver spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.h2.console.enabled=true @@ -37,14 +40,15 @@ spring.jackson.mapper.accept-case-insensitive-enums=true #spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect # Liquibase properties -spring.liquibase.enabled=false +spring.liquibase.enabled=true +spring.liquibase.change-log=db/changelog/changelog.sql # Hibernate properties # for production never ever use create, create-drop. It's BEST to use validate spring.jpa.hibernate.ddl-auto=update spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl spring.jpa.show-sql=false -spring.jpa.properties.hibernate.format_sql=false +spring.jpa.properties.hibernate.format_sql=true spring.jpa.properties.hibernate.check_nullability=true spring.jpa.hibernate.use-new-id-generator-mappings=true @@ -80,6 +84,12 @@ shibui.nameid-filter-ui-schema-location=classpath:nameid-filter.schema.json # shibui.metadataProviders.target=file:/opt/shibboleth-idp/conf/shibui-metadata-providers.xml # shibui.metadataProviders.taskRunRate=30000 +# Set the following property to periodically write out external metadata providers (ie metadata-filters) configuration. +# There is no default value; the following is just an example +# @see - https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1279033515/ByReferenceFilter +# shibui.external.metadataProviders.target=file:/opt/shibboleth-idp/conf/metadata-filters.xml +# shibui.external.metadataProviders.taskRunRate=30000 + # Email configuration (local mailhog) # spring.mail.host=mailhog # spring.mail.port=1025 @@ -106,4 +116,15 @@ shibui.roles.authenticated=ADMIN,ENABLE,USER #This property must be set to true in order to enable posting stats to beacon endpoint. Furthermore, appropriate #environment variables must be set for beacon publisher to be used (the ones that are set when running shib-ui in #docker container -shibui.beacon-enabled=true \ No newline at end of file +shibui.beacon-enabled=true + +### Swagger/Springdoc patterns +springdoc.use-management-port=true +springdoc.swagger-ui.tagsSorter: alpha +springdoc.writer-with-order-by-keys: true +springdoc.pathsToMatch=/entities, /api/** +# This property enables the openapi and swagger-ui endpoints to be exposed beneath the actuator base path. +management.endpoints.web.exposure.include=openapi, swagger-ui, info +management.server.port=9090 +management.endpoints.web.cors.allowed-origins=* +management.endpoints.web.cors.allowed-headers=* \ No newline at end of file diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index 671000aa6..ffeab970c 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -1,3 +1,12 @@ +#spring: +# jpa: +# show-sql: false +# properties: +# hibernate: +# format_sql: true +# dialect: org.hibernate.dialect.PostgreSQL95Dialect +# OR SEE: https://access.redhat.com/webassets/avalon/d/red-hat-jboss-enterprise-application-platform/7.2/javadocs/org/hibernate/dialect/package-summary.html + #shibui: ## Default password must be set for the default user to be configured and setup # default-rootuser:root diff --git a/backend/src/main/resources/db/changelog/README.txt b/backend/src/main/resources/db/changelog/README.txt new file mode 100644 index 000000000..2ebb5d59f --- /dev/null +++ b/backend/src/main/resources/db/changelog/README.txt @@ -0,0 +1,18 @@ +Understanding the liquidbase changelog.sql file + +" -- liquibase formatted sql" - this is required at the top of this file " + +" -- changeset liquibase:1.11.0 dbms:mariadb,mysql,postgresql " +This indicates a change set and the version - please use the release version that the change matches so that looking at the DB should +give a good indication of what has been run. + +The dbms section indicates which DBs the changeset that follows is valid to be run on. If this is not present, Liquidbase will try +to run the changeset always. + +" -- preconditions onFail:MARK_RAN " +" -- precondition-sql-check expectedResult:1 SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'users' " + +@see - https://docs.liquibase.com/concepts/changelogs/preconditions.html +The check here is looking to see if the schema has been built out yet. If it has not, then the db is new and will be created +correctly without needing to be updated, so MARK_RAN ensures that the given changeset will not be run, but will be added to the +liquibase changesetlog table indicating that it was checked. \ No newline at end of file diff --git a/backend/src/main/resources/db/changelog/changelog.sql b/backend/src/main/resources/db/changelog/changelog.sql new file mode 100644 index 000000000..0a63846a3 --- /dev/null +++ b/backend/src/main/resources/db/changelog/changelog.sql @@ -0,0 +1,178 @@ +-- liquibase formatted sql + +-- changeset liquibase:1.11.0.1 dbms:mysql,mariadb +-- preconditions onFail:MARK_RAN +-- precondition-sql-check expectedResult:1 SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'users' +-- comment: /* we don't need to run this if the system is new */ +ALTER TABLE custom_entity_attr_list_items + CHANGE value item_value varchar(255); +GO +ALTER TABLE custom_entity_attr_list_items_aud + CHANGE value item_value varchar(255); +GO +ALTER TABLE entity_attributes_filter_target_value + CHANGE value target_value varchar(255); +GO +ALTER TABLE entity_attributes_filter_target_value_aud + CHANGE value target_value varchar(255); +GO +ALTER TABLE name_id_format_filter_target_value + CHANGE value target_value varchar(255); +GO +ALTER TABLE name_id_format_filter_target_value_aud + CHANGE value target_value varchar(255); +GO +ALTER TABLE organizationurl + CHANGE value uri_value varchar(255); +GO +ALTER TABLE organizationurl_aud + CHANGE value uri_value varchar(255); +GO +ALTER TABLE organization_display_name + CHANGE value name_value varchar(255); +GO +ALTER TABLE organization_display_name_aud + CHANGE value name_value varchar(255); +GO +ALTER TABLE organization_name + CHANGE value name_value varchar(255); +GO +ALTER TABLE organization_name_aud + CHANGE value name_value varchar(255); +GO +ALTER TABLE resource_backed_metadata_resolver + CHANGE file file_resource varchar(255); +GO +ALTER TABLE resource_backed_metadata_resolver_aud + CHANGE file file_resource varchar(255); +GO +ALTER TABLE service_description + CHANGE value name_value varchar(255); +GO +ALTER TABLE service_description_aud + CHANGE value name_value varchar(255); +GO +ALTER TABLE service_name + CHANGE value name_value varchar(255); +GO +ALTER TABLE service_name_aud + CHANGE value name_value varchar(255); +GO + + +-- changeset liquibase:1.11.0.1 dbms:postgresql +-- preconditions onFail:MARK_RAN +-- precondition-sql-check expectedResult:1 SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'users' +-- comment: /* we don't need to run this if the system is new */ +ALTER TABLE custom_entity_attr_list_items + RENAME "value" TO "item_value"; +GO +ALTER TABLE custom_entity_attr_list_items_aud + RENAME "value" TO "item_value"; +GO +ALTER TABLE entity_attributes_filter_target_value + RENAME "value" TO "target_value"; +GO +ALTER TABLE entity_attributes_filter_target_value_aud + RENAME "value" TO "target_value"; +GO +ALTER TABLE name_id_format_filter_target_value + RENAME "value" TO "target_value"; +GO +ALTER TABLE name_id_format_filter_target_value_aud + RENAME "value" TO "target_value"; +GO +ALTER TABLE organizationurl + RENAME "value" TO "uri_value"; +GO +ALTER TABLE organizationurl_aud + RENAME "value" TO "uri_value"; +GO +ALTER TABLE organization_display_name + RENAME "value" TO "name_value"; +GO +ALTER TABLE organization_display_name_aud + RENAME "value" TO "name_value"; +GO +ALTER TABLE organization_name + RENAME "value" TO "name_value"; +GO +ALTER TABLE organization_name_aud + RENAME "value" TO "name_value"; +GO +ALTER TABLE resource_backed_metadata_resolver + RENAME "file" TO "file_resource"; +GO +ALTER TABLE resource_backed_metadata_resolver_aud + RENAME "file" TO "file_resource"; +GO +ALTER TABLE service_description + RENAME "value" TO "name_value"; +GO +ALTER TABLE service_description_aud + RENAME "value" TO "name_value"; +GO +ALTER TABLE service_name + RENAME "value" TO "name_value"; +GO +ALTER TABLE service_name_aud + RENAME "value" TO "name_value"; +GO + + +-- changeset liquibase:1.11.0.1 dbms:mssql +-- preconditions onFail:MARK_RAN +-- precondition-sql-check expectedResult:1 SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'users' +-- comment: /* we don't need to run this if the system is new */ +EXEC sp_rename 'custom_entity_attr_list_items.value', item_value, 'COLUMN' +GO +EXEC sp_rename 'custom_entity_attr_list_items_aud.value', item_value, 'COLUMN' +GO +EXEC sp_rename 'entity_attributes_filter_target_value.value', target_value, 'COLUMN' +GO +EXEC sp_rename 'entity_attributes_filter_target_value_aud.value', target_value, 'COLUMN' +GO +EXEC sp_rename 'name_id_format_filter_target_value.value', target_value, 'COLUMN' +GO +EXEC sp_rename 'name_id_format_filter_target_value_aud.value', target_value, 'COLUMN' +GO +EXEC sp_rename 'organizationurl.value', uri_value, 'COLUMN' +GO +EXEC sp_rename 'organizationurl_aud.value', uri_value, 'COLUMN' +GO +EXEC sp_rename 'organization_display_name.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'organization_display_name_aud.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'organization_name.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'organization_name_aud.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'service_description.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'service_description_aud.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'service_name.value', name_value, 'COLUMN' +GO +EXEC sp_rename 'service_name_aud.value', name_value, 'COLUMN' +GO + +-- changeset liquibase:1.11.0.2 dbms:mariadb,postgresql,mssql,mysql +-- preconditions onFail:MARK_RAN +-- precondition-sql-check expectedResult:1 SELECT count(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'users' +-- comment: /* we don't need to run this if the system is new */ + +update filesystem_metadata_resolver set min_refresh_delay ='PT5M'; +update filesystem_metadata_resolver_aud set min_refresh_delay ='PT5M'; +update filesystem_metadata_resolver set max_refresh_delay ='PT4H'; +update filesystem_metadata_resolver_aud set max_refresh_delay ='PT4H'; + +update file_backed_http_metadata_resolver set min_refresh_delay ='PT5M'; +update file_backed_http_metadata_resolver_aud set min_refresh_delay ='PT5M'; +update file_backed_http_metadata_resolver set max_refresh_delay ='PT4H'; +update file_backed_http_metadata_resolver_aud set max_refresh_delay ='PT4H'; + +update resource_backed_metadata_resolver set min_refresh_delay ='PT5M'; +update resource_backed_metadata_resolver_aud set min_refresh_delay ='PT5M'; +update resource_backed_metadata_resolver set max_refresh_delay ='PT4H'; +update resource_backed_metadata_resolver_aud set max_refresh_delay ='PT4H'; \ No newline at end of file diff --git a/backend/src/main/resources/dynamic-http-metadata-provider.schema.json b/backend/src/main/resources/dynamic-http-metadata-provider.schema.json index cd4ef1d60..b1719f8c6 100644 --- a/backend/src/main/resources/dynamic-http-metadata-provider.schema.json +++ b/backend/src/main/resources/dynamic-http-metadata-provider.schema.json @@ -253,60 +253,18 @@ "type": "string", "title": "label.connection-request-timeout", "description": "tooltip.connection-request-timeout", - "widget": { - "id": "datalist", - "data": [ - "PT0S", - "PT30S", - "PT1M", - "PT10M", - "PT30M", - "PT1H", - "PT4H", - "PT12H", - "PT24H" - ] - }, "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" }, "connectionTimeout": { "type": "string", "title": "label.connection-timeout", "description": "tooltip.connection-timeout", - "widget": { - "id": "datalist", - "data": [ - "PT0S", - "PT30S", - "PT1M", - "PT10M", - "PT30M", - "PT1H", - "PT4H", - "PT12H", - "PT24H" - ] - }, "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" }, "socketTimeout": { "type": "string", "title": "label.socket-timeout", "description": "tooltip.socket-timeout", - "widget": { - "id": "datalist", - "data": [ - "PT0S", - "PT30S", - "PT1M", - "PT10M", - "PT30M", - "PT1H", - "PT4H", - "PT12H", - "PT24H" - ] - }, "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" }, "tlsTrustEngineRef": { diff --git a/backend/src/main/resources/external.schema.json b/backend/src/main/resources/external.schema.json new file mode 100644 index 000000000..daa8c4503 --- /dev/null +++ b/backend/src/main/resources/external.schema.json @@ -0,0 +1,43 @@ +{ + "type": "object", + "required": [ + "name", + "@type", + "xmlId", + "description" + ], + "properties": { + "name": { + "title": "label.metadata-provider-name-dashboard-display-only", + "description": "tooltip.metadata-provider-name-dashboard-display-only", + "type": "string", + "widget": { + "id": "string", + "help": "message.must-be-unique" + } + }, + "@type": { + "title": "label.metadata-provider-type", + "description": "tooltip.metadata-provider-type", + "type": "string", + "const": "FilesystemMetadataResolver" + }, + "xmlId": { + "title": "label.metadata-resolver-id", + "description": "tooltip.xml-id", + "type": "string", + "minLength": 1 + }, + "enabled": { + "title": "label.enable-provider-upon-saving", + "description": "tooltip.enable-provider-upon-saving", + "type": "boolean", + "default": false + }, + "description": { + "title": "label.description", + "description": "tooltip.description", + "type": "string" + } + } +} \ No newline at end of file diff --git a/backend/src/main/resources/file-system-metadata-provider.schema.json b/backend/src/main/resources/file-system-metadata-provider.schema.json index 7969495f2..a4db5a52d 100644 --- a/backend/src/main/resources/file-system-metadata-provider.schema.json +++ b/backend/src/main/resources/file-system-metadata-provider.schema.json @@ -1,11 +1,6 @@ { "type": "object", - "required": [ - "name", - "@type", - "xmlId", - "metadataFile" - ], + "required": ["name", "@type", "xmlId", "metadataFile"], "properties": { "name": { "title": "label.metadata-provider-name-dashboard-display-only", @@ -47,18 +42,21 @@ }, "reloadableMetadataResolverAttributes": { "type": "object", + "required": ["minRefreshDelay", "maxRefreshDelay"], "properties": { "minRefreshDelay": { "title": "label.min-refresh-delay", "description": "tooltip.min-refresh-delay", "type": "string", - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$", + "default": "PT5M" }, "maxRefreshDelay": { "title": "label.max-refresh-delay", "description": "tooltip.max-refresh-delay", "type": "string", - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$", + "default": "PT4H" }, "refreshDelayFactor": { "title": "label.refresh-delay-factor", @@ -71,4 +69,4 @@ } } } -} \ No newline at end of file +} diff --git a/backend/src/main/resources/filebacked-http-metadata-provider.schema.json b/backend/src/main/resources/filebacked-http-metadata-provider.schema.json index f678ee306..277f3d3f9 100644 --- a/backend/src/main/resources/filebacked-http-metadata-provider.schema.json +++ b/backend/src/main/resources/filebacked-http-metadata-provider.schema.json @@ -101,152 +101,104 @@ "order": [], "type": "object", "properties": { - "disregardTLSCertificate": { - "type": "boolean", - "title": "label.disregard-tls-cert", - "description": "tooltip.disregard-tls-cert" + "disregardTLSCertificate": { + "type": "boolean", + "title": "label.disregard-tls-cert", + "description": "tooltip.disregard-tls-cert" + }, + "httpClientRef": { + "type": "string", + "title": "", + "description": "", + "widget": "hidden" + }, + "connectionRequestTimeout": { + "type": "string", + "title": "label.connection-request-timeout", + "description": "tooltip.connection-request-timeout", + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + }, + "connectionTimeout": { + "type": "string", + "title": "label.connection-timeout", + "description": "tooltip.connection-timeout", + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + }, + "socketTimeout": { + "type": "string", + "title": "label.socket-timeout", + "description": "tooltip.socket-timeout", + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + }, + "tlsTrustEngineRef": { + "type": "string", + "title": "", + "description": "" + }, + "httpClientSecurityParametersRef": { + "type": "string", + "title": "", + "description": "" + }, + "proxyHost": { + "type": "string", + "title": "label.proxy-host", + "description": "tooltip.proxy-host" + }, + "proxyPort": { + "type": "string", + "title": "label.proxy-port", + "description": "tooltip.proxy-port" + }, + "proxyUser": { + "type": "string", + "title": "label.proxy-user", + "description": "tooltip.proxy-user" + }, + "proxyPassword": { + "type": "string", + "title": "label.proxy-password", + "description": "tooltip.proxy-password" + }, + "httpCaching": { + "type": "string", + "title": "label.http-caching", + "description": "tooltip.http-caching", + "widget": { + "id": "select" }, - "httpClientRef": { - "type": "string", - "title": "", - "description": "", - "widget": "hidden" - }, - "connectionRequestTimeout": { - "type": "string", - "title": "label.connection-request-timeout", - "description": "tooltip.connection-request-timeout", - "widget": { - "id": "datalist", - "data": [ - "PT0S", - "PT30S", - "PT1M", - "PT10M", - "PT30M", - "PT1H", - "PT4H", - "PT12H", - "PT24H" - ] - }, - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" - }, - "connectionTimeout": { - "type": "string", - "title": "label.connection-timeout", - "description": "tooltip.connection-timeout", - "widget": { - "id": "datalist", - "data": [ - "PT0S", - "PT30S", - "PT1M", - "PT10M", - "PT30M", - "PT1H", - "PT4H", - "PT12H", - "PT24H" - ] - }, - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" - }, - "socketTimeout": { - "type": "string", - "title": "label.socket-timeout", - "description": "tooltip.socket-timeout", - "widget": { - "id": "datalist", - "data": [ - "PT0S", - "PT30S", - "PT1M", - "PT10M", - "PT30M", - "PT1H", - "PT4H", - "PT12H", - "PT24H" - ] - }, - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" - }, - "tlsTrustEngineRef": { - "type": "string", - "title": "", - "description": "" - }, - "httpClientSecurityParametersRef": { - "type": "string", - "title": "", - "description": "" - }, - "proxyHost": { - "type": "string", - "title": "label.proxy-host", - "description": "tooltip.proxy-host" - }, - "proxyPort": { - "type": "string", - "title": "label.proxy-port", - "description": "tooltip.proxy-port" - }, - "proxyUser": { - "type": "string", - "title": "label.proxy-user", - "description": "tooltip.proxy-user" - }, - "proxyPassword": { - "type": "string", - "title": "label.proxy-password", - "description": "tooltip.proxy-password" - }, - "httpCaching": { - "type": "string", - "title": "label.http-caching", - "description": "tooltip.http-caching", - "widget": { - "id": "select" - }, - "oneOf": [ - { - "enum": [ - "none" - ], - "description": "value.none" - }, - { - "enum": [ - "file" - ], - "description": "value.file" - }, - { - "enum": [ - "memory" - ], - "description": "value.memory" - } - ] - }, - "httpCacheDirectory": { - "type": "string", - "title": "label.http-caching-directory", - "description": "tooltip.http-caching-directory" - }, - "httpMaxCacheEntries": { - "type": "integer", - "title": "label.http-max-cache-entries", - "description": "tooltip.http-max-cache-entries", - "minimum": 0 - }, - "httpMaxCacheEntrySize": { - "type": "integer", - "title": "label.max-cache-entry-size", - "description": "tooltip.max-cache-entry-size", - "minimum": 0 - } + "oneOf": [ + { + "enum": ["none"], + "description": "value.none" + }, + { + "enum": ["file"], + "description": "value.file" + }, + { + "enum": ["memory"], + "description": "value.memory" + } + ] + }, + "httpCacheDirectory": { + "type": "string", + "title": "label.http-caching-directory", + "description": "tooltip.http-caching-directory" + }, + "httpMaxCacheEntries": { + "type": "integer", + "title": "label.http-max-cache-entries", + "description": "tooltip.http-max-cache-entries", + "minimum": 0 + }, + "httpMaxCacheEntrySize": { + "type": "integer", + "title": "label.max-cache-entry-size", + "description": "tooltip.max-cache-entry-size", + "minimum": 0 + } } }, "reloadableMetadataResolverAttributes": { @@ -257,13 +209,15 @@ "title": "label.min-refresh-delay", "description": "tooltip.min-refresh-delay", "type": "string", - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$", + "default": "PT5M" }, "maxRefreshDelay": { "title": "label.max-refresh-delay", "description": "tooltip.max-refresh-delay", "type": "string", - "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$" + "pattern": "^$|^(R\\d*\\/)?P(?:\\d+(?:\\.\\d+)?Y)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?W)?(?:\\d+(?:\\.\\d+)?D)?(?:T(?:\\d+(?:\\.\\d+)?H)?(?:\\d+(?:\\.\\d+)?M)?(?:\\d+(?:\\.\\d+)?S)?)?$", + "default": "PT4H" }, "refreshDelayFactor": { "title": "label.refresh-delay-factor", diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 0a7880b36..3b3e67e83 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -85,8 +85,8 @@ value.not-current=Not Current value.none=None value.file=File value.memory=Memory -value.true=True -value.false=False +value.true=true +value.false=false value.regex=Regex value.script=Script value.entity-id=Entity ID @@ -344,6 +344,7 @@ label.default-authentication-methods=Default Authentication Method(s) label.new-of-type=New { type } label.filters=Filters label.attributes=Attributes +label.metadata-resolver-id=Metadata Resolver ID label.metadata-filter-name=Metadata Filter Name (Dashboard Display Only) label.filter-enable=Enable this Filter? @@ -409,6 +410,7 @@ label.remove-roleless-entity-descriptors=Remove Roleless Entity Descriptors? label.remove-empty-entities-descriptors=Remove Empty Entities Descriptors? label.select-metadata-provider-type=Select Metadata Provider Type +label.select-metadata-filter-type=Select Metadata Filter Type label.filter-list=Filter List label.common-attributes=Common Attributes label.reloading-attributes=Reloading Attributes @@ -540,6 +542,7 @@ message.must-be-number=Must be a number. message.name-must-be-unique=Name must be unique. message.uri-valid-format=URI must be valid format. message.id-unique=ID must be unique. +message.name-unique=Service provider name must be unique. message.array-items-must-be-unique=Items in list must be unique. message.valid-duration=Must be a valid duration. message.valid-name=No special characters or whitespace allowed. @@ -684,7 +687,7 @@ tooltip.retained-roles=Note that property replacement cannot be used on this ele tooltip.remove-roleless-entity-descriptors=Controls whether to keep entity descriptors that contain no roles. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one role descriptor. tooltip.remove-empty-entities-descriptors=Controls whether to keep entities descriptors that contain no entity descriptors. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one child element, either an element or an element. -tooltip.min-refresh-delay=Lower bound on the next refresh from the time calculated based on the metadata\u0027s expiration. +tooltip.min-refresh-delay=Lower bound on the next refresh from the time calculated based on the metadata\u0027s expiration. Setting this to 0 will result in the default value being used. tooltip.max-refresh-delay=Upper bound on the next refresh from the time calculated based on the metadata\u0027s expiration. tooltip.refresh-delay-factor=A factor applied to the initially determined refresh time in order to determine the next refresh time (typically to ensure refresh takes place prior to the metadata\u0027s expiration). Attempts to refresh metadata will generally begin around the product of this number and the maximum refresh delay. tooltip.resolve-via-predicates-only=Flag indicating whether resolution may be performed solely by applying predicates to the entire metadata collection, when an entityID input criterion is not supplied. diff --git a/backend/src/main/resources/i18n/messages_en.properties b/backend/src/main/resources/i18n/messages_en.properties index f9f64d4d2..ca93cdbb3 100644 --- a/backend/src/main/resources/i18n/messages_en.properties +++ b/backend/src/main/resources/i18n/messages_en.properties @@ -54,8 +54,8 @@ value.disabled=Disabled value.none=None value.file=File value.memory=Memory -value.true=True -value.false=False +value.true=true +value.false=false value.regex=Regex value.script=Script value.entity-id=Entity ID @@ -531,7 +531,7 @@ tooltip.retained-roles=Note that property replacement cannot be used on this ele tooltip.remove-roleless-entity-descriptors=Controls whether to keep entity descriptors that contain no roles. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one role descriptor. tooltip.remove-empty-entities-descriptors=Controls whether to keep entities descriptors that contain no entity descriptors. Note: If this attribute is set to false, the resulting output may not be schema-valid since an element must include at least one child element, either an element or an element. -tooltip.min-refresh-delay=Lower bound on the next refresh from the time calculated based on the metadata\u0027s expiration. +tooltip.min-refresh-delay=Lower bound on the next refresh from the time calculated based on the metadata\u0027s expiration. Setting this to 0 will result in the default value being used. tooltip.max-refresh-delay=Upper bound on the next refresh from the time calculated based on the metadata\u0027s expiration. tooltip.refresh-delay-factor=A factor applied to the initially determined refresh time in order to determine the next refresh time (typically to ensure refresh takes place prior to the metadata\u0027s expiration). Attempts to refresh metadata will generally begin around the product of this number and the maximum refresh delay. tooltip.resolve-via-predicates-only=Flag indicating whether resolution may be performed solely by applying predicates to the entire metadata collection, when an entityID input criterion is not supplied. diff --git a/backend/src/main/resources/jpa-saml2-metadata-config.xml b/backend/src/main/resources/jpa-saml2-metadata-config.xml index 91a2de51a..b008809ce 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-config.xml @@ -21,10 +21,10 @@ - - + + - + @@ -41,15 +41,15 @@ - - + + - + - - + + @@ -81,24 +81,24 @@ - - + + - - + + - - + + - + @@ -115,24 +115,24 @@ - - + + - - + + - - + + - + @@ -149,15 +149,15 @@ - - + + - - + + @@ -202,8 +202,8 @@ - - + + @@ -235,22 +235,22 @@ - - + + - - + + - - + + @@ -269,22 +269,22 @@ - - + + - - + + - - + + @@ -316,29 +316,29 @@ - - + + - - + + - - + + - - + + @@ -357,16 +357,16 @@ - - + + - - + + - + \ No newline at end of file diff --git a/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml b/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml index 868961e13..f2dd17dfe 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-reqinit-config.xml @@ -7,8 +7,8 @@ - - + + diff --git a/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml b/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml index 1ab941897..b9aa1bb66 100644 --- a/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml +++ b/backend/src/main/resources/jpa-saml2-metadata-ui-config.xml @@ -9,8 +9,8 @@ - - + + @@ -44,8 +44,8 @@ - - + + @@ -69,8 +69,8 @@ - - + + @@ -98,8 +98,8 @@ - - + + @@ -116,4 +116,4 @@ - + \ No newline at end of file diff --git a/backend/src/main/resources/jpa-signature-config.xml b/backend/src/main/resources/jpa-signature-config.xml index 0a6696db5..9a8da32e8 100644 --- a/backend/src/main/resources/jpa-signature-config.xml +++ b/backend/src/main/resources/jpa-signature-config.xml @@ -39,7 +39,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + \ No newline at end of file diff --git a/backend/src/main/resources/modified-saml2-assertion-config.xml b/backend/src/main/resources/modified-saml2-assertion-config.xml index 1f9d649a0..3349e4558 100644 --- a/backend/src/main/resources/modified-saml2-assertion-config.xml +++ b/backend/src/main/resources/modified-saml2-assertion-config.xml @@ -46,15 +46,15 @@ - - + + - - + + @@ -73,8 +73,8 @@ - - + + @@ -93,8 +93,8 @@ - - + + @@ -113,22 +113,22 @@ - - + + - - + + - - + + @@ -207,8 +207,8 @@ - - + + @@ -221,16 +221,28 @@ - - + + - - + + - + + + + + + + + + + + + + @@ -310,4 +322,4 @@ - + \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy index bda1b4dfa..d64fa8861 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntitiesControllerIntegrationTests.groovy @@ -2,17 +2,12 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository -import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService -import groovy.json.JsonOutput import net.shibboleth.ext.spring.resource.ResourceHelper import net.shibboleth.utilities.java.support.resolver.CriteriaSet - -import org.joda.time.DateTime import org.opensaml.core.criterion.EntityIdCriterion import org.opensaml.saml.metadata.resolver.ChainingMetadataResolver import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain -import org.opensaml.saml.metadata.resolver.impl.FilesystemMetadataResolver import org.opensaml.saml.metadata.resolver.impl.ResourceBackedMetadataResolver import org.spockframework.spring.SpringBean import org.springframework.beans.factory.annotation.Autowired @@ -22,15 +17,14 @@ import org.springframework.context.annotation.Bean import org.springframework.core.io.ClassPathResource import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.reactive.server.WebTestClient -import org.springframework.test.web.servlet.result.MockMvcResultHandlers -import org.springframework.web.reactive.function.client.WebClient -import org.springframework.web.util.DefaultUriBuilderFactory import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import org.xmlunit.diff.DefaultNodeMatcher import org.xmlunit.diff.ElementSelectors import spock.lang.Specification +import java.time.Instant + /** * @author Bill Smith (wsmith@unicon.net) */ @@ -165,7 +159,7 @@ class EntitiesControllerIntegrationTests extends Specification { def resource = ResourceHelper.of(new ClassPathResource("/metadata/aggregate.xml")) def aggregate = new ResourceBackedMetadataResolver(resource){ @Override - DateTime getLastRefresh() { + Instant getLastRefresh() { return null } } @@ -186,4 +180,4 @@ class EntitiesControllerIntegrationTests extends Specification { } } } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerTests.groovy index c0a7d0e68..82bee21b2 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataFiltersControllerTests.groovy @@ -96,6 +96,11 @@ class MetadataFiltersControllerTests extends AbstractBaseDataJpaTest { return null } + @Override + Document generateExternalMetadataFilterConfiguration() { + return null + } + @Override MetadataResolver findByResourceId(String resourceId) throws EntityNotFoundException { // This won't get called diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy index 90c70f38e..0f52dc668 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/MetadataResolversControllerIntegrationTests.groovy @@ -1,8 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.controller import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.SerializationFeature -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.configuration.CustomPropertiesConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.EntitiesVersioningConfiguration @@ -10,22 +8,19 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConf import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverConverterConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.MetadataResolverValidationConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration -import edu.internet2.tier.shibboleth.admin.ui.configuration.StringTrimModule import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.FileBackedHttpMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.validator.MetadataResolverValidationService -import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolversPositionOrderContainerRepository import edu.internet2.tier.shibboleth.admin.ui.service.DefaultMetadataResolversPositionOrderContainerService import edu.internet2.tier.shibboleth.admin.ui.service.DirectoryService import edu.internet2.tier.shibboleth.admin.ui.service.DirectoryServiceImpl import edu.internet2.tier.shibboleth.admin.ui.service.IndexWriterService -import edu.internet2.tier.shibboleth.admin.ui.service.JPAMetadataResolverServiceImpl import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverConverterService import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverService import edu.internet2.tier.shibboleth.admin.ui.service.MetadataResolverVersionService @@ -46,7 +41,6 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.transaction.annotation.Transactional import spock.lang.Unroll -import static com.fasterxml.jackson.annotation.JsonInclude.Include.NON_NULL import static org.springframework.http.MediaType.APPLICATION_JSON import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post @@ -92,6 +86,34 @@ class MetadataResolversControllerIntegrationTests extends AbstractBaseDataJpaTes metadataResolverRepository.deleteAll() } + @WithMockAdmin + def "SHIBUI-2303: POST new FileBackedHttp -> "() { + given: + def resolver = new FileBackedHttpMetadataResolver().with { + it.name = 'HTTPMetadata' + it.xmlId = 'HTTPMetadata' + it.backingFile = '%{idp.home}/metadata/metadata.xml' + it.metadataURL = 'https://idp.unicon.net/idp/shibboleth' + + it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { +// it.minRefreshDelay = 'PT1M' // min > max + it.maxRefreshDelay = 'PT0M' + it + } + it.enabled = Boolean.FALSE + it.doInitialization = Boolean.TRUE + it.resourceId = 'fbhmr_res_id' + it + } + + when: + def result = mockMvc.perform(post(BASE_URI).contentType(APPLICATION_JSON).content(mapper.writeValueAsString(resolver))) + + then: + result.andExpect(status().isCreated()).andExpect(content().contentType(APPLICATION_JSON)) + .andExpect(jsonPath("\$.name").value("HTTPMetadata")) + } + @WithMockAdmin def "GET empty -> /api/MetadataResolvers"() { when: 'No resolvers are available in data store' diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/OpenSamlResourceBackedMetadataResolverTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/OpenSamlResourceBackedMetadataResolverTests.groovy index 28223b2f8..52ae52374 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/OpenSamlResourceBackedMetadataResolverTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/resolvers/OpenSamlResourceBackedMetadataResolverTests.groovy @@ -15,10 +15,10 @@ class OpenSamlResourceBackedMetadataResolverTests extends Specification { def 'test refresh'() { when: def rbmr = new ResourceBackedMetadataResolver(name: 'test', xmlId: 'test', classpathMetadataResource: new ClasspathMetadataResource('metadata/metadata.xml')) - def x = new OpenSamlResourceBackedMetadataResolver(openSamlObjects.parserPool, null, rbmr, ResourceHelper.of(new ClassPathResource(rbmr.classpathMetadataResource.file))) + def x = new OpenSamlResourceBackedMetadataResolver(openSamlObjects.parserPool, null, rbmr, ResourceHelper.of(new ClassPathResource(rbmr.classpathMetadataResource.fileResource))) x.refilter() then: noExceptionThrown() } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy index 703e44f7a..9905dbcea 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/JPAMetadataResolverServiceImplTests.groovy @@ -1,14 +1,19 @@ package edu.internet2.tier.shibboleth.admin.ui.service +import com.google.common.collect.Lists import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.configuration.PlaceholderResolverComponentsConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration +import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute +import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeValue +import edu.internet2.tier.shibboleth.admin.ui.domain.XSString import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilterTarget import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter import edu.internet2.tier.shibboleth.admin.ui.domain.filters.RequiredValidUntilFilter import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ClasspathMetadataResource import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.DynamicHttpMetadataResolver +import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ExternalMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.LocalDynamicMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProtocolScheme import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.RegexScheme @@ -18,11 +23,11 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSaml import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository import edu.internet2.tier.shibboleth.admin.ui.util.TestObjectGenerator +import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import groovy.xml.DOMBuilder import groovy.xml.MarkupBuilder import net.shibboleth.ext.spring.resource.ResourceHelper import net.shibboleth.utilities.java.support.resolver.CriteriaSet -import org.joda.time.DateTime import org.opensaml.core.criterion.EntityIdCriterion import org.opensaml.saml.metadata.resolver.MetadataResolver import org.opensaml.saml.metadata.resolver.filter.MetadataFilterChain @@ -32,11 +37,15 @@ import org.springframework.boot.test.context.TestConfiguration import org.springframework.context.annotation.Bean import org.springframework.core.io.ClassPathResource import org.springframework.test.context.ContextConfiguration +import org.w3c.dom.Document +import org.w3c.dom.Node import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import spock.lang.Ignore import spock.lang.Unroll +import java.time.Instant + import static edu.internet2.tier.shibboleth.admin.ui.util.TestHelpers.generatedXmlIsTheSameAsExpectedXml @ContextConfiguration(classes=[ JPAMRSIConfig, PlaceholderResolverComponentsConfiguration ]) @@ -66,6 +75,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { @Autowired TestObjectGenerator testObjectGenerator + AttributeUtility attributeUtility DOMBuilder domBuilder = DOMBuilder.newInstance() StringWriter writer = new StringWriter() MarkupBuilder markupBuilder @@ -74,6 +84,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { markupBuilder = new MarkupBuilder(writer) markupBuilder.omitNullAttributes = true markupBuilder.omitEmptyAttributes = true + attributeUtility = new AttributeUtility(openSamlObjects) } def cleanup() { @@ -81,6 +92,43 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { writer.close() } + def 'test generating ExternalMetadataResolver XML'() { + given: + def resolver = new ExternalMetadataResolver().with { + it.setEnabled(true) + it.setName("testme") + it.setXmlId("InCommonMD") + it.setDescription("some description that won't appear in the xml") + it.addFilter(new EntityAttributesFilter().with { + it.name = 'EntityAttributes' + EntityAttributesFilterTarget filterTarget = testObjectGenerator.buildEntityAttributesFilterTarget() + filterTarget.setSingleValue("https://sp.example.org/shibboleth") + it.setEntityAttributesFilterTarget(filterTarget) + def attribute = attributeUtility.createAttributeWithStringValues('http://shibboleth.net/ns/attributes/releaseAllValues', null, 'eduPersonPrincipalName') + attribute.nameFormat = 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri' + attribute.namespacePrefix = 'saml2' + attribute.attributeValues.each { val -> + ((XSString)val).namespacePrefix = 'saml2' + + '' + } + it.attributes = [attribute] + it.intoTransientRepresentation() + it.enabled = true; + it + }) + it + } + metadataResolverRepository.save(resolver) + metadataResolverService.reloadFilters("testme") + + when: + Document doc = JPAMetadataResolverServiceImpl.cast(metadataResolverService).generateExternalMetadataFilterConfiguration() + Node node = doc.getFirstChild() + + then: + generatedXmlIsTheSameAsExpectedXml('/conf/2269.xml', node) + } + def 'test adding a filter'() { given: def expectedXML = ''' @@ -93,10 +141,8 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { givenName employeeNumber + testme - - testme - @@ -109,7 +155,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { it.resourceId = "testme" it.name = "testme" it.classpathMetadataResource = new ClasspathMetadataResource().with { - it.file = "metadata/aggregate.xml" + it.fileResource = "metadata/aggregate.xml" it } it.metadataFilters.add(new EntityAttributesFilter().with { @@ -131,7 +177,9 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { assert metadataResolverRepository.findAll().size() > 0 def ed = metadataResolver.resolveSingle(new CriteriaSet(new EntityIdCriterion('http://test.scaldingspoon.org/test1'))) def resultString = openSamlObjects.marshalToXmlString(ed) + println("RESULTSTRING:") println(resultString) + // line 99 above being added to release all values, not its own thing def diff = DiffBuilder.compare(Input.fromString(expectedXML)).withTest(Input.fromString(resultString)).ignoreComments().ignoreWhitespace().build() !diff.hasDifferences() } @@ -274,7 +322,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { def resolver = new edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver().with { it.xmlId = 'ClasspathResourceMetadata' it.classpathMetadataResource = new ClasspathMetadataResource().with { - it.file = '/path/to/a/classpath/location/metadata.xml' + it.fileResource = '/path/to/a/classpath/location/metadata.xml' it } it @@ -475,7 +523,7 @@ class JPAMetadataResolverServiceImplTests extends AbstractBaseDataJpaTest { MetadataResolver metadataResolver(OpenSamlObjects openSamlObjects) { def aggregate = new ResourceBackedMetadataResolver(ResourceHelper.of(new ClassPathResource("/metadata/aggregate.xml"))){ @Override - DateTime getLastRefresh() { + Instant getLastRefresh() { return null } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy index 321ef2b38..d25e9813c 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/EntityDescriptorConversionUtilsTests.groovy @@ -1005,7 +1005,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.extensions = openSAMLObjects.buildDefaultInstanceOfType(Extensions).with { it.unknownXMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(UIInfo).with { it.XMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(Logo).with { - it.url = 'http://test' + it.uri = 'http://test' it.height = 5 it.width = 25 it.XMLLang = 'en' @@ -1034,7 +1034,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.extensions = openSAMLObjects.buildDefaultInstanceOfType(Extensions).with { it.unknownXMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(UIInfo).with { it.XMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(Logo).with { - it.url = 'http://test' + it.uri = 'http://test' it.height = 5 it.width = 25 it.XMLLang = 'en' @@ -1070,7 +1070,7 @@ class EntityDescriptorConversionUtilsTests extends Specification { it.extensions = openSAMLObjects.buildDefaultInstanceOfType(Extensions).with { it.unknownXMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(UIInfo).with { it.XMLObjects.add(openSAMLObjects.buildDefaultInstanceOfType(Logo).with { - it.url = 'http://test' + it.uri = 'http://test' it.height = 5 it.width = 25 it.XMLLang = 'en' diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy index f50263663..e2d67412e 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestHelpers.groovy @@ -3,20 +3,20 @@ package edu.internet2.tier.shibboleth.admin.ui.util import edu.internet2.tier.shibboleth.admin.ui.security.model.User import groovy.xml.XmlUtil import junit.framework.Assert -import javax.xml.transform.Source; -import javax.xml.transform.Transformer -import javax.xml.transform.TransformerException -import javax.xml.transform.TransformerFactory -import javax.xml.transform.dom.DOMSource -import javax.xml.transform.stream.StreamResult - import org.apache.commons.lang.StringUtils -import org.springframework.security.core.context.SecurityContextHolder import org.w3c.dom.Document +import org.w3c.dom.Node import org.xmlunit.builder.DiffBuilder import org.xmlunit.builder.Input import org.xmlunit.builder.Input.Builder +import javax.xml.transform.Source +import javax.xml.transform.Transformer +import javax.xml.transform.TransformerException +import javax.xml.transform.TransformerFactory +import javax.xml.transform.dom.DOMSource +import javax.xml.transform.stream.StreamResult + /** * @author Bill Smith (wsmith@unicon.net) */ @@ -50,6 +50,19 @@ class TestHelpers { Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences()); } + static void generatedXmlIsTheSameAsExpectedXml(String expectedXmlResource, Node generatedXml) { + def Builder builder = Input.fromNode(generatedXml) + def Source source = builder.build() + def myDiff = DiffBuilder.compare(Input.fromStream(TestHelpers.getResourceAsStream(expectedXmlResource))) + .withTest(builder) + .withAttributeFilter({attribute -> !attribute.name.equals("sourceDirectory")}) + .ignoreComments() + .ignoreWhitespace() + .build() + System.out.println("@@@ \n" + getString(source) + "\n") + Assert.assertFalse(myDiff.toString(), myDiff.hasDifferences()); + } + public static String getString(DOMSource domSource) throws TransformerException { StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); @@ -67,4 +80,4 @@ class TestHelpers { def user = new User(username: username, role: rolename) Optional.of(user) } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy index bf17b107e..7b2865462 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/util/TestObjectGenerator.groovy @@ -30,7 +30,6 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataQueryProt import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ReloadableMetadataResolverAttributes import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.SvnMetadataResource import edu.internet2.tier.shibboleth.admin.util.AttributeUtility import edu.internet2.tier.shibboleth.admin.util.MDDCConstants import edu.internet2.tier.shibboleth.admin.util.ModelRepresentationConversions @@ -607,7 +606,7 @@ class TestObjectGenerator { it.name = 'ClasspathResourceMetadata' it.xmlId = 'ClasspathResourceMetadata' it.classpathMetadataResource = new ClasspathMetadataResource().with { - it.file = 'metadata/metadata.xml' + it.fileResource = 'metadata/metadata.xml' it } it.reloadableMetadataResolverAttributes = new ReloadableMetadataResolverAttributes().with { diff --git a/backend/src/test/resources/conf/2269.xml b/backend/src/test/resources/conf/2269.xml new file mode 100644 index 000000000..f4c166e29 --- /dev/null +++ b/backend/src/test/resources/conf/2269.xml @@ -0,0 +1,21 @@ + + + + + + + eduPersonPrincipalName + + https://sp.example.org/shibboleth + + + + \ No newline at end of file diff --git a/beacon/core/build.gradle b/beacon/core/build.gradle index c80df0931..b4ddfd4ca 100644 --- a/beacon/core/build.gradle +++ b/beacon/core/build.gradle @@ -1,16 +1,21 @@ import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { - id 'org.springframework.boot' version '2.4.2' apply false + id 'org.springframework.boot' id 'io.spring.dependency-management' version '1.0.6.RELEASE' + id 'groovy' } -apply plugin: 'groovy' sourceCompatibility = 11 targetCompatibility = 11 +bootJar.enabled = false + repositories { jcenter() + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } } dependencyManagement { @@ -20,14 +25,13 @@ dependencyManagement { } dependencies { - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.spockframework:spock-core:1.3-groovy-2.5" - testCompile "org.spockframework:spock-spring:1.3-groovy-2.5" - - testCompile 'org.junit.jupiter:junit-jupiter-api:5.5.2' - testCompile 'org.junit.jupiter:junit-jupiter-engine:5.5.2' + testCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + compile 'org.codehaus.groovy:groovy-all:3.0.10' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" + testImplementation "org.spockframework:spock-spring" } jar { archiveName = "beacon-core-${version}.jar" -} +} \ No newline at end of file diff --git a/beacon/spring/build.gradle b/beacon/spring/build.gradle index 61ab07be5..eb6d1e991 100644 --- a/beacon/spring/build.gradle +++ b/beacon/spring/build.gradle @@ -1,7 +1,7 @@ import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { - id 'org.springframework.boot' version '2.0.0.RELEASE' apply false + id 'org.springframework.boot' id 'io.spring.dependency-management' version '1.0.6.RELEASE' } @@ -9,8 +9,13 @@ apply plugin: 'java' sourceCompatibility = 11 targetCompatibility = 11 +bootJar.enabled = false + repositories { jcenter() + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } } jar { diff --git a/build.gradle b/build.gradle index ee0af8876..3fcdff1c6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ plugins { id 'base' - id 'net.researchgate.release' version '2.6.0' + id 'net.researchgate.release' version '3.0.0' id 'com.github.breadmoirai.github-release' version '2.2.9' } @@ -23,9 +23,10 @@ githubRelease { release { git { - pushToRemote = 'i2' + pushToRemote.set(project.'i2.git.remote') + requireBranch.set(project.'i2.git.branch') } } afterReleaseBuild.dependsOn project.getTasksByName('githubRelease', false) -afterReleaseBuild.dependsOn project.getTasksByName('dockerTagsPush', true) +afterReleaseBuild.dependsOn project.getTasksByName('dockerTagsPush', true) \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 79bee945d..7efe1ae08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,15 +1,26 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.11.0-SNAPSHOT +version=1.12.0-SNAPSHOT -shibboleth.version=3.4.4 -opensaml.version=3.4.3 +### library versions ### +commonsCollections4Version=4.4 +cryptacularVersion=1.2.4 +hibernateVersion=5.6.9.Final +luceneVersion=8.1.1 +log4JVersion=2.17.2 +lombokVersion=5.3.3.3 +opensamlVersion=4.2.0 +pac4JVersion=5.4.3 +pac4jSpringSecurityVersion=7.0.3 +shibbolethVersion=4.2.1 +springbootVersion=2.7.0 +springSecurityVersion=5.7.1 -spring-boot.version=2.4.2 - -hibernate.version=5.5.0.Final - -lucene.version=8.1.1 +### DB Driver Versions ### +mariadbVersion=3.0.4 +mysqlVersion=8.0.29 +postgresVersion=42.3.4 +sqlserverVersion=9.4.1.jre11 org.gradle.jvmargs=-Xmx1g -XX:-UseGCOverheadLimit @@ -18,4 +29,9 @@ i2.github.token= i2.github.owner=TIER i2.github.repo=shib-idp-ui i2.github.apiEndpoint=https://github.internet2.edu/api/v3 +i2.git.remote=i2 +i2.git.branch=master +## NOTES +# pac4j spring security 7.0.3 here uses the pac4j 5.4.3 core, thus differences in versions (they used use the same versions, now +# keeping them in sync takes paying attention \ No newline at end of file diff --git a/pac4j-module/build.gradle b/pac4j-module/build.gradle index 8803d22c9..4080df12a 100644 --- a/pac4j-module/build.gradle +++ b/pac4j-module/build.gradle @@ -1,20 +1,30 @@ plugins { id 'groovy' id 'jacoco' - id 'org.springframework.boot' version '2.4.2' apply false + id 'org.springframework.boot' id 'io.spring.dependency-management' version '1.0.7.RELEASE' - id 'io.freefair.lombok' version '5.3.0' + id 'io.freefair.lombok' } sourceCompatibility = 11 targetCompatibility = 11 +bootJar.enabled = false + repositories { jcenter() + mavenCentral() maven { url 'https://build.shibboleth.net/nexus/content/groups/public' artifactUrls = ['https://build.shibboleth.net/nexus/content/repositories/thirdparty-snapshots'] } + maven { // for the springboot plugin + url "https://plugins.gradle.org/m2/" + } +} + +test { + useJUnitPlatform() // Needed by spock to find specification tests } dependencyManagement { @@ -28,27 +38,27 @@ generateLombokConfig.enabled = false dependencies { compileOnly project(':backend') - compile "org.pac4j:spring-security-pac4j:4.0.0" - compile "org.pac4j:pac4j-core:3.3.0" - compile "org.pac4j:pac4j-http:3.3.0" - compile "org.pac4j:pac4j-saml:3.3.0", { + compile "org.pac4j:spring-security-pac4j:${project.'pac4jSpringSecurityVersion'}" + compile "org.pac4j:pac4j-core:${project.'pac4JVersion'}" + compile "org.pac4j:pac4j-http:${project.'pac4JVersion'}" + compile "org.pac4j:pac4j-saml:${project.'pac4JVersion'}", { // opensaml libraries are provided exclude group: 'org.opensaml' + exclude group: 'commons-collections' } + // But we do need this opensaml lib that wasn't provided + implementation "org.opensaml:opensaml-storage-impl:${project.'opensamlVersion'}" + compile "org.apache.commons:commons-collections4:${project.'commonsCollections4Version'}" -// These updated versions don't play well with the opensaml 3.4.6 version - until we can update openSAML.... -// compile "org.pac4j:spring-security-pac4j:6.0.0" // pac4j is "off" - spring 6.0.0 here uses 5.1 core, thus differences in versions -// compile "org.pac4j:pac4j-core:5.1.0" -// compile "org.pac4j:pac4j-http:5.1.0" -// compile "org.pac4j:pac4j-saml:5.1.0", { -// // opensaml libraries are provided -// exclude group: 'org.opensaml' -// } testCompile project(':backend') - testCompile "org.springframework.boot:spring-boot-starter-test" - testCompile "org.spockframework:spock-core:1.3-groovy-2.5" - testCompile "org.spockframework:spock-spring:1.3-groovy-2.5" + testCompile "org.opensaml:opensaml-saml-api:${project.'opensamlVersion'}" + + testCompile "org.springframework.boot:spring-boot-starter-test:${project.'springbootVersion'}" + compile 'org.codehaus.groovy:groovy-all:3.0.10' + testImplementation platform("org.spockframework:spock-bom:2.1-groovy-3.0") + testImplementation "org.spockframework:spock-core" + testImplementation "org.spockframework:spock-spring" - annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" + annotationProcessor "org.springframework.boot:spring-boot-configuration-processor:${project.'springbootVersion'}" } \ No newline at end of file diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java index c0c9048fa..c7ed5fd71 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/AddNewUserFilter.java @@ -11,10 +11,12 @@ import edu.internet2.tier.shibboleth.admin.ui.service.EmailService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.RandomStringUtils; -import org.pac4j.core.context.J2EContext; import org.pac4j.core.context.WebContext; -import org.pac4j.core.matching.Matcher; +import org.pac4j.core.context.session.SessionStore; +import org.pac4j.core.matching.matcher.Matcher; import org.pac4j.core.profile.CommonProfile; +import org.pac4j.jee.context.JEEContext; +import org.pac4j.jee.context.session.JEESessionStore; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.crypto.bcrypt.BCrypt; @@ -103,8 +105,10 @@ public void destroy() { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { - WebContext context = new J2EContext((HttpServletRequest)request, (HttpServletResponse)response); - if (!matcher.matches(context)) { + WebContext context = new JEEContext((HttpServletRequest)request, (HttpServletResponse)response); + Optional optionalSession = JEESessionStore.INSTANCE.buildFromTrackableSession(context, ((HttpServletRequest) request).getSession()); + SessionStore session = optionalSession.isPresent() ? (SessionStore) optionalSession.get() : null; + if (!matcher.matches(context, session)) { return; } Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java index 5d9642409..4ec901998 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/LocalUserProfileAuthorizationGenerator.java @@ -4,7 +4,8 @@ import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; import org.pac4j.core.authorization.generator.AuthorizationGenerator; import org.pac4j.core.context.WebContext; -import org.pac4j.core.profile.CommonProfile; +import org.pac4j.core.context.session.SessionStore; +import org.pac4j.core.profile.UserProfile; import java.util.Optional; @@ -16,9 +17,9 @@ public LocalUserProfileAuthorizationGenerator(UserRepository userRepository) { } @Override - public CommonProfile generate(WebContext context, CommonProfile profile) { + public Optional generate(WebContext context, SessionStore sessionStore, UserProfile profile) { Optional user = userRepository.findByUsername(profile.getUsername()); user.ifPresent(u -> profile.addRole(u.getRole())); - return profile; + return Optional.of(profile); } } \ No newline at end of file diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java index 26d32708f..fd018d4b6 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfiguration.java @@ -8,11 +8,11 @@ import net.unicon.shibui.pac4j.authenticator.ShibuiSAML2Authenticator; import org.pac4j.core.client.Clients; import org.pac4j.core.config.Config; -import org.pac4j.core.matching.PathMatcher; +import org.pac4j.core.matching.matcher.PathMatcher; import org.pac4j.core.profile.definition.CommonProfileDefinition; import org.pac4j.http.client.direct.HeaderClient; import org.pac4j.saml.client.SAML2Client; -import org.pac4j.saml.client.SAML2ClientConfiguration; +import org.pac4j.saml.config.SAML2Configuration; import org.pac4j.saml.credentials.authenticator.SAML2Authenticator; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -69,7 +69,7 @@ public Config config(final Pac4jConfigurationProperties pac4jConfigProps, case "SAML2": default: log.info("**** Configuring PAC4J SAML2"); - final SAML2ClientConfiguration saml2Config = new SAML2ClientConfiguration(); + final SAML2Configuration saml2Config = new SAML2Configuration(); saml2Config.setKeystorePath(pac4jConfigProps.getKeystorePath()); saml2Config.setKeystorePassword(pac4jConfigProps.getKeystorePassword()); saml2Config.setPrivateKeyPassword(pac4jConfigProps.getPrivateKeyPassword()); diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java index 17bc554ff..884569ac7 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/WebSecurity.java @@ -5,9 +5,9 @@ import edu.internet2.tier.shibboleth.admin.ui.security.service.IRolesService; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; import edu.internet2.tier.shibboleth.admin.ui.service.EmailService; -import static net.unicon.shibui.pac4j.Pac4jConfiguration.PAC4J_CLIENT_NAME; +import org.pac4j.core.authorization.authorizer.DefaultAuthorizers; import org.pac4j.core.config.Config; -import org.pac4j.core.matching.Matcher; +import org.pac4j.core.matching.matcher.Matcher; import org.pac4j.springframework.security.web.CallbackFilter; import org.pac4j.springframework.security.web.SecurityFilter; import org.springframework.boot.autoconfigure.AutoConfigureAfter; @@ -26,6 +26,8 @@ import javax.servlet.Filter; import java.util.Optional; +import static net.unicon.shibui.pac4j.Pac4jConfiguration.PAC4J_CLIENT_NAME; + @Configuration @AutoConfigureOrder(-1) @ConditionalOnProperty(name = "shibui.pac4j-enabled", havingValue = "true") @@ -62,7 +64,8 @@ public Pac4jWebSecurityConfigurerAdapter(final Config config, UserService userSe protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/unsecured/**/*").permitAll(); - final SecurityFilter securityFilter = new SecurityFilter(this.config, PAC4J_CLIENT_NAME); + // adding the authorizor bypasses the default behavior of checking CSRF in Pac4J's default securitylogic+defaultauthorizationchecker + final SecurityFilter securityFilter = new SecurityFilter(this.config, PAC4J_CLIENT_NAME, DefaultAuthorizers.IS_AUTHENTICATED); // add filter based on auth type http.antMatcher("/**").addFilterBefore(getFilter(config, pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class); diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java index 1109b5d72..0c1a9e084 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiPac4JHeaderClientAuthenticator.java @@ -4,6 +4,7 @@ import lombok.AllArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.pac4j.core.context.WebContext; +import org.pac4j.core.context.session.SessionStore; import org.pac4j.core.credentials.Credentials; import org.pac4j.core.credentials.TokenCredentials; import org.pac4j.core.credentials.authenticator.Authenticator; @@ -18,7 +19,7 @@ public class ShibuiPac4JHeaderClientAuthenticator implements Authenticator { private UserService userService; @Override - public void validate(Credentials credentials, WebContext context) { + public void validate(Credentials credentials, WebContext context, SessionStore sessionStore) { { if (credentials instanceof TokenCredentials) { TokenCredentials creds = (TokenCredentials) credentials; diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java index c5eb8f18b..f2d2738e0 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/authenticator/ShibuiSAML2Authenticator.java @@ -1,10 +1,10 @@ package net.unicon.shibui.pac4j.authenticator; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; -import lombok.AllArgsConstructor; import org.pac4j.core.context.WebContext; +import org.pac4j.core.context.session.SessionStore; +import org.pac4j.core.credentials.Credentials; import org.pac4j.core.profile.CommonProfile; -import org.pac4j.saml.credentials.SAML2Credentials; import org.pac4j.saml.credentials.authenticator.SAML2Authenticator; import java.util.Map; @@ -23,9 +23,9 @@ public ShibuiSAML2Authenticator(final String attributeAsId, final Map Shibboleth Metadata Management - - + +
-
- +
+
+ + + +
User request received

Your request has been received and is being reviewed. You will be notified with access status.

diff --git a/ui/public/unsecured/favicon-96x96.png b/ui/public/unsecured/favicon-96x96.png new file mode 100644 index 000000000..e19516fff Binary files /dev/null and b/ui/public/unsecured/favicon-96x96.png differ diff --git a/ui/public/unsecured/favicon.ico b/ui/public/unsecured/favicon.ico new file mode 100644 index 000000000..9c1f419d3 Binary files /dev/null and b/ui/public/unsecured/favicon.ico differ diff --git a/ui/public/unsecured/shibboleth_icon_color_130x130.png b/ui/public/unsecured/shibboleth_icon_color_130x130.png new file mode 100644 index 000000000..313df313e Binary files /dev/null and b/ui/public/unsecured/shibboleth_icon_color_130x130.png differ diff --git a/ui/src/app/App.constant.js b/ui/src/app/App.constant.js index 3b6af7f89..afa7a688c 100644 --- a/ui/src/app/App.constant.js +++ b/ui/src/app/App.constant.js @@ -5,8 +5,18 @@ export const getBasePath = () => { //replace(/^\/|\/$/g, '') }; +export const getActuatorPath = () => { + const url = new URL(document.getElementsByTagName('base')[0].href); + + var foo = document.createElement("a"); + foo.href = url.pathname?.replace(/^\/+/g, ''); + foo.port = "9090" + return foo.href; +} + export const BASE_PATH = getBasePath(); export const API_BASE_PATH = `${BASE_PATH}api`; +export const ACTUATOR_PATH = getActuatorPath(); export const FILTER_PLUGIN_TYPES = ['RequiredValidUntil', 'SignatureValidation', 'EntityRoleWhiteList']; diff --git a/ui/src/app/App.js b/ui/src/app/App.js index 20331e4e8..546241f10 100644 --- a/ui/src/app/App.js +++ b/ui/src/app/App.js @@ -33,6 +33,7 @@ import { SessionModal } from './core/user/SessionModal'; import { Roles } from './admin/Roles'; import { Groups } from './admin/Groups'; import { BASE_PATH } from './App.constant'; +import { ProtectRoute } from './core/components/ProtectRoute'; function App() { @@ -81,12 +82,32 @@ function App() { - - - + + + + + } /> + + + + + } /> + + + + + } /> - - + + + + + } /> + + + + + } /> diff --git a/ui/src/app/core/components/Spinner.js b/ui/src/app/core/components/Spinner.js new file mode 100644 index 000000000..880f53d2a --- /dev/null +++ b/ui/src/app/core/components/Spinner.js @@ -0,0 +1,9 @@ +import React from 'react'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faSpinner } from '@fortawesome/free-solid-svg-icons'; + +export function Spinner ({ size, className }) { + return () +} + +export default Spinner; \ No newline at end of file diff --git a/ui/src/app/core/components/VersionInfo.js b/ui/src/app/core/components/VersionInfo.js index 1c6badfc1..1c88ad271 100644 --- a/ui/src/app/core/components/VersionInfo.js +++ b/ui/src/app/core/components/VersionInfo.js @@ -1,7 +1,7 @@ import React from 'react'; import useFetch from 'use-http'; -import { BASE_PATH } from '../../App.constant'; +import { ACTUATOR_PATH } from '../../App.constant'; import Translate from '../../i18n/components/translate'; @@ -11,11 +11,15 @@ const year = new Date().getFullYear(); const params = { year }; export function VersionInfo () { - - const { data = {} } = useFetch(`${BASE_PATH}actuator/info`, {}, []); + var opts = { + headers: { + 'mode':'no-cors' + } + } + const { data = {} } = useFetch(`${ACTUATOR_PATH}actuator/info`, opts, []); const [ versionData, setVersionData ] = React.useState(''); - + React.useEffect(() => { setVersionData(formatter(data)); }, [data]); @@ -29,4 +33,4 @@ export function VersionInfo () { ); } -export default VersionInfo; \ No newline at end of file +export default VersionInfo; diff --git a/ui/src/app/core/user/UserContext.js b/ui/src/app/core/user/UserContext.js index f2438a9ef..ddd1897ef 100644 --- a/ui/src/app/core/user/UserContext.js +++ b/ui/src/app/core/user/UserContext.js @@ -26,7 +26,7 @@ function UserProvider({ children }) { const [user, setUser] = React.useState({}); - const providerValue = React.useMemo(() => ({ user, loading }), [user, loading]); + const providerValue = React.useMemo(() => ({ user, loading, loadUser }), [user, loading, loadUser]); return ( {children} @@ -43,6 +43,11 @@ function useCurrentUserLoading() { return loading; } +function useCurrentUserLoader() { + const { loadUser } = React.useContext(UserContext); + return loadUser; +} + function useIsAdmin() { const user = useCurrentUser(); return user.role === 'ROLE_ADMIN'; @@ -100,6 +105,7 @@ export { useIsAdminOrInGroup, useCanEnable, useCurrentUserLoading, + useCurrentUserLoader, useUserGroupRegexValidator, useUserGroup, useUserGroupNames diff --git a/ui/src/app/dashboard/view/ActionsTab.js b/ui/src/app/dashboard/view/ActionsTab.js index 30bc9e371..eda40b751 100644 --- a/ui/src/app/dashboard/view/ActionsTab.js +++ b/ui/src/app/dashboard/view/ActionsTab.js @@ -1,11 +1,12 @@ import React from 'react'; import { MetadataActions } from '../../admin/container/MetadataActions'; import UserActions from '../../admin/container/UserActions'; +import Spinner from '../../core/components/Spinner'; import Translate from '../../i18n/components/translate'; import SourceList from '../../metadata/domain/source/component/SourceList'; -export function ActionsTab({ sources, users, reloadSources, reloadUsers }) { +export function ActionsTab({ sources, users, reloadSources, reloadUsers, loadingSources, loadingUsers }) { return ( <> @@ -21,7 +22,9 @@ export function ActionsTab({ sources, users, reloadSources, reloadUsers }) {
{(enable) => - enable(s, e, reloadSources)} /> + enable(s, e, reloadSources)}> + {loadingSources &&
} +
}
@@ -36,7 +39,9 @@ export function ActionsTab({ sources, users, reloadSources, reloadUsers }) {
- + + {loadingUsers &&
} +
diff --git a/ui/src/app/dashboard/view/AdminTab.js b/ui/src/app/dashboard/view/AdminTab.js index 5c116c242..ba71e0685 100644 --- a/ui/src/app/dashboard/view/AdminTab.js +++ b/ui/src/app/dashboard/view/AdminTab.js @@ -5,12 +5,13 @@ import UserMaintenance from '../../admin/component/UserMaintenance'; import API_BASE_PATH from '../../App.constant'; import Translate from '../../i18n/components/translate'; +import Spinner from '../../core/components/Spinner'; export function AdminTab () { const [users, setUsers] = React.useState([]); - const { get, response } = useFetch(`${API_BASE_PATH}/admin/users`, { + const { get, response, loading } = useFetch(`${API_BASE_PATH}/admin/users`, { cachePolicy: 'no-cache' }, []); @@ -46,7 +47,9 @@ export function AdminTab () { onChangeUserRole={onChangeUserRole} onDeleteUser={onDeleteUser} onChangeUserGroup={onChangeUserGroup} />} + + {loading &&
}
diff --git a/ui/src/app/dashboard/view/Dashboard.js b/ui/src/app/dashboard/view/Dashboard.js index e5f145572..7644b6def 100644 --- a/ui/src/app/dashboard/view/Dashboard.js +++ b/ui/src/app/dashboard/view/Dashboard.js @@ -26,13 +26,13 @@ export function Dashboard () { const isAdmin = useIsAdmin(); - const loading = useCurrentUserLoading(); + const loadingUser = useCurrentUserLoading(); const [actions, setActions] = React.useState(0); const [users, setUsers] = React.useState([]); const [sources, setSources] = React.useState([]); - const { get, response } = useFetch(`${API_BASE_PATH}`, { + const { get, response, loading } = useFetch(`${API_BASE_PATH}`, { cachePolicy: 'no-cache' }); @@ -64,7 +64,7 @@ export function Dashboard () { return (
- {loading ? + {loadingUser ?
@@ -109,9 +109,18 @@ export function Dashboard () { } /> - + } /> + + + }
diff --git a/ui/src/app/dashboard/view/ProvidersTab.js b/ui/src/app/dashboard/view/ProvidersTab.js index 023a7f78a..d986f3f68 100644 --- a/ui/src/app/dashboard/view/ProvidersTab.js +++ b/ui/src/app/dashboard/view/ProvidersTab.js @@ -8,13 +8,14 @@ import { Ordered } from '../component/Ordered'; import { useIsAdmin } from '../../core/user/UserContext'; import Alert from 'react-bootstrap/Alert'; import { MetadataActions } from '../../admin/container/MetadataActions'; +import Spinner from '../../core/components/Spinner'; const searchProps = ['name', '@type', 'createdBy']; export function ProvidersTab () { const [providers, setProviders] = React.useState([]); - const { get, response } = useMetadataEntities('provider', { + const { get, response, loading } = useMetadataEntities('provider', { cachePolicy: 'no-cache' }); @@ -54,7 +55,9 @@ export function ProvidersTab () { last={last} onEnable={(p, e) => enable(p, e, loadProviders)} onOrderUp={onOrderUp} - onOrderDown={onOrderDown}> + onOrderDown={onOrderDown}> + {loading &&
} + } } diff --git a/ui/src/app/dashboard/view/SourcesTab.js b/ui/src/app/dashboard/view/SourcesTab.js index b564a3872..40ff4dd4f 100644 --- a/ui/src/app/dashboard/view/SourcesTab.js +++ b/ui/src/app/dashboard/view/SourcesTab.js @@ -5,9 +5,11 @@ import Translate from '../../i18n/components/translate'; import SourceList from '../../metadata/domain/source/component/SourceList'; import { useMetadataEntities, useMetadataEntity } from '../../metadata/hooks/api'; import { Search } from '../component/Search'; +import { Spinner } from '../../core/components/Spinner'; import { NotificationContext, createNotificationAction, NotificationTypes } from '../../notifications/hoc/Notifications'; + const searchProps = ['serviceProviderName', 'entityId', 'createdBy']; export function SourcesTab () { @@ -16,7 +18,7 @@ export function SourcesTab () { const [sources, setSources] = React.useState([]); - const { get, response } = useMetadataEntities('source', { + const { get, response, loading } = useMetadataEntities('source', { cachePolicy: 'no-cache' }); @@ -68,7 +70,9 @@ export function SourcesTab () { entities={searched} onDelete={(id) => remove(id, loadSources)} onEnable={(s, e) => enable(s, e, loadSources) } - onChangeGroup={changeSourceGroup} /> + onChangeGroup={changeSourceGroup}> + {loading &&
} + } } diff --git a/ui/src/app/form/component/fields/FilterTargetField.js b/ui/src/app/form/component/fields/FilterTargetField.js index 125b26b0d..0866ab2bf 100644 --- a/ui/src/app/form/component/fields/FilterTargetField.js +++ b/ui/src/app/form/component/fields/FilterTargetField.js @@ -11,6 +11,7 @@ import useFetch from 'use-http'; import queryString from 'query-string'; import API_BASE_PATH from '../../../App.constant'; import isNil from 'lodash/isNil'; +import capitalize from 'lodash/capitalize'; import Editor from 'react-simple-code-editor'; // import { highlight, languages } from 'prismjs/components/prism-core'; // import 'prismjs/components/prism-clike'; @@ -68,6 +69,9 @@ const FilterTargetField = ({ const [touched, setTouched] = React.useState(false); const [ids, setSearchIds] = React.useState([]); + const [errors, setErrors] = React.useState(); + const translator = useTranslator(); + const { get, response } = useFetch(`${API_BASE_PATH}/EntityIds/search`, { cachePolicy: 'no-cache' }); @@ -128,6 +132,10 @@ const FilterTargetField = ({ setSelectedType(option); }; + React.useEffect(() => { + setErrors(errorSchema?.value?.__errors?.map((error, eIdx) => capitalize(translator(error))).join(', ')); + }, [errorSchema]); + return (
@@ -231,11 +239,8 @@ const FilterTargetField = ({ onChange={ ({target: { value }}) => handleTextChange(value) } /> {errorSchema?.value?.__errors ? - {errorSchema?.value?.__errors?.map((error, eIdx) => - - {error} - - )} + {errors} + : Required for Regex diff --git a/ui/src/app/form/component/widgets/AttributeReleaseWidget.js b/ui/src/app/form/component/widgets/AttributeReleaseWidget.js index 1ec9506d8..2ed6dd9bc 100644 --- a/ui/src/app/form/component/widgets/AttributeReleaseWidget.js +++ b/ui/src/app/form/component/widgets/AttributeReleaseWidget.js @@ -141,7 +141,7 @@ const AttributeReleaseWidget = ({ enumDisabled && (enumDisabled).indexOf(option.value) !== -1; return ( -1 ? 'text-light bg-info' : ''}`}> - {option.label} + {option.label}
diff --git a/ui/src/app/form/component/widgets/TextWidget.js b/ui/src/app/form/component/widgets/TextWidget.js index d4801ab4e..2f8c183b0 100644 --- a/ui/src/app/form/component/widgets/TextWidget.js +++ b/ui/src/app/form/component/widgets/TextWidget.js @@ -7,6 +7,7 @@ import Form from "react-bootstrap/Form"; import Translate from "../../../i18n/components/translate"; import { InfoIcon } from "../InfoIcon"; +import { useTranslator } from "../../../i18n/hooks"; const TextWidget = ({ id, @@ -43,6 +44,8 @@ const TextWidget = ({ onChange(fieldValue); }, [fieldValue, onChange]); + const translator = useTranslator(); + // const classNames = [rawErrors?.length > 0 ? "is-invalid" : "", type === 'file' ? 'custom-file-label': ""] return ( @@ -57,7 +60,7 @@ const TextWidget = ({ p.entityId); + const sections = useMetadataSourceSections(); + return ( <>
@@ -162,7 +155,7 @@ export function CopySource({ copy, onNext }) { onSelect(item, checked)} diff --git a/ui/src/app/metadata/domain/data.js b/ui/src/app/metadata/domain/data.js index 45412d300..82b307ebb 100644 --- a/ui/src/app/metadata/domain/data.js +++ b/ui/src/app/metadata/domain/data.js @@ -1,12 +1,25 @@ export const DurationOptions = [ - "PT0S", + "PT5S", + "PT10S", "PT30S", "PT1M", + "PT5M", "PT10M", + "PT15M", "PT30M", - "PT1H", +]; + +export const MinRefreshOptions = [ + "PT30S", + "PT1M", + "PT5M", + "PT10M", + "PT15M", +]; + +export const MaxRefreshOptions = [ "PT4H", "PT8H", "PT12H", - "PT24H" -]; \ No newline at end of file + "PT24H", +]; diff --git a/ui/src/app/metadata/domain/provider/component/ProviderList.js b/ui/src/app/metadata/domain/provider/component/ProviderList.js index 3e559eb2a..9a9ac90d4 100644 --- a/ui/src/app/metadata/domain/provider/component/ProviderList.js +++ b/ui/src/app/metadata/domain/provider/component/ProviderList.js @@ -12,88 +12,92 @@ import { Scroller } from '../../../../dashboard/component/Scroller'; import { useIsAdmin } from '../../../../core/user/UserContext'; import { useTranslator } from '../../../../i18n/hooks'; -export function ProviderList({ entities, reorder = true, first, last, onEnable, onOrderUp, onOrderDown }) { +export function ProviderList({ children, entities, reorder = true, first, last, onEnable, onOrderUp, onOrderDown }) { const isAdmin = useIsAdmin(); const translator = useTranslator(); return ( - - {(limited) =>
- - - - - - - - - - - - - {limited.map((provider, idx) => - - + + )} + +
OrderTitleProvider TypeAuthorCreated DateEnabled
-
- {reorder ? -
{idx + 1}
+ + + {(limited) =>
+ + + + + + + + + + + + + {limited.map((provider, idx) => + + + + + + + - - - - - - - )} - -
OrderTitleProvider TypeAuthorCreated DateEnabled
+
+ {reorder ? +
{idx + 1}
+ : +
+ } +   + + +
+
+ {provider.name} + { provider['@type'] }{ provider.createdBy } + + {onEnable && isAdmin ? + onEnable(provider, checked)} + checked={provider.enabled} + > + : -
+ + + } -   - - - -
- {provider.name} - { provider['@type'] }{ provider.createdBy } - - {onEnable && isAdmin ? - onEnable(provider, checked)} - checked={provider.enabled} - > - - : - - - - } - -
-
- } -
+ +
+
+ } +
+ {children} + + ); } diff --git a/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js index 143cd78a3..12e61ae0f 100644 --- a/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js +++ b/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js @@ -1,5 +1,4 @@ import { metadataFilterProcessor } from '../utility/providerFilterProcessor'; -import { DurationOptions } from '../../data'; import { MetadataFilterTypes } from '../../filter'; export const BaseProviderDefinition = { @@ -173,18 +172,12 @@ export const HttpMetadataResolverAttributesSchema = { } }, connectionRequestTimeout: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, connectionTimeout: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, socketTimeout: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, httpClientRef: { @@ -222,8 +215,6 @@ export const MetadataFilterPluginsSchema = { } }, maxValidityInterval: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' } } diff --git a/ui/src/app/metadata/domain/provider/definition/DynamicHttpMetadataProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/DynamicHttpMetadataProviderDefinition.js index 3c9a828ff..6c2952bdf 100644 --- a/ui/src/app/metadata/domain/provider/definition/DynamicHttpMetadataProviderDefinition.js +++ b/ui/src/app/metadata/domain/provider/definition/DynamicHttpMetadataProviderDefinition.js @@ -2,7 +2,6 @@ import { BaseProviderDefinition, HttpMetadataResolverAttributesSchema, MetadataF import API_BASE_PATH from '../../../../App.constant'; import defaultsDeep from 'lodash/defaultsDeep'; import isNil from 'lodash/isNil'; -import { DurationOptions } from '../../data'; import { isValidRegex } from '../../../../core/utility/is_valid_regex'; function findById(o, id) { @@ -193,28 +192,18 @@ export const DynamicHttpMetadataProviderWizard = { } }, minCacheDuration: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, maxCacheDuration: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, maxIdleEntityData: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, cleanupTaskInterval: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, backgroundInitializationFromCacheDelay: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration', visibleIf: { initializeFromPersistentCacheInBackground: true diff --git a/ui/src/app/metadata/domain/provider/definition/ExternalMetadataProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/ExternalMetadataProviderDefinition.js new file mode 100644 index 000000000..a72d3601d --- /dev/null +++ b/ui/src/app/metadata/domain/provider/definition/ExternalMetadataProviderDefinition.js @@ -0,0 +1,92 @@ +import defaultsDeep from 'lodash/defaultsDeep'; +import API_BASE_PATH from "../../../../App.constant"; +import { BaseProviderDefinition } from "./BaseProviderDefinition"; + +export const ExternalMetadataProviderWizard = { + ...BaseProviderDefinition, + label: 'ExternalMetadataProvider', + type: 'ExternalMetadataResolver', + // schema: 'assets/schema/provider/external.schema.json', + schema: `${API_BASE_PATH}/ui/MetadataResolver/ExternalMetadataResolver`, + steps: [ + ...BaseProviderDefinition.steps, + { + id: 'common', + label: 'label.common-attributes', + index: 2, + initialValues: [], + fields: [ + 'xmlId', + 'metadataFile', + 'description' + ] + }, + { + id: 'summary', + label: 'label.finished', + index: 2, + initialValues: [], + fields: [ + 'enabled', + ] + }, + ], + uiSchema: defaultsDeep({ + layout: { + groups: [ + { + size: 8, + classNames: 'bg-light border rounded px-4 pt-4 pb-3 mb-4', + fields: [ + 'name', + '@type' + ] + }, + { + size: 8, + fields: [ + 'xmlId', + 'description', + ] + } + ] + }, + description: { + 'ui:widget': 'textarea' + } + }, BaseProviderDefinition.uiSchema) +}; + + +export const ExternalMetadataProviderEditor = { + ...ExternalMetadataProviderWizard, + steps: [ + { + id: 'common', + label: 'label.common-attributes', + index: 1, + initialValues: [], + fields: [ + 'name', + 'xmlId', + '@type', + 'description', + 'enabled' + ], + override: { + '@type': { + type: 'string', + readOnly: true, + widget: 'string', + oneOf: [{ enum: ['ExternalMetadataResolver'], + description: 'value.file-system-metadata-provider' }] + } + } + } + ], + uiSchema: defaultsDeep({ + '@type': { + 'ui:readonly': true + } + }, ExternalMetadataProviderWizard.uiSchema) +}; diff --git a/ui/src/app/metadata/domain/provider/definition/FileBackedHttpMetadataProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/FileBackedHttpMetadataProviderDefinition.js index 106edfa55..e1d94ccaf 100644 --- a/ui/src/app/metadata/domain/provider/definition/FileBackedHttpMetadataProviderDefinition.js +++ b/ui/src/app/metadata/domain/provider/definition/FileBackedHttpMetadataProviderDefinition.js @@ -1,7 +1,6 @@ import defaultsDeep from 'lodash/defaultsDeep'; import { BaseProviderDefinition, HttpMetadataResolverAttributesSchema, MetadataFilterPluginsSchema } from './BaseProviderDefinition'; - -import { DurationOptions } from '../../data'; +import { DurationOptions, MaxRefreshOptions, MinRefreshOptions } from '../../data'; import { BASE_PATH } from '../../../../App.constant'; export const FileBackedHttpMetadataProviderWizard = { @@ -155,12 +154,12 @@ export const FileBackedHttpMetadataProviderWizard = { reloadableMetadataResolverAttributes: { minRefreshDelay: { 'ui:widget': 'OptionWidget', - options: DurationOptions, + options: MinRefreshOptions, 'ui:placeholder': 'label.duration' }, maxRefreshDelay: { 'ui:widget': 'OptionWidget', - options: DurationOptions, + options: MaxRefreshOptions, 'ui:placeholder': 'label.duration' }, refreshDelayFactor: { diff --git a/ui/src/app/metadata/domain/provider/definition/FileSystemMetadataProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/FileSystemMetadataProviderDefinition.js index d97b8e041..1cb158d80 100644 --- a/ui/src/app/metadata/domain/provider/definition/FileSystemMetadataProviderDefinition.js +++ b/ui/src/app/metadata/domain/provider/definition/FileSystemMetadataProviderDefinition.js @@ -1,7 +1,7 @@ import defaultsDeep from 'lodash/defaultsDeep'; import API_BASE_PATH from "../../../../App.constant"; import { BaseProviderDefinition } from "./BaseProviderDefinition"; -import { DurationOptions } from '../../data'; +import { MaxRefreshOptions, MinRefreshOptions } from '../../data'; export const FileSystemMetadataProviderWizard = { ...BaseProviderDefinition, @@ -74,12 +74,12 @@ export const FileSystemMetadataProviderWizard = { reloadableMetadataResolverAttributes: { minRefreshDelay: { 'ui:widget': 'OptionWidget', - options: DurationOptions, + options: MinRefreshOptions, 'ui:placeholder': 'label.duration' }, maxRefreshDelay: { 'ui:widget': 'OptionWidget', - options: DurationOptions, + options: MaxRefreshOptions, 'ui:placeholder': 'label.duration' }, refreshDelayFactor: { diff --git a/ui/src/app/metadata/domain/provider/definition/LocalDynamicMetadataProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/LocalDynamicMetadataProviderDefinition.js index 66b48d6c4..948df7788 100644 --- a/ui/src/app/metadata/domain/provider/definition/LocalDynamicMetadataProviderDefinition.js +++ b/ui/src/app/metadata/domain/provider/definition/LocalDynamicMetadataProviderDefinition.js @@ -1,7 +1,6 @@ import defaultsDeep from 'lodash/defaultsDeep'; import API_BASE_PATH from "../../../../App.constant"; -import {DurationOptions} from '../../data'; import { BaseProviderDefinition } from "./BaseProviderDefinition"; export const LocalDynamicMetadataProviderWizard = { @@ -77,23 +76,15 @@ export const LocalDynamicMetadataProviderWizard = { } }, minCacheDuration: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, maxCacheDuration: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, maxIdleEntityData: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' }, cleanupTaskInterval: { - 'ui:widget': 'OptionWidget', - options: DurationOptions, 'ui:placeholder': 'label.duration' } } diff --git a/ui/src/app/metadata/domain/provider/index.js b/ui/src/app/metadata/domain/provider/index.js index 05c0e057d..9368df466 100644 --- a/ui/src/app/metadata/domain/provider/index.js +++ b/ui/src/app/metadata/domain/provider/index.js @@ -2,22 +2,26 @@ import { FileBackedHttpMetadataProviderWizard, FileBackedHttpMetadataProviderEdi import { DynamicHttpMetadataProviderWizard, DynamicHttpMetadataProviderEditor } from './definition/DynamicHttpMetadataProviderDefinition'; import { LocalDynamicMetadataProviderWizard, LocalDynamicMetadataProviderEditor } from './definition/LocalDynamicMetadataProviderDefinition'; import { FileSystemMetadataProviderWizard, FileSystemMetadataProviderEditor } from './definition/FileSystemMetadataProviderDefinition'; +import { ExternalMetadataProviderWizard, ExternalMetadataProviderEditor } from './definition/ExternalMetadataProviderDefinition'; export const MetadataProviderWizardTypes = [ FileBackedHttpMetadataProviderWizard, DynamicHttpMetadataProviderWizard, FileSystemMetadataProviderWizard, - LocalDynamicMetadataProviderWizard + LocalDynamicMetadataProviderWizard, + ExternalMetadataProviderWizard, ]; export const MetadataProviderEditorTypes = [ FileBackedHttpMetadataProviderEditor, DynamicHttpMetadataProviderEditor, LocalDynamicMetadataProviderEditor, - FileSystemMetadataProviderEditor + FileSystemMetadataProviderEditor, + ExternalMetadataProviderEditor, ]; export const FilterableProviders = [ FileBackedHttpMetadataProviderEditor.type, - DynamicHttpMetadataProviderEditor.type + DynamicHttpMetadataProviderEditor.type, + ExternalMetadataProviderEditor.type, ]; diff --git a/ui/src/app/metadata/domain/source/component/SourceList.js b/ui/src/app/metadata/domain/source/component/SourceList.js index 109396c2c..8e8a10825 100644 --- a/ui/src/app/metadata/domain/source/component/SourceList.js +++ b/ui/src/app/metadata/domain/source/component/SourceList.js @@ -16,14 +16,15 @@ import { useTranslator } from '../../../../i18n/hooks'; import { useCanEnable, useIsAdmin } from '../../../../core/user/UserContext'; import { GroupsProvider } from '../../../../admin/hoc/GroupsProvider'; -export default function SourceList({ entities, onDelete, onEnable, onChangeGroup }) { +export default function SourceList({ entities, onDelete, onEnable, onChangeGroup, children }) { const translator = useTranslator(); const isAdmin = useIsAdmin(); const canEnable = useCanEnable(); return ( - + + {(limited) =>
@@ -124,6 +125,9 @@ export default function SourceList({ entities, onDelete, onEnable, onChangeGroup
} -
+
+ {children} + + ); } diff --git a/ui/src/app/metadata/domain/source/definition/SourceDefinition.js b/ui/src/app/metadata/domain/source/definition/SourceDefinition.js index 70e686ed7..41d409907 100644 --- a/ui/src/app/metadata/domain/source/definition/SourceDefinition.js +++ b/ui/src/app/metadata/domain/source/definition/SourceDefinition.js @@ -6,6 +6,7 @@ import API_BASE_PATH from '../../../../App.constant'; import {removeNull} from '../../../../core/utility/remove_null'; import { detailedDiff } from 'deep-object-diff'; import isNil from 'lodash/isNil'; +import { useMetadataSchemaContext } from '../../../hoc/MetadataSchema'; export const SourceBase = { label: 'Metadata Source', @@ -24,6 +25,7 @@ export const SourceBase = { const sources = current ? data.filter(s => s.id !== current.id) : data; const entityIds = sources.map(s => s.entityId); + const names = sources.map(s => s.serviceProviderName); const pattern = group?.validationRegex ? new RegExp(group?.validationRegex) : null; return (formData, errors) => { @@ -32,6 +34,10 @@ export const SourceBase = { errors.entityId.addError('message.id-unique'); } + if (names.indexOf(formData.serviceProviderName) > -1) { + errors.serviceProviderName.addError('message.name-unique'); + } + if (pattern && !pattern?.test(formData.entityId)) { errors.entityId.addError(translator('message.group-pattern-fail', {regex: group?.validationRegex})); } @@ -529,4 +535,35 @@ export const SourceWizard = { fields: [] } ] +} + +export const sections = [ + { i18nKey: 'organizationInformation', property: 'organization' }, + { i18nKey: 'contacts', property: 'contacts' }, + { i18nKey: 'uiMduiInfo', property: 'mdui' }, + { i18nKey: 'spSsoDescriptorInfo', property: 'serviceProviderSsoDescriptor' }, + { i18nKey: 'logoutEndpoints', property: 'logoutEndpoints' }, + { i18nKey: 'securityDescriptorInfo', property: 'securityInfo' }, + { i18nKey: 'assertionConsumerServices', property: 'assertionConsumerServices' }, + { i18nKey: 'relyingPartyOverrides', property: 'relyingPartyOverrides' }, + { i18nKey: 'attributeRelease', property: 'attributeRelease' } +]; + +export function useMetadataSourceSections() { + const schema = useMetadataSchemaContext(); + + const keys = Object.keys(schema.properties); + const properties = sections.map((s) => s.property); + + const reduced = keys.reduce( + (collection, key) => { + if (properties.indexOf(key) > -1) { + collection.push(sections.find(s => s.property === key)); + } + return collection; + }, + [] + ); + + return reduced; } \ No newline at end of file diff --git a/ui/src/app/metadata/hoc/MetadataSchema.js b/ui/src/app/metadata/hoc/MetadataSchema.js index 025e7a415..ea14361d9 100644 --- a/ui/src/app/metadata/hoc/MetadataSchema.js +++ b/ui/src/app/metadata/hoc/MetadataSchema.js @@ -5,10 +5,12 @@ import { useTranslator } from '../../i18n/hooks'; export const MetadataSchemaContext = React.createContext(); export const MetadataDefinitionContext = React.createContext(); +export const MetadataSchemaLoading = React.createContext(); export function MetadataSchema({ type, children, wizard = false }) { const definition = React.useMemo(() => wizard ? getWizard(type) : getDefinition(type), [type, wizard]); + const [loading, setLoading] = React.useState(false); const { get, response } = useFetch(``, { cachePolicy: 'no-cache' @@ -21,19 +23,23 @@ export function MetadataSchema({ type, children, wizard = false }) { if (response.ok) { setSchema(source); } + setLoading(false); } /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { setSchema(null); loadSchema(definition); + setLoading(true); }, [definition]); return ( {type && definition && schema && - - {children} + + + {children} + } @@ -44,6 +50,10 @@ export function useMetadataSchemaContext () { return React.useContext(MetadataSchemaContext); } +export function useMetadataSchemaLoading () { + return React.useContext(MetadataSchemaLoading); +} + export function useMetadataDefinitionContext() { return React.useContext(MetadataDefinitionContext); } diff --git a/ui/src/app/metadata/hoc/MetadataVersionsLoader.js b/ui/src/app/metadata/hoc/MetadataVersionsLoader.js index 025cea743..d957903d9 100644 --- a/ui/src/app/metadata/hoc/MetadataVersionsLoader.js +++ b/ui/src/app/metadata/hoc/MetadataVersionsLoader.js @@ -4,12 +4,15 @@ import { getMetadataPath } from '../hooks/api'; import API_BASE_PATH from '../../App.constant'; import useFetch from 'use-http'; import { last } from 'lodash'; +import Spinner from '../../core/components/Spinner'; export function MetadataVersionsLoader ({versions, children}) { const ref = React.useRef({}); const [list, setList] = React.useState({}); + const [loading, setLoading] = React.useState(false); + const { type, id } = useParams(); const { get, response } = useFetch(`/${API_BASE_PATH}${getMetadataPath(type)}/${id}/Versions`, { @@ -22,6 +25,8 @@ export function MetadataVersionsLoader ({versions, children}) { addToList(v, l); if (last(versions) !== v) { loadNext(versions[versions.indexOf(v) + 1]); + } else { + setLoading(false); } } } @@ -36,14 +41,19 @@ export function MetadataVersionsLoader ({versions, children}) { function loadNext (v) { loadVersion(v); + } /*eslint-disable react-hooks/exhaustive-deps*/ React.useEffect(() => { loadNext(versions[0]); + setLoading(true); }, [versions]); - return ( - {children(versions.map(v => list[v]).filter(v => !!v))} - ); + return ( + + {loading &&
} + {children(versions.map(v => list[v]).filter(v => !!v))} +
+ ); } \ No newline at end of file diff --git a/ui/src/app/metadata/hooks/utility.js b/ui/src/app/metadata/hooks/utility.js index 05546fd8a..e11532ea9 100644 --- a/ui/src/app/metadata/hooks/utility.js +++ b/ui/src/app/metadata/hooks/utility.js @@ -130,9 +130,9 @@ export const assignValueToProperties = (models, properties, definition, schema) const items = prop.type === 'array' && prop.items?.enum ? ({ ...prop.items, - enum: prop.items.enum.map(item => ({ + enum: prop.items.enum.map((item, index) => ({ key: item, - label: `label.attribute-${item}`, + label: `${prop?.items?.enumNames ? prop?.items?.enumNames[index] : item}`, differences: models .map((model) => { const value = model[prop.id]; diff --git a/ui/src/app/metadata/new/NewProvider.js b/ui/src/app/metadata/new/NewProvider.js index 43a9ed715..9a9b87ad7 100644 --- a/ui/src/app/metadata/new/NewProvider.js +++ b/ui/src/app/metadata/new/NewProvider.js @@ -7,7 +7,7 @@ import { MetadataProviderTypeSelector } from '../wizard/MetadataProviderTypeSele export function NewProvider() { - const { data } = useMetadataProviderTypes({}, []); + const { data = [], loading } = useMetadataProviderTypes({}, []); return (
@@ -20,7 +20,7 @@ export function NewProvider() {
- + {(data, onRestart) => { + scroller.scrollTo(element, { + duration: 500, + smooth: true, + offset + }); + }; export function MetadataComparison () { @@ -54,6 +63,12 @@ export function MetadataComparison () {   Version History + {type === 'provider' && canFilter && + + }
{type === 'provider' && canFilter && v && - +

Metadata Filter @@ -74,7 +89,7 @@ export function MetadataComparison () { {(c) => } - +

}
} diff --git a/ui/src/app/metadata/view/MetadataHistory.js b/ui/src/app/metadata/view/MetadataHistory.js index 719ce8dc3..6df6a7c2e 100644 --- a/ui/src/app/metadata/view/MetadataHistory.js +++ b/ui/src/app/metadata/view/MetadataHistory.js @@ -9,6 +9,7 @@ import Translate from '../../i18n/components/translate'; import { useMetadataHistory } from '../hooks/api'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faUndo } from '@fortawesome/free-solid-svg-icons'; +import Spinner from '../../core/components/Spinner'; const sortVersionsByDate = (versions) => { return versions.sort((a, b) => { @@ -107,16 +108,13 @@ export function MetadataHistory () { )} + {loading &&
}
} - {loading &&
- - Loading... -
} ); } \ No newline at end of file diff --git a/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js b/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js index 09260c018..ff16b61a4 100644 --- a/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js +++ b/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js @@ -41,14 +41,14 @@ export function MetadataFilterTypeSelector({ types = [], children, actions}) {
- - + + - + {types.map(t => )} diff --git a/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js b/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js index fbc890fb9..e53f06b13 100644 --- a/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js +++ b/ui/src/app/metadata/wizard/MetadataProviderTypeSelector.js @@ -1,5 +1,5 @@ import React from 'react'; -import { faArrowCircleRight, faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { faArrowCircleRight, faAsterisk, faSpinner } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useForm } from 'react-hook-form'; @@ -10,11 +10,11 @@ import { InfoIcon } from '../../form/component/InfoIcon'; import { useTranslator } from '../../i18n/hooks'; import { useMetadataProviders } from '../hooks/api'; -export function MetadataProviderTypeSelector({ type, types = [], children}) { +export function MetadataProviderTypeSelector({ type, types = [], loading, children}) { const translator = useTranslator(); - const { data = [], loading } = useMetadataProviders({cachePolicy: 'no-cache'}, []); + const { data = [] } = useMetadataProviders({cachePolicy: 'no-cache'}, []); const [showSelector, setShowSelector] = React.useState(true); @@ -81,7 +81,10 @@ export function MetadataProviderTypeSelector({ type, types = [], children}) { - + + + + + {loading && } diff --git a/ui/src/app/metadata/wizard/MetadataProviderWizard.js b/ui/src/app/metadata/wizard/MetadataProviderWizard.js index d2cbc0864..72df681fd 100644 --- a/ui/src/app/metadata/wizard/MetadataProviderWizard.js +++ b/ui/src/app/metadata/wizard/MetadataProviderWizard.js @@ -2,7 +2,7 @@ import React from 'react'; import { WizardNav } from './WizardNav'; import { MetadataWizardForm } from './MetadataWizardForm'; import { setWizardIndexAction, useCurrentIndex, useIsLastPage, useWizardDispatcher } from './Wizard'; -import { useMetadataDefinitionContext, useMetadataDefinitionValidator, useMetadataSchemaContext } from '../hoc/MetadataSchema'; +import { useMetadataDefinitionContext, useMetadataDefinitionValidator, useMetadataSchemaContext, useMetadataSchemaLoading } from '../hoc/MetadataSchema'; import { checkChanges, useMetadataSchema } from '../hooks/schema'; import { useMetadataFormDispatcher, setFormDataAction, setFormErrorAction, useMetadataFormData, useMetadataFormErrors } from '../hoc/MetadataFormContext'; import { MetadataConfiguration } from '../component/MetadataConfiguration'; @@ -12,6 +12,7 @@ import { useMetadataProviders } from '../hooks/api'; import { removeNull } from '../../core/utility/remove_null'; import { useUserGroup } from '../../core/user/UserContext'; +import Spinner from '../../core/components/Spinner'; export function MetadataProviderWizard({onSave, loading, block}) { @@ -20,6 +21,7 @@ export function MetadataProviderWizard({onSave, loading, block}) { const definition = useMetadataDefinitionContext(); const schema = useMetadataSchemaContext(); + const schemaLoading = useMetadataSchemaLoading(); const processed = useMetadataSchema(definition, schema); @@ -49,7 +51,7 @@ export function MetadataProviderWizard({onSave, loading, block}) { return ( <> - +

+ {schemaLoading &&
}
{ + userLoader(); + }, []); + const { data } = useMetadataSources({ cachePolicy: 'no-cache' }, []); @@ -68,6 +77,7 @@ export function MetadataSourceWizard ({ onShowNav, onSave, block, loading }) {

+ {schemaLoading &&
} {warnings && warnings.hasOwnProperty(current) &&