From 900da38824242d420453b2917408e7adbba80239 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Fri, 29 Jul 2022 14:01:19 -0400 Subject: [PATCH 01/71] init setup Former-commit-id: 5181702e57e39598f5f75839d9d262045b220e30 --- testbed/smoke-test/cheat.html | 110 ++++++++++++++++++++++ testbed/smoke-test/docker-compose.yml | 105 +++++++++++++++++++++ testbed/smoke-test/shibui/application.yml | 40 ++++++++ 3 files changed, 255 insertions(+) create mode 100644 testbed/smoke-test/cheat.html create mode 100644 testbed/smoke-test/docker-compose.yml create mode 100644 testbed/smoke-test/shibui/application.yml diff --git a/testbed/smoke-test/cheat.html b/testbed/smoke-test/cheat.html new file mode 100644 index 000000000..74682f912 --- /dev/null +++ b/testbed/smoke-test/cheat.html @@ -0,0 +1,110 @@ + + +

Reload Service

+
+ + + +
+

Attribute Resolution

+
+ + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + + +
+ + +
+
+

Metadata Query

+ + + + + +
+ + + +
+ +
+
+

Reload Metadata

+ + + + + +
+ + + +
+ +
+
+

Unsolicited SSO

+ + + + + +
+ + + +
+ +
+metrics + + diff --git a/testbed/smoke-test/docker-compose.yml b/testbed/smoke-test/docker-compose.yml new file mode 100644 index 000000000..ec2f2c854 --- /dev/null +++ b/testbed/smoke-test/docker-compose.yml @@ -0,0 +1,105 @@ +version: "3.8" + +services: + reverse-proxy: + image: library/traefik:v2.5.2 + command: + - "--api.insecure=true" + - "--providers.docker=true" + - "--providers.docker.exposedbydefault=false" + - "--entrypoints.web-secure.address=:443" + - "--providers.file.directory=/configuration/" + - "--providers.file.watch=true" + # - "--log.level=DEBUG" + networks: + reverse-proxy: + aliases: + - idp.unicon.local + ports: + - "80:80" + - "8080:8080" + - "443:443" + - "8443:8443" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - ../reverse-proxy/:/configuration/ + - ../reverse-proxy/certs/:/certs/ + directory: + build: ../directory + networks: + - idp + volumes: + - directory_data:/var/lib/ldap + - directory_config:/etc/ldap/slapd.d + - ../directory/certs:/container/service/slapd/assets/certs + environment: + LDAP_BASE_DN: "dc=unicon,dc=local" + LDAP_DOMAIN: "unicon.local" + HOSTNAME: "directory" + LDAP_TLS_VERIFY_CLIENT: "try" + idp: + build: ../integration/shibboleth-idp + labels: + - "traefik.http.routers.idp.rule=Host(`idp.unicon.local`)" + - "traefik.http.services.idp.loadbalancer.server.port=8080" + - "traefik.http.routers.idp.tls=true" + - "traefik.docker.network=integration_reverse-proxy" + - "traefik.enable=true" + depends_on: + - directory + - reverse-proxy + networks: + - reverse-proxy + - idp + volumes: + - ../directory/certs/ca.crt:/opt/shibboleth-idp/credentials/ldap-server.crt + - dynamic_metadata:/opt/shibboleth-idp/metadata/dynamic + - dynamic_config:/opt/shibboleth-idp/conf/dynamic + - ../integration/shibboleth-idp/metadata/dynamic:/opt/shibboleth-idp/metadata/dynamic + - ../authentication/shibboleth-idp/config/shib-idp/conf/attribute-filter.xml:/opt/shibboleth-idp/conf/attribute-filter.xml + healthcheck: + disable: true + shib-idp-ui: + image: unicon/shibui:latest + labels: + - "traefik.http.routers.shibui.rule=Host(`shibui.unicon.local`)" + - "traefik.http.services.shibui.loadbalancer.server.port=8080" + - "traefik.http.routers.shibui.tls=true" + - "traefik.docker.network=integration_reverse-proxy" + - "traefik.enable=true" + networks: + - reverse-proxy + - backend + volumes: + - ../authentication/shibui:/conf + - ./shibui/application.yml:/application.yml + - dynamic_metadata:/var/shibboleth/dynamic_metadata + - dynamic_config:/var/shibboleth/dynamic_config + - ../integration/shibboleth-idp/credentials/shib-idp/inc-md-cert-mdq.pem:/opt/shibboleth-idp/credentials/inc-md-cert-mdq.pem + environment: + - "IDP_HOME=/opt/shibboleth-idp" + database: + image: postgres:14-alpine + environment: + POSTGRES_PASSWORD: shibui + POSTGRES_USER: shibui + POSTGRES_DB: shibui + networks: + - backend + volumes: + - database_data:/var/lib/postgresql/data +networks: + reverse-proxy: + idp: + backend: +volumes: + directory_data: + driver: local + directory_config: + driver: local + dynamic_metadata: + driver: local + dynamic_config: + driver: local + database_data: + driver: local diff --git a/testbed/smoke-test/shibui/application.yml b/testbed/smoke-test/shibui/application.yml new file mode 100644 index 000000000..126256f0d --- /dev/null +++ b/testbed/smoke-test/shibui/application.yml @@ -0,0 +1,40 @@ +server: + forward-headers-strategy: NATIVE +spring: + profiles: + include: + datasource: + platform: postgres + driver-class-name: org.postgresql.Driver + url: jdbc:postgresql://database:5432/shibui + username: shibui + password: shibui + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect +shibui: + default-password: "{noop}letmein7" + metadata-dir: /var/shibboleth/dynamic_metadata + metadataProviders: + target: file:/var/shibboleth/dynamic_config/metadata-providers.xml + user-bootstrap-resource: file:/conf/users.csv + roles: ROLE_ADMIN,ROLE_NONE,ROLE_USER,ROLE_ENABLE,ROLE_PONY + pac4j-enabled: true + pac4j: + keystorePath: "/conf/samlKeystore.jks" + keystorePassword: "changeit" + privateKeyPassword: "changeit" + serviceProviderEntityId: "https://unicon.net/test/shibui" + serviceProviderMetadataPath: "/conf/sp-metadata.xml" + identityProviderMetadataPath: "/conf/idp-metadata.xml" + forceServiceProviderMetadataGeneration: true + callbackUrl: "https://shibui.unicon.local/callback" + maximumAuthenticationLifetime: 3600000 + simpleProfileMapping: + username: urn:oid:0.9.2342.19200300.100.1.1 + firstName: urn:oid:2.5.4.42 + lastName: urn:oid:2.5.4.4 + email: urn:oid:0.9.2342.19200300.100.1.3 + groups: urn:oid:2.5.4.15 # businessCategory + roles: urn:oid:1.3.6.1.4.1.5923.1.1.1.7 # eduPersonEntitlement From 90d05708210edb769d2540f8c95c53040d8bb26c Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Fri, 5 Aug 2022 14:45:00 -0400 Subject: [PATCH 02/71] auth and integration testbeds combined Former-commit-id: 09cf8130a77974ecff8968d079945b9cb8d4017b --- testbed/smoke-test/docker-compose.yml | 17 +-- .../shibboleth-idp/conf/access-control.xml | 68 ++++++++++++ .../conf/metadata-providers.xml | 101 ++++++++++++++++++ .../metadata/test-provider-config.xml | 38 +++++++ 4 files changed, 217 insertions(+), 7 deletions(-) create mode 100644 testbed/smoke-test/shibboleth-idp/conf/access-control.xml create mode 100644 testbed/smoke-test/shibboleth-idp/conf/metadata-providers.xml create mode 100644 testbed/smoke-test/shibboleth-idp/metadata/test-provider-config.xml diff --git a/testbed/smoke-test/docker-compose.yml b/testbed/smoke-test/docker-compose.yml index ec2f2c854..0c92cad01 100644 --- a/testbed/smoke-test/docker-compose.yml +++ b/testbed/smoke-test/docker-compose.yml @@ -10,7 +10,7 @@ services: - "--entrypoints.web-secure.address=:443" - "--providers.file.directory=/configuration/" - "--providers.file.watch=true" - # - "--log.level=DEBUG" + #- "--log.level=DEBUG" networks: reverse-proxy: aliases: @@ -43,7 +43,7 @@ services: - "traefik.http.routers.idp.rule=Host(`idp.unicon.local`)" - "traefik.http.services.idp.loadbalancer.server.port=8080" - "traefik.http.routers.idp.tls=true" - - "traefik.docker.network=integration_reverse-proxy" + - "traefik.docker.network=smoke-test_reverse-proxy" - "traefik.enable=true" depends_on: - directory @@ -52,11 +52,14 @@ services: - reverse-proxy - idp volumes: - - ../directory/certs/ca.crt:/opt/shibboleth-idp/credentials/ldap-server.crt - dynamic_metadata:/opt/shibboleth-idp/metadata/dynamic - dynamic_config:/opt/shibboleth-idp/conf/dynamic - - ../integration/shibboleth-idp/metadata/dynamic:/opt/shibboleth-idp/metadata/dynamic + - ../directory/certs/ca.crt:/opt/shibboleth-idp/credentials/ldap-server.crt - ../authentication/shibboleth-idp/config/shib-idp/conf/attribute-filter.xml:/opt/shibboleth-idp/conf/attribute-filter.xml + - ./shibboleth-idp/conf/metadata-providers.xml:/opt/shibboleth-idp/conf/metadata-providers.xml + - ./shibboleth-idp/conf/access-control.xml:/opt/shibboleth-idp/conf/access-control.xml + - ./shibboleth-idp/metadata/test-provider-config.xml:/opt/shibboleth-idp/metadata/test-provider-config.xml + - ../integration/shibboleth-idp/metadata/dynamic/700bfe6fa4495100f5c193fa5b7ca4192c150923.xml:/opt/shibboleth-idp/metadata/700bfe6fa4495100f5c193fa5b7ca4192c150923.xml healthcheck: disable: true shib-idp-ui: @@ -65,16 +68,16 @@ services: - "traefik.http.routers.shibui.rule=Host(`shibui.unicon.local`)" - "traefik.http.services.shibui.loadbalancer.server.port=8080" - "traefik.http.routers.shibui.tls=true" - - "traefik.docker.network=integration_reverse-proxy" + - "traefik.docker.network=smoke-test_reverse-proxy" - "traefik.enable=true" networks: - reverse-proxy - backend volumes: - - ../authentication/shibui:/conf - - ./shibui/application.yml:/application.yml - dynamic_metadata:/var/shibboleth/dynamic_metadata - dynamic_config:/var/shibboleth/dynamic_config + - ../authentication/shibui:/conf + - ./shibui/application.yml:/application.yml - ../integration/shibboleth-idp/credentials/shib-idp/inc-md-cert-mdq.pem:/opt/shibboleth-idp/credentials/inc-md-cert-mdq.pem environment: - "IDP_HOME=/opt/shibboleth-idp" diff --git a/testbed/smoke-test/shibboleth-idp/conf/access-control.xml b/testbed/smoke-test/shibboleth-idp/conf/access-control.xml new file mode 100644 index 000000000..053bc22c7 --- /dev/null +++ b/testbed/smoke-test/shibboleth-idp/conf/access-control.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/testbed/smoke-test/shibboleth-idp/conf/metadata-providers.xml b/testbed/smoke-test/shibboleth-idp/conf/metadata-providers.xml new file mode 100644 index 000000000..bd90a4751 --- /dev/null +++ b/testbed/smoke-test/shibboleth-idp/conf/metadata-providers.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + https://mdq.incommon.org/ + + + diff --git a/testbed/smoke-test/shibboleth-idp/metadata/test-provider-config.xml b/testbed/smoke-test/shibboleth-idp/metadata/test-provider-config.xml new file mode 100644 index 000000000..caec9caf4 --- /dev/null +++ b/testbed/smoke-test/shibboleth-idp/metadata/test-provider-config.xml @@ -0,0 +1,38 @@ + + + + + + +MIIECDCCAnCgAwIBAgIUXOD+38b0Cpaynm5Wrclnzigz9rcwDQYJKoZIhvcNAQEL +BQAwHTEbMBkGA1UEAxMSdW5pY29uLXNwb3J0aC0yNjU4MB4XDTIyMDgwNTE3MDE1 +NloXDTMyMDgwMjE3MDE1NlowHTEbMBkGA1UEAxMSdW5pY29uLXNwb3J0aC0yNjU4 +MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAynP0dUXXr0yb4oAYT5OG +/ik+24jor0W0Z/0T0g3C4IXqDMHMdHlfPSrp6rf+PDlS+0L+GCZQC2IpntmGNEdf +miCs9UcssZ3aBHoch0R0Og4rxu74Vk488NVXHsX75RTom5B0atPGxdmHRNIPUPNp +F4AqAMMV18y35+ElJj5UuPZe9QEgJVzGqdH0dGvaNFPZfB7HCD7lGJiO0Remhufn +umwrRqfQETmefCD4Wrv60I4LgUrUSqlZTpD4TaR3o1N6uSKaJPy7iANqQXoEqc3p +jbiM+Tkv6t+q6FbEIF3zKwODzHcycaVYzqOxzVMGWtyPADBm3P/8wvDZnHWEqAcy +9cHY7THHq8s6bdR8aIO+T0uvIqXJAO0orGVJ4b1X2OBRRneUVtxFbzbAXWN+wwKW +Xn8M1sP9hteV9CAkp4nbyPnfwWlZYaN48QytMZhu3oQywlcc/VuDEst04IeAt/1f +YTWmSliJwAduFXpRtQjgB/ejfLUkJHugNJe2N23dNb8ZAgMBAAGjQDA+MB0GA1Ud +EQQWMBSCEnVuaWNvbi1zcG9ydGgtMjY1ODAdBgNVHQ4EFgQUuAUQzGLs2Psbx5aw +ec5sz66h4TIwDQYJKoZIhvcNAQELBQADggGBAEqDt2lXrAEJ80yWLYZKM2qdif5j +DbFI4oGMJ+6Wicfjh9iSm6CG2pSdZllypNLd7KmUJbGFS5wmP7qPAiPLOiHn6hBC +L5ke3y8bJsaEazOmZt0IgKv2w6naEAfvR5dKbEbXsipf/k+WHyk6uLFoz9iGxZ0g +f8MA+nWa1tJcPcGVOReN3wNNeBaRZ5y0r6oWSpwYtoBJH+wp2EoLPYhOXFjUoAZ0 +d4b+G2x9FyHU4yfnN9sTLocl/BVDiVdazMQqSvZDSWbccRsD8sz4BaLnXkLOtulv +0qOYuVTdCivgU0lBMhvXjiEpn0ZwU+UlSgtfEgaVP8pZVgHxKrMhoOxAe85dNHun +RyYCrByqg4lyFGzRKSTAUlx0YittvEyYOEqbSsXExViSIl+elg4PtghsYAaUphm4 ++FHJo8B1rNNQp4vqikGF2WOr3D2usIS9ZbiGvTC0M8TSG39jGCqgQZaclV2yshEC +cXQllPfIyCtMzlaGVjpXPEqahwkug4ywml9yAw== + + + + + + + + + + From fb95938505137c4f2d16a8a9cfae26a365dd7b21 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Mon, 8 Aug 2022 15:59:20 -0400 Subject: [PATCH 03/71] added ability to switch database backends Former-commit-id: d5595768a00fe18cb7df74399cafb0ee307a9eaf --- .../mariadb.docker-compose.override.yml | 19 +++++++++++++ testbed/smoke-test/db_configs/mariadb.yml | 13 +++++++++ .../mysql.docker-compose.override.yml | 19 +++++++++++++ testbed/smoke-test/db_configs/mysql.yml | 13 +++++++++ testbed/smoke-test/db_configs/postgres.yml | 13 +++++++++ .../sqlServer.docker-compose.override.yml | 17 ++++++++++++ testbed/smoke-test/db_configs/sqlServer.yml | 13 +++++++++ testbed/smoke-test/docker-compose.yml | 22 ++++++++------- testbed/smoke-test/setdb.sh | 22 +++++++++++++++ testbed/smoke-test/shibui/application.yml | 26 +++++++++--------- .../smoke-test/shibui/application.yml.nodb | 27 +++++++++++++++++++ 11 files changed, 181 insertions(+), 23 deletions(-) create mode 100644 testbed/smoke-test/db_configs/mariadb.docker-compose.override.yml create mode 100644 testbed/smoke-test/db_configs/mariadb.yml create mode 100644 testbed/smoke-test/db_configs/mysql.docker-compose.override.yml create mode 100644 testbed/smoke-test/db_configs/mysql.yml create mode 100644 testbed/smoke-test/db_configs/postgres.yml create mode 100644 testbed/smoke-test/db_configs/sqlServer.docker-compose.override.yml create mode 100644 testbed/smoke-test/db_configs/sqlServer.yml create mode 100755 testbed/smoke-test/setdb.sh create mode 100644 testbed/smoke-test/shibui/application.yml.nodb diff --git a/testbed/smoke-test/db_configs/mariadb.docker-compose.override.yml b/testbed/smoke-test/db_configs/mariadb.docker-compose.override.yml new file mode 100644 index 000000000..ad9f8ae09 --- /dev/null +++ b/testbed/smoke-test/db_configs/mariadb.docker-compose.override.yml @@ -0,0 +1,19 @@ +services: + database: + image: mariadb + environment: + MYSQL_DATABASE: shibui + MYSQL_USER: shibui + MYSQL_PASSWORD: shibui + MYSQL_ROOT_PASSWORD: root + healthcheck: + test: mysql -u shibui --password=shibui shibui -e "select 1" + interval: 5s + retries: 5 + start_period: 5s + timeout: 10s + shib-idp-ui: + depends_on: + database: + condition: service_healthy + \ No newline at end of file diff --git a/testbed/smoke-test/db_configs/mariadb.yml b/testbed/smoke-test/db_configs/mariadb.yml new file mode 100644 index 000000000..9b64f680f --- /dev/null +++ b/testbed/smoke-test/db_configs/mariadb.yml @@ -0,0 +1,13 @@ +spring: + profiles: + include: + datasource: + platform: mysql + driver-class-name: com.mariadb.jdbc.Driver + url: jdbc:mariadb://database:3306/shibui + username: shibui + password: shibui + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MariaDB103Dialect diff --git a/testbed/smoke-test/db_configs/mysql.docker-compose.override.yml b/testbed/smoke-test/db_configs/mysql.docker-compose.override.yml new file mode 100644 index 000000000..6d511c7e6 --- /dev/null +++ b/testbed/smoke-test/db_configs/mysql.docker-compose.override.yml @@ -0,0 +1,19 @@ +services: + database: + image: mysql + environment: + MYSQL_DATABASE: shibui + MYSQL_USER: shibui + MYSQL_PASSWORD: shibui + MYSQL_ROOT_PASSWORD: root + healthcheck: + test: mysql -u shibui --password=shibui shibui -e "select 1" + interval: 5s + retries: 5 + start_period: 5s + timeout: 10s + shib-idp-ui: + depends_on: + database: + condition: service_healthy + \ No newline at end of file diff --git a/testbed/smoke-test/db_configs/mysql.yml b/testbed/smoke-test/db_configs/mysql.yml new file mode 100644 index 000000000..b3d434d8a --- /dev/null +++ b/testbed/smoke-test/db_configs/mysql.yml @@ -0,0 +1,13 @@ +spring: + profiles: + include: + datasource: + platform: mysql + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://database:3306/shibui + username: shibui + password: shibui + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect diff --git a/testbed/smoke-test/db_configs/postgres.yml b/testbed/smoke-test/db_configs/postgres.yml new file mode 100644 index 000000000..c9117f2e5 --- /dev/null +++ b/testbed/smoke-test/db_configs/postgres.yml @@ -0,0 +1,13 @@ +spring: + profiles: + include: + datasource: + platform: postgres + driver-class-name: org.postgresql.Driver + url: jdbc:postgresql://database:5432/shibui + username: shibui + password: shibui + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file diff --git a/testbed/smoke-test/db_configs/sqlServer.docker-compose.override.yml b/testbed/smoke-test/db_configs/sqlServer.docker-compose.override.yml new file mode 100644 index 000000000..13d5a0670 --- /dev/null +++ b/testbed/smoke-test/db_configs/sqlServer.docker-compose.override.yml @@ -0,0 +1,17 @@ +services: + database: + build: + context: ../sqlServer + dockerfile: ../sqlServer/docker/Dockerfile + image: smoke-test_database +# healthcheck: +# test: mysql -u shibui --password=shibui shibui -e "select 1" +# interval: 5s +# retries: 5 +# start_period: 5s +# timeout: 10s +# shib-idp-ui: +# depends_on: +# database: +# condition: service_healthy + \ No newline at end of file diff --git a/testbed/smoke-test/db_configs/sqlServer.yml b/testbed/smoke-test/db_configs/sqlServer.yml new file mode 100644 index 000000000..d6e7a3e68 --- /dev/null +++ b/testbed/smoke-test/db_configs/sqlServer.yml @@ -0,0 +1,13 @@ +spring: + profiles: + include: + datasource: + platform: sqlserver + driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver + url: jdbc:sqlserver://database:1433 + username: sa + password: Password1 + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.SQLServerDialect \ No newline at end of file diff --git a/testbed/smoke-test/docker-compose.yml b/testbed/smoke-test/docker-compose.yml index 0c92cad01..9e2ac5340 100644 --- a/testbed/smoke-test/docker-compose.yml +++ b/testbed/smoke-test/docker-compose.yml @@ -37,6 +37,14 @@ services: LDAP_DOMAIN: "unicon.local" HOSTNAME: "directory" LDAP_TLS_VERIFY_CLIENT: "try" + database: + image: postgres:14-alpine + networks: + - backend + environment: + POSTGRES_PASSWORD: shibui + POSTGRES_USER: shibui + POSTGRES_DB: shibui idp: build: ../integration/shibboleth-idp labels: @@ -70,6 +78,9 @@ services: - "traefik.http.routers.shibui.tls=true" - "traefik.docker.network=smoke-test_reverse-proxy" - "traefik.enable=true" + depends_on: + database: + condition: service_started networks: - reverse-proxy - backend @@ -81,16 +92,7 @@ services: - ../integration/shibboleth-idp/credentials/shib-idp/inc-md-cert-mdq.pem:/opt/shibboleth-idp/credentials/inc-md-cert-mdq.pem environment: - "IDP_HOME=/opt/shibboleth-idp" - database: - image: postgres:14-alpine - environment: - POSTGRES_PASSWORD: shibui - POSTGRES_USER: shibui - POSTGRES_DB: shibui - networks: - - backend - volumes: - - database_data:/var/lib/postgresql/data + networks: reverse-proxy: idp: diff --git a/testbed/smoke-test/setdb.sh b/testbed/smoke-test/setdb.sh new file mode 100755 index 000000000..e4347a298 --- /dev/null +++ b/testbed/smoke-test/setdb.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +DB=$1 + +if [[ ! "$DB" =~ ^(postgres|mariadb|mysql|sqlServer)$ ]]; +then + echo "argument mst be one of: postgres mariadb mysql sqlServer" + exit 0; +fi + +if [[ $DB == "postgres" ]]; +then +rm -f docker-compose.override.yml +else +rm -f docker-compose.override.yml +ln -s db_configs/$DB.docker-compose.override.yml docker-compose.override.yml +fi + +rm -f shibui/application.yml +cat shibui/application.yml.nodb db_configs/$DB.yml >> shibui/application.yml + +echo "shibui will now use the $DB container" diff --git a/testbed/smoke-test/shibui/application.yml b/testbed/smoke-test/shibui/application.yml index 126256f0d..df9137c0b 100644 --- a/testbed/smoke-test/shibui/application.yml +++ b/testbed/smoke-test/shibui/application.yml @@ -1,18 +1,5 @@ server: forward-headers-strategy: NATIVE -spring: - profiles: - include: - datasource: - platform: postgres - driver-class-name: org.postgresql.Driver - url: jdbc:postgresql://database:5432/shibui - username: shibui - password: shibui - jpa: - properties: - hibernate: - dialect: org.hibernate.dialect.PostgreSQLDialect shibui: default-password: "{noop}letmein7" metadata-dir: /var/shibboleth/dynamic_metadata @@ -38,3 +25,16 @@ shibui: email: urn:oid:0.9.2342.19200300.100.1.3 groups: urn:oid:2.5.4.15 # businessCategory roles: urn:oid:1.3.6.1.4.1.5923.1.1.1.7 # eduPersonEntitlement +spring: + profiles: + include: + datasource: + platform: postgres + driver-class-name: org.postgresql.Driver + url: jdbc:postgresql://database:5432/shibui + username: shibui + password: shibui + jpa: + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect \ No newline at end of file diff --git a/testbed/smoke-test/shibui/application.yml.nodb b/testbed/smoke-test/shibui/application.yml.nodb new file mode 100644 index 000000000..b4a070c2c --- /dev/null +++ b/testbed/smoke-test/shibui/application.yml.nodb @@ -0,0 +1,27 @@ +server: + forward-headers-strategy: NATIVE +shibui: + default-password: "{noop}letmein7" + metadata-dir: /var/shibboleth/dynamic_metadata + metadataProviders: + target: file:/var/shibboleth/dynamic_config/metadata-providers.xml + user-bootstrap-resource: file:/conf/users.csv + roles: ROLE_ADMIN,ROLE_NONE,ROLE_USER,ROLE_ENABLE,ROLE_PONY + pac4j-enabled: true + pac4j: + keystorePath: "/conf/samlKeystore.jks" + keystorePassword: "changeit" + privateKeyPassword: "changeit" + serviceProviderEntityId: "https://unicon.net/test/shibui" + serviceProviderMetadataPath: "/conf/sp-metadata.xml" + identityProviderMetadataPath: "/conf/idp-metadata.xml" + forceServiceProviderMetadataGeneration: true + callbackUrl: "https://shibui.unicon.local/callback" + maximumAuthenticationLifetime: 3600000 + simpleProfileMapping: + username: urn:oid:0.9.2342.19200300.100.1.1 + firstName: urn:oid:2.5.4.42 + lastName: urn:oid:2.5.4.4 + email: urn:oid:0.9.2342.19200300.100.1.3 + groups: urn:oid:2.5.4.15 # businessCategory + roles: urn:oid:1.3.6.1.4.1.5923.1.1.1.7 # eduPersonEntitlement From 713038872d24e4e280cae2419eed9d6f8c5c8032 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Tue, 9 Aug 2022 09:47:23 -0400 Subject: [PATCH 04/71] cleanup, fix mariadb driver name Former-commit-id: d005502b82ee636664925b5b2ac9f596031ee602 --- .../db_configs/{mariadb.yml => mariadb.application.yml} | 2 +- .../smoke-test/db_configs/{mysql.yml => mysql.application.yml} | 0 .../db_configs/{postgres.yml => postgres.application.yml} | 0 .../db_configs/{sqlServer.yml => sqlServer.application.yml} | 0 testbed/smoke-test/setdb.sh | 2 +- 5 files changed, 2 insertions(+), 2 deletions(-) rename testbed/smoke-test/db_configs/{mariadb.yml => mariadb.application.yml} (84%) rename testbed/smoke-test/db_configs/{mysql.yml => mysql.application.yml} (100%) rename testbed/smoke-test/db_configs/{postgres.yml => postgres.application.yml} (100%) rename testbed/smoke-test/db_configs/{sqlServer.yml => sqlServer.application.yml} (100%) diff --git a/testbed/smoke-test/db_configs/mariadb.yml b/testbed/smoke-test/db_configs/mariadb.application.yml similarity index 84% rename from testbed/smoke-test/db_configs/mariadb.yml rename to testbed/smoke-test/db_configs/mariadb.application.yml index 9b64f680f..a42a5c8bc 100644 --- a/testbed/smoke-test/db_configs/mariadb.yml +++ b/testbed/smoke-test/db_configs/mariadb.application.yml @@ -3,7 +3,7 @@ spring: include: datasource: platform: mysql - driver-class-name: com.mariadb.jdbc.Driver + driver-class-name: org.mariadb.jdbc.Driver url: jdbc:mariadb://database:3306/shibui username: shibui password: shibui diff --git a/testbed/smoke-test/db_configs/mysql.yml b/testbed/smoke-test/db_configs/mysql.application.yml similarity index 100% rename from testbed/smoke-test/db_configs/mysql.yml rename to testbed/smoke-test/db_configs/mysql.application.yml diff --git a/testbed/smoke-test/db_configs/postgres.yml b/testbed/smoke-test/db_configs/postgres.application.yml similarity index 100% rename from testbed/smoke-test/db_configs/postgres.yml rename to testbed/smoke-test/db_configs/postgres.application.yml diff --git a/testbed/smoke-test/db_configs/sqlServer.yml b/testbed/smoke-test/db_configs/sqlServer.application.yml similarity index 100% rename from testbed/smoke-test/db_configs/sqlServer.yml rename to testbed/smoke-test/db_configs/sqlServer.application.yml diff --git a/testbed/smoke-test/setdb.sh b/testbed/smoke-test/setdb.sh index e4347a298..06821b37c 100755 --- a/testbed/smoke-test/setdb.sh +++ b/testbed/smoke-test/setdb.sh @@ -17,6 +17,6 @@ ln -s db_configs/$DB.docker-compose.override.yml docker-compose.override.yml fi rm -f shibui/application.yml -cat shibui/application.yml.nodb db_configs/$DB.yml >> shibui/application.yml +cat shibui/application.yml.nodb db_configs/$DB.application.yml >> shibui/application.yml echo "shibui will now use the $DB container" From 1d75bc1661a10d963eab6742a572a94b26d157d0 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Tue, 9 Aug 2022 12:48:05 -0400 Subject: [PATCH 05/71] typo Former-commit-id: 7c03bb88d7ee526c0868ff8d0dd8f16e3fbd9b42 --- testbed/smoke-test/setdb.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testbed/smoke-test/setdb.sh b/testbed/smoke-test/setdb.sh index 06821b37c..4795526a2 100755 --- a/testbed/smoke-test/setdb.sh +++ b/testbed/smoke-test/setdb.sh @@ -4,7 +4,7 @@ DB=$1 if [[ ! "$DB" =~ ^(postgres|mariadb|mysql|sqlServer)$ ]]; then - echo "argument mst be one of: postgres mariadb mysql sqlServer" + echo "argument must be one of: postgres mariadb mysql sqlServer" exit 0; fi From 136f35b3de5aad50c91ca08bd788314c0bc5321e Mon Sep 17 00:00:00 2001 From: chasegawa Date: Mon, 15 Aug 2022 14:59:04 -0700 Subject: [PATCH 06/71] SHIBUI-2333 Added logic to correctly support IDP logout Former-commit-id: dc92857b78f0f8ca91de34ae16fbf2f5e7584c71 --- .../shibui/pac4j/Pac4jConfiguration.java | 34 ++++++++++++------- .../pac4j/Pac4jConfigurationProperties.java | 1 + .../net/unicon/shibui/pac4j/WebSecurity.java | 18 ++++++++-- testbed/authentication/shibui/application.yml | 1 + 4 files changed, 38 insertions(+), 16 deletions(-) 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 fd018d4b6..5853da065 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,6 +8,7 @@ import net.unicon.shibui.pac4j.authenticator.ShibuiSAML2Authenticator; import org.pac4j.core.client.Clients; import org.pac4j.core.config.Config; +import org.pac4j.core.engine.LogoutLogic; import org.pac4j.core.matching.matcher.PathMatcher; import org.pac4j.core.profile.definition.CommonProfileDefinition; import org.pac4j.http.client.direct.HeaderClient; @@ -69,32 +70,39 @@ public Config config(final Pac4jConfigurationProperties pac4jConfigProps, case "SAML2": default: log.info("**** Configuring PAC4J SAML2"); - final SAML2Configuration saml2Config = new SAML2Configuration(); - saml2Config.setKeystorePath(pac4jConfigProps.getKeystorePath()); - saml2Config.setKeystorePassword(pac4jConfigProps.getKeystorePassword()); - saml2Config.setPrivateKeyPassword(pac4jConfigProps.getPrivateKeyPassword()); - saml2Config.setIdentityProviderMetadataPath(pac4jConfigProps.getIdentityProviderMetadataPath()); - saml2Config.setMaximumAuthenticationLifetime(pac4jConfigProps.getMaximumAuthenticationLifetime()); - saml2Config.setServiceProviderEntityId(pac4jConfigProps.getServiceProviderEntityId()); - saml2Config.setServiceProviderMetadataPath(pac4jConfigProps.getServiceProviderMetadataPath()); - saml2Config.setForceServiceProviderMetadataGeneration(pac4jConfigProps.isForceServiceProviderMetadataGeneration()); - saml2Config.setWantsAssertionsSigned(pac4jConfigProps.isWantAssertionsSigned()); - saml2Config.setAttributeAsId(pac4jConfigProps.getSimpleProfileMapping().getUsername()); + final SAML2Configuration saml2Config = buildSaml2ConfigFromPac4JConfiguration(pac4jConfigProps); + final SAML2Client saml2Client = new SAML2Client(saml2Config); + saml2Client.setName(PAC4J_CLIENT_NAME); saml2Client.addAuthorizationGenerator(saml2ModelAuthorizationGenerator); SAML2Authenticator saml2Authenticator = new ShibuiSAML2Authenticator(saml2Config.getAttributeAsId(), saml2Config.getMappedAttributes(), userService); saml2Authenticator.setProfileDefinition(new CommonProfileDefinition(p -> new BetterSAML2Profile(pac4jConfigProps.getSimpleProfileMapping()))); saml2Client.setAuthenticator(saml2Authenticator); - saml2Client.setName(PAC4J_CLIENT_NAME); clients.setClients(saml2Client); break; } config.setClients(clients); return config; } - + + private SAML2Configuration buildSaml2ConfigFromPac4JConfiguration(Pac4jConfigurationProperties pac4jConfigProps) { + SAML2Configuration saml2Config = new SAML2Configuration(); + saml2Config.setKeystorePath(pac4jConfigProps.getKeystorePath()); + saml2Config.setKeystorePassword(pac4jConfigProps.getKeystorePassword()); + saml2Config.setPrivateKeyPassword(pac4jConfigProps.getPrivateKeyPassword()); + saml2Config.setIdentityProviderMetadataPath(pac4jConfigProps.getIdentityProviderMetadataPath()); + saml2Config.setMaximumAuthenticationLifetime(pac4jConfigProps.getMaximumAuthenticationLifetime()); + saml2Config.setServiceProviderEntityId(pac4jConfigProps.getServiceProviderEntityId()); + saml2Config.setServiceProviderMetadataPath(pac4jConfigProps.getServiceProviderMetadataPath()); + saml2Config.setForceServiceProviderMetadataGeneration(pac4jConfigProps.isForceServiceProviderMetadataGeneration()); + saml2Config.setWantsAssertionsSigned(pac4jConfigProps.isWantAssertionsSigned()); + saml2Config.setAttributeAsId(pac4jConfigProps.getSimpleProfileMapping().getUsername()); + saml2Config.setPostLogoutURL(pac4jConfigProps.getPostLogoutURL()); + return saml2Config; + } + @Bean public ErrorPageRegistrar errorPageRegistrar() { return this::registerErrorPages; diff --git a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfigurationProperties.java b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfigurationProperties.java index 30311ba84..19507d1c0 100644 --- a/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfigurationProperties.java +++ b/pac4j-module/src/main/java/net/unicon/shibui/pac4j/Pac4jConfigurationProperties.java @@ -29,6 +29,7 @@ public class Pac4jConfigurationProperties { private String serviceProviderEntityId = "https://unicon.net/shibui"; private String serviceProviderMetadataPath = "/tmp/sp-metadata.xml"; private String typeOfAuth = "SAML2"; + private String postLogoutURL; private boolean wantAssertionsSigned = true; 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 884569ac7..00383f770 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,10 +5,12 @@ 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 org.jadira.usertype.spi.utils.lang.StringUtils; import org.pac4j.core.authorization.authorizer.DefaultAuthorizers; import org.pac4j.core.config.Config; import org.pac4j.core.matching.matcher.Matcher; import org.pac4j.springframework.security.web.CallbackFilter; +import org.pac4j.springframework.security.web.LogoutFilter; import org.pac4j.springframework.security.web.SecurityFilter; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureOrder; @@ -67,9 +69,19 @@ protected void configure(HttpSecurity http) throws Exception { // 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); + final LogoutFilter logoutFilter = new LogoutFilter(config); + logoutFilter.setLocalLogout(Boolean.TRUE); + if (StringUtils.isNotEmpty(pac4jConfigurationProperties.getPostLogoutURL())){ + logoutFilter.setSuffix("login"); // "logout" is redirected before we ever hit the filters - sent to /login?logout + logoutFilter.setCentralLogout(Boolean.TRUE); + logoutFilter.setDefaultUrl(pac4jConfigurationProperties.getPostLogoutURL()); + } + + // add filters + http.antMatcher("/**").addFilterBefore(logoutFilter, BasicAuthenticationFilter.class); + http.antMatcher("/**").addFilterBefore(getFilter(pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class); http.antMatcher("/**").addFilterBefore(securityFilter, BasicAuthenticationFilter.class); + // add the new user filter http.addFilterAfter(new AddNewUserFilter(pac4jConfigurationProperties, userService, rolesService, getPathMatcher("exclude-paths-matcher"), groupService, emailService), SecurityFilter.class); @@ -84,7 +96,7 @@ private Matcher getPathMatcher(String name) { return config.getMatchers().get(name); } - private Filter getFilter(Config config2, String typeOfAuth) { + private Filter getFilter(String typeOfAuth) { switch (typeOfAuth) { case "SAML2": return new CallbackFilter(this.config); diff --git a/testbed/authentication/shibui/application.yml b/testbed/authentication/shibui/application.yml index 14085a9b7..cb789f06c 100644 --- a/testbed/authentication/shibui/application.yml +++ b/testbed/authentication/shibui/application.yml @@ -18,6 +18,7 @@ shibui: forceServiceProviderMetadataGeneration: true callbackUrl: "https://shibui.unicon.local/callback" maximumAuthenticationLifetime: 3600000 + postLogoutURL: "https://idp.unicon.local/idp/profile/Logout" simpleProfileMapping: username: urn:oid:0.9.2342.19200300.100.1.1 firstName: urn:oid:2.5.4.42 From 6fd4e8dfa0e1bd0650758ca6d6205b3221929cfc Mon Sep 17 00:00:00 2001 From: chasegawa Date: Mon, 15 Aug 2022 15:15:03 -0700 Subject: [PATCH 07/71] SHIBUI-2333 Added logic to correctly support IDP logout Former-commit-id: 3c212397b7c31755739ef36aaaa9b7cce65cebce --- backend/src/main/resources/application.yml | 1 + .../main/java/net/unicon/shibui/pac4j/WebSecurity.java | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml index ffeab970c..0d2308307 100644 --- a/backend/src/main/resources/application.yml +++ b/backend/src/main/resources/application.yml @@ -22,6 +22,7 @@ # identityProviderMetadataPath: "/etc/shibui/idp-metadata.xml" # forceServiceProviderMetadataGeneration: false # callbackUrl: "https://localhost:8443/callback" +# postLogoutURL: "https://idp.example.com/idp/profile/Logout" # Must set this to get IDP logout # maximumAuthenticationLifetime: 3600000 # requireAssertedRoleForNewUsers: false # saml2ProfileMapping: 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 00383f770..cc5ce8e25 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 @@ -66,19 +66,20 @@ public Pac4jWebSecurityConfigurerAdapter(final Config config, UserService userSe protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests().antMatchers("/unsecured/**/*").permitAll(); - // adding the authorizor bypasses the default behavior of checking CSRF in Pac4J's default securitylogic+defaultauthorizationchecker + // adding the authorizer 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); - final LogoutFilter logoutFilter = new LogoutFilter(config); - logoutFilter.setLocalLogout(Boolean.TRUE); + // If the post logout URL is configured, setup the logout filter if (StringUtils.isNotEmpty(pac4jConfigurationProperties.getPostLogoutURL())){ + final LogoutFilter logoutFilter = new LogoutFilter(config); + logoutFilter.setLocalLogout(Boolean.TRUE); logoutFilter.setSuffix("login"); // "logout" is redirected before we ever hit the filters - sent to /login?logout logoutFilter.setCentralLogout(Boolean.TRUE); logoutFilter.setDefaultUrl(pac4jConfigurationProperties.getPostLogoutURL()); + http.antMatcher("/**").addFilterBefore(logoutFilter, BasicAuthenticationFilter.class); } // add filters - http.antMatcher("/**").addFilterBefore(logoutFilter, BasicAuthenticationFilter.class); http.antMatcher("/**").addFilterBefore(getFilter(pac4jConfigurationProperties.getTypeOfAuth()), BasicAuthenticationFilter.class); http.antMatcher("/**").addFilterBefore(securityFilter, BasicAuthenticationFilter.class); From c810e209539ab12824daac6b3475c14ea31ffac3 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 16 Aug 2022 09:26:51 -0700 Subject: [PATCH 08/71] SHIBUI-1699 Correcting date format output for versions to match the date format supplied to the UI in the rest of the application Former-commit-id: b407e5bf3268323f302092f92f19e8b828953181 --- .../tier/shibboleth/admin/ui/domain/versioning/Version.java | 4 ++-- .../versioning/VersionJsonSerializationBasicTests.groovy | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java index 100b0fdbd..55fc0566d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/Version.java @@ -26,9 +26,9 @@ public class Version implements Serializable { private String creator; - @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS") private ZonedDateTime date; private static final long serialVersionUID = 3429591830989243421L; -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy index b7fecdf4d..2ceb78df6 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/domain/versioning/VersionJsonSerializationBasicTests.groovy @@ -27,7 +27,7 @@ class VersionJsonSerializationBasicTests extends Specification { { "id": "2", "creator": "kramer", - "date": "2019-05-20T15:00:00.574Z" + "date": "2019-05-20T15:00:00.574000" } """ def expectedJsonMap = jsonSlurper.parseText(expectedJson) @@ -40,4 +40,4 @@ class VersionJsonSerializationBasicTests extends Specification { deSerializedJsonMap.id == expectedJsonMap.id deSerializedJsonMap.creator == expectedJsonMap.creator } -} +} \ No newline at end of file From 1dc1b7a899206e8cd5abb8e547b81bec9975fe80 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 25 Aug 2022 14:00:12 -0700 Subject: [PATCH 09/71] Fixed issue with changing filter type Former-commit-id: 3939df3761d61522aff021e35f278af2848b2c03 --- ui/src/app/metadata/Filter.js | 2 -- ui/src/app/metadata/editor/MetadataFilterEditor.js | 8 ++++++++ ui/src/app/metadata/hooks/schema.js | 6 +++++- ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ui/src/app/metadata/Filter.js b/ui/src/app/metadata/Filter.js index 58b867040..4c1bc707c 100644 --- a/ui/src/app/metadata/Filter.js +++ b/ui/src/app/metadata/Filter.js @@ -11,8 +11,6 @@ export function Filter() { const { path, url } = useRouteMatch(); - console.log(path, url) - return ( diff --git a/ui/src/app/metadata/editor/MetadataFilterEditor.js b/ui/src/app/metadata/editor/MetadataFilterEditor.js index 538c85d0e..972905e0a 100644 --- a/ui/src/app/metadata/editor/MetadataFilterEditor.js +++ b/ui/src/app/metadata/editor/MetadataFilterEditor.js @@ -25,6 +25,13 @@ export function MetadataFilterEditor({children, onNavigate, block}) { const schema = React.useContext(MetadataSchemaContext); const current = React.useContext(MetadataFilterContext); + React.useEffect(() => { + const step = definition.steps.find(step => step.id === section); + if (!step) { + onNavigate(definition.steps[0].id); + } + }, [section, current, onNavigate, definition]); + const { state, dispatch } = React.useContext(MetadataFormContext); const { metadata, errors } = state; @@ -38,6 +45,7 @@ export function MetadataFilterEditor({children, onNavigate, block}) { const warnings = definition.warnings && definition.warnings(metadata); + return (
diff --git a/ui/src/app/metadata/hooks/schema.js b/ui/src/app/metadata/hooks/schema.js index 5083559b1..b8bfcf7ca 100644 --- a/ui/src/app/metadata/hooks/schema.js +++ b/ui/src/app/metadata/hooks/schema.js @@ -11,7 +11,11 @@ export function useUiSchema(definition, schema, current, locked = true) { const ui = React.useMemo(() => definition ? { ...definition.uiSchema } : {}, [definition]); const schemaKeys = React.useMemo(() => schema ? Object.keys(schema.properties) : [], [schema]); - const step = React.useMemo(() => definition ? definition.steps.find(step => step.id === current) : {fields: []}, [definition, current]); + let step = React.useMemo(() => definition ? definition.steps.find(step => step.id === current) : {fields: []}, [definition, current]); + + if (!step) { + step = definition.steps[0]; + } const filled = React.useMemo(() => fillInRootProperties(schemaKeys, ui), [schemaKeys, ui]); const mapped = React.useMemo(() => Object.keys(filled).reduce((sch, key) => { diff --git a/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js b/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js index ff16b61a4..d46e79999 100644 --- a/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js +++ b/ui/src/app/metadata/wizard/MetadataFilterTypeSelector.js @@ -5,7 +5,7 @@ import Translate from '../../i18n/components/translate'; import { InfoIcon } from '../../form/component/InfoIcon'; import { useTranslator } from '../../i18n/hooks'; -export function MetadataFilterTypeSelector({ types = [], children, actions}) { +export function MetadataFilterTypeSelector({ types = [], children}) { const translator = useTranslator(); @@ -29,7 +29,7 @@ export function MetadataFilterTypeSelector({ types = [], children, actions}) { React.useEffect(() => { setBase({ '@type': type - }) + }); }, [type]) return ( From fbca08abb1caf11964fd1f36bfb1e88ff6c6041d Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 25 Aug 2022 14:03:02 -0700 Subject: [PATCH 10/71] Fixed message Former-commit-id: dc238e818afa99c340c591484c913d3b28cd1616 --- backend/src/main/resources/i18n/messages.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 92f1edb6f..29aaf5de9 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -534,7 +534,7 @@ label.role=Role message.delete-role-title=Delete Role? message.delete-role-body=You are requesting to delete a role. If you complete this process the role will be removed. This cannot be undone. Do you wish to continue? -message.duration=Requires a valid ISO 8601 duration (ex. PT2D) +message.duration=Requires a valid ISO 8601 duration (ex. PT4H) message.delete-user-title=Delete User? message.delete-user-body=You are requesting to delete a user. If you complete this process the user will be removed. This cannot be undone. Do you wish to continue? From 0bfaa00b318a96264fb4c3295b496a45e2abb622 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 14:34:59 -0700 Subject: [PATCH 11/71] [Gradle Release Plugin] - pre tag commit: '1.12.0'. Former-commit-id: 21f5c8c21c6ab86303d96accb72a220f0a5b2903 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7efe1ae08..da3a66a9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0-SNAPSHOT +version=1.12.0 ### library versions ### commonsCollections4Version=4.4 From 28c46d905de721c7bf3c6b33eeb8241bade5e3cf Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 15:35:42 -0700 Subject: [PATCH 12/71] NOJIRA change to version to snapshot Former-commit-id: 6dc0b7df54c91ba9a9eae53aa99eaf99c6eafdbf --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index da3a66a9f..7efe1ae08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0 +version=1.12.0-SNAPSHOT ### library versions ### commonsCollections4Version=4.4 From 2b4ce668e88f0e1f771da8bf080f8a538c67c80f Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 15:51:32 -0700 Subject: [PATCH 13/71] [Gradle Release Plugin] - pre tag commit: '1.12.0'. Former-commit-id: d23265d0c394f490dc81d563be38f07437123bb6 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7efe1ae08..da3a66a9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0-SNAPSHOT +version=1.12.0 ### library versions ### commonsCollections4Version=4.4 From e6aae3b6c48e05c955d000c214f2d31d451f2a0b Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 15:56:33 -0700 Subject: [PATCH 14/71] NOJIRA change to version to snapshot Former-commit-id: 27410d2c775443d069663268dbcc5394e3303794 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index da3a66a9f..7efe1ae08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0 +version=1.12.0-SNAPSHOT ### library versions ### commonsCollections4Version=4.4 From f415c97929fdde5cc978623e8a7b45d08960427f Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 16:26:50 -0700 Subject: [PATCH 15/71] [Gradle Release Plugin] - pre tag commit: '1.12.0'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7efe1ae08..da3a66a9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0-SNAPSHOT +version=1.12.0 ### library versions ### commonsCollections4Version=4.4 From 5961c908b8c27d5e6bba037c106145873f721761 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 18:25:34 -0700 Subject: [PATCH 16/71] NOJIRA change to version to snapshot --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index da3a66a9f..7efe1ae08 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0 +version=1.12.0-SNAPSHOT ### library versions ### commonsCollections4Version=4.4 From 69d2947820ebdf10f93ccdb239e89e3b2aad7a63 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 18:35:08 -0700 Subject: [PATCH 17/71] [Gradle Release Plugin] - pre tag commit: '1.12.0'. --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 7efe1ae08..da3a66a9f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0-SNAPSHOT +version=1.12.0 ### library versions ### commonsCollections4Version=4.4 From 1d81472ae3c06575f65a65b2816095ef351cef65 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 26 Aug 2022 19:22:16 -0700 Subject: [PATCH 18/71] NOJIRA change to version to snapshot --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index da3a66a9f..1594d2baa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ name=shibui group=edu.internet2.tier.shibboleth.admin.ui -version=1.12.0 +version=1.13.0-SNAPSHOT ### library versions ### commonsCollections4Version=4.4 From 2813d25d8e889ba6002b3632a835fa5f23ef9802 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Mon, 29 Aug 2022 13:25:22 -0700 Subject: [PATCH 19/71] Updated configuration builder --- ui/package-lock.json | 14 +- ui/package.json | 2 +- ui/public/assets/data/configuration.json | 29 +++ .../app/admin/component/ConfigurationForm.js | 174 +++++++----------- .../app/admin/component/PropertySelector.js | 92 +++++++++ .../app/admin/container/ConfigurationList.js | 12 +- .../app/admin/container/EditConfiguration.js | 76 ++++---- .../app/admin/container/NewConfiguration.js | 30 ++- .../app/admin/hoc/ConfigurationsProvider.js | 2 +- ui/src/app/admin/hoc/PropertiesProvider.js | 4 +- ui/src/app/admin/hooks.js | 8 +- ui/src/theme/project/configuration.scss | 11 ++ ui/src/theme/project/index.scss | 1 + 13 files changed, 271 insertions(+), 184 deletions(-) create mode 100644 ui/public/assets/data/configuration.json create mode 100644 ui/src/app/admin/component/PropertySelector.js create mode 100644 ui/src/theme/project/configuration.scss diff --git a/ui/package-lock.json b/ui/package-lock.json index 0cc5f3665..2083b22a0 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -25,7 +25,7 @@ "react-bootstrap": "^2.3.0", "react-bootstrap-typeahead": "^5.1.4", "react-dom": "^18.0.0", - "react-hook-form": "^7.30.0", + "react-hook-form": "^7.34.0", "react-infinite-scroll-component": "^6.1.0", "react-router": "^5.1.0", "react-router-dom": "^5.1.0", @@ -13536,9 +13536,9 @@ "dev": true }, "node_modules/react-hook-form": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", - "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "version": "7.34.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.34.2.tgz", + "integrity": "sha512-1lYWbEqr0GW7HHUjMScXMidGvV0BE2RJV3ap2BL7G0EJirkqpccTaawbsvBO8GZaB3JjCeFBEbnEWI1P8ZoLRQ==", "engines": { "node": ">=12.22.0" }, @@ -26712,9 +26712,9 @@ "dev": true }, "react-hook-form": { - "version": "7.30.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.30.0.tgz", - "integrity": "sha512-DzjiM6o2vtDGNMB9I4yCqW8J21P314SboNG1O0obROkbg7KVS0I7bMtwSdKyapnCPjHgnxc3L7E5PEdISeEUcQ==", + "version": "7.34.2", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.34.2.tgz", + "integrity": "sha512-1lYWbEqr0GW7HHUjMScXMidGvV0BE2RJV3ap2BL7G0EJirkqpccTaawbsvBO8GZaB3JjCeFBEbnEWI1P8ZoLRQ==", "requires": {} }, "react-infinite-scroll-component": { diff --git a/ui/package.json b/ui/package.json index 25cc8cd8a..b32a48b1d 100644 --- a/ui/package.json +++ b/ui/package.json @@ -21,7 +21,7 @@ "react-bootstrap": "^2.3.0", "react-bootstrap-typeahead": "^5.1.4", "react-dom": "^18.0.0", - "react-hook-form": "^7.30.0", + "react-hook-form": "^7.34.0", "react-infinite-scroll-component": "^6.1.0", "react-router": "^5.1.0", "react-router-dom": "^5.1.0", diff --git a/ui/public/assets/data/configuration.json b/ui/public/assets/data/configuration.json new file mode 100644 index 000000000..82e86dd4d --- /dev/null +++ b/ui/public/assets/data/configuration.json @@ -0,0 +1,29 @@ +{ + "resourceId": 11, + "name": "setname1", + "properties": [ + { + "resourceId":"577", + "category":"OPSubClaim", + "configFile":"oidc.properties", + "description":"The source attribute used in generating the sub claim", + "idpVersion":"4.1", + "module":"idp.oidc.OP", + "moduleVersion":"3", + "propertyName":"idp.oidc.subject.sourceAttribute", + "displayType":"string", + "propertyValue": "foo" + }, + { + "resourceId": "393", + "category": "ReloadableServices", + "configFile": "services.properties", + "defaultValue": "false", + "description": "Fail at startup if MetadataConfiguration is invalid", + "idpVersion": "all", + "propertyName": "idp.service.metadata.failFast", + "displayType": "boolean", + "propertyValue": "true" + } + ] +} diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index ff890a6a2..9db9756da 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -1,74 +1,34 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import Button from 'react-bootstrap/Button'; +import { useFieldArray, useForm } from 'react-hook-form'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSpinner, faSave, faTrash } from '@fortawesome/free-solid-svg-icons'; -import { Highlighter, Menu, MenuItem, Token, Typeahead } from 'react-bootstrap-typeahead'; + import Translate from '../../i18n/components/translate'; -import { ToggleButton } from '../../form/component/ToggleButton'; +import PropertySelector from './PropertySelector'; import { useProperties, usePropertiesLoading } from '../hoc/PropertiesProvider'; -import { groupBy } from 'lodash'; -import { useCallback } from 'react'; + import Form from 'react-bootstrap/Form'; import FloatingLabel from 'react-bootstrap/FloatingLabel'; -export function ConfigurationForm({ configuration = {}, errors = [], schema, onSave, onCancel }) { - - const properties = useProperties(); - const loading = usePropertiesLoading(); +export function ConfigurationForm({ configuration = {}, schema, onSave, onCancel }) { - const select = (data) => { - console.log(data); - setSelected(data); - }; + const { control, register, getValues, watch, formState: { errors } } = useForm({ + defaultValues: { + ...configuration + } + }); - const [selected, setSelected] = React.useState([]); + const { fields, prepend, remove } = useFieldArray({ + control, + name: "properties", + }); - const [config, setConfig] = React.useState({ name: '', properties: [] }); - - // config.properties.filter(p => p.category === item.category).length === properties.filter(p => p.category === item.category).length - - const menu = useCallback((results, menuProps, state) => { - let index = 0; - const mapped = results.map(p => !p.category || p.category === '?' ? { ...p, category: 'Misc' } : p); - const grouped = groupBy(mapped, 'category'); - const items = Object.keys(grouped).sort().map((item) => ( - - {index !== 0 && } - - - {item} - Add all - - - {grouped[item].map((i) => { - const item = - p.propertyName === i.propertyName) }> - - {`- ${i.propertyName}`} - - ; - index += 1; - return item; - })} - - )); - - return {items}; - }, [config.properties]); - - const token = (option, { onRemove }, index) => ( - - {`${option.propertyName}`} - - ); + const properties = useProperties(); + const loading = usePropertiesLoading(); const addProperties = (props) => { - const parsed = props.reduce((coll, prop, idx) => { if (prop.isCategory) { return [...coll, ...properties.filter(p => p.category === prop.category)]; @@ -77,17 +37,20 @@ export function ConfigurationForm({ configuration = {}, errors = [], schema, onS } }, []); - setConfig({ - ...config, - properties: [ - ...config.properties, - ...parsed, - ] - }); - setSelected([]); + prepend(parsed); }; - React.useEffect(() => console.log(selected), [selected]); + const saveConfig = (formValues) => { + const parsed = formValues.properties.map(p => ({ + propertyName: p.propertyName, + propertyValue: p.propertyValue, + configFile: p.configFile, + })); + onSave({ + ...formValues, + properties: parsed + }); + }; return (<>
@@ -95,7 +58,7 @@ export function ConfigurationForm({ configuration = {}, errors = [], schema, onS

-
-
-
-
- - select(selected)} - options={[...properties]} - selected={selected} - labelKey={option => `${option.propertyName}`} - filterBy={['propertyName', 'category', 'displayType']} - renderMenu={ menu } - multiple={ true } - renderToken={ token } - > - {({ isMenuShown, toggleMenu }) => ( - toggleMenu()}> - Options - - )} - +
+
+
+ + Name + + +
+
+
+
+
+
-
-
-
-
-
- +
+
+
@@ -154,20 +102,27 @@ export function ConfigurationForm({ configuration = {}, errors = [], schema, onS - {config.properties.map((p, idx) => ( - + {fields.map((p, idx) => ( +
{ p.propertyName } { p.category } { p.displayType } - - - + {p.displayType !== 'boolean' ? + + + + : + + } - @@ -176,10 +131,9 @@ export function ConfigurationForm({ configuration = {}, errors = [], schema, onS ))}
- +
-
+
) -} -/**/ \ No newline at end of file +} \ No newline at end of file diff --git a/ui/src/app/admin/component/PropertySelector.js b/ui/src/app/admin/component/PropertySelector.js new file mode 100644 index 000000000..44cdfd085 --- /dev/null +++ b/ui/src/app/admin/component/PropertySelector.js @@ -0,0 +1,92 @@ +import React, { Fragment, useCallback } from 'react'; +import { groupBy } from 'lodash'; +import { Highlighter, Menu, MenuItem, Token, Typeahead } from 'react-bootstrap-typeahead'; +import Button from 'react-bootstrap/Button'; + +import { ToggleButton } from '../../form/component/ToggleButton'; + +export function PropertySelector ({ properties, options, onAddProperties }) { + + // React.useEffect(() => console.log(properties), [properties]); + + const menu = useCallback((results, menuProps, state) => { + let index = 0; + const mapped = results.map(p => !p.category || p.category === '?' ? { ...p, category: 'Misc' } : p); + const grouped = groupBy(mapped, 'category'); + const items = Object.keys(grouped).sort().map((item) => ( + + {index !== 0 && } + + + {item} - Add all + + + {grouped[item].map((i) => { + const item = + p.propertyName === i.propertyName) }> + + {`- ${i.propertyName}`} + + ; + index += 1; + return item; + })} + + )); + + return {items}; + }, [properties]); + + const token = (option, { onRemove }, index) => ( + + {`${option.propertyName}`} + + ); + + const select = (data) => { + setSelected(data); + }; + + const [selected, setSelected] = React.useState([]); + + const add = (s) => { + onAddProperties(s); + setSelected([]); + } + + return ( + +
+ + select(selected)} + options={[...options]} + selected={selected} + labelKey={option => `${option.propertyName}`} + filterBy={['propertyName', 'category', 'displayType']} + renderMenu={ menu } + multiple={ true } + renderToken={ token } + > + {({ isMenuShown, toggleMenu }) => ( + toggleMenu()}> + Options + + )} + +
+ +
+ ) +} + +export default PropertySelector; \ No newline at end of file diff --git a/ui/src/app/admin/container/ConfigurationList.js b/ui/src/app/admin/container/ConfigurationList.js index fcad47048..4acffc1c2 100644 --- a/ui/src/app/admin/container/ConfigurationList.js +++ b/ui/src/app/admin/container/ConfigurationList.js @@ -1,5 +1,5 @@ import React from 'react'; -import { faDownload, faEdit, faPlusCircle, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faDownload, faPlusCircle, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Button from 'react-bootstrap/Button'; @@ -46,13 +46,17 @@ export function ConfigurationList({ configurations, onDelete }) { {(configurations?.length > 0) ? configurations.map((c, i) => - {c.name} + + + {c.name} + + - +
diff --git a/ui/src/app/admin/container/NewConfiguration.js b/ui/src/app/admin/container/NewConfiguration.js index d2ece36a9..a358c1f84 100644 --- a/ui/src/app/admin/container/NewConfiguration.js +++ b/ui/src/app/admin/container/NewConfiguration.js @@ -21,11 +21,11 @@ export function NewConfiguration() { const [blocking, setBlocking] = React.useState(false); - async function save(property) { + async function save(config) { let toast; - const resp = await post(``, property); + const resp = await post(``, config); if (response.ok) { - gotoDetail({ refresh: true }); + gotoList({ refresh: true }); toast = createNotificationAction(`Added property successfully.`, NotificationTypes.SUCCESS); } else { toast = createNotificationAction(`${resp.errorCode} - ${translator(resp.errorMessage)}`, NotificationTypes.ERROR); @@ -36,14 +36,16 @@ export function NewConfiguration() { }; const cancel = () => { - gotoDetail(); + gotoList(); }; - const gotoDetail = (state = null) => { + const gotoList = (state = null) => { setBlocking(false); - history.push(`/properties`, state); + history.push(`/configurations`, state); }; + const [configuration] = React.useState({}); + return (
{(schema) => - - {(data, errors) => - save(data)} - onCancel={() => cancel()} />} - } + save(data)} + onCancel={() => cancel()} />}
diff --git a/ui/src/app/admin/hoc/ConfigurationsProvider.js b/ui/src/app/admin/hoc/ConfigurationsProvider.js index 661c00d80..aa23ddd45 100644 --- a/ui/src/app/admin/hoc/ConfigurationsProvider.js +++ b/ui/src/app/admin/hoc/ConfigurationsProvider.js @@ -15,7 +15,7 @@ export function ConfigurationsProvider({ children, cache = 'no-cache' }) { }); async function loadConfigurations() { - const list = await get(`assets/data/configurations.json`); + const list = await get(`shib/property/set`); if (response.ok) { setConfigurations(list); } diff --git a/ui/src/app/admin/hoc/PropertiesProvider.js b/ui/src/app/admin/hoc/PropertiesProvider.js index 55dde0696..bf62be7cc 100644 --- a/ui/src/app/admin/hoc/PropertiesProvider.js +++ b/ui/src/app/admin/hoc/PropertiesProvider.js @@ -1,8 +1,6 @@ import React from 'react'; import useFetch from 'use-http'; -import API_BASE_PATH, { BASE_PATH } from '../../App.constant'; -import has from 'lodash/has'; -import { groupBy } from 'lodash'; +import API_BASE_PATH from '../../App.constant'; const PropertiesContext = React.createContext(); diff --git a/ui/src/app/admin/hooks.js b/ui/src/app/admin/hooks.js index 50f0b51c7..11184e55e 100644 --- a/ui/src/app/admin/hooks.js +++ b/ui/src/app/admin/hooks.js @@ -1,7 +1,7 @@ import useFetch from 'use-http'; import isNil from 'lodash/isNil'; import {isValidRegex} from '../core/utility/is_valid_regex'; -import API_BASE_PATH, { BASE_PATH } from '../App.constant'; +import API_BASE_PATH from '../App.constant'; export function useGroups (opts = { cachePolicy: 'no-cache' }) { return useFetch(`${API_BASE_PATH}/admin/groups`, opts); @@ -48,11 +48,11 @@ export function useRoleUiSchema() { } export function useConfigurations (opts = { cachePolicy: 'no-cache' }) { - return useFetch(`${BASE_PATH}/`, opts); + return useFetch(`${API_BASE_PATH}/`, opts); } -export function useConfiguration(id, opts = { cachePolicy: 'no-cache' }) { - return useFetch(`${API_BASE_PATH}/admin/configuration/${id}`, opts); +export function useConfiguration(opts = { cachePolicy: 'no-cache' }) { + return useFetch(`${API_BASE_PATH}/shib/property/set`, opts); } export function useConfigurationUiSchema () { diff --git a/ui/src/theme/project/configuration.scss b/ui/src/theme/project/configuration.scss new file mode 100644 index 000000000..0da05f1ff --- /dev/null +++ b/ui/src/theme/project/configuration.scss @@ -0,0 +1,11 @@ +#property-selector { + .dropdown-header { + padding-right: 0rem; + padding-left: 0rem; + font-size: 1rem; + + .dropdown-item { + font-weight: bold; + } + } +} \ No newline at end of file diff --git a/ui/src/theme/project/index.scss b/ui/src/theme/project/index.scss index 6d0de6f9a..fd2b6a070 100644 --- a/ui/src/theme/project/index.scss +++ b/ui/src/theme/project/index.scss @@ -14,6 +14,7 @@ @import './notifications'; @import './filters'; @import './typeahead'; +@import './configuration'; html, body { height: 100%; From 58fa44542e2b15b5ad117039599c8e0a37834489 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Mon, 29 Aug 2022 14:45:49 -0700 Subject: [PATCH 20/71] NOJIRA fixed typo --- .../admin/ui/controller/ShibPropertiesController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java index b5895db41..f90392108 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java @@ -58,7 +58,7 @@ public ResponseEntity getAllPropertySets() { return ResponseEntity.ok(service.getAllPropertySets()); } - @GetMapping(value="/property/set/{resourceId}", produces="applcation/json") + @GetMapping(value="/property/set/{resourceId}", produces="application/json") @Transactional(readOnly = true) @Operation(description = "Return the property set with the given resourceId", summary = "Return the property set with the given resourceId", method = "GET") From f0211d05a7f14aee4efeeeb647dc07dba9f90783 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Mon, 29 Aug 2022 15:14:28 -0700 Subject: [PATCH 21/71] NOJIRA fixed typo --- .../admin/ui/controller/ShibPropertiesController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java index b5895db41..f90392108 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java @@ -58,7 +58,7 @@ public ResponseEntity getAllPropertySets() { return ResponseEntity.ok(service.getAllPropertySets()); } - @GetMapping(value="/property/set/{resourceId}", produces="applcation/json") + @GetMapping(value="/property/set/{resourceId}", produces="application/json") @Transactional(readOnly = true) @Operation(description = "Return the property set with the given resourceId", summary = "Return the property set with the given resourceId", method = "GET") From 61d05800a03a44b7a6fa39a635faa7caeaa1fe6a Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 30 Aug 2022 09:52:46 -0700 Subject: [PATCH 22/71] SHIBUI-2270 Adding export file as a single property file option --- .../controller/ShibPropertiesController.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java index f90392108..b613c2b4f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java @@ -76,6 +76,16 @@ public ResponseEntity getPropertySetAsZip(@PathVariable Integer resourceId) t return ResponseEntity.ok().header("Content-Disposition", sb.toString()).body(prepDownloadAsZip(convertPropertiesToMaps(set.getProperties()))); } + @GetMapping(value="/property/set/{resourceId}/onefile", produces="application/zip") + @Transactional(readOnly = true) + @Operation(description = "Return the property set with the given resourceId as a zip file of a single properties files", + summary = "Return the property set with the given resourceId as a zip file of a single properties files", method = "GET") + public ResponseEntity getPropertySetOneFileAsZip(@PathVariable Integer resourceId) throws EntityNotFoundException, IOException { + ShibPropertySet set = service.getSet(resourceId); + StringBuilder sb = new StringBuilder("attachment; filename=\"").append(set.getName()).append(".zip\""); + return ResponseEntity.ok().header("Content-Disposition", sb.toString()).body(prepDownloadAsZipWithSingleFile(convertPropertiesToMaps(set.getProperties()))); + } + private Map> convertPropertiesToMaps(List properties) { HashMap> result = new HashMap<>(); for (ShibPropertySetting setting:properties){ @@ -90,6 +100,25 @@ private Map> convertPropertiesToMaps(List> propertiesFiles) throws IOException { + ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); + ZipOutputStream zipOutputStream = new ZipOutputStream(byteOutputStream); + zipOutputStream.putNextEntry(new ZipEntry("shibboleth.properties")); + + for (String filename : propertiesFiles.keySet()) { + Map properties = propertiesFiles.get(filename); + StringBuilder props = new StringBuilder(); + for (String key : properties.keySet()) { + props.append(key).append("=").append(properties.get(key)).append("\n"); + } + ByteArrayInputStream inputStream = new ByteArrayInputStream(props.toString().getBytes()); + IOUtils.copy(inputStream, zipOutputStream); + } + zipOutputStream.closeEntry(); + zipOutputStream.close(); + return byteOutputStream.toByteArray(); + } + private byte[] prepDownloadAsZip(Map> propertiesFiles) throws IOException { ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream(); ZipOutputStream zipOutputStream = new ZipOutputStream(byteOutputStream); From 0e0eff995a2ea0d7846b0bd435b6554c1239f0b9 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 30 Aug 2022 09:59:56 -0700 Subject: [PATCH 23/71] Added spinners --- .../app/admin/component/ConfigurationForm.js | 11 ++++--- .../app/admin/container/ConfigurationList.js | 29 +++++++++++++------ .../app/admin/container/EditConfiguration.js | 22 ++++++++------ 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index e48062f01..61e82dba6 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -7,12 +7,12 @@ import { faSpinner, faSave, faTrash } from '@fortawesome/free-solid-svg-icons'; import Translate from '../../i18n/components/translate'; import PropertySelector from './PropertySelector'; -import { useProperties, usePropertiesLoading } from '../hoc/PropertiesProvider'; +import { useProperties } from '../hoc/PropertiesProvider'; import Form from 'react-bootstrap/Form'; import FloatingLabel from 'react-bootstrap/FloatingLabel'; -export function ConfigurationForm({ configuration = {}, schema, onSave, onCancel }) { +export function ConfigurationForm({ configuration = {}, loading, onSave, onCancel }) { const { control, register, getValues, watch, formState: { errors } } = useForm({ defaultValues: { @@ -26,7 +26,6 @@ export function ConfigurationForm({ configuration = {}, schema, onSave, onCancel }); const properties = useProperties(); - const loading = usePropertiesLoading(); const addProperties = (props) => { const parsed = props.reduce((coll, prop, idx) => { @@ -52,6 +51,8 @@ export function ConfigurationForm({ configuration = {}, schema, onSave, onCancel }); }; + React.useEffect(() => console.log(configuration), [configuration]); + return (<>
@@ -66,7 +67,9 @@ export function ConfigurationForm({ configuration = {}, schema, onSave, onCancel diff --git a/ui/src/app/admin/container/ConfigurationList.js b/ui/src/app/admin/container/ConfigurationList.js index 4acffc1c2..527f65c50 100644 --- a/ui/src/app/admin/container/ConfigurationList.js +++ b/ui/src/app/admin/container/ConfigurationList.js @@ -1,15 +1,16 @@ import React from 'react'; -import { faDownload, faPlusCircle, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faDownload, faEdit, faPlusCircle, faSpinner, faTrash } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Button from 'react-bootstrap/Button'; +import ButtonGroup from 'react-bootstrap/ButtonGroup'; import { Link } from 'react-router-dom'; import { Translate } from '../../i18n/components/translate'; import { DeleteConfirmation } from '../../core/components/DeleteConfirmation'; -export function ConfigurationList({ configurations, onDelete }) { +export function ConfigurationList({ configurations, onDelete, loading }) { const remove = (id) => { onDelete(id); @@ -19,6 +20,11 @@ export function ConfigurationList({ configurations, onDelete }) { {(block) =>
+ {loading ? +
+ +
+ :
@@ -52,16 +58,20 @@ export function ConfigurationList({ configurations, onDelete }) { - - - + + + +   Edit + + - + ) : @@ -73,6 +83,7 @@ export function ConfigurationList({ configurations, onDelete }) {
+ }
}
diff --git a/ui/src/app/admin/container/EditConfiguration.js b/ui/src/app/admin/container/EditConfiguration.js index 7ff66b46d..692c353c9 100644 --- a/ui/src/app/admin/container/EditConfiguration.js +++ b/ui/src/app/admin/container/EditConfiguration.js @@ -10,6 +10,8 @@ import { createNotificationAction, NotificationTypes, useNotificationDispatcher import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; import { PropertiesProvider } from '../hoc/PropertiesProvider'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faSpinner } from '@fortawesome/free-solid-svg-icons'; export function EditConfiguration() { const history = useHistory(); @@ -73,17 +75,19 @@ export function EditConfiguration() {
+ {loading ? +
+ +
+ : - - {(schema) => - save(data)} - onCancel={() => cancel()} />} - + {configuration && save(data)} + onCancel={() => cancel()} /> } + }
From 0563ebdfc03b3c5f5adc08bc549e1334b28f4025 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 30 Aug 2022 10:42:04 -0700 Subject: [PATCH 24/71] Fixed label --- backend/src/main/resources/i18n/messages.properties | 1 + ui/src/app/admin/container/EditConfiguration.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index ddfa6947f..19ab8999c 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -538,6 +538,7 @@ label.role=Role label.configuration-management=Manage Shibboleth configurations label.configuration-name=Shibboleth configuration sets label.new-configuration=Create new configuration set +label.edit-configuration=Edit configuration set message.delete-role-title=Delete Role? diff --git a/ui/src/app/admin/container/EditConfiguration.js b/ui/src/app/admin/container/EditConfiguration.js index 692c353c9..bad543b69 100644 --- a/ui/src/app/admin/container/EditConfiguration.js +++ b/ui/src/app/admin/container/EditConfiguration.js @@ -70,7 +70,7 @@ export function EditConfiguration() {
- Create new configuration set + Edit configuration set
From d7228d00018041bb48287e4ad95b06d687395729 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 30 Aug 2022 11:49:16 -0700 Subject: [PATCH 25/71] SHIBUI-2270 Adding category and dsiplay type --- .../ui/domain/shib/properties/ShibPropertySetting.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java index 2fa85ff2b..1fd4d73fd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java @@ -26,4 +26,10 @@ public class ShibPropertySetting { @Column private String propertyValue; + @Column + private String category; + + @Column + private String displayType; + } \ No newline at end of file From 0e7c7aa75d0c938da7c170c685a30a0923f084d6 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 30 Aug 2022 11:52:42 -0700 Subject: [PATCH 26/71] SHIBUI-2270 Adding category and dsiplay type --- .../admin/ui/service/ShibConfigurationServiceImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java index 74d9e3637..1c3c2a513 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java @@ -118,8 +118,11 @@ private ShibPropertySet save(ShibPropertySet incomingPropSet) { } else { // get the entity from the map, update it, save to update list ShibPropertySetting updatedEntity = existingPropMap.get(prop.getPropertyName()); + // the value is really the only thing that should change... updatedEntity.setConfigFile(prop.getConfigFile()); updatedEntity.setPropertyValue(prop.getPropertyValue()); + updatedEntity.setCategory(prop.getCategory()); + updatedEntity.setDisplayType(prop.getDisplayType()); propertiesToUpdate.add(shibPropertySettingRepository.save(updatedEntity)); } }); From 909102722e3d9014db6f76b9bfc665698549a34c Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 30 Aug 2022 13:01:25 -0700 Subject: [PATCH 27/71] Fixed invalid duration setting --- backend/src/main/resources/i18n/messages.properties | 1 + .../provider/definition/BaseProviderDefinition.js | 13 +++++++++++++ 2 files changed, 14 insertions(+) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 92f1edb6f..9e1392ecd 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -535,6 +535,7 @@ message.delete-role-title=Delete Role? message.delete-role-body=You are requesting to delete a role. If you complete this process the role will be removed. This cannot be undone. Do you wish to continue? message.duration=Requires a valid ISO 8601 duration (ex. PT2D) +message.invalid-duration=Invalid duration for this field. message.delete-user-title=Delete User? message.delete-user-body=You are requesting to delete a user. If you complete this process the user will be removed. This cannot be undone. Do you wish to continue? diff --git a/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js b/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js index 12e61ae0f..b94258159 100644 --- a/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js +++ b/ui/src/app/metadata/domain/provider/definition/BaseProviderDefinition.js @@ -1,5 +1,6 @@ import { metadataFilterProcessor } from '../utility/providerFilterProcessor'; import { MetadataFilterTypes } from '../../filter'; +import { has } from 'lodash'; export const BaseProviderDefinition = { schemaPreprocessor: metadataFilterProcessor, @@ -18,6 +19,18 @@ export const BaseProviderDefinition = { errors.xmlId.addError('message.id-unique'); } + if (has(formData, 'reloadableMetadataResolverAttributes.minRefreshDelay')) { + if (formData.reloadableMetadataResolverAttributes.minRefreshDelay === 'PT0S') { + errors.reloadableMetadataResolverAttributes.minRefreshDelay.addError('message.invalid-duration'); + } + } + + if (has(formData, 'reloadableMetadataResolverAttributes.maxRefreshDelay')) { + if (formData.reloadableMetadataResolverAttributes.maxRefreshDelay === 'PT0S') { + errors.reloadableMetadataResolverAttributes.maxRefreshDelay.addError('message.invalid-duration'); + } + } + return errors; } }, From 16e50099bc5937e2593d6b01886179d5313c3f96 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 30 Aug 2022 14:43:00 -0700 Subject: [PATCH 28/71] SHIBUI-2341 Adding capacity to handle long character descriptions --- .../admin/ui/domain/Description.java | 4 +++- .../main/resources/db/changelog/changelog.sql | 22 ++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java index db994740a..b86c86b1d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/Description.java @@ -6,6 +6,7 @@ import javax.annotation.Nullable; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.Lob; @Entity @EqualsAndHashCode(callSuper = true) @@ -16,6 +17,7 @@ public class Description extends AbstractXMLObject implements org.opensaml.saml. private String xmlLang; @Column(name = "descriptionValue") + @Lob private String value; @Nullable @@ -39,4 +41,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/resources/db/changelog/changelog.sql b/backend/src/main/resources/db/changelog/changelog.sql index 0a63846a3..f1494b2ca 100644 --- a/backend/src/main/resources/db/changelog/changelog.sql +++ b/backend/src/main/resources/db/changelog/changelog.sql @@ -175,4 +175,24 @@ 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 +update resource_backed_metadata_resolver_aud set max_refresh_delay ='PT4H'; + +-- changeset liquibase:1.13.0.1 dbms:mariadb,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 */ + +ALTER TABLE description ALTER COLUMN descriptionValue LONGTEXT; +GO +ALTER TABLE description)aud ALTER COLUMN descriptionValue LONGTEXT; +GO + +-- changeset liquibase:1.13.0.2 dbms:postgresql,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 */ + +ALTER TABLE description ALTER COLUMN descriptionValue TEXT; +GO +ALTER TABLE description_aud ALTER COLUMN descriptionValue TEXT; +GO \ No newline at end of file From b108413603eb5d4c54689f865a66775d839b3b9b Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 31 Aug 2022 11:46:08 -0700 Subject: [PATCH 29/71] Implemented download buttons --- .../main/resources/i18n/messages.properties | 16 +++++ .../app/admin/component/ConfigurationForm.js | 36 ++++++---- .../app/admin/component/PropertySelector.js | 2 +- .../app/admin/container/ConfigurationList.js | 71 +++++++++++++++++-- .../app/admin/container/EditConfiguration.js | 2 - .../app/admin/hoc/ConfigurationsProvider.js | 2 +- ui/src/app/admin/hooks.js | 8 ++- .../{download_as_xml.js => download_as.js} | 7 +- .../app/core/utility/download_as_xml.test.js | 2 +- .../app/metadata/hoc/FilterTargetPreview.js | 2 +- ui/src/app/metadata/view/MetadataXml.js | 2 +- ui/src/theme/project/forms.scss | 4 ++ 12 files changed, 123 insertions(+), 31 deletions(-) rename ui/src/app/core/utility/{download_as_xml.js => download_as.js} (54%) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 19ab8999c..816a0bf80 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -757,6 +757,22 @@ tooltip.role-description=A description of the purpose of the role. tooltip.contact-information=Add a contact to organization information. Contacts provide information about how to contact the organization responsible for standing up the entity. +tooltip.download-single-config=Putting all the properties in one file can make it easier for deploying or moving among environments. +tooltip.download-multi-config=Putting the properties into individual files will follow the distribution layout and more closely align with the Shibboleth wiki page sections describing each property. +action.download-single-config=Single file +action.download-multi-config=Separated files +label.download-config=Downloads +message.configurations-none=No configurations defined. +label.configuration-name=Name +label.configuration-name-placeholder=Enter name +label.configuration-property=Property +label.configuration-category=Category +label.configuration-type=Type +label.configuration-value=Value +label.configuration-action=Action +message.delete-property-title=Delete Configuration? +message.delete-property-body=You are requesting to delete a configuration set. If you complete this process the set will be removed. This cannot be undone. Do you wish to continue? + label.external-description=Description tooltip.external-description=A brief description of the purpose of this filter. diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 61e82dba6..87a8739dc 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -11,6 +11,7 @@ import { useProperties } from '../hoc/PropertiesProvider'; import Form from 'react-bootstrap/Form'; import FloatingLabel from 'react-bootstrap/FloatingLabel'; +import { useTranslator } from '../../i18n/hooks'; export function ConfigurationForm({ configuration = {}, loading, onSave, onCancel }) { @@ -20,7 +21,7 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance } }); - const { fields, prepend, remove } = useFieldArray({ + const { fields, append, remove } = useFieldArray({ control, name: "properties", }); @@ -36,7 +37,7 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance } }, []); - prepend(parsed); + append(parsed); }; const saveConfig = (formValues) => { @@ -44,6 +45,8 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance propertyName: p.propertyName, propertyValue: p.propertyValue, configFile: p.configFile, + category: p.category, + displayType: p.displayType })); onSave({ ...formValues, @@ -51,7 +54,7 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance }); }; - React.useEffect(() => console.log(configuration), [configuration]); + const translator = useTranslator(); return (<>
@@ -79,8 +82,8 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance
- Name - + Name +
@@ -97,11 +100,11 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance - - - - - + + + + + @@ -114,20 +117,23 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance {p.displayType !== 'boolean' ? - + label={translator('label.configuration-value')}> + : } - diff --git a/ui/src/app/admin/component/PropertySelector.js b/ui/src/app/admin/component/PropertySelector.js index 44cdfd085..976e0d220 100644 --- a/ui/src/app/admin/component/PropertySelector.js +++ b/ui/src/app/admin/component/PropertySelector.js @@ -82,7 +82,7 @@ export function PropertySelector ({ properties, options, onAddProperties }) { diff --git a/ui/src/app/admin/container/ConfigurationList.js b/ui/src/app/admin/container/ConfigurationList.js index 527f65c50..688535642 100644 --- a/ui/src/app/admin/container/ConfigurationList.js +++ b/ui/src/app/admin/container/ConfigurationList.js @@ -4,11 +4,17 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import Button from 'react-bootstrap/Button'; import ButtonGroup from 'react-bootstrap/ButtonGroup'; +import Popover from 'react-bootstrap/Popover'; import { Link } from 'react-router-dom'; import { Translate } from '../../i18n/components/translate'; import { DeleteConfirmation } from '../../core/components/DeleteConfirmation'; +import OverlayTrigger from 'react-bootstrap/esm/OverlayTrigger'; +import { useTranslator } from '../../i18n/hooks'; +import useFetch from 'use-http'; +import API_BASE_PATH from '../../App.constant'; +import { downloadAsZip } from '../../core/utility/download_as'; export function ConfigurationList({ configurations, onDelete, loading }) { @@ -16,6 +22,25 @@ export function ConfigurationList({ configurations, onDelete, loading }) { onDelete(id); } + const translate = useTranslator(); + + const downloader = useFetch(`${API_BASE_PATH}/shib/property/set`, { + cachePolicy: 'no-cache', + headers: { + 'Content-Type': 'application/zip', + 'Accept': 'application/zip' + } + }); + + const download = async (id, type) => { + await downloader.get(`/${id}${ type === 'single' ? '/onefile' : '' }`); + const file = await downloader.response.blob(); + if (downloader.response.ok) { + downloadAsZip('configuration', file); + console.log(file); + } + }; + return ( {(block) => @@ -46,7 +71,12 @@ export function ConfigurationList({ configurations, onDelete, loading }) { - + + @@ -57,17 +87,42 @@ export function ConfigurationList({ configurations, onDelete, loading }) { {c.name} + ) : - + }
PropertyCategoryTypeValueActionPropertyCategoryTypeValueAction
+
Configuration Name (label) Actions + Download + + Actions +
+
+ + + + + )} + aria-label={translate('')}> + + +
+ + + + )} + aria-label={translate('')}> + + + {downloader.loading && } +
+
-   Edit - @@ -75,7 +130,9 @@ export function ConfigurationList({ configurations, onDelete, loading }) {
No configurations. + No configurations. +
diff --git a/ui/src/app/admin/container/EditConfiguration.js b/ui/src/app/admin/container/EditConfiguration.js index bad543b69..d164c20e0 100644 --- a/ui/src/app/admin/container/EditConfiguration.js +++ b/ui/src/app/admin/container/EditConfiguration.js @@ -3,12 +3,10 @@ import React from 'react'; import { Prompt, useHistory, useParams } from 'react-router-dom'; import Translate from '../../i18n/components/translate'; import { useConfiguration } from '../hooks'; -import { Schema } from '../../form/Schema'; import { ConfigurationForm } from '../component/ConfigurationForm'; import { createNotificationAction, NotificationTypes, useNotificationDispatcher } from '../../notifications/hoc/Notifications'; import { useTranslator } from '../../i18n/hooks'; -import { BASE_PATH } from '../../App.constant'; import { PropertiesProvider } from '../hoc/PropertiesProvider'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; diff --git a/ui/src/app/admin/hoc/ConfigurationsProvider.js b/ui/src/app/admin/hoc/ConfigurationsProvider.js index aa23ddd45..2cd146260 100644 --- a/ui/src/app/admin/hoc/ConfigurationsProvider.js +++ b/ui/src/app/admin/hoc/ConfigurationsProvider.js @@ -23,7 +23,7 @@ export function ConfigurationsProvider({ children, cache = 'no-cache' }) { async function removeConfiguration(id) { let toast; - const resp = await del(`/${id}`); + const resp = await del(`shib/property/set/${id}`); if (response.ok) { loadConfigurations(); toast = createNotificationAction(`Deleted property successfully.`, NotificationTypes.SUCCESS); diff --git a/ui/src/app/admin/hooks.js b/ui/src/app/admin/hooks.js index 11184e55e..54d9d3117 100644 --- a/ui/src/app/admin/hooks.js +++ b/ui/src/app/admin/hooks.js @@ -61,4 +61,10 @@ export function useConfigurationUiSchema () { 'ui:widget': 'textarea' } }; -} \ No newline at end of file +} + +export function useConfigDownload () { + return useFetch(`${API_BASE_PATH}/shib/property/set`, { + cachePolicy: 'no-cache' + }); +} diff --git a/ui/src/app/core/utility/download_as_xml.js b/ui/src/app/core/utility/download_as.js similarity index 54% rename from ui/src/app/core/utility/download_as_xml.js rename to ui/src/app/core/utility/download_as.js index a9256fc63..4fc0cc4fd 100644 --- a/ui/src/app/core/utility/download_as_xml.js +++ b/ui/src/app/core/utility/download_as.js @@ -1,6 +1,11 @@ import * as FileSaver from 'file-saver'; +export const downloadAsZip = (fileName, data) => { + // const blob = new Blob([data], { type: 'text/zip;charset=utf-8' }); + FileSaver.saveAs(data, `${fileName}.zip`); +} + export const downloadAsXml = (fileName, xml) => { const blob = new Blob([xml], { type: 'text/xml;charset=utf-8' }); FileSaver.saveAs(blob, `${fileName}.xml`); -} \ No newline at end of file +} diff --git a/ui/src/app/core/utility/download_as_xml.test.js b/ui/src/app/core/utility/download_as_xml.test.js index 38a87e6fe..3e8583fe9 100644 --- a/ui/src/app/core/utility/download_as_xml.test.js +++ b/ui/src/app/core/utility/download_as_xml.test.js @@ -1,5 +1,5 @@ import * as FileSaver from 'file-saver'; -import { downloadAsXml } from './download_as_xml'; +import { downloadAsXml } from './download_as'; jest.mock('file-saver'); it('attempts to save the provided content', () => { diff --git a/ui/src/app/metadata/hoc/FilterTargetPreview.js b/ui/src/app/metadata/hoc/FilterTargetPreview.js index 8bd8550d3..2fd81e4c3 100644 --- a/ui/src/app/metadata/hoc/FilterTargetPreview.js +++ b/ui/src/app/metadata/hoc/FilterTargetPreview.js @@ -4,7 +4,7 @@ import { useFetch } from 'use-http'; import Modal from 'react-bootstrap/Modal'; import Button from 'react-bootstrap/Button'; import Translate from '../../i18n/components/translate'; -import { downloadAsXml } from '../../core/utility/download_as_xml'; +import { downloadAsXml } from '../../core/utility/download_as'; export function FilterTargetPreview ({ entityId, children }) { diff --git a/ui/src/app/metadata/view/MetadataXml.js b/ui/src/app/metadata/view/MetadataXml.js index 17e79d26a..fa6252cd9 100644 --- a/ui/src/app/metadata/view/MetadataXml.js +++ b/ui/src/app/metadata/view/MetadataXml.js @@ -9,7 +9,7 @@ import { MetadataObjectContext } from '../hoc/MetadataSelector'; import { MetadataXmlContext } from '../hoc/MetadataXmlLoader'; import { MetadataViewToggle } from '../component/MetadataViewToggle'; -import { downloadAsXml } from '../../core/utility/download_as_xml'; +import { downloadAsXml } from '../../core/utility/download_as'; export function MetadataXml () { const { xml, reload } = React.useContext(MetadataXmlContext); diff --git a/ui/src/theme/project/forms.scss b/ui/src/theme/project/forms.scss index b60471ce0..daa0d8cb9 100644 --- a/ui/src/theme/project/forms.scss +++ b/ui/src/theme/project/forms.scss @@ -124,6 +124,10 @@ mark { } } +.form-floating > label { + color:#9299A0; +} + @media only screen and (max-width: 1200px) { .form-section:not(:first-child) { border-left: 0px; From 12b9d1ebad5dbddf51268f01999ad9e6a3343f0d Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 31 Aug 2022 13:21:14 -0700 Subject: [PATCH 30/71] Fixed flicker in search --- .../app/admin/component/ConfigurationForm.js | 3 + .../app/admin/component/PropertySelector.js | 71 +++++++++++-------- 2 files changed, 44 insertions(+), 30 deletions(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 87a8739dc..cc13aa791 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -29,8 +29,11 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance const properties = useProperties(); const addProperties = (props) => { + const parsed = props.reduce((coll, prop, idx) => { if (prop.isCategory) { + console.log(properties.filter(p => p.category === prop.category)) + return [...coll, ...properties.filter(p => p.category === prop.category)]; } else { return [...coll, prop]; diff --git a/ui/src/app/admin/component/PropertySelector.js b/ui/src/app/admin/component/PropertySelector.js index 976e0d220..f0016e42e 100644 --- a/ui/src/app/admin/component/PropertySelector.js +++ b/ui/src/app/admin/component/PropertySelector.js @@ -1,5 +1,5 @@ import React, { Fragment, useCallback } from 'react'; -import { groupBy } from 'lodash'; +import { groupBy, orderBy } from 'lodash'; import { Highlighter, Menu, MenuItem, Token, Typeahead } from 'react-bootstrap-typeahead'; import Button from 'react-bootstrap/Button'; @@ -7,34 +7,44 @@ import { ToggleButton } from '../../form/component/ToggleButton'; export function PropertySelector ({ properties, options, onAddProperties }) { - // React.useEffect(() => console.log(properties), [properties]); - const menu = useCallback((results, menuProps, state) => { let index = 0; - const mapped = results.map(p => !p.category || p.category === '?' ? { ...p, category: 'Misc' } : p); - const grouped = groupBy(mapped, 'category'); - const items = Object.keys(grouped).sort().map((item) => ( - - {index !== 0 && } - - - {item} - Add all - - - {grouped[item].map((i) => { - const item = - p.propertyName === i.propertyName) }> - - {`- ${i.propertyName}`} - - ; - index += 1; - return item; - })} - - )); + const mapped = results.map((p, idx) => !p.category || p.category === '?' ? { ...p, category: 'Misc' } : p); + const ordered = orderBy(mapped, 'category'); + const grouped = groupBy(ordered, 'category'); + const items = Object.keys(grouped).sort().map((item) => { + index = index + 1; + const used = grouped[item].filter((i) => properties.some((p) => p.propertyName === i.propertyName)); + if (used.length >= grouped[item].length) { + return + } + return ( + + {index !== 0 && } + + + {item} - Add all + + + {grouped[item].map((i) => { + if (!properties.some((p) => p.propertyName === i.propertyName)) { + index = index + 1; + const item = + + + {`- ${i.propertyName}`} + + ; + return item; + } + return null; + })} + + ); + }); return {items}; }, [properties]); @@ -66,14 +76,15 @@ export function PropertySelector ({ properties, options, onAddProperties }) { select(selected)} - options={[...options]} + options={options} selected={selected} labelKey={option => `${option.propertyName}`} filterBy={['propertyName', 'category', 'displayType']} renderMenu={ menu } + paginate={false} multiple={ true } - renderToken={ token } - > + maxResults={options.length} + renderToken={ token }> {({ isMenuShown, toggleMenu }) => ( toggleMenu()}> Options From 5e41183e5f76368f9603064c13786b42b9580217 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 31 Aug 2022 13:37:43 -0700 Subject: [PATCH 31/71] Fixed build error --- ui/src/app/admin/container/ConfigurationList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/admin/container/ConfigurationList.js b/ui/src/app/admin/container/ConfigurationList.js index 688535642..cef6880b2 100644 --- a/ui/src/app/admin/container/ConfigurationList.js +++ b/ui/src/app/admin/container/ConfigurationList.js @@ -10,7 +10,7 @@ import { Link } from 'react-router-dom'; import { Translate } from '../../i18n/components/translate'; import { DeleteConfirmation } from '../../core/components/DeleteConfirmation'; -import OverlayTrigger from 'react-bootstrap/esm/OverlayTrigger'; +import OverlayTrigger from 'react-bootstrap/OverlayTrigger'; import { useTranslator } from '../../i18n/hooks'; import useFetch from 'use-http'; import API_BASE_PATH from '../../App.constant'; From 1e04e06830f005e1b07f05c27bc9e55378c5b5be Mon Sep 17 00:00:00 2001 From: chasegawa Date: Wed, 31 Aug 2022 16:20:10 -0700 Subject: [PATCH 32/71] SHIBUI-2341 Fixing logic to correctly import the XML --- .../ui/controller/EntityDescriptorController.java | 6 ++++-- .../admin/ui/domain/AttributeConsumingService.java | 11 ++++++++++- .../shibboleth/admin/ui/domain/SPSSODescriptor.java | 4 ++-- .../admin/ui/service/EntityDescriptorService.java | 2 ++ .../ui/service/JPAEntityDescriptorServiceImpl.java | 10 ++++++++-- .../controller/EntityDescriptorControllerTests.groovy | 8 ++++++-- testbed/postgres/docker-compose.yml | 2 ++ 7 files changed, 34 insertions(+), 9 deletions(-) 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 c2d9b81a0..a31838f1a 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,7 @@ 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.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; import lombok.extern.slf4j.Slf4j; @@ -33,6 +34,7 @@ import javax.annotation.PostConstruct; import java.net.URI; import java.util.ConcurrentModificationException; +import java.util.Optional; @RestController @RequestMapping("/api") @@ -127,8 +129,8 @@ public ResponseEntity getSpecificVersion(@PathVariable String resourceId, @Pa private ResponseEntity handleUploadingEntityDescriptorXml(byte[] rawXmlBytes, String spName) throws Exception { final EntityDescriptor ed = EntityDescriptor.class.cast(openSamlObjects.unmarshalFromXml(rawXmlBytes)); ed.setServiceProviderName(spName); - - EntityDescriptorRepresentation persistedEd = entityDescriptorService.createNew(ed); + + EntityDescriptorRepresentation persistedEd = entityDescriptorService.createNewEntityDescriptorFromXMLOrigin(ed); return ResponseEntity.created(getResourceUriFor(persistedEd.getId())).body(persistedEd); } 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 632bcb888..9adb45e2e 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 @@ -2,6 +2,7 @@ import lombok.EqualsAndHashCode; import org.hibernate.envers.Audited; +import org.opensaml.core.xml.XMLObject; import org.opensaml.core.xml.schema.XSBooleanValue; import javax.persistence.CascadeType; @@ -17,7 +18,6 @@ @EqualsAndHashCode(callSuper = true) @Audited public class AttributeConsumingService extends AbstractXMLObject implements org.opensaml.saml.saml2.metadata.AttributeConsumingService { - private int acsIndex; private boolean isDefault; @@ -93,4 +93,13 @@ public List getRequestedAtt public void setRequestedAttributes(List requestedAttributes) { this.requestedAttributes = requestedAttributes; } + + @Override + public List getOrderedChildren() { + List childXMLObjects = new ArrayList<>(); + childXMLObjects.addAll(serviceNames); + childXMLObjects.addAll(serviceDescriptions); + childXMLObjects.addAll(requestedAttributes); + return childXMLObjects; + } } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java index e90542c5a..52d37bf1f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/SPSSODescriptor.java @@ -95,7 +95,7 @@ public AssertionConsumerService getDefaultAssertionConsumerService() { @Override public List getAttributeConsumingServices() { - return Lists.newArrayList(attributeConsumingServices); + return (List)(List) attributeConsumingServices; } public void setAttributeConsumingServices(List attributeConsumingServices) { @@ -124,4 +124,4 @@ public List getOrderedChildren() { public Optional getOptionalExtensions() { return Optional.ofNullable(this.getExtensions()); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java index b2bf96ac3..ed3f7be0e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java @@ -114,4 +114,6 @@ EntityDescriptorRepresentation update(EntityDescriptorRepresentation edRepresent void updateDescriptorFromRepresentation(final org.opensaml.saml.saml2.metadata.EntityDescriptor entityDescriptor, final EntityDescriptorRepresentation representation); EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resourceId, boolean status) throws EntityNotFoundException, ForbiddenException; + + EntityDescriptorRepresentation createNewEntityDescriptorFromXMLOrigin(EntityDescriptor ed); } \ 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 f6c419b31..be79e3097 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 @@ -102,11 +102,17 @@ public EntityDescriptor createDescriptorFromRepresentation(final EntityDescripto } @Override - public EntityDescriptorRepresentation createNew(EntityDescriptor ed) - throws ForbiddenException, ObjectIdExistsException, InvalidPatternMatchException { + public EntityDescriptorRepresentation createNew(EntityDescriptor ed) throws ForbiddenException, ObjectIdExistsException, InvalidPatternMatchException { return createNew(createRepresentationFromDescriptor(ed)); } + @Override + public EntityDescriptorRepresentation createNewEntityDescriptorFromXMLOrigin(EntityDescriptor ed) { + ed.setIdOfOwner(userService.getCurrentUserGroup().getOwnerId()); + EntityDescriptor savedEntity = entityDescriptorRepository.save(ed); + return createRepresentationFromDescriptor(savedEntity); + } + @Override public EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRep) throws ForbiddenException, ObjectIdExistsException, InvalidPatternMatchException { diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy index 8861d1613..94de774b3 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy @@ -530,6 +530,11 @@ class EntityDescriptorControllerTests extends AbstractBaseDataJpaTest { urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified + + Shrink Space + Shrink Space Authenticator + + ''' @@ -551,7 +556,6 @@ class EntityDescriptorControllerTests extends AbstractBaseDataJpaTest { .andExpect(jsonPath("\$.assertionConsumerServices[0].binding").value("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")) .andExpect(jsonPath("\$.assertionConsumerServices[0].makeDefault").value(false)) .andExpect(jsonPath("\$.assertionConsumerServices[0].locationUrl").value("https://test.scaldingspoon.org/test1/acs")) - } @WithMockAdmin @@ -691,4 +695,4 @@ class EntityDescriptorControllerTests extends AbstractBaseDataJpaTest { e instanceof ConcurrentModificationException } } -} +} \ No newline at end of file diff --git a/testbed/postgres/docker-compose.yml b/testbed/postgres/docker-compose.yml index c66b591a8..1a3dd4d82 100644 --- a/testbed/postgres/docker-compose.yml +++ b/testbed/postgres/docker-compose.yml @@ -18,9 +18,11 @@ services: - 8080:8080 - 5005:5005 - 8443:8443 + - 8000:8000 volumes: - ./conf:/conf - ./conf/application.yml:/application.yml + entrypoint: ["/usr/bin/java", "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000", "-jar", "app.war"] networks: - front depends_on: From d7bed884421789be89802f8c96fab644effd1811 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Wed, 31 Aug 2022 16:38:13 -0700 Subject: [PATCH 33/71] SHIBUI-2341 Fixing logic to correctly save SurName --- .../edu/internet2/tier/shibboleth/admin/ui/domain/SurName.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b6be50f64..031dc8eec 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 @@ -18,6 +18,6 @@ public String getValue() { @Override public void setValue(String name) { - this.value = value; + this.value = name; } } \ No newline at end of file From 6ceb83276f7d32dc605fda0e6c4c618065a5b3ff Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 1 Sep 2022 13:02:46 -0700 Subject: [PATCH 34/71] Fixed issue with duplicate properties --- ui/src/app/admin/component/ConfigurationForm.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index cc13aa791..a97b1051e 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -12,6 +12,7 @@ import { useProperties } from '../hoc/PropertiesProvider'; import Form from 'react-bootstrap/Form'; import FloatingLabel from 'react-bootstrap/FloatingLabel'; import { useTranslator } from '../../i18n/hooks'; +import { includes } from 'lodash'; export function ConfigurationForm({ configuration = {}, loading, onSave, onCancel }) { @@ -27,20 +28,23 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance }); const properties = useProperties(); + const selected = watch('properties'); const addProperties = (props) => { const parsed = props.reduce((coll, prop, idx) => { if (prop.isCategory) { - console.log(properties.filter(p => p.category === prop.category)) - return [...coll, ...properties.filter(p => p.category === prop.category)]; } else { return [...coll, prop]; } }, []); - append(parsed); + const names = selected.map(p => p.propertyName); + + const filtered = parsed.filter(p => includes(names, p.propertyName) ? false : true); + + append(filtered); }; const saveConfig = (formValues) => { From cf6f47208ca02bd04a90547bb25d1206c2e2da33 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 1 Sep 2022 13:47:02 -0700 Subject: [PATCH 35/71] Fixed issue with validation on name field --- .../main/resources/i18n/messages.properties | 1 + ui/src/app/admin/IdpConfiguration.js | 13 +++++- .../app/admin/component/ConfigurationForm.js | 40 ++++++++++++++++--- .../app/admin/container/EditConfiguration.js | 3 +- .../app/admin/container/NewConfiguration.js | 3 +- .../app/admin/hoc/ConfigurationsProvider.js | 2 +- 6 files changed, 51 insertions(+), 11 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index fcdf71519..5ce496eca 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -773,6 +773,7 @@ label.configuration-value=Value label.configuration-action=Action message.delete-property-title=Delete Configuration? message.delete-property-body=You are requesting to delete a configuration set. If you complete this process the set will be removed. This cannot be undone. Do you wish to continue? +message.name-required=Name is required. label.external-description=Description diff --git a/ui/src/app/admin/IdpConfiguration.js b/ui/src/app/admin/IdpConfiguration.js index 6f774d9ea..50bacf1e6 100644 --- a/ui/src/app/admin/IdpConfiguration.js +++ b/ui/src/app/admin/IdpConfiguration.js @@ -20,10 +20,19 @@ export function IdpConfiguration() { } /> - + + {(configurations) => + + } + + } /> - + + {(configurations) => + + } + } /> diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index a97b1051e..3744a61df 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -14,12 +14,16 @@ import FloatingLabel from 'react-bootstrap/FloatingLabel'; import { useTranslator } from '../../i18n/hooks'; import { includes } from 'lodash'; -export function ConfigurationForm({ configuration = {}, loading, onSave, onCancel }) { +export function ConfigurationForm({ configurations, configuration = {}, loading, onSave, onCancel }) { - const { control, register, getValues, watch, formState: { errors } } = useForm({ + const [names, setNames] = React.useState([]); + + const { control, register, getValues, watch, formState: { errors, isValid }, handleSubmit } = useForm({ defaultValues: { ...configuration - } + }, + reValidateMode: 'onChange', + mode: 'onChange', }); const { fields, append, remove } = useFieldArray({ @@ -63,6 +67,16 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance const translator = useTranslator(); + React.useEffect(() => { + setNames(configurations.map(p => p.name)); + }, [configurations]); + + React.useEffect(() => console.log(errors, names), [errors, names]); + + const onNext = (data) => { + console.log(data); + }; + return (<>
@@ -70,7 +84,7 @@ export function ConfigurationForm({ configuration = {}, loading, onSave, onCance

-
+
Name - + !includes(names, v) + } + })} /> + + {errors?.name?.type === 'unique' && } + {errors?.name?.type === 'required' && } +
diff --git a/ui/src/app/admin/container/EditConfiguration.js b/ui/src/app/admin/container/EditConfiguration.js index d164c20e0..f3749f2a0 100644 --- a/ui/src/app/admin/container/EditConfiguration.js +++ b/ui/src/app/admin/container/EditConfiguration.js @@ -11,7 +11,7 @@ import { PropertiesProvider } from '../hoc/PropertiesProvider'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faSpinner } from '@fortawesome/free-solid-svg-icons'; -export function EditConfiguration() { +export function EditConfiguration({ configurations }) { const history = useHistory(); const notifier = useNotificationDispatcher(); const translator = useTranslator(); @@ -81,6 +81,7 @@ export function EditConfiguration() { {configuration && save(data)} onCancel={() => cancel()} /> } diff --git a/ui/src/app/admin/container/NewConfiguration.js b/ui/src/app/admin/container/NewConfiguration.js index 84477fe40..34a587b45 100644 --- a/ui/src/app/admin/container/NewConfiguration.js +++ b/ui/src/app/admin/container/NewConfiguration.js @@ -11,7 +11,7 @@ import { useTranslator } from '../../i18n/hooks'; import { BASE_PATH } from '../../App.constant'; import { PropertiesProvider } from '../hoc/PropertiesProvider'; -export function NewConfiguration() { +export function NewConfiguration({ configurations }) { const history = useHistory(); const notifier = useNotificationDispatcher(); const translator = useTranslator(); @@ -67,6 +67,7 @@ export function NewConfiguration() { {(schema) => save(data)} diff --git a/ui/src/app/admin/hoc/ConfigurationsProvider.js b/ui/src/app/admin/hoc/ConfigurationsProvider.js index 2cd146260..99220c94c 100644 --- a/ui/src/app/admin/hoc/ConfigurationsProvider.js +++ b/ui/src/app/admin/hoc/ConfigurationsProvider.js @@ -39,4 +39,4 @@ export function ConfigurationsProvider({ children, cache = 'no-cache' }) { React.useEffect(() => { loadConfigurations() }, []); return (<>{children(configurations, removeConfiguration, loading)}); -} \ No newline at end of file +} From d2d567d4a1d5e44ee7595a9f805eddc803ed6e2a Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 1 Sep 2022 13:49:02 -0700 Subject: [PATCH 36/71] Removed console log --- ui/src/app/admin/component/ConfigurationForm.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 3744a61df..49f8abb7f 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -71,11 +71,7 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, setNames(configurations.map(p => p.name)); }, [configurations]); - React.useEffect(() => console.log(errors, names), [errors, names]); - - const onNext = (data) => { - console.log(data); - }; + const onNext = (data) => {}; return (<>
From b4d56c5bfdbea5497a4fe866e8ae04e31afa0840 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 1 Sep 2022 13:58:23 -0700 Subject: [PATCH 37/71] Fixed sets without properties --- backend/src/main/resources/i18n/messages.properties | 1 + ui/src/app/admin/component/ConfigurationForm.js | 12 +++++++++++- ui/src/app/admin/component/PropertySelector.js | 3 +-- ui/src/app/admin/hoc/PropertiesProvider.js | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/backend/src/main/resources/i18n/messages.properties b/backend/src/main/resources/i18n/messages.properties index 5ce496eca..dcd97aee4 100644 --- a/backend/src/main/resources/i18n/messages.properties +++ b/backend/src/main/resources/i18n/messages.properties @@ -774,6 +774,7 @@ label.configuration-action=Action message.delete-property-title=Delete Configuration? message.delete-property-body=You are requesting to delete a configuration set. If you complete this process the set will be removed. This cannot be undone. Do you wish to continue? message.name-required=Name is required. +message.properties-none=At least one property is required. label.external-description=Description diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 49f8abb7f..90bd31db9 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -29,6 +29,9 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, const { fields, append, remove } = useFieldArray({ control, name: "properties", + rules: { + minLength: 1 + } }); const properties = useProperties(); @@ -80,7 +83,7 @@ export function ConfigurationForm({ configurations, configuration = {}, loading,
diff --git a/ui/src/app/admin/component/PropertySelector.js b/ui/src/app/admin/component/PropertySelector.js index f0016e42e..85da52888 100644 --- a/ui/src/app/admin/component/PropertySelector.js +++ b/ui/src/app/admin/component/PropertySelector.js @@ -9,8 +9,7 @@ export function PropertySelector ({ properties, options, onAddProperties }) { const menu = useCallback((results, menuProps, state) => { let index = 0; - const mapped = results.map((p, idx) => !p.category || p.category === '?' ? { ...p, category: 'Misc' } : p); - const ordered = orderBy(mapped, 'category'); + const ordered = orderBy(results, 'category'); const grouped = groupBy(ordered, 'category'); const items = Object.keys(grouped).sort().map((item) => { index = index + 1; diff --git a/ui/src/app/admin/hoc/PropertiesProvider.js b/ui/src/app/admin/hoc/PropertiesProvider.js index 95bbc5d04..5ab7bde75 100644 --- a/ui/src/app/admin/hoc/PropertiesProvider.js +++ b/ui/src/app/admin/hoc/PropertiesProvider.js @@ -30,7 +30,7 @@ function PropertiesProvider({ children, cache = 'no-cache' }) { function useProperties() { const { properties } = React.useContext(PropertiesContext); - return properties; + return properties.map((p, idx) => !p.category || p.category === '?' ? { ...p, category: 'Misc' } : p);; } function usePropertiesLoading() { From b0ff7e20db1a0cafc28834cf90d9ef98bc2cc134 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 1 Sep 2022 14:43:14 -0700 Subject: [PATCH 38/71] Updated text for notifications --- ui/src/app/admin/component/PropertySelector.js | 4 ++-- ui/src/app/admin/container/EditConfiguration.js | 2 +- ui/src/app/admin/container/NewConfiguration.js | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/src/app/admin/component/PropertySelector.js b/ui/src/app/admin/component/PropertySelector.js index 85da52888..375b75747 100644 --- a/ui/src/app/admin/component/PropertySelector.js +++ b/ui/src/app/admin/component/PropertySelector.js @@ -11,11 +11,11 @@ export function PropertySelector ({ properties, options, onAddProperties }) { let index = 0; const ordered = orderBy(results, 'category'); const grouped = groupBy(ordered, 'category'); - const items = Object.keys(grouped).sort().map((item) => { + const items = Object.keys(grouped).sort().map((item, idx) => { index = index + 1; const used = grouped[item].filter((i) => properties.some((p) => p.propertyName === i.propertyName)); if (used.length >= grouped[item].length) { - return + return } return ( diff --git a/ui/src/app/admin/container/EditConfiguration.js b/ui/src/app/admin/container/EditConfiguration.js index f3749f2a0..dfa90aa8e 100644 --- a/ui/src/app/admin/container/EditConfiguration.js +++ b/ui/src/app/admin/container/EditConfiguration.js @@ -28,7 +28,7 @@ export function EditConfiguration({ configurations }) { const resp = await put(`${config.resourceId}`, config); if (response.ok) { gotoList({ refresh: true }); - toast = createNotificationAction(`Added property successfully.`, NotificationTypes.SUCCESS); + toast = createNotificationAction(`Updated configuration successfully.`, NotificationTypes.SUCCESS); } else { toast = createNotificationAction(`${resp.errorCode} - ${translator(resp.errorMessage)}`, NotificationTypes.ERROR); } diff --git a/ui/src/app/admin/container/NewConfiguration.js b/ui/src/app/admin/container/NewConfiguration.js index 34a587b45..d9a1bf33c 100644 --- a/ui/src/app/admin/container/NewConfiguration.js +++ b/ui/src/app/admin/container/NewConfiguration.js @@ -25,7 +25,7 @@ export function NewConfiguration({ configurations }) { const resp = await post(``, config); if (response.ok) { gotoList({ refresh: true }); - toast = createNotificationAction(`Added property successfully.`, NotificationTypes.SUCCESS); + toast = createNotificationAction(`Added configuration successfully.`, NotificationTypes.SUCCESS); } else { toast = createNotificationAction(`${resp.errorCode} - ${translator(resp.errorMessage)}`, NotificationTypes.ERROR); } From 7eead4a72b75a71aac6c4308b1f15c5ce62d2a4f Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 2 Sep 2022 10:00:34 -0700 Subject: [PATCH 39/71] SHIBUI-2270 / SHIBUI-2373 Fixing output JSON for the UI so type values are correct --- .../shib/properties/ShibPropertySetting.java | 2 + .../ShibPropertySettingJacksonSerializer.java | 43 +++++++++++++ .../ShibPropertiesControllerTests.groovy | 60 +++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java index 1fd4d73fd..aeb1bd579 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySetting.java @@ -1,5 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; import lombok.Data; import org.hibernate.envers.Audited; @@ -12,6 +13,7 @@ @Entity(name = "shib_property_setting") @Audited @Data +@JsonSerialize(using = ShibPropertySettingJacksonSerializer.class) public class ShibPropertySetting { @Id @GeneratedValue diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java new file mode 100644 index 000000000..6bd5b926c --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java @@ -0,0 +1,43 @@ +package edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +import java.io.IOException; + +public class ShibPropertySettingJacksonSerializer extends StdSerializer { + public ShibPropertySettingJacksonSerializer() { + this(null); + } + + public ShibPropertySettingJacksonSerializer(Class t) { + super(t); + } + + @Override + public void serialize(ShibPropertySetting sps, JsonGenerator generator, SerializerProvider provider) throws IOException { + generator.writeStartObject(); + generator.writeNumberField("resourceId", sps.getResourceId()); + generator.writeStringField("configFile", sps.getConfigFile()); + generator.writeStringField("propertyName", sps.getPropertyName()); + if (sps.getCategory() != null) { + generator.writeStringField("category", sps.getCategory()); + } + generator.writeStringField("displayType", sps.getDisplayType()); + + switch (sps.getDisplayType()) { + case "boolean": + generator.writeBooleanField("propertyValue", Boolean.valueOf(sps.getPropertyValue())); + break; + case "number": + generator.writeNumberField("propertyValue", Long.parseLong(sps.getPropertyValue())); + break; + default: + generator.writeStringField("propertyValue", sps.getPropertyValue()); + } + + generator.writeEndObject(); + } + +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy index e5c418f9d..c5ab4a003 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy @@ -63,6 +63,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { it.propertyName = 'foo' it.configFile = 'defaults.properties' it.propertyValue = 'bar' + it.displayType = 'string' it } @@ -71,6 +72,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { it.propertyName = 'foo2' it.configFile = 'defaults.properties' it.propertyValue = 'bar2' + it.displayType = 'string' it } @@ -151,6 +153,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { it.propertyName = 'food.for.thought' it.configFile = 'defaults.properties' it.propertyValue = 'true' + it.displayType = 'boolean' it } @@ -158,6 +161,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { it.propertyName = 'food2.for2.thought' it.configFile = 'defaults.properties' it.propertyValue = 'true' + it.displayType = 'boolean' it } @@ -207,4 +211,60 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { result.andExpect(status().isOk()).andExpect(jsonPath("\$.name").value("newName")) propertySetRepo.findByResourceId(defaultSetResourceId).name.equals("newName") } + + @WithMockAdmin + def "Validate that JSON data is correct for UI"() { + given: + ShibPropertySetting prop = new ShibPropertySetting().with { it -> + it.propertyName = 'asBoolean' + it.configFile = 'defaults.properties' + it.propertyValue = 'true' + it.displayType = 'boolean' + + it + } + propertySettingRepo.save(prop) + ShibPropertySetting prop2 = new ShibPropertySetting().with { it -> + it.propertyName = 'asNumber' + it.configFile = 'defaults.properties' + it.propertyValue = '33' + it.displayType = 'number' + + it + } + propertySettingRepo.save(prop2) + ShibPropertySetting prop3 = new ShibPropertySetting().with { it -> + it.propertyName = 'anythingElse' + it.configFile = 'defaults.properties' + it.propertyValue = '33' + it.displayType = 'string' + + it + } + propertySettingRepo.save(prop3) + ShibPropertySet set = new ShibPropertySet().with {it -> + it.properties.add(prop) + it.properties.add(prop2) + it.properties.add(prop3) + it.name = 'somerandom' + + it + } + def savedSet = propertySetRepo.save(set) + entityManager.flush() + entityManager.clear() + + when: + def result = mockMvc.perform(get("/api/shib/property/set/" + savedSet.getResourceId())) + System.println(result.andReturn().getResponse().getContentAsString()) + then: + result.andExpect(status().isOk()) + .andExpect(jsonPath("\$.resourceId").value(savedSet.getResourceId())) + .andExpect(jsonPath("\$.properties[0].propertyName").value("asBoolean")) + .andExpect(jsonPath("\$.properties[0].propertyValue").value(Boolean.TRUE)) + .andExpect(jsonPath("\$.properties[1].propertyName").value("asNumber")) + .andExpect(jsonPath("\$.properties[1].propertyValue").value(33)) + .andExpect(jsonPath("\$.properties[2].propertyName").value("anythingElse")) + .andExpect(jsonPath("\$.properties[2].propertyValue").value("33")) + } } \ No newline at end of file From f011dca576be2189f2c9745b70ddf07ddb370f4e Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 2 Sep 2022 10:15:53 -0700 Subject: [PATCH 40/71] SHIBUI-2374 Added logic so that entities with the same entity id won't be created. --- .../admin/ui/controller/EntityDescriptorController.java | 4 ++++ .../admin/ui/service/EntityDescriptorService.java | 2 ++ .../admin/ui/service/JPAEntityDescriptorServiceImpl.java | 5 +++++ .../ui/controller/EntityDescriptorControllerTests.groovy | 7 +++++++ 4 files changed, 18 insertions(+) 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 a31838f1a..81d62a1ad 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 @@ -128,6 +128,10 @@ public ResponseEntity getSpecificVersion(@PathVariable String resourceId, @Pa private ResponseEntity handleUploadingEntityDescriptorXml(byte[] rawXmlBytes, String spName) throws Exception { final EntityDescriptor ed = EntityDescriptor.class.cast(openSamlObjects.unmarshalFromXml(rawXmlBytes)); + if (entityDescriptorService.entityExists(ed.getEntityID())) { + throw new ObjectIdExistsException("Entity with ID: " + ed.getEntityID() + "exists"); + } + ed.setServiceProviderName(spName); EntityDescriptorRepresentation persistedEd = entityDescriptorService.createNewEntityDescriptorFromXMLOrigin(ed); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java index ed3f7be0e..6ecf9073e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java @@ -116,4 +116,6 @@ EntityDescriptorRepresentation update(EntityDescriptorRepresentation edRepresent EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resourceId, boolean status) throws EntityNotFoundException, ForbiddenException; EntityDescriptorRepresentation createNewEntityDescriptorFromXMLOrigin(EntityDescriptor ed); + + boolean entityExists(String entityID); } \ 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 be79e3097..ec5c28048 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 @@ -113,6 +113,11 @@ public EntityDescriptorRepresentation createNewEntityDescriptorFromXMLOrigin(Ent return createRepresentationFromDescriptor(savedEntity); } + @Override + public boolean entityExists(String entityID) { + return entityDescriptorRepository.findByEntityID(entityID) != null ; + } + @Override public EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRep) throws ForbiddenException, ObjectIdExistsException, InvalidPatternMatchException { diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy index 94de774b3..35bd77ea2 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy @@ -556,6 +556,13 @@ class EntityDescriptorControllerTests extends AbstractBaseDataJpaTest { .andExpect(jsonPath("\$.assertionConsumerServices[0].binding").value("urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST")) .andExpect(jsonPath("\$.assertionConsumerServices[0].makeDefault").value(false)) .andExpect(jsonPath("\$.assertionConsumerServices[0].locationUrl").value("https://test.scaldingspoon.org/test1/acs")) + + try { + mockMvc.perform(post("/api/EntityDescriptor").contentType(APPLICATION_XML).content(postedBody).param("spName", spName)) + } + catch (Exception e) { + e instanceof ObjectIdExistsException + } } @WithMockAdmin From be32e8644d805e9ebc1650877fe655a07876028f Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 2 Sep 2022 10:49:47 -0700 Subject: [PATCH 41/71] SHIBUI-2270 fixed broken test --- .../ui/service/ShibConfigurationServiceTests.groovy | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceTests.groovy index 36f548215..4454ef8ca 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceTests.groovy @@ -30,7 +30,7 @@ class ShibConfigurationServiceTests extends AbstractBaseDataJpaTest { * We use the object mapper to transform to json and then back to new objects so that what we send to the service is never * the actual hibernate entity from the db, but an unattached copy (ie what the service would be getting as input in reality) */ - def ObjectMapper objectMapper = new ObjectMapper(); + ObjectMapper objectMapper = new ObjectMapper() @Transactional def setup() { @@ -38,6 +38,7 @@ class ShibConfigurationServiceTests extends AbstractBaseDataJpaTest { it.propertyName = 'foo' it.configFile = 'defaults.properties' it.propertyValue = 'bar' + it.displayType = 'string' it } @@ -46,6 +47,7 @@ class ShibConfigurationServiceTests extends AbstractBaseDataJpaTest { it.propertyName = 'foo2' it.configFile = 'defaults.properties' it.propertyValue = 'bar2' + it.displayType = 'string' it } @@ -68,8 +70,8 @@ class ShibConfigurationServiceTests extends AbstractBaseDataJpaTest { def "check delete"() { given: - def long setCount = propertySetRepo.count() - def long propsCount = propertySettingRepo.count() + long setCount = propertySetRepo.count() + long propsCount = propertySettingRepo.count() expect: setCount == 1 @@ -120,6 +122,7 @@ class ShibConfigurationServiceTests extends AbstractBaseDataJpaTest { it.propertyName = 'food.for.thought' it.configFile = 'defaults.properties' it.propertyValue = 'true' + it.displayType = 'boolean' it } From 31ef5a3ba07b552c96f7c4af4377d4f84c5881ee Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 2 Sep 2022 11:06:28 -0700 Subject: [PATCH 42/71] Fixed x mark in dropdown --- ui/src/theme/project/typeahead.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/theme/project/typeahead.scss b/ui/src/theme/project/typeahead.scss index 0fca115fa..5bf91a8ca 100644 --- a/ui/src/theme/project/typeahead.scss +++ b/ui/src/theme/project/typeahead.scss @@ -35,7 +35,7 @@ height: 1em; padding: .25em .25em; color: inherit; - background: transparent url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='#007bff' %3e%3cpath d='M.293.293a1 1 0 0 1 1.414 0L8 6.586 14.293.293a1 1 0 1 1 1.414 1.414L9.414 8l6.293 6.293a1 1 0 0 1-1.414 1.414L8 9.414l-6.293 6.293a1 1 0 0 1-1.414-1.414L6.586 8 .293 1.707a1 1 0 0 1 0-1.414z'/%3e%3c/svg%3e") center/1em auto no-repeat; + background: transparent center/1em auto no-repeat; border: 0; border-radius: .375rem; } From 8ed3fe3b52c1f6359873a5c661d789ed55b93c83 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 2 Sep 2022 12:19:42 -0700 Subject: [PATCH 43/71] Fixed issue with validation of set names --- ui/src/app/admin/component/ConfigurationForm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 90bd31db9..e4088f98d 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -110,8 +110,9 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, placeholder={translator('label.configuration-name-placeholder')} {...register(`name`, { required: true, + value: configuration.value || null, validate: { - unique: v => !includes(names, v) + unique: v => v.trim() === configuration.name || !includes(names, v) } })} /> From c2cb961b9cd5f8629c4e22168d78491779febbf8 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 2 Sep 2022 12:34:15 -0700 Subject: [PATCH 44/71] Fixed issue with duplicated properties from categories --- .../app/admin/component/PropertySelector.js | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/ui/src/app/admin/component/PropertySelector.js b/ui/src/app/admin/component/PropertySelector.js index 375b75747..9f219e403 100644 --- a/ui/src/app/admin/component/PropertySelector.js +++ b/ui/src/app/admin/component/PropertySelector.js @@ -1,11 +1,12 @@ import React, { Fragment, useCallback } from 'react'; -import { groupBy, orderBy } from 'lodash'; +import { groupBy, includes, orderBy } from 'lodash'; import { Highlighter, Menu, MenuItem, Token, Typeahead } from 'react-bootstrap-typeahead'; import Button from 'react-bootstrap/Button'; import { ToggleButton } from '../../form/component/ToggleButton'; export function PropertySelector ({ properties, options, onAddProperties }) { + const [selected, setSelected] = React.useState([]); const menu = useCallback((results, menuProps, state) => { let index = 0; @@ -14,17 +15,20 @@ export function PropertySelector ({ properties, options, onAddProperties }) { const items = Object.keys(grouped).sort().map((item, idx) => { index = index + 1; const used = grouped[item].filter((i) => properties.some((p) => p.propertyName === i.propertyName)); - if (used.length >= grouped[item].length) { + if (used.length >= grouped[item].length || includes(selected, item)) { return } + const cat = {category: item, propertyName: item, isCategory: true}; + const catSelected = selected.some(s => s.propertyName === item); return ( {index !== 0 && } + className="fw-bold" + disabled={catSelected}> {item} - Add all @@ -32,7 +36,7 @@ export function PropertySelector ({ properties, options, onAddProperties }) { if (!properties.some((p) => p.propertyName === i.propertyName)) { index = index + 1; const item = - + s.propertyName === i.propertyName)}> {`- ${i.propertyName}`} @@ -46,7 +50,7 @@ export function PropertySelector ({ properties, options, onAddProperties }) { }); return {items}; - }, [properties]); + }, [properties, selected]); const token = (option, { onRemove }, index) => ( { onAddProperties(s); setSelected([]); - } + }; return ( From 5197db034398b0e671b6a98b9d6c5132cc450eff Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Tue, 6 Sep 2022 09:50:20 -0700 Subject: [PATCH 45/71] Fixed issue with duplicate properties --- ui/src/app/admin/component/ConfigurationForm.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index e4088f98d..751e94310 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -12,7 +12,7 @@ import { useProperties } from '../hoc/PropertiesProvider'; import Form from 'react-bootstrap/Form'; import FloatingLabel from 'react-bootstrap/FloatingLabel'; import { useTranslator } from '../../i18n/hooks'; -import { includes } from 'lodash'; +import { includes, uniqBy } from 'lodash'; export function ConfigurationForm({ configurations, configuration = {}, loading, onSave, onCancel }) { @@ -51,7 +51,9 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, const filtered = parsed.filter(p => includes(names, p.propertyName) ? false : true); - append(filtered); + const deduped = uniqBy(filtered, (i) => i.propertyName); + + append(deduped); }; const saveConfig = (formValues) => { From 47168290b9da41b946f1b2457e385f904993544d Mon Sep 17 00:00:00 2001 From: chasegawa Date: Tue, 6 Sep 2022 13:32:44 -0700 Subject: [PATCH 46/71] SHIBUI-2270 Added cleanup of settings to the danger controller --- .../admin/ui/controller/DangerController.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DangerController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DangerController.java index 2ab357a03..7af217eb2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DangerController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/DangerController.java @@ -7,6 +7,8 @@ import edu.internet2.tier.shibboleth.admin.ui.repository.FilterRepository; 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.repository.ShibPropertySetRepository; +import edu.internet2.tier.shibboleth.admin.ui.repository.ShibPropertySettingRepository; import edu.internet2.tier.shibboleth.admin.ui.security.repository.GroupsRepository; import edu.internet2.tier.shibboleth.admin.ui.security.repository.OwnershipRepository; import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; @@ -59,6 +61,12 @@ public class DangerController { @Autowired private OwnershipRepository ownershipRepository; + @Autowired + private ShibPropertySetRepository shibPropertySetRepository; + + @Autowired + private ShibPropertySettingRepository shibPropertySettingRepository; + @Autowired UserRepository userRepository; @@ -84,9 +92,18 @@ public ResponseEntity wipeOut() { clearUsersAndGroups(); + clearShibSettings(); + return ResponseEntity.ok("yes, you did it"); } + private void clearShibSettings() { + shibPropertySetRepository.findAll().forEach(shibPropSet -> { + shibPropertySettingRepository.deleteAll(shibPropSet.getProperties()); + shibPropertySetRepository.delete(shibPropSet); + }); + } + private void clearUsersAndGroups() { groupRepository.deleteAll(); ownershipRepository.clearAllOwnedByGroup(); @@ -99,4 +116,4 @@ private void clearUsersAndGroups() { groupService.ensureAdminGroupExists(); devConfig.createDevUsersAndGroups(); } -} +} \ No newline at end of file From 4e96769041300d8aa97f4f54f833ca5e5664efde Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Wed, 7 Sep 2022 10:29:50 -0400 Subject: [PATCH 47/71] SHIBUI-2270 Added selenium tests for properties CRUD operations. --- .../admin/ui/SeleniumSIDETest.groovy | 2 + .../integration/resources/SHIBUI-2270-1.side | 562 +++++ .../integration/resources/SHIBUI-2270-2.side | 2143 +++++++++++++++++ 3 files changed, 2707 insertions(+) create mode 100644 backend/src/integration/resources/SHIBUI-2270-1.side create mode 100644 backend/src/integration/resources/SHIBUI-2270-2.side 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 beb593a70..4a903610e 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 @@ -157,6 +157,8 @@ class SeleniumSIDETest extends Specification { 'SHIBUI-1674: Verify metadata source tooltips' | '/SHIBUI-1674-1.side' 'SHIBUI-1674: Verify metadata provider tooltips' | '/SHIBUI-1674-2.side' 'SHIBUI-1674: Verify advanced menu tooltips' | '/SHIBUI-1674-3.side' + 'SHIBUI-2270: Verify property set CRUD' | '/SHIBUI-2270-1.side' + 'SHIBUI-2270: Verify full property set' | '/SHIBUI-2270-2.side' 'SHIBUI-2268: Verify Algorithm Filter' | '/SHIBUI-2268.side' 'SHIBUI-2269: Verify XML generation of external filters' | '/SHIBUI-2269.side' } diff --git a/backend/src/integration/resources/SHIBUI-2270-1.side b/backend/src/integration/resources/SHIBUI-2270-1.side new file mode 100644 index 000000000..b9d67cff4 --- /dev/null +++ b/backend/src/integration/resources/SHIBUI-2270-1.side @@ -0,0 +1,562 @@ +{ + "id": "1b31a551-eb09-4bd4-8db9-694bf1539a46", + "version": "2.0", + "name": "SHIBUI-2270-1", + "url": "http://localhost:10101", + "tests": [{ + "id": "841ade0e-83bd-4a4b-94f2-de6bd5c536b2", + "name": "SHIBUI-2270-1", + "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": "d388e4d3-79b7-4948-a6f6-907d0a46f35c", + "comment": "", + "command": "click", + "target": "id=advanced-nav-dropdown-toggle", + "targets": [ + ["id=advanced-nav-dropdown-toggle", "id"], + ["css=#advanced-nav-dropdown-toggle", "css:finder"], + ["xpath=//button[@id='advanced-nav-dropdown-toggle']", "xpath:attributes"], + ["xpath=//div[@id='advanced-nav-dropdown']/button", "xpath:idRelative"], + ["xpath=//div[3]/button", "xpath:position"], + ["xpath=//button[contains(.,'Advanced')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "14841cc4-c8f1-48c2-9f85-a7aaf9f0a91d", + "comment": "", + "command": "click", + "target": "id=advanced-nav-dropdown-properties", + "targets": [ + ["id=advanced-nav-dropdown-properties", "id"], + ["linkText=Shibboleth configurations", "linkText"], + ["css=#advanced-nav-dropdown-properties", "css:finder"], + ["xpath=//a[contains(text(),'Shibboleth configurations')]", "xpath:link"], + ["xpath=//a[@id='advanced-nav-dropdown-properties']", "xpath:attributes"], + ["xpath=//div[@id='advanced-nav-dropdown']/div/a[5]", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/configurations')]", "xpath:href"], + ["xpath=//a[5]", "xpath:position"], + ["xpath=//a[contains(.,'Shibboleth configurations')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "8a824b21-89be-4531-baa3-db217375dfb1", + "comment": "", + "command": "click", + "target": "linkText=Create Shibboleth configuration set", + "targets": [ + ["linkText=Create Shibboleth configuration set", "linkText"], + ["css=.btn-success", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/configurations/new')]", "xpath:href"], + ["xpath=//div[2]/div/a", "xpath:position"], + ["xpath=//a[contains(.,'  Create Shibboleth configuration set')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "da25d3be-ebb4-4ad7-8264-dfb688ef157d", + "comment": "", + "command": "type", + "target": "id=formName", + "targets": [ + ["id=formName", "id"], + ["name=name", "name"], + ["css=#formName", "css:finder"], + ["xpath=//input[@id='formName']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "Test Configuration" + }, { + "id": "7d40119c-c87f-4743-bdfb-3368f556ce89", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div/div/div/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "a9ae0330-b553-49d6-aafd-0566d6ef8015", + "comment": "", + "command": "click", + "target": "id=property-selector-item-2", + "targets": [ + ["id=property-selector-item-2", "id"], + ["linkText=- idp.resolvertest.accessPolicy", "linkText"], + ["css=#property-selector-item-2", "css:finder"], + ["xpath=//a[contains(text(),'- idp.resolvertest.accessPolicy')]", "xpath:link"], + ["xpath=//a[@id='property-selector-item-2']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[2]", "xpath:href"], + ["xpath=//div[2]/div/div/div/div/div[2]/a", "xpath:position"], + ["xpath=//a[contains(.,'- idp.resolvertest.accessPolicy')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "e9a4a85f-b6bb-4d3a-9042-4d873c3b6cc6", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "e4bc2487-9f04-45ee-b6ac-dd2b0de2b54e", + "comment": "", + "command": "click", + "target": "id=property-selector-item-10", + "targets": [ + ["id=property-selector-item-10", "id"], + ["linkText=- idp.lockout.defaultAuthenticationMethods", "linkText"], + ["css=#property-selector-item-10", "css:finder"], + ["xpath=//a[contains(text(),'- idp.lockout.defaultAuthenticationMethods')]", "xpath:link"], + ["xpath=//a[@id='property-selector-item-10']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/a[8]", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[10]", "xpath:href"], + ["xpath=//a[8]", "xpath:position"], + ["xpath=//a[contains(.,'- idp.lockout.defaultAuthenticationMethods')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "1384295d-fed8-42f4-9651-27a900fbb2ac", + "comment": "", + "command": "click", + "target": "css=.ms-2", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[10]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" + }, { + "id": "e90d0c3a-ef37-4c83-a7d1-1fc053e6404c", + "comment": "", + "command": "type", + "target": "id=valueInput-idp.resolvertest.accessPolicy", + "targets": [ + ["id=valueInput-idp.resolvertest.accessPolicy", "id"], + ["name=properties.0.propertyValue", "name"], + ["css=#valueInput-idp\\.resolvertest\\.accessPolicy", "css:finder"], + ["xpath=//input[@id='valueInput-idp.resolvertest.accessPolicy']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr/td[4]/div/input", "xpath:idRelative"], + ["xpath=//td[4]/div/input", "xpath:position"] + ], + "value": "test1" + }, { + "id": "fa61e81b-309a-4e32-b5ce-61f7dcd06eb3", + "comment": "", + "command": "type", + "target": "id=valueInput-idp.lockout.defaultAuthenticationMethods", + "targets": [ + ["id=valueInput-idp.lockout.defaultAuthenticationMethods", "id"], + ["name=properties.1.propertyValue", "name"], + ["css=#valueInput-idp\\.lockout\\.defaultAuthenticationMethods", "css:finder"], + ["xpath=//input[@id='valueInput-idp.lockout.defaultAuthenticationMethods']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[2]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] + ], + "value": "test2" + }, { + "id": "18d127f8-a5b9-4634-bf44-d4432fe4122d", + "comment": "", + "command": "click", + "target": "css=tr:nth-child(2) .svg-inline--fa", + "targets": [ + ["css=tr:nth-child(2) .svg-inline--fa", "css:finder"] + ], + "value": "" + }, { + "id": "63f4e5a3-8846-4d80-8c42-3d1f5d8ec5c9", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div/div/div/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "420da5f7-5e5d-46c9-b58c-ff33e51bcd04", + "comment": "", + "command": "click", + "target": "id=property-selector-item-10", + "targets": [ + ["id=property-selector-item-10", "id"], + ["linkText=- idp.lockout.defaultAuthenticationMethods", "linkText"], + ["css=#property-selector-item-10", "css:finder"], + ["xpath=//a[contains(text(),'- idp.lockout.defaultAuthenticationMethods')]", "xpath:link"], + ["xpath=//a[@id='property-selector-item-10']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/a[8]", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[10]", "xpath:href"], + ["xpath=//a[8]", "xpath:position"], + ["xpath=//a[contains(.,'- idp.lockout.defaultAuthenticationMethods')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f54f3946-a1f5-4392-99c0-0e1ce5958993", + "comment": "", + "command": "click", + "target": "css=.ms-2", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" + }, { + "id": "7206299c-901e-4273-86f2-7f14002ff78b", + "comment": "", + "command": "type", + "target": "id=valueInput-idp.lockout.defaultAuthenticationMethods", + "targets": [ + ["id=valueInput-idp.lockout.defaultAuthenticationMethods", "id"], + ["name=properties.1.propertyValue", "name"], + ["css=#valueInput-idp\\.lockout\\.defaultAuthenticationMethods", "css:finder"], + ["xpath=//input[@id='valueInput-idp.lockout.defaultAuthenticationMethods']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[2]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] + ], + "value": "test3" + }, { + "id": "23de6d39-9745-47a5-a3e1-84c0fb35d1e1", + "comment": "", + "command": "click", + "target": "css=.btn-info", + "targets": [ + ["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": "" + }, { + "id": "dfaa87c9-7a0b-445d-aa7a-942bc73d2f02", + "comment": "", + "command": "click", + "target": "linkText=Edit", + "targets": [ + ["linkText=Edit", "linkText"], + ["css=.btn-primary", "css:finder"], + ["xpath=//a[contains(text(),'Edit')]", "xpath:link"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/div/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '/configurations/28/edit')])[2]", "xpath:href"], + ["xpath=//td[3]/div/a", "xpath:position"], + ["xpath=//a[contains(.,'  Edit')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ed029697-17af-4ca6-9299-862ba5c43864", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div/div/div/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "9b66c662-75a5-4ad8-9e19-ebe65905a108", + "comment": "", + "command": "click", + "target": "id=property-selector-item-58", + "targets": [ + ["id=property-selector-item-58", "id"], + ["linkText=- idp.csrf.token.parameter", "linkText"], + ["css=#property-selector-item-58", "css:finder"], + ["xpath=//a[contains(text(),'- idp.csrf.token.parameter')]", "xpath:link"], + ["xpath=//a[@id='property-selector-item-58']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/a[51]", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[58]", "xpath:href"], + ["xpath=//a[51]", "xpath:position"], + ["xpath=//a[contains(.,'- idp.csrf.token.parameter')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "2c2ccf47-4386-4e3d-8a2b-0b3e183462a7", + "comment": "", + "command": "click", + "target": "css=.ms-2", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" + }, { + "id": "e5a94855-f4c7-404c-8fa6-06c19f0f16f6", + "comment": "", + "command": "type", + "target": "id=valueInput-idp.csrf.token.parameter", + "targets": [ + ["id=valueInput-idp.csrf.token.parameter", "id"], + ["name=properties.2.propertyValue", "name"], + ["css=#valueInput-idp\\.csrf\\.token\\.parameter", "css:finder"], + ["xpath=//input[@id='valueInput-idp.csrf.token.parameter']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[3]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[3]/td[4]/div/input", "xpath:position"] + ], + "value": "test4" + }, { + "id": "4e763745-940a-410b-9e49-89483a0927fd", + "comment": "", + "command": "click", + "target": "css=.btn-info", + "targets": [ + ["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": "" + }, { + "id": "137da111-edeb-4e27-a9f0-8b00d8f44e9f", + "comment": "", + "command": "click", + "target": "linkText=Create Shibboleth configuration set", + "targets": [ + ["linkText=Create Shibboleth configuration set", "linkText"], + ["css=.btn-success", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/configurations/new')]", "xpath:href"], + ["xpath=//div[2]/div/a", "xpath:position"], + ["xpath=//a[contains(.,'  Create Shibboleth configuration set')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "3348ed8d-812e-46cc-bfb4-bc751893291a", + "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/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a74652db-1910-473f-8f3a-7c955182895d", + "comment": "", + "command": "click", + "target": "id=property-selector-item-17", + "targets": [ + ["id=property-selector-item-17", "id"], + ["linkText=AttendedRestartConfiguration - Add all", "linkText"], + ["css=#property-selector-item-17", "css:finder"], + ["xpath=//a[@id='property-selector-item-17']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[6]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[17]", "xpath:href"], + ["xpath=//div[6]/a", "xpath:position"], + ["xpath=//a[contains(.,'AttendedRestartConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a7279237-b6c7-47ca-a16b-145405569c44", + "comment": "", + "command": "type", + "target": "id=formName", + "targets": [ + ["id=formName", "id"], + ["name=name", "name"], + ["css=#formName", "css:finder"], + ["xpath=//input[@id='formName']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "Test Configuration 2" + }, { + "id": "eadfb399-b11f-46d1-a665-a526a53f90b0", + "comment": "", + "command": "click", + "target": "css=.ms-2", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" + }, { + "id": "309348c8-22c7-4ff6-90c2-43a0aa2c68cc", + "comment": "", + "command": "assertText", + "target": "css=tr:nth-child(7) > td:nth-child(1)", + "targets": [ + ["css=tr:nth-child(7) > td:nth-child(1)", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[7]/td", "xpath:idRelative"], + ["xpath=//tr[7]/td", "xpath:position"], + ["xpath=//td[contains(.,'idp.unlock-keys.authenticated')]", "xpath:innerText"] + ], + "value": "idp.unlock-keys.authenticated" + }, { + "id": "2be9a988-be21-4258-9c8f-21928e860a24", + "comment": "", + "command": "click", + "target": "css=.fa-floppy-disk > path", + "targets": [ + ["css=.fa-floppy-disk > path", "css:finder"] + ], + "value": "" + }, { + "id": "728c88fd-020a-49dc-a979-ba123f7ed53a", + "comment": "", + "command": "click", + "target": "css=tr:nth-child(1) .btn-danger", + "targets": [ + ["css=tr:nth-child(1) .btn-danger", "css:finder"], + ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/div/button", "xpath:idRelative"], + ["xpath=//td[3]/div/button", "xpath:position"], + ["xpath=//button[contains(.,'  Delete')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "9c03d978-0d3b-4590-af7e-3b024c699e15", + "comment": "", + "command": "click", + "target": "css=.btn-danger:nth-child(1)", + "targets": [ + ["css=.btn-danger:nth-child(1)", "css:finder"], + ["xpath=(//button[@type='button'])[11]", "xpath:attributes"], + ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] + ], + "value": "" + }, { + "id": "a8a0060c-a5d9-4597-ba57-f390073fc98b", + "comment": "", + "command": "click", + "target": "css=.btn-danger", + "targets": [ + ["css=.btn-danger", "css:finder"], + ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/div/button", "xpath:idRelative"], + ["xpath=//td[3]/div/button", "xpath:position"], + ["xpath=//button[contains(.,'  Delete')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "7dc604df-8358-43bb-9401-49717be23ac6", + "comment": "", + "command": "click", + "target": "css=.btn-danger:nth-child(1)", + "targets": [ + ["css=.btn-danger:nth-child(1)", "css:finder"], + ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], + ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] + ], + "value": "" + }, { + "id": "e339a2e6-6e87-4a37-899c-8f7e9e309866", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "7e35b427-036a-49f6-a9f2-b31bc916490c", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] + }], + "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-2270-2.side b/backend/src/integration/resources/SHIBUI-2270-2.side new file mode 100644 index 000000000..2872ad331 --- /dev/null +++ b/backend/src/integration/resources/SHIBUI-2270-2.side @@ -0,0 +1,2143 @@ +{ + "id": "1b31a551-eb09-4bd4-8db9-694bf1539a46", + "version": "2.0", + "name": "SHIBUI-2270-2", + "url": "http://localhost:10101", + "tests": [{ + "id": "841ade0e-83bd-4a4b-94f2-de6bd5c536b2", + "name": "SHIBUI-2270-2", + "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": "d388e4d3-79b7-4948-a6f6-907d0a46f35c", + "comment": "", + "command": "click", + "target": "id=advanced-nav-dropdown-toggle", + "targets": [ + ["id=advanced-nav-dropdown-toggle", "id"], + ["css=#advanced-nav-dropdown-toggle", "css:finder"], + ["xpath=//button[@id='advanced-nav-dropdown-toggle']", "xpath:attributes"], + ["xpath=//div[@id='advanced-nav-dropdown']/button", "xpath:idRelative"], + ["xpath=//div[3]/button", "xpath:position"], + ["xpath=//button[contains(.,'Advanced')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "14841cc4-c8f1-48c2-9f85-a7aaf9f0a91d", + "comment": "", + "command": "click", + "target": "id=advanced-nav-dropdown-properties", + "targets": [ + ["id=advanced-nav-dropdown-properties", "id"], + ["linkText=Shibboleth configurations", "linkText"], + ["css=#advanced-nav-dropdown-properties", "css:finder"], + ["xpath=//a[contains(text(),'Shibboleth configurations')]", "xpath:link"], + ["xpath=//a[@id='advanced-nav-dropdown-properties']", "xpath:attributes"], + ["xpath=//div[@id='advanced-nav-dropdown']/div/a[5]", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/configurations')]", "xpath:href"], + ["xpath=//a[5]", "xpath:position"], + ["xpath=//a[contains(.,'Shibboleth configurations')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "8a824b21-89be-4531-baa3-db217375dfb1", + "comment": "", + "command": "click", + "target": "linkText=Create Shibboleth configuration set", + "targets": [ + ["linkText=Create Shibboleth configuration set", "linkText"], + ["css=.btn-success", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '/configurations/new')]", "xpath:href"], + ["xpath=//div[2]/div/a", "xpath:position"], + ["xpath=//a[contains(.,'  Create Shibboleth configuration set')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "da25d3be-ebb4-4ad7-8264-dfb688ef157d", + "comment": "", + "command": "type", + "target": "id=formName", + "targets": [ + ["id=formName", "id"], + ["name=name", "name"], + ["css=#formName", "css:finder"], + ["xpath=//input[@id='formName']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div/div/div/input", "xpath:idRelative"], + ["xpath=//input", "xpath:position"] + ], + "value": "Test Configuration" + }, { + "id": "3fae037d-0e59-4b9d-adf2-dbd624b72613", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div/input", "xpath:idRelative"], + ["xpath=//div/div/div/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "2fe0a124-dfe0-4c40-a3b3-b1d8861505a8", + "comment": "", + "command": "click", + "target": "id=property-selector-item-1", + "targets": [ + ["id=property-selector-item-1", "id"], + ["linkText=AACLI - Add all", "linkText"], + ["css=#property-selector-item-1", "css:finder"], + ["xpath=//a[@id='property-selector-item-1']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[2]/a", "xpath:idRelative"], + ["xpath=//a[contains(@href, '#')]", "xpath:href"], + ["xpath=//div[2]/a", "xpath:position"], + ["xpath=//a[contains(.,'AACLI - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "be761931-fb77-4030-bc2c-2577d3a99580", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div[2]/input", "xpath:idRelative"], + ["xpath=//div[2]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "eb50041f-bf6e-4ef4-92ee-9319f79b8336", + "comment": "", + "command": "click", + "target": "id=property-selector-item-9", + "targets": [ + ["id=property-selector-item-9", "id"], + ["linkText=AccountLockoutManagement - Add all", "linkText"], + ["css=#property-selector-item-9", "css:finder"], + ["xpath=//a[@id='property-selector-item-9']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[4]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[9]", "xpath:href"], + ["xpath=//div[4]/a", "xpath:position"], + ["xpath=//a[contains(.,'AccountLockoutManagement - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "de63d0c0-9504-4339-b76f-ce21b7c9f5f8", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[9]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "9f0ee002-e494-4409-9461-35d70ec30bf3", + "comment": "", + "command": "click", + "target": "id=property-selector-item-17", + "targets": [ + ["id=property-selector-item-17", "id"], + ["linkText=AttendedRestartConfiguration - Add all", "linkText"], + ["css=#property-selector-item-17", "css:finder"], + ["xpath=//a[@id='property-selector-item-17']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[6]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[17]", "xpath:href"], + ["xpath=//div[6]/a", "xpath:position"], + ["xpath=//a[contains(.,'AttendedRestartConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "b1cb5ac9-027c-45f2-b7c2-d1a661378928", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div[4]/input", "xpath:idRelative"], + ["xpath=//div[4]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "53354967-a636-428a-8dea-c771e2ee3add", + "comment": "", + "command": "click", + "target": "id=property-selector-item-25", + "targets": [ + ["id=property-selector-item-25", "id"], + ["linkText=AttributePostLoginC14NConfiguration - Add all", "linkText"], + ["css=#property-selector-item-25", "css:finder"], + ["xpath=//a[@id='property-selector-item-25']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[8]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[25]", "xpath:href"], + ["xpath=//div[8]/a", "xpath:position"], + ["xpath=//a[contains(.,'AttributePostLoginC14NConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ff91bfaf-f6ce-42c2-9dd4-1c52268d140d", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "825680dd-0180-4b92-a2df-40d041c24831", + "comment": "", + "command": "click", + "target": "id=property-selector-item-33", + "targets": [ + ["id=property-selector-item-33", "id"], + ["linkText=AuditLoggingConfiguration - Add all", "linkText"], + ["css=#property-selector-item-33", "css:finder"], + ["xpath=//a[@id='property-selector-item-33']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[10]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[33]", "xpath:href"], + ["xpath=//div[10]/a", "xpath:position"], + ["xpath=//a[contains(.,'AuditLoggingConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "1c671949-1992-4cbd-930c-0153e1fea983", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[12]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "7e6f1147-95fa-4f2e-b71c-bdc2265c8537", + "comment": "", + "command": "click", + "target": "id=property-selector-item-49", + "targets": [ + ["id=property-selector-item-49", "id"], + ["linkText=AuthenticationConfiguration - Add all", "linkText"], + ["css=#property-selector-item-49", "css:finder"], + ["xpath=//a[@id='property-selector-item-49']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[12]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[49]", "xpath:href"], + ["xpath=//div[12]/a", "xpath:position"], + ["xpath=//a[contains(.,'AuthenticationConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "384ea0fc-0bc1-4f63-b736-7e1d67277662", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div[7]/input", "xpath:idRelative"], + ["xpath=//div[7]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "2158cbdc-85be-4082-938c-00a14e0d6d63", + "comment": "", + "command": "click", + "target": "id=property-selector-item-59", + "targets": [ + ["id=property-selector-item-59", "id"], + ["linkText=CSRF - Add all", "linkText"], + ["css=#property-selector-item-59", "css:finder"], + ["xpath=//a[@id='property-selector-item-59']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[14]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[59]", "xpath:href"], + ["xpath=//div[14]/a", "xpath:position"], + ["xpath=//a[contains(.,'CSRF - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a861c6d1-277e-438f-a49c-d47521f67dcc", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[14]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f71b15c0-ff1b-4f26-8630-b755e1af00aa", + "comment": "", + "command": "click", + "target": "id=property-selector-item-62", + "targets": [ + ["id=property-selector-item-62", "id"], + ["linkText=CasProtocolConfiguration - Add all", "linkText"], + ["css=#property-selector-item-62", "css:finder"], + ["xpath=//a[@id='property-selector-item-62']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[16]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[62]", "xpath:href"], + ["xpath=//div[16]/a", "xpath:position"], + ["xpath=//a[contains(.,'CasProtocolConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "50f0c334-c0ca-43dc-8464-6d5d5b64de3e", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[15]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ab25fbad-3959-4b65-ae5b-cd8cf81679d3", + "comment": "", + "command": "click", + "target": "id=property-selector-item-66", + "targets": [ + ["id=property-selector-item-66", "id"], + ["linkText=ConsentConfiguration - Add all", "linkText"], + ["css=#property-selector-item-66", "css:finder"], + ["xpath=//a[@id='property-selector-item-66']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[18]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[66]", "xpath:href"], + ["xpath=//div[18]/a", "xpath:position"], + ["xpath=//a[contains(.,'ConsentConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5b5e0325-1735-4b9a-9920-5dac993cbb13", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[16]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "d06957b0-f5fa-4960-ac87-750566eb8484", + "comment": "", + "command": "click", + "target": "id=property-selector-item-84", + "targets": [ + ["id=property-selector-item-84", "id"], + ["linkText=Core - Add all", "linkText"], + ["css=#property-selector-item-84", "css:finder"], + ["xpath=//a[@id='property-selector-item-84']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[20]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[84]", "xpath:href"], + ["xpath=//div[20]/a", "xpath:position"], + ["xpath=//a[contains(.,'Core - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "cf7d85ba-7edc-4bf1-938a-a88fd04c7252", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[17]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "630e9dc2-89d6-435e-bd3d-040814109f16", + "comment": "", + "command": "click", + "target": "id=property-selector-item-100", + "targets": [ + ["id=property-selector-item-100", "id"], + ["linkText=DuoAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-100", "css:finder"], + ["xpath=//a[@id='property-selector-item-100']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[22]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[100]", "xpath:href"], + ["xpath=//div[22]/a", "xpath:position"], + ["xpath=//a[contains(.,'DuoAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "9f2f0c50-7465-4879-bb68-822bca1f0fa3", + "comment": "", + "command": "click", + "target": "css=.rbt-input-main", + "targets": [ + ["css=.rbt-input-main", "css:finder"], + ["xpath=//input[@value='']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/div/div/div[12]/input", "xpath:idRelative"], + ["xpath=//div[12]/input", "xpath:position"] + ], + "value": "" + }, { + "id": "6f28c9cc-1006-456b-ae72-b70006636829", + "comment": "", + "command": "click", + "target": "id=property-selector-item-127", + "targets": [ + ["id=property-selector-item-127", "id"], + ["linkText=DuoOIDCAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-127", "css:finder"], + ["xpath=//a[@id='property-selector-item-127']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[24]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[127]", "xpath:href"], + ["xpath=//div[24]/a", "xpath:position"], + ["xpath=//a[contains(.,'DuoOIDCAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "3b326c6f-96d3-4f6c-ba82-e9ffd95517f1", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "ec3ac03f-c46b-4e1c-a89d-e2dc9826ca98", + "comment": "", + "command": "click", + "target": "id=property-selector-item-169", + "targets": [ + ["id=property-selector-item-169", "id"], + ["linkText=ErrorHandlingConfiguration - Add all", "linkText"], + ["css=#property-selector-item-169", "css:finder"], + ["xpath=//a[@id='property-selector-item-169']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[26]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[169]", "xpath:href"], + ["xpath=//div[26]/a", "xpath:position"], + ["xpath=//a[contains(.,'ErrorHandlingConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ce43ffb1-3979-4381-a155-9a2a59d1ac95", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[20]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "62d42fb7-00e2-400d-a1be-adcbf826ce3a", + "comment": "", + "command": "click", + "target": "id=property-selector-item-175", + "targets": [ + ["id=property-selector-item-175", "id"], + ["linkText=ExternalAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-175", "css:finder"], + ["xpath=//a[@id='property-selector-item-175']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[28]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[175]", "xpath:href"], + ["xpath=//div[28]/a", "xpath:position"], + ["xpath=//a[contains(.,'ExternalAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "b1c01f80-778c-4ea3-b952-dd84c18e5904", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[21]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "8a3757ee-2564-436e-abc5-e0584a59a82e", + "comment": "", + "command": "click", + "target": "id=property-selector-item-192", + "targets": [ + ["id=property-selector-item-192", "id"], + ["linkText=FTICKSLoggingConfiguration - Add all", "linkText"], + ["css=#property-selector-item-192", "css:finder"], + ["xpath=//a[@id='property-selector-item-192']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[30]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[192]", "xpath:href"], + ["xpath=//div[30]/a", "xpath:position"], + ["xpath=//a[contains(.,'FTICKSLoggingConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "c6bfe838-9027-4c25-990e-e451e9d04a4d", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "0c462504-cb92-421d-aeb0-8afecac90aec", + "comment": "", + "command": "click", + "target": "id=property-selector-item-199", + "targets": [ + ["id=property-selector-item-199", "id"], + ["linkText=FunctionAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-199", "css:finder"], + ["xpath=//a[@id='property-selector-item-199']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[32]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[199]", "xpath:href"], + ["xpath=//div[32]/a", "xpath:position"], + ["xpath=//a[contains(.,'FunctionAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "892d14a0-9ab0-4c05-945b-bd96d461eba8", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[23]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "9a809145-1f01-4a6b-8eaf-836f91a9bd5a", + "comment": "", + "command": "click", + "target": "id=property-selector-item-214", + "targets": [ + ["id=property-selector-item-214", "id"], + ["linkText=HelloWorldConfiguration - Add all", "linkText"], + ["css=#property-selector-item-214", "css:finder"], + ["xpath=//a[@id='property-selector-item-214']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[34]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[214]", "xpath:href"], + ["xpath=//div[34]/a", "xpath:position"], + ["xpath=//a[contains(.,'HelloWorldConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "8e3dc610-99f9-4a85-a0c0-cd572ccf0a84", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[24]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "fa182a6d-bba7-4f50-a6d8-a5391b592004", + "comment": "", + "command": "click", + "target": "id=property-selector-item-222", + "targets": [ + ["id=property-selector-item-222", "id"], + ["linkText=IPAddressAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-222", "css:finder"], + ["xpath=//a[@id='property-selector-item-222']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[36]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[222]", "xpath:href"], + ["xpath=//div[36]/a", "xpath:position"], + ["xpath=//a[contains(.,'IPAddressAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "17e45a4b-9d00-478f-9add-c1a7138a7959", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[25]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "2a3578cb-56d5-4805-8e82-2058e17c3ad5", + "comment": "", + "command": "click", + "target": "id=property-selector-item-237", + "targets": [ + ["id=property-selector-item-237", "id"], + ["linkText=JAASAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-237", "css:finder"], + ["xpath=//a[@id='property-selector-item-237']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[38]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[237]", "xpath:href"], + ["xpath=//div[38]/a", "xpath:position"], + ["xpath=//a[contains(.,'JAASAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "3aedee37-3445-4679-afe8-62e53b348e52", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down > path", + "targets": [ + ["css=.fa-caret-down > path", "css:finder"] + ], + "value": "" + }, { + "id": "fce00a94-ffe3-4771-b33d-e6c8cde6c690", + "comment": "", + "command": "click", + "target": "id=property-selector-item-240", + "targets": [ + ["id=property-selector-item-240", "id"], + ["linkText=KerberosAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-240", "css:finder"], + ["xpath=//a[@id='property-selector-item-240']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[40]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[240]", "xpath:href"], + ["xpath=//div[40]/a", "xpath:position"], + ["xpath=//a[contains(.,'KerberosAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "37642e97-2b2a-4cfd-9b71-d150c13b1b2d", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[27]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "fdae4c41-909b-44b1-b245-469c430a09a0", + "comment": "", + "command": "click", + "target": "id=property-selector-item-245", + "targets": [ + ["id=property-selector-item-245", "id"], + ["linkText=LDAPAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-245", "css:finder"], + ["xpath=//a[@id='property-selector-item-245']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[42]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[245]", "xpath:href"], + ["xpath=//div[42]/a", "xpath:position"], + ["xpath=//a[contains(.,'LDAPAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f34f0217-ff82-441b-a73b-b25f791bc546", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[28]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "d30d9da8-65e0-41a1-b27f-c4cc998c97fd", + "comment": "", + "command": "click", + "target": "id=property-selector-item-281", + "targets": [ + ["id=property-selector-item-281", "id"], + ["linkText=LogoutConfiguration - Add all", "linkText"], + ["css=#property-selector-item-281", "css:finder"], + ["xpath=//a[@id='property-selector-item-281']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[44]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[281]", "xpath:href"], + ["xpath=//div[44]/a", "xpath:position"], + ["xpath=//a[contains(.,'LogoutConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "cb442dbe-c609-4b8b-ac55-2d32362be80b", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[29]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "19b1de66-7601-4e41-a345-657c5417f23f", + "comment": "", + "command": "click", + "target": "id=property-selector-item-288", + "targets": [ + ["id=property-selector-item-288", "id"], + ["linkText=MetadataQuery - Add all", "linkText"], + ["css=#property-selector-item-288", "css:finder"], + ["xpath=//a[@id='property-selector-item-288']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[46]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[288]", "xpath:href"], + ["xpath=//div[46]/a", "xpath:position"], + ["xpath=//a[contains(.,'MetadataQuery - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "513c8bd3-cbb4-443f-9a90-8a2ae9d5c0ce", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[30]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "515cc435-61ee-430a-8cdc-ac41e3926fbc", + "comment": "", + "command": "click", + "target": "id=property-selector-item-296", + "targets": [ + ["id=property-selector-item-296", "id"], + ["linkText=MetadataReload - Add all", "linkText"], + ["css=#property-selector-item-296", "css:finder"], + ["xpath=//a[@id='property-selector-item-296']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[48]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[296]", "xpath:href"], + ["xpath=//div[48]/a", "xpath:position"], + ["xpath=//a[contains(.,'MetadataReload - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "6d5dcd3a-0d08-4140-9634-196e2e2fdb90", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "2b2a05d9-4e8b-45cf-882f-08328cb0b6e5", + "comment": "", + "command": "click", + "target": "id=property-selector-item-304", + "targets": [ + ["id=property-selector-item-304", "id"], + ["linkText=Metadatagen - Add all", "linkText"], + ["css=#property-selector-item-304", "css:finder"], + ["xpath=//a[@id='property-selector-item-304']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[50]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[304]", "xpath:href"], + ["xpath=//div[50]/a", "xpath:position"], + ["xpath=//a[contains(.,'Metadatagen - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f1709162-b102-48da-81b0-5862158fd74d", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[32]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "643c1db8-10f8-4146-94fb-bf920b007c00", + "comment": "", + "command": "click", + "target": "id=property-selector-item-313", + "targets": [ + ["id=property-selector-item-313", "id"], + ["linkText=MetricsConfiguration - Add all", "linkText"], + ["css=#property-selector-item-313", "css:finder"], + ["xpath=//a[@id='property-selector-item-313']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[52]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[313]", "xpath:href"], + ["xpath=//div[52]/a", "xpath:position"], + ["xpath=//a[contains(.,'MetricsConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "206468ff-7786-4e32-96dd-4c0e9a2194b7", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[33]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "00f2e151-13aa-4ac0-bb0c-d7e531f422a5", + "comment": "", + "command": "click", + "target": "id=property-selector-item-320", + "targets": [ + ["id=property-selector-item-320", "id"], + ["linkText=Misc - Add all", "linkText"], + ["css=#property-selector-item-320", "css:finder"], + ["xpath=//a[@id='property-selector-item-320']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[54]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[320]", "xpath:href"], + ["xpath=//div[54]/a", "xpath:position"], + ["xpath=//a[contains(.,'Misc - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "c06b4caf-e093-49b4-8cac-f71bda476995", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "031e88e8-bde7-4d25-8aab-919bc8882901", + "comment": "", + "command": "click", + "target": "id=property-selector-item-326", + "targets": [ + ["id=property-selector-item-326", "id"], + ["linkText=MultiFactorAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-326", "css:finder"], + ["xpath=//a[@id='property-selector-item-326']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[56]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[326]", "xpath:href"], + ["xpath=//div[56]/a", "xpath:position"], + ["xpath=//a[contains(.,'MultiFactorAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "7ab63a23-e0ab-4a07-8ef8-9fdb6af9f59b", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[35]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "34cbdae8-4b4c-4faa-a38c-f3a9c5475e45", + "comment": "", + "command": "click", + "target": "id=property-selector-item-342", + "targets": [ + ["id=property-selector-item-342", "id"], + ["linkText=NameIDConsumptionConfiguration - Add all", "linkText"], + ["css=#property-selector-item-342", "css:finder"], + ["xpath=//a[@id='property-selector-item-342']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[58]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[342]", "xpath:href"], + ["xpath=//div[58]/a", "xpath:position"], + ["xpath=//a[contains(.,'NameIDConsumptionConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "15c61405-c967-475f-b494-6bdb461b5283", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[36]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "6e13ab35-510b-4e7b-976c-457d59f65606", + "comment": "", + "command": "click", + "target": "id=property-selector-item-345", + "targets": [ + ["id=property-selector-item-345", "id"], + ["linkText=NameIDGenerationConfiguration - Add all", "linkText"], + ["css=#property-selector-item-345", "css:finder"], + ["xpath=//a[@id='property-selector-item-345']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[60]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[345]", "xpath:href"], + ["xpath=//div[60]/a", "xpath:position"], + ["xpath=//a[contains(.,'NameIDGenerationConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "74505e9c-1a4b-441d-9e21-fce8077576b4", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[37]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ec03564e-9ff9-4c53-914e-e33e8efec3b8", + "comment": "", + "command": "click", + "target": "id=property-selector-item-349", + "targets": [ + ["id=property-selector-item-349", "id"], + ["linkText=OAuth2ClientAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-349", "css:finder"], + ["xpath=//a[@id='property-selector-item-349']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[62]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[349]", "xpath:href"], + ["xpath=//div[62]/a", "xpath:position"], + ["xpath=//a[contains(.,'OAuth2ClientAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "9bc758f1-8c06-429e-abf4-78fadd181d56", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[38]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a81e8d28-41b8-47d1-901b-6d36fb90398d", + "comment": "", + "command": "click", + "target": "id=property-selector-item-358", + "targets": [ + ["id=property-selector-item-358", "id"], + ["linkText=OIDC OP - Add all", "linkText"], + ["css=#property-selector-item-358", "css:finder"], + ["xpath=//a[@id='property-selector-item-358']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[64]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[358]", "xpath:href"], + ["xpath=//div[64]/a", "xpath:position"], + ["xpath=//a[contains(.,'OIDC OP - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5e1646f3-7841-4b97-96c9-639c6f7ef3ca", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[39]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f3865e29-6b36-49ab-99a4-44370b5ed974", + "comment": "", + "command": "click", + "target": "id=property-selector-item-371", + "targets": [ + ["id=property-selector-item-371", "id"], + ["linkText=OPAuthorization - Add all", "linkText"], + ["css=#property-selector-item-371", "css:finder"], + ["xpath=//a[@id='property-selector-item-371']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[66]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[371]", "xpath:href"], + ["xpath=//div[66]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPAuthorization - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "821c3a6d-b9a6-45bf-bda3-46c2f1e87303", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[40]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "72620249-22a8-436b-b506-670fad77fefa", + "comment": "", + "command": "click", + "target": "id=property-selector-item-378", + "targets": [ + ["id=property-selector-item-378", "id"], + ["linkText=OPClientAuthentication - Add all", "linkText"], + ["css=#property-selector-item-378", "css:finder"], + ["xpath=//a[@id='property-selector-item-378']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[68]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[378]", "xpath:href"], + ["xpath=//div[68]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPClientAuthentication - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "e8d736c8-be22-4411-87d4-0a1eefcc821e", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "d8ef3cf9-1398-4bcd-b976-92a2a471ce1c", + "comment": "", + "command": "click", + "target": "id=property-selector-item-380", + "targets": [ + ["id=property-selector-item-380", "id"], + ["linkText=OPClientCredentialsGrant - Add all", "linkText"], + ["css=#property-selector-item-380", "css:finder"], + ["xpath=//a[@id='property-selector-item-380']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[70]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[380]", "xpath:href"], + ["xpath=//div[70]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPClientCredentialsGrant - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ed236cf8-e185-4b41-a47f-2a9219eab773", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "d4965727-9cc9-465a-9d4d-9e3a16c9507a", + "comment": "", + "command": "click", + "target": "id=property-selector-item-383", + "targets": [ + ["id=property-selector-item-383", "id"], + ["linkText=OPClientResolution - Add all", "linkText"], + ["css=#property-selector-item-383", "css:finder"], + ["xpath=//a[@id='property-selector-item-383']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[72]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[383]", "xpath:href"], + ["xpath=//div[72]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPClientResolution - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "899a5897-0786-4f40-8d1f-2c3cc64f4666", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[43]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a08f536a-166d-45e0-a477-b7aece98a6bc", + "comment": "", + "command": "click", + "target": "id=property-selector-item-387", + "targets": [ + ["id=property-selector-item-387", "id"], + ["linkText=OPCustomFilterRegistration - Add all", "linkText"], + ["css=#property-selector-item-387", "css:finder"], + ["xpath=//a[@id='property-selector-item-387']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[74]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[387]", "xpath:href"], + ["xpath=//div[74]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPCustomFilterRegistration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "90ec186d-d13c-49a1-9912-744f62873feb", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[44]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "185cd9b2-0f1b-4f64-a4a5-b62f5a881d45", + "comment": "", + "command": "click", + "target": "css=.p-3", + "targets": [ + ["css=.p-3", "css:finder"], + ["xpath=//div[@id='root']/div/main/div", "xpath:idRelative"], + ["xpath=//main/div", "xpath:position"] + ], + "value": "" + }, { + "id": "2a295dc3-422a-436e-8450-03dbcc88a1b0", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[44]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "6fdf6ef4-52e8-44a9-8dc5-8126e2ba11b0", + "comment": "", + "command": "click", + "target": "id=property-selector-item-389", + "targets": [ + ["id=property-selector-item-389", "id"], + ["linkText=OPDiscovery - Add all", "linkText"], + ["css=#property-selector-item-389", "css:finder"], + ["xpath=//a[@id='property-selector-item-389']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[76]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[389]", "xpath:href"], + ["xpath=//div[76]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPDiscovery - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "614f715d-8fcc-4e84-8d0d-dd947fc7c99f", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "a3bbcc78-ce50-4b17-9419-f228664dc9fc", + "comment": "", + "command": "click", + "target": "id=property-selector-item-392", + "targets": [ + ["id=property-selector-item-392", "id"], + ["linkText=OPDynamicClientRegistration - Add all", "linkText"], + ["css=#property-selector-item-392", "css:finder"], + ["xpath=//a[@id='property-selector-item-392']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[78]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[392]", "xpath:href"], + ["xpath=//div[78]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPDynamicClientRegistration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ec8f2a2b-b45d-4345-af4b-dd5965f9dc54", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[46]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "ba6779d8-9a40-4981-a41f-c8c22df7027a", + "comment": "", + "command": "click", + "target": "id=property-selector-item-407", + "targets": [ + ["id=property-selector-item-407", "id"], + ["linkText=OPMetadataPolicies - Add all", "linkText"], + ["css=#property-selector-item-407", "css:finder"], + ["xpath=//a[@id='property-selector-item-407']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[80]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[407]", "xpath:href"], + ["xpath=//div[80]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPMetadataPolicies - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "b93aed8b-bd95-496a-ad07-b9bfe23f8522", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down > path", + "targets": [ + ["css=.fa-caret-down > path", "css:finder"] + ], + "value": "" + }, { + "id": "57fc676c-34fc-4220-915e-be3c30821030", + "comment": "", + "command": "click", + "target": "id=property-selector-item-409", + "targets": [ + ["id=property-selector-item-409", "id"], + ["linkText=OPRevocation - Add all", "linkText"], + ["css=#property-selector-item-409", "css:finder"], + ["xpath=//a[@id='property-selector-item-409']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[82]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[409]", "xpath:href"], + ["xpath=//div[82]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPRevocation - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "85efb0c2-9a2b-4816-b77d-4c84816f3499", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[48]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "0c424441-f80c-4f42-9a4a-2df0be1ad937", + "comment": "", + "command": "click", + "target": "id=property-selector-item-412", + "targets": [ + ["id=property-selector-item-412", "id"], + ["linkText=OPSecurity - Add all", "linkText"], + ["css=#property-selector-item-412", "css:finder"], + ["xpath=//a[@id='property-selector-item-412']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[84]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[412]", "xpath:href"], + ["xpath=//div[84]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPSecurity - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "686dc5ad-4686-4364-865e-e8c95210f7e3", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[49]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "da318a35-6cdf-4346-b357-3aadeaf46640", + "comment": "", + "command": "click", + "target": "id=property-selector-item-420", + "targets": [ + ["id=property-selector-item-420", "id"], + ["linkText=OPSubClaim - Add all", "linkText"], + ["css=#property-selector-item-420", "css:finder"], + ["xpath=//a[@id='property-selector-item-420']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[86]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[420]", "xpath:href"], + ["xpath=//div[86]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPSubClaim - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5f8f249d-2052-4b6f-be83-9cdde0f5a06d", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[50]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f36fb2c2-bf28-4fb0-8a6e-083b8a7d854e", + "comment": "", + "command": "click", + "target": "id=property-selector-item-424", + "targets": [ + ["id=property-selector-item-424", "id"], + ["linkText=OPToken - Add all", "linkText"], + ["css=#property-selector-item-424", "css:finder"], + ["xpath=//a[@id='property-selector-item-424']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[88]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[424]", "xpath:href"], + ["xpath=//div[88]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPToken - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5e7fc6cc-c7e3-4d4b-b682-ec939c8a5db1", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[51]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "24fa8f94-9a62-4e11-9125-a6c576695e77", + "comment": "", + "command": "click", + "target": "id=property-selector-item-436", + "targets": [ + ["id=property-selector-item-436", "id"], + ["linkText=PersistentNameIDGenerationConfiguration - Add all", "linkText"], + ["css=#property-selector-item-436", "css:finder"], + ["xpath=//a[@id='property-selector-item-436']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[90]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[436]", "xpath:href"], + ["xpath=//div[90]/a", "xpath:position"], + ["xpath=//a[contains(.,'PersistentNameIDGenerationConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "f7c7f42d-b4cb-4f92-997f-d9677a00758f", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "7bfdfde0-3399-4161-9cbc-e67f10ae44b5", + "comment": "", + "command": "click", + "target": "id=property-selector-item-460", + "targets": [ + ["id=property-selector-item-460", "id"], + ["linkText=ReloadableServices - Add all", "linkText"], + ["css=#property-selector-item-460", "css:finder"], + ["xpath=//a[@id='property-selector-item-460']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[92]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[460]", "xpath:href"], + ["xpath=//div[92]/a", "xpath:position"], + ["xpath=//a[contains(.,'ReloadableServices - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5a3ad5c4-37e2-4060-88bd-ed96b94d037e", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "db192d5c-0857-4059-869d-d1ff40fd8844", + "comment": "", + "command": "click", + "target": "id=property-selector-item-501", + "targets": [ + ["id=property-selector-item-501", "id"], + ["linkText=RelyingPartyConfiguration - Add all", "linkText"], + ["css=#property-selector-item-501", "css:finder"], + ["xpath=//a[@id='property-selector-item-501']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[94]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[501]", "xpath:href"], + ["xpath=//div[94]/a", "xpath:position"], + ["xpath=//a[contains(.,'RelyingPartyConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "46e1fd14-ca91-4f92-a919-695dcff58622", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[54]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "bf5ba1a6-ba55-4397-91fa-7f1c1cd28e0d", + "comment": "", + "command": "click", + "target": "id=property-selector-item-507", + "targets": [ + ["id=property-selector-item-507", "id"], + ["linkText=RemoteUserAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-507", "css:finder"], + ["xpath=//a[@id='property-selector-item-507']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[96]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[507]", "xpath:href"], + ["xpath=//div[96]/a", "xpath:position"], + ["xpath=//a[contains(.,'RemoteUserAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "fde12162-843c-4425-bc3e-f404f52cd232", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "e1313d05-d1ff-4196-8ae7-eb04c1088afd", + "comment": "", + "command": "click", + "target": "id=property-selector-item-524", + "targets": [ + ["id=property-selector-item-524", "id"], + ["linkText=RemoteUserInternalAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-524", "css:finder"], + ["xpath=//a[@id='property-selector-item-524']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[98]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[524]", "xpath:href"], + ["xpath=//div[98]/a", "xpath:position"], + ["xpath=//a[contains(.,'RemoteUserInternalAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "1b2b7432-6d03-4b84-922c-59b9cee6ccc5", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[56]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "31fff123-cc89-4473-9943-a7b5d1206de7", + "comment": "", + "command": "click", + "target": "id=property-selector-item-549", + "targets": [ + ["id=property-selector-item-549", "id"], + ["linkText=SAML2ProxyTransformPostLoginC14NConfiguration - Add all", "linkText"], + ["css=#property-selector-item-549", "css:finder"], + ["xpath=//a[@id='property-selector-item-549']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[100]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[549]", "xpath:href"], + ["xpath=//div[100]/a", "xpath:position"], + ["xpath=//a[contains(.,'SAML2ProxyTransformPostLoginC14NConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "10926b24-5952-4685-be81-802f5fc7ca4a", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "746398e5-d85c-412c-8a64-45c6d2a669ee", + "comment": "", + "command": "click", + "target": "id=property-selector-item-552", + "targets": [ + ["id=property-selector-item-552", "id"], + ["linkText=SAMLAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-552", "css:finder"], + ["xpath=//a[@id='property-selector-item-552']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[102]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[552]", "xpath:href"], + ["xpath=//div[102]/a", "xpath:position"], + ["xpath=//a[contains(.,'SAMLAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5558c433-213a-49de-b68d-e6d9ac396b86", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "a85d9957-d3f3-4304-bd85-dd25ae70592b", + "comment": "", + "command": "click", + "target": "id=property-selector-item-572", + "targets": [ + ["id=property-selector-item-572", "id"], + ["linkText=SPNEGOAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-572", "css:finder"], + ["xpath=//a[@id='property-selector-item-572']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[104]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[572]", "xpath:href"], + ["xpath=//div[104]/a", "xpath:position"], + ["xpath=//a[contains(.,'SPNEGOAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "62dcb81a-9265-4f8f-ac8e-6ae7027a3601", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[59]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "18da3cfc-943f-43e5-ab16-6a9070336d5c", + "comment": "", + "command": "click", + "target": "id=property-selector-item-592", + "targets": [ + ["id=property-selector-item-592", "id"], + ["linkText=SecurityConfiguration - Add all", "linkText"], + ["css=#property-selector-item-592", "css:finder"], + ["xpath=//a[@id='property-selector-item-592']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[106]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[592]", "xpath:href"], + ["xpath=//div[106]/a", "xpath:position"], + ["xpath=//a[contains(.,'SecurityConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "894853a1-2202-4ff4-bc06-f0f7faf32505", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[60]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "12440bab-1419-4d7d-948c-71811b067df2", + "comment": "", + "command": "click", + "target": "id=property-selector-item-626", + "targets": [ + ["id=property-selector-item-626", "id"], + ["linkText=SessionConfiguration - Add all", "linkText"], + ["css=#property-selector-item-626", "css:finder"], + ["xpath=//a[@id='property-selector-item-626']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[108]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[626]", "xpath:href"], + ["xpath=//div[108]/a", "xpath:position"], + ["xpath=//a[contains(.,'SessionConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5bf0b70b-e413-49eb-bfcb-f97a4265c70b", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down > path", + "targets": [ + ["css=.fa-caret-down > path", "css:finder"] + ], + "value": "" + }, { + "id": "eb83e85f-6924-44ac-9922-9c5a1fcbcbc5", + "comment": "", + "command": "click", + "target": "id=property-selector-item-639", + "targets": [ + ["id=property-selector-item-639", "id"], + ["linkText=SimplePostLoginC14NConfiguration - Add all", "linkText"], + ["css=#property-selector-item-639", "css:finder"], + ["xpath=//a[@id='property-selector-item-639']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[110]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[639]", "xpath:href"], + ["xpath=//div[110]/a", "xpath:position"], + ["xpath=//a[contains(.,'SimplePostLoginC14NConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "d941d154-a6a3-4684-ad04-ca9d45acf2aa", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[62]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "cd98777e-1800-417f-af35-9f6d531decfa", + "comment": "", + "command": "click", + "target": "css=form", + "targets": [ + ["css=form", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form", "xpath:idRelative"], + ["xpath=//form", "xpath:position"] + ], + "value": "" + }, { + "id": "2ac41455-f406-4e71-88c0-8c30b7c23eab", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "a729126e-0c39-4db6-882c-b506db087119", + "comment": "", + "command": "click", + "target": "id=property-selector-item-643", + "targets": [ + ["id=property-selector-item-643", "id"], + ["linkText=Status - Add all", "linkText"], + ["css=#property-selector-item-643", "css:finder"], + ["xpath=//a[@id='property-selector-item-643']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[112]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[643]", "xpath:href"], + ["xpath=//div[112]/a", "xpath:position"], + ["xpath=//a[contains(.,'Status - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "602156fa-9fed-4a42-9182-4aa66338dd24", + "comment": "", + "command": "click", + "target": "css=td", + "targets": [ + ["css=td", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr/td", "xpath:idRelative"], + ["xpath=//td", "xpath:position"], + ["xpath=//td[contains(.,'At least one property is required.')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "878447bd-6424-440f-8dcf-461f994a6478", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[63]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "3b964802-50ee-4a2a-8db6-d24a51a61483", + "comment": "", + "command": "click", + "target": "id=property-selector-item-651", + "targets": [ + ["id=property-selector-item-651", "id"], + ["linkText=StorageConfiguration - Add all", "linkText"], + ["css=#property-selector-item-651", "css:finder"], + ["xpath=//a[@id='property-selector-item-651']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[114]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[651]", "xpath:href"], + ["xpath=//div[114]/a", "xpath:position"], + ["xpath=//a[contains(.,'StorageConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "eca7bf2d-db81-4cad-873b-eba9440bd0e5", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down", + "targets": [ + ["css=.fa-caret-down", "css:finder"] + ], + "value": "" + }, { + "id": "40ca1af5-e808-4b69-a5dd-3b545c1b233d", + "comment": "", + "command": "click", + "target": "id=property-selector-item-659", + "targets": [ + ["id=property-selector-item-659", "id"], + ["linkText=TOTP - Add all", "linkText"], + ["css=#property-selector-item-659", "css:finder"], + ["xpath=//a[@id='property-selector-item-659']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[116]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[659]", "xpath:href"], + ["xpath=//div[116]/a", "xpath:position"], + ["xpath=//a[contains(.,'TOTP - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "d6e986cb-865d-4472-b791-ea9ba459a849", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[65]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "26be9d61-f3c2-482e-8d0d-759a00c9b28f", + "comment": "", + "command": "click", + "target": "id=property-selector-item-677", + "targets": [ + ["id=property-selector-item-677", "id"], + ["linkText=X500PostLoginC14NConfiguration - Add all", "linkText"], + ["css=#property-selector-item-677", "css:finder"], + ["xpath=//a[@id='property-selector-item-677']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[118]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[677]", "xpath:href"], + ["xpath=//div[118]/a", "xpath:position"], + ["xpath=//a[contains(.,'X500PostLoginC14NConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "966c35be-39a4-4fa9-aded-8ba6fa1394a2", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[66]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "5124a661-4c33-4468-9c08-505268f78ff0", + "comment": "", + "command": "click", + "target": "id=property-selector-item-683", + "targets": [ + ["id=property-selector-item-683", "id"], + ["linkText=X509AuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-683", "css:finder"], + ["xpath=//a[@id='property-selector-item-683']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[120]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[683]", "xpath:href"], + ["xpath=//div[120]/a", "xpath:position"], + ["xpath=//a[contains(.,'X509AuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a11e93fd-5a1b-4456-a875-f0b8a8582058", + "comment": "", + "command": "click", + "target": "css=.fa-caret-down > path", + "targets": [ + ["css=.fa-caret-down > path", "css:finder"] + ], + "value": "" + }, { + "id": "299da229-ce40-43ac-87c6-2bb6c1122d93", + "comment": "", + "command": "click", + "target": "id=property-selector-item-699", + "targets": [ + ["id=property-selector-item-699", "id"], + ["linkText=X509InternalAuthnConfiguration - Add all", "linkText"], + ["css=#property-selector-item-699", "css:finder"], + ["xpath=//a[@id='property-selector-item-699']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[122]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[699]", "xpath:href"], + ["xpath=//div[122]/a", "xpath:position"], + ["xpath=//a[contains(.,'X509InternalAuthnConfiguration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "2a8c3086-a40d-4e9c-857a-7fda2bd2e8f5", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[68]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "93a9c033-0fcc-4af9-85b5-7e18d882bf68", + "comment": "", + "command": "click", + "target": "css=.col-12 > .d-flex", + "targets": [ + ["css=.col-12 > .d-flex", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div", "xpath:position"] + ], + "value": "" + }, { + "id": "d06a3e9a-849f-4b8d-83a1-797f8abf6794", + "comment": "", + "command": "click", + "target": "css=.ms-2", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" + }, { + "id": "1e726b4f-8ae7-40eb-ba52-747c88ae2e89", + "comment": "", + "command": "assertText", + "target": "css=tr:nth-child(653) > td:nth-child(1)", + "targets": [ + ["css=tr:nth-child(653) > td:nth-child(1)", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[653]/td", "xpath:idRelative"], + ["xpath=//tr[653]/td", "xpath:position"], + ["xpath=//td[contains(.,'idp.authn.X509Internal.discoveryRequired')]", "xpath:innerText"] + ], + "value": "idp.authn.X509Internal.discoveryRequired" + }, { + "id": "9af817b8-7f25-4f90-8b9a-f24582b7c19b", + "comment": "", + "command": "click", + "target": "css=.btn-info", + "targets": [ + ["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": "" + }, { + "id": "0e2f3bef-0c6c-457f-83c0-d1b464508daa", + "comment": "", + "command": "click", + "target": "linkText=Edit", + "targets": [ + ["linkText=Edit", "linkText"], + ["css=.btn-primary", "css:finder"], + ["xpath=//a[contains(text(),'Edit')]", "xpath:link"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/div/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '/configurations/831/edit')])[2]", "xpath:href"], + ["xpath=//td[3]/div/a", "xpath:position"], + ["xpath=//a[contains(.,'  Edit')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "caeb6c0b-c99d-4e4f-87b1-874ac54f30a8", + "comment": "", + "command": "click", + "target": "id=valueInput-idp.resolvertest.accessPolicy", + "targets": [ + ["id=valueInput-idp.resolvertest.accessPolicy", "id"], + ["name=properties.0.propertyValue", "name"], + ["css=#valueInput-idp\\.resolvertest\\.accessPolicy", "css:finder"], + ["xpath=//input[@id='valueInput-idp.resolvertest.accessPolicy']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr/td[4]/div/input", "xpath:idRelative"], + ["xpath=//td[4]/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "812d8a90-f462-470a-9a4d-efd2cca679c2", + "comment": "", + "command": "type", + "target": "id=valueInput-idp.resolvertest.accessPolicy", + "targets": [ + ["id=valueInput-idp.resolvertest.accessPolicy", "id"], + ["name=properties.0.propertyValue", "name"], + ["css=#valueInput-idp\\.resolvertest\\.accessPolicy", "css:finder"], + ["xpath=//input[@id='valueInput-idp.resolvertest.accessPolicy']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr/td[4]/div/input", "xpath:idRelative"], + ["xpath=//td[4]/div/input", "xpath:position"] + ], + "value": "foo" + }, { + "id": "8c98218b-9d71-42ac-8682-36d2aeb0f39e", + "comment": "", + "command": "click", + "target": "id=valueInput-idp.resolvertest.logging", + "targets": [ + ["id=valueInput-idp.resolvertest.logging", "id"], + ["name=properties.1.propertyValue", "name"], + ["css=#valueInput-idp\\.resolvertest\\.logging", "css:finder"], + ["xpath=//input[@id='valueInput-idp.resolvertest.logging']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[2]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "948ac5c1-aa09-44af-a024-c0dc898616d1", + "comment": "", + "command": "type", + "target": "id=valueInput-idp.resolvertest.logging", + "targets": [ + ["id=valueInput-idp.resolvertest.logging", "id"], + ["name=properties.1.propertyValue", "name"], + ["css=#valueInput-idp\\.resolvertest\\.logging", "css:finder"], + ["xpath=//input[@id='valueInput-idp.resolvertest.logging']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[2]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] + ], + "value": "bar" + }, { + "id": "46d0e1ac-4706-47cf-9336-683b7b6519f2", + "comment": "", + "command": "click", + "target": "name=properties.2.propertyValue", + "targets": [ + ["name=properties.2.propertyValue", "name"], + ["css=tr:nth-child(3) .form-check-input", "css:finder"], + ["xpath=//input[@name='properties.2.propertyValue']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[3]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[3]/td[4]/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "d3898399-e0c0-4ac1-9f66-ab1ef682cc4e", + "comment": "", + "command": "click", + "target": "css=.btn-info", + "targets": [ + ["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": "" + }, { + "id": "47617f08-9b12-47f0-b8bc-bf97636014fb", + "comment": "", + "command": "click", + "target": "css=.fa-pen-to-square > path", + "targets": [ + ["css=.fa-pen-to-square > path", "css:finder"] + ], + "value": "" + }, { + "id": "aaab6ac3-6c55-4b8f-8e97-4913e4d658d6", + "comment": "", + "command": "click", + "target": "name=properties.2.propertyValue", + "targets": [ + ["name=properties.2.propertyValue", "name"], + ["css=tr:nth-child(3) .form-check-input", "css:finder"], + ["xpath=//input[@name='properties.2.propertyValue']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[3]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[3]/td[4]/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "dea3ef04-ea08-40ea-8dce-eafc87ab2051", + "comment": "", + "command": "click", + "target": "name=properties.3.propertyValue", + "targets": [ + ["name=properties.3.propertyValue", "name"], + ["css=tr:nth-child(4) .form-check-input", "css:finder"], + ["xpath=//input[@name='properties.3.propertyValue']", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[4]/td[4]/div/input", "xpath:idRelative"], + ["xpath=//tr[4]/td[4]/div/input", "xpath:position"] + ], + "value": "" + }, { + "id": "fea5a053-a52e-4b5c-8477-51325b5baf40", + "comment": "", + "command": "click", + "target": "css=.btn-info", + "targets": [ + ["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": "" + }, { + "id": "cd64daba-9c2c-4523-a17d-8168f91b4f93", + "comment": "", + "command": "click", + "target": "css=.btn-danger", + "targets": [ + ["css=.btn-danger", "css:finder"], + ["xpath=(//button[@type='button'])[7]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td[3]/div/button", "xpath:idRelative"], + ["xpath=//td[3]/div/button", "xpath:position"], + ["xpath=//button[contains(.,'  Delete')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "debe5850-a226-47d1-b38b-17015449edf9", + "comment": "", + "command": "click", + "target": "css=.btn-danger:nth-child(1)", + "targets": [ + ["css=.btn-danger:nth-child(1)", "css:finder"], + ["xpath=(//button[@type='button'])[8]", "xpath:attributes"], + ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] + ], + "value": "" + }, { + "id": "efc6da0e-490c-4c8b-b4d2-07b71059d0ef", + "comment": "", + "command": "open", + "target": "/api/heheheheheheheWipeout", + "targets": [], + "value": "" + }, { + "id": "80cfb61f-79a5-429b-9b7e-b5991b8e279f", + "comment": "", + "command": "assertText", + "target": "css=body", + "targets": [], + "value": "yes, you did it" + }] + }], + "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 From 71c3c24b1063ec91fc52d3e8d28f60466fc70a03 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Wed, 7 Sep 2022 09:23:02 -0700 Subject: [PATCH 48/71] Fixed responsive table --- .../app/admin/component/ConfigurationForm.js | 98 ++++++++++--------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 751e94310..747a70452 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -134,56 +134,58 @@ export function ConfigurationForm({ configurations, configuration = {}, loading,
- - - - - - - - - - - - {fields.map((p, idx) => ( - - - - - - +
PropertyCategoryTypeValueAction
{ p.propertyName }{ p.category }{ p.displayType } - {p.displayType !== 'boolean' ? - - - - : - - } - - +
+ + + + + + + + + + + + {fields.map((p, idx) => ( + + + + + + + + ))} + {fields.length === 0 && + + - ))} - {fields.length === 0 && - - - - } - -
PropertyCategoryTypeValueAction
{ p.propertyName }{ p.category }{ p.displayType } + {p.displayType !== 'boolean' ? + + + + : + + } + + +
+ At least one property is required.
- At least one property is required. -
+ } +
+
From 91875029d119ffe3694c90a735e0cd208e473710 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Wed, 7 Sep 2022 15:03:34 -0400 Subject: [PATCH 49/71] shibui-2378 move bulk-upload into repo --- bulk-upload/README.md | 43 +++ bulk-upload/docker-build/Dockerfile | 10 + bulk-upload/docker-build/README.txt | 1 + bulk-upload/docker-build/shibui-md-upload.pl | 337 +++++++++++++++++++ bulk-upload/run.sh | 15 + bulk-upload/upload.conf | 35 ++ 6 files changed, 441 insertions(+) create mode 100644 bulk-upload/README.md create mode 100644 bulk-upload/docker-build/Dockerfile create mode 100644 bulk-upload/docker-build/README.txt create mode 100755 bulk-upload/docker-build/shibui-md-upload.pl create mode 100755 bulk-upload/run.sh create mode 100644 bulk-upload/upload.conf diff --git a/bulk-upload/README.md b/bulk-upload/README.md new file mode 100644 index 000000000..c436394e8 --- /dev/null +++ b/bulk-upload/README.md @@ -0,0 +1,43 @@ +This script can be used to bulk upload metadata files into the Shibboleth IdP UI + +### requirements ### +The shibui must be configured without SAML authentication enabled. The API is currently only accessible using Basic auth. +If shibui is using SAML auth, you can temporarily disable it by setting pac4j-enabled: false in application.yml and restarting shibui. +After uploading you can re-enable SAML auth by setting pac4j-enabled: true in application.yml and restarting shibui. + +### usage ### +`./run.sh -e` + +Where is one of: + +path to a dir containing individual metadata files, aggregate files, or a mix of both +path to one metadata file or aggregate file. + +-e enable metadata source after upload + +### configuration ### +Configuration is done in upload.conf. This file must reside in the same dir as run.sh +At a minimum it must contain the shibui api info. It can also be used to add entity attributes to the metadata as it is uploaded (examples are in upload.conf). + +#a entity attribute configuration in upload.conf like: +attr[0][FriendlyName] = signAssertions +attr[0][Name] = http://shibboleth.net/ns/profiles/saml2/sso/browser/signAssertions +attr[0][type] = xsd:boolean +attr[0][Value] = false + +#turns into: +```xml + + false + +``` + +### docker image ### +run.sh will pull the shibui-bulk-upload image from dockerhub and run the script within +If you need to build the image yourself, `cd docker-build;docker build -t unicon/shibui-bulk-upload .` + +### running without docker ### +The docker-build/shibui-md-upload.pl script can be run manually. +Depending on OS you may need to install some additional non dist Perl modules. REST::Client , XML::LibXML , JSON , Config::File +`perl shibui-md-upload.pl -c -m -e (enable metadata source after upload)` + diff --git a/bulk-upload/docker-build/Dockerfile b/bulk-upload/docker-build/Dockerfile new file mode 100644 index 000000000..dd7384667 --- /dev/null +++ b/bulk-upload/docker-build/Dockerfile @@ -0,0 +1,10 @@ +FROM debian:stable-slim +MAINTAINER sporth@unicon.net + +RUN apt-get clean \ + && apt-get -y update \ + && apt-get install -y librest-client-perl libconfig-file-perl jq libxml-libxml-perl libjson-perl + +WORKDIR /opt +COPY shibui-md-upload.pl /opt/shibui-md-upload.pl +ENTRYPOINT ["/opt/shibui-md-upload.pl"] diff --git a/bulk-upload/docker-build/README.txt b/bulk-upload/docker-build/README.txt new file mode 100644 index 000000000..823f746c5 --- /dev/null +++ b/bulk-upload/docker-build/README.txt @@ -0,0 +1 @@ +docker build -t unicon/shibui-bulk-upload . diff --git a/bulk-upload/docker-build/shibui-md-upload.pl b/bulk-upload/docker-build/shibui-md-upload.pl new file mode 100755 index 000000000..3aae45aa8 --- /dev/null +++ b/bulk-upload/docker-build/shibui-md-upload.pl @@ -0,0 +1,337 @@ +#!/usr/bin/perl + +use strict; +use warnings; + +use Getopt::Std; +use Config::File; +use REST::Client; +use MIME::Base64; +use HTTP::Cookies; +use XML::LibXML; +use XML::LibXML::XPathContext; +use Encode; +use JSON; + +##process arguments +our ($opt_e,$opt_m,$opt_c); +getopts('em:c:'); +my $enable = ($opt_e) ? 'true' : 'false'; +my $md = ($opt_m) ? $opt_m : '/opt/metadata/'; +my $uc = ($opt_c) ? $opt_c : '/opt/conf/upload.conf'; +## + +#config file is required, will contain the api information and other optional settings for adding extensions to the MD +my $conf = Config::File::read_config_file($uc); + +##setup REST::Client +my $unpw = encode_base64($conf->{api_user} . ':' . $conf->{api_pass}); +my $cookies = HTTP::Cookies->new( {} ); +my $client = REST::Client->new(); +$client->getUseragent()->cookie_jar($cookies); + +if ($conf->{api_selfsigned} =~ m/true/) { + $client->getUseragent()->ssl_opts(verify_hostname => 0); + $client->getUseragent()->ssl_opts(SSL_verify_mode => 0); +} + +$client->addHeader('Accept', 'application/json'); +$client->addHeader('Authorization', "Basic $unpw"); +$client->setHost($conf->{api_host}); + +#create auth token +$client->HEAD('/'); +my $token = &get_cookie_value($cookies, 'XSRF-TOKEN'); +$client->addHeader('X-XSRF-TOKEN', $token); +## + +#for stats +my $i = 0; +my $j = 0; + +##load the MD +#check whether we are reading a dir or file +if (-d $md) { + opendir(my $DH, $md) or die "Can't open $md: $!"; + + while (readdir $DH) { + next if ($_ =~ m/^\.|\.\./); + my $file = $_; + + my $xpc = &load_xml("$md/$file"); + + #check if file is aggregate, or individual entity + my $root = $xpc->findnodes("/*[local-name()='EntitiesDescriptor']"); + + if ($root) { + print "\nprocessing aggregate file: $file ....\n"; + + my $entity = $xpc->findnodes("//*[local-name()='EntityDescriptor']"); + + foreach my $var ($entity->get_nodelist) { + my ($name,$entid,$xml) = &get_entity($var); + print "\nimporting entity $entid\n"; + + #check if config file indicates entity attributes are to be added and add them to the parsed xml as needed + my $attr = get_attr_xml($xpc,$xml); + $xml = $attr if ($attr); + + my $code = &call_api($name,$entid,$xml,$enable); + $i++ if ($code == 201); + $j++ if ($code == 409); + } + + } else { + print "\nprocessing MD file: $file ....\n"; + + open(my $fh,"$md/$file"); + read $fh, my $xml, -s $fh; + + my ($name,$entid) = &get_names($xpc); + + #check if config file indicates entity attributes are to be added and add them to the parsed xml as needed + my $attr = get_attr_xml($xpc,$xml); + $xml = $attr if ($attr); + + my $code = &call_api($name,$entid,$xml,$enable); + $i++ if ($code == 201); + $j++ if ($code == 409); + } + } + closedir $DH; + +#single file +} elsif (-f $md) { + my $xpc = &load_xml("$md"); + + #check if file is aggregate, or individual entity + my $root = $xpc->findnodes("/*[local-name()='EntitiesDescriptor']"); + + if ($root) { + print "\nprocessing aggregate file: $md ....\n"; + + my $entity = $xpc->findnodes("//*[local-name()='EntityDescriptor']"); + + foreach my $var ($entity->get_nodelist) { + my ($name,$entid,$xml) = &get_entity($var); + print "\nimporting entity $entid\n"; + + #check if config file indicates entity attributes are to be added and add them to the parsed xml as needed + my $attr = get_attr_xml($xpc,$xml); + $xml = $attr if ($attr); + + my $code = &call_api($name,$entid,$xml,$enable); + $i++ if ($code == 201); + $j++ if ($code == 409); + } + + } else { + print "\nprocessing MD file: $md ....\n"; + + open(my $fh,$md); + read $fh, my $xml, -s $fh; + + my ($name,$entid) = &get_names($xpc); + + #check if config file indicates entity attributes are to be added and add them to the parsed xml as needed + my $attr = get_attr_xml($xpc,$xml); + $xml = $attr if ($attr); + + my $code = &call_api($name,$entid,$xml,$enable); + $i++ if ($code == 201); + $j++ if ($code == 409); + } + +} else { + print "$md can not be found\n"; + exit 1; +} + +print "\nmetadata uploaded: $i\nduplicate: $j\n"; + +sub load_xml { + my $file = shift; + + my $dom = XML::LibXML->load_xml(location => "$file"); + my $xpc = XML::LibXML::XPathContext->new(); + $xpc->registerNs('md', 'urn:oasis:names:tc:SAML:2.0:metadata'); + $xpc->registerNs('mdui', 'urn:oasis:names:tc:SAML:metadata:ui'); + $xpc->setContextNode($dom); + return $xpc; +} + +sub get_cookie_value { + my $cookies = $_[0]; + my $name = $_[1]; + my $result = 0; + + $cookies->scan(sub + { + if ($_[1] eq $name) + { + $result = $_[2]; + }; + }); + + return $result; +} + +sub get_names { + my $node = shift; + my $name; + + my $entid = $node->findnodes("//*[local-name()='EntityDescriptor']/\@entityID"); + my $orgname = $node->findnodes("//*[local-name()='Organization']/*[local-name()='OrganizationDisplayName']/text()"); + my $uiname = $node->findnodes("//*[local-name()='UIInfo']/*[local-name()='DisplayName']/text()"); + $name = ($orgname) ? $orgname : $entid; + $name = ($uiname) ? $uiname : $name; + + return ($name,$entid); +} + + +sub call_api { + my $name = shift; + my $entid = shift; + my $xml = shift; + my $enable = shift; + my ($params,$code,$result); + + my $utf8 = encode_utf8($xml); + + $params = "?spName=$name"; + $params .= "&enableService=true" if ($enable); + + $client->addHeader('Content-Type', "application/xml; charset='utf8'"); + $client->POST("/api/EntityDescriptor$params",$utf8); + + $code = $client->responseCode(); + $result = $client->responseContent(); + + if ($code == 201) { + + if ($enable =~ m/true/) { + + my $res = JSON->new->decode($result); + my $id = $res->{id}; + + $client->PATCH("/api/activate/entityDescriptor/$id/enable"); + + my $ecode = $client->responseCode(); + my $eresult = $client->responseContent(); + + if ($ecode == 200 || $ecode == 201) { + print "$ecode: entity $name uploaded sucessfully and enabled\n"; + } else { + print "$ecode: entity $name uploaded sucessfully but enabling failed:\n"; + open(my $pipe, '|-', "jq ."); + print $pipe $eresult; + } + + } else { + print "$code: entity $name uploaded sucessfully\n"; + } + } elsif ($code == 409) { + print "$code: entity $name already exists\n"; + } elsif ($code == 500) { + print "$code: $result\n"; + } else { + open(my $pipe, '|-', "jq ."); + print $pipe $result; + } + + return $code; +} + +sub get_entity { + my $node = shift; + + my $entid = $node->findnodes('./@entityID'); + my $orgname = $node->findnodes("./*[local-name()='Organization']/*[local-name()='OrganizationDisplayName']/text()"); + my $uiname = $node->findnodes("./*[local-name()='SPSSODescriptor']/*[local-name()='Extensions']/*[local-name()='UIInfo']/*[local-name()='DisplayName']/text()"); + my $name = ($orgname) ? $orgname : $entid; + $name = ($uiname) ? $uiname : $name; + + #have to add the NS from EntityDescriptor so each parsed xml fragment is valid + my $ns = qq(xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport" xmlns:mdrpi="urn:oasis:names:tc:SAML:metadata:rpi" xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:mdui="urn:oasis:names:tc:SAML:metadata:ui" xmlns:remd="http://refeds.org/metadata" xmlns:idpdisc="urn:oasis:names:tc:SAML:profiles:SSO:idp-discovery-protocol" xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"); + + $node =~ s/\\n{attr}; + my ($nxml,$vxml); + + if ($attr) { + my $n = keys %$attr; + + #if md:Extensions + my $ext = $xpc->findnodes("//*[local-name()='Extensions']"); + if ($ext) { + my $ea = $xpc->findnodes("//*[local-name()='EntityAttributes']"); + if ($ea) { + $nxml .= &create_attrs($attr,$n); + $xml =~ s/\<\/mdattr\:EntityAttributes\>/$nxml<\/mdattr:EntityAttributes>/; + } else { + $nxml = qq(); + $nxml .= &create_attrs($attr,$n); + $nxml .= qq(); + + $xml =~ s/\<\/md\:Extensions\>/$nxml<\/md:Extensions>/; + } + } else { + $nxml = qq(); + $nxml .= qq(); + $nxml .= &create_attrs($attr,$n); + $nxml .= qq(); + $nxml .= qq(); + + $xml =~ s/\<\/md\:EntityDescriptor\>/$nxml<\/md:EntityDescriptor>/; + } + + return $xml; + } +return 0; +} + +sub create_attrs { + my $attr = shift; + my $n = shift; + my ($nxml,$vxml); + + for(my $i = 0; $i < $n; $i++){ + my @val; + my $afname = $attr->{$i}{FriendlyName}; + my $aname = $attr->{$i}{Name}; + my $atype = $attr->{$i}{type}; + my $avalue = $attr->{$i}{Value}; + + if (ref $avalue eq ref {}) { + my $n = keys %$avalue; + for(my $j = 0; $j < $n; $j++){ + push(@val,$attr->{$i}{Value}{$j}); + } + } else { + push(@val,$avalue); + } + + undef $vxml; + foreach my $var (@val) { + $vxml .= qq($var\n); + } + $vxml =~ s/\n$//; + + $nxml .= qq( + + $vxml + ); + + } + $nxml =~ s/\<\/saml2\:Attribute\>$/<\/saml2:Attribute>\n/; + + return $nxml; +} diff --git a/bulk-upload/run.sh b/bulk-upload/run.sh new file mode 100755 index 000000000..86c128c6f --- /dev/null +++ b/bulk-upload/run.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +MD=$1 +LAST=$(basename "$MD") + +if [ -z "$1" ];then +echo "usage: ./run.sh or -e (to enable metadata as it is uploaded)"; +exit 1; +fi + +if [ -z "${1%%/*}" ];then + docker run --network=host --mount type=bind,source=$MD,target=/opt/$LAST --mount type=bind,source=$PWD/upload.conf,target=/opt/conf/upload.conf -t unicon/shibui-bulk-upload -m /opt/$LAST $2 +else + docker run --network=host --mount type=bind,source=$PWD/$MD,target=/opt/$LAST --mount type=bind,source=$PWD/upload.conf,target=/opt/conf/upload.conf -t unicon/shibui-bulk-upload -m /opt/$LAST $2 +fi diff --git a/bulk-upload/upload.conf b/bulk-upload/upload.conf new file mode 100644 index 000000000..b0a82d6e5 --- /dev/null +++ b/bulk-upload/upload.conf @@ -0,0 +1,35 @@ + +##shibui API info +#required + +api_user=root +api_pass=letmein7 +api_host=https://shibui.unicon.local + +#if the API is running with self signed certs +api_selfsigned=true + +## + +##EntityAttributes +#optional +#this configuration will transform these entity attribute values into xml and add them to the parsed xml as it us uploaded +#to add more attributes copy the first block and increment the index + +#single value example + +#attr[0][FriendlyName] = signAssertions +#attr[0][Name] = http://shibboleth.net/ns/profiles/saml2/sso/browser/signAssertions +#attr[0][type] = xsd:boolean +#attr[0][Value] = false + +#multi value example + +#attr[1][FriendlyName] = nameIDFormatPrecedence +#attr[1][Name] = http://shibboleth.net/ns/profiles/nameIDFormatPrecedence +#attr[1][type] = xsd:string +#attr[1][Value][0] = urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress +#attr[1][Value][1] = urn:oasis:names:tc:SAML:2.0:nameid-format:transient +#attr[1][Value][2] = urn:oasis:names:tc:SAML:2.0:nameid-format:persistent + +## \ No newline at end of file From b41c6452a5bf056ead8cea4b1f9634b201f98ef4 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Thu, 8 Sep 2022 10:01:30 -0700 Subject: [PATCH 50/71] SHIBUI-2270 Code clean up from Dima's code review comments --- ...rsEntityDescriptorVersionServiceTests.groovy | 4 ++-- .../JPAMetadataResolverServiceImpl.groovy | 6 +++--- .../MigrationTasksContextLoadedListener.java | 4 ---- .../admin/ui/controller/ActivateController.java | 13 +++++++------ .../ui/controller/ActivateExceptionHandler.java | 8 ++++---- .../controller/AttributeBundleController.java | 11 ++++------- .../AttributeBundleExceptionHandler.java | 6 +++--- .../controller/EntityDescriptorController.java | 17 ++++++++--------- ...ityDescriptorControllerExceptionHandler.java | 6 +++--- .../ui/controller/ShibPropertiesController.java | 17 +++++++++-------- ...hibPropertiesControllerExceptionHandler.java | 8 ++++---- ...ption.java => PersistentEntityNotFound.java} | 4 ++-- .../ui/security/controller/GroupController.java | 10 +++++----- .../GroupControllerExceptionHandler.java | 6 +++--- .../ui/security/controller/RolesController.java | 9 +++++---- .../controller/RolesExceptionHandler.java | 8 ++++---- .../ui/security/controller/UsersController.java | 4 ++-- .../ui/security/service/GroupServiceImpl.java | 8 ++++---- .../ui/security/service/IGroupService.java | 7 +++---- .../ui/security/service/IRolesService.java | 8 ++++---- .../ui/security/service/RolesServiceImpl.java | 12 ++++++------ .../admin/ui/security/service/UserService.java | 6 +++--- .../ui/service/AttributeBundleService.java | 14 +++++++------- ...omEntityAttributesDefinitionServiceImpl.java | 5 +---- .../ui/service/EntityDescriptorService.java | 17 +++++++++-------- .../service/EntityDescriptorVersionService.java | 9 +++++---- .../EnversEntityDescriptorVersionService.java | 13 +++++++------ .../admin/ui/service/FilterService.java | 7 ++++--- .../service/JPAEntityDescriptorServiceImpl.java | 17 +++++++++-------- .../admin/ui/service/JPAFilterServiceImpl.java | 8 +++----- .../ui/service/MetadataResolverService.java | 5 ++--- .../ui/service/ShibConfigurationService.java | 8 ++++---- .../service/ShibConfigurationServiceImpl.java | 14 +++++++------- .../ui/configuration/TestConfiguration.groovy | 1 - .../AttributeBundleControllerTests.groovy | 8 ++++---- .../EntityDescriptorControllerTests.groovy | 4 ++-- .../MetadataFiltersControllerTests.groovy | 4 ++-- .../ShibPropertiesControllerTests.groovy | 12 ++++-------- .../EntityDescriptorRepositoryTest.groovy | 3 +-- .../GroupsControllerIntegrationTests.groovy | 7 +++---- 40 files changed, 162 insertions(+), 176 deletions(-) rename backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/{EntityNotFoundException.java => PersistentEntityNotFound.java} (58%) diff --git a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy index f996c534d..76ca684e8 100644 --- a/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy +++ b/backend/src/enversTest/groovy/edu/internet2/tier/shibboleth/admin/ui/service/envers/EnversEntityDescriptorVersionServiceTests.groovy @@ -6,7 +6,7 @@ import edu.internet2.tier.shibboleth.admin.ui.configuration.Internationalization import edu.internet2.tier.shibboleth.admin.ui.configuration.SearchConfiguration import edu.internet2.tier.shibboleth.admin.ui.configuration.TestConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository import edu.internet2.tier.shibboleth.admin.ui.repository.envers.EnversTestsSupport import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService @@ -121,7 +121,7 @@ class EnversEntityDescriptorVersionServiceTests extends Specification { def edRepresentation = entityDescriptorVersionService.findSpecificVersionOfEntityDescriptor(ed.resourceId, '1000') false } - catch (EntityNotFoundException expected) { + catch (PersistentEntityNotFound expected) { true } } 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 bb86a1915..f207512ae 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 @@ -26,7 +26,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.ResourceBackedMet import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.TemplateScheme import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.opensaml.Refilterable -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException import edu.internet2.tier.shibboleth.admin.ui.exception.InitializationException import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects @@ -498,10 +498,10 @@ class JPAMetadataResolverServiceImpl implements MetadataResolverService { } } - public edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver findByResourceId(String resourceId) throws EntityNotFoundException { + public edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver findByResourceId(String resourceId) throws PersistentEntityNotFound { edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver result = metadataResolverRepository.findByResourceId(resourceId) if (result == null ) { - throw new EntityNotFoundException("No Provider with resourceId[" + resourceId + "] was found") + throw new PersistentEntityNotFound("No Provider with resourceId[" + resourceId + "] was found") } return result } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/MigrationTasksContextLoadedListener.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/MigrationTasksContextLoadedListener.java index 4dbe3656d..d9dc38c1e 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/MigrationTasksContextLoadedListener.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/configuration/auto/MigrationTasksContextLoadedListener.java @@ -1,7 +1,5 @@ package edu.internet2.tier.shibboleth.admin.ui.configuration.auto; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; -import edu.internet2.tier.shibboleth.admin.ui.security.exception.InvalidGroupRegexException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; @@ -16,8 +14,6 @@ import edu.internet2.tier.shibboleth.admin.ui.security.service.IGroupService; import edu.internet2.tier.shibboleth.admin.ui.security.service.UserService; -import java.util.List; - /** * After the context loads, do any needed migration tasks */ 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 c9e0f20f5..487bd56c2 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 @@ -5,12 +5,10 @@ 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; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @@ -18,7 +16,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InitializationException; import edu.internet2.tier.shibboleth.admin.ui.service.EntityDescriptorService; @@ -41,7 +39,8 @@ public class ActivateController { @PatchMapping(path = "/entityDescriptor/{resourceId}/{mode}") @Transactional - public ResponseEntity enableEntityDescriptor(@PathVariable String resourceId, @PathVariable String mode) throws EntityNotFoundException, ForbiddenException { + public ResponseEntity enableEntityDescriptor(@PathVariable String resourceId, @PathVariable String mode) throws + PersistentEntityNotFound, ForbiddenException { boolean status = "enable".equalsIgnoreCase(mode); EntityDescriptorRepresentation edr = entityDescriptorService.updateEntityDescriptorEnabledStatus(resourceId, status); return ResponseEntity.ok(edr); @@ -49,7 +48,8 @@ public ResponseEntity enableEntityDescriptor(@PathVariable String resourceId, @PatchMapping(path = "/MetadataResolvers/{metadataResolverId}/Filter/{resourceId}/{mode}") @Transactional - public ResponseEntity enableFilter(@PathVariable String metadataResolverId, @PathVariable String resourceId, @PathVariable String mode) throws EntityNotFoundException, ForbiddenException, ScriptException { + public ResponseEntity enableFilter(@PathVariable String metadataResolverId, @PathVariable String resourceId, @PathVariable String mode) throws + PersistentEntityNotFound, ForbiddenException, ScriptException { boolean status = "enable".equalsIgnoreCase(mode); MetadataFilter persistedFilter = filterService.updateFilterEnabledStatus(metadataResolverId, resourceId, status); return ResponseEntity.ok(persistedFilter); @@ -57,7 +57,8 @@ public ResponseEntity enableFilter(@PathVariable String metadataResolverId, @ @PatchMapping("/MetadataResolvers/{resourceId}/{mode}") @Transactional - public ResponseEntity enableProvider(@PathVariable String resourceId, @PathVariable String mode) throws EntityNotFoundException, ForbiddenException, MetadataFileNotFoundException, InitializationException { + public ResponseEntity enableProvider(@PathVariable String resourceId, @PathVariable String mode) throws + PersistentEntityNotFound, ForbiddenException, MetadataFileNotFoundException, InitializationException { boolean status = "enable".equalsIgnoreCase(mode); MetadataResolver existingResolver = metadataResolverService.findByResourceId(resourceId); existingResolver.setEnabled(status); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateExceptionHandler.java index 0c766c53c..fe6f7c0f2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ActivateExceptionHandler.java @@ -12,15 +12,15 @@ import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; import edu.internet2.tier.shibboleth.admin.ui.domain.exceptions.MetadataFileNotFoundException; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InitializationException; @ControllerAdvice(assignableTypes = {ActivateController.class}) public class ActivateExceptionHandler extends ResponseEntityExceptionHandler { - @ExceptionHandler({ EntityNotFoundException.class }) - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { + @ExceptionHandler({ PersistentEntityNotFound.class }) + public ResponseEntity handleEntityNotFoundException(PersistentEntityNotFound e, WebRequest request) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(HttpStatus.NOT_FOUND, e.getMessage())); } @@ -45,4 +45,4 @@ public ResponseEntity handleScriptException(ScriptException e, WebRequest req } -} +} \ 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 92c498781..53335d340 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 @@ -1,11 +1,8 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; -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.service.AttributeBundleService; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; @@ -42,7 +39,7 @@ public ResponseEntity create(@RequestBody AttributeBundle bundle) throws Obje @Secured("ROLE_ADMIN") @DeleteMapping("/{resourceId}") @Transactional - public ResponseEntity delete(@PathVariable String resourceId) throws EntityNotFoundException { + public ResponseEntity delete(@PathVariable String resourceId) throws PersistentEntityNotFound { attributeBundleService.deleteDefinition(resourceId); return ResponseEntity.noContent().build(); } @@ -55,14 +52,14 @@ public ResponseEntity getAll() { @GetMapping("/{resourceId}") @Transactional(readOnly = true) - public ResponseEntity getOne(@PathVariable String resourceId) throws EntityNotFoundException { + public ResponseEntity getOne(@PathVariable String resourceId) throws PersistentEntityNotFound { return ResponseEntity.ok(attributeBundleService.findByResourceId(resourceId)); } @Secured("ROLE_ADMIN") @PutMapping @Transactional - public ResponseEntity update(@RequestBody AttributeBundle bundle) throws EntityNotFoundException { + public ResponseEntity update(@RequestBody AttributeBundle bundle) throws PersistentEntityNotFound { AttributeBundle result = attributeBundleService.updateBundle(bundle); return ResponseEntity.ok(result); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleExceptionHandler.java index 9f5266c3c..44f32f6ea 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleExceptionHandler.java @@ -1,6 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -12,8 +12,8 @@ @ControllerAdvice(assignableTypes = {AttributeBundleController.class}) public class AttributeBundleExceptionHandler extends ResponseEntityExceptionHandler { - @ExceptionHandler({ EntityNotFoundException.class }) - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { + @ExceptionHandler({ PersistentEntityNotFound.class }) + public ResponseEntity handleEntityNotFoundException(PersistentEntityNotFound e, WebRequest request) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(HttpStatus.NOT_FOUND, e.getMessage())); } 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 81d62a1ad..f7cfb019a 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 @@ -2,14 +2,13 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; 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.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tags; import lombok.extern.slf4j.Slf4j; @@ -34,7 +33,6 @@ import javax.annotation.PostConstruct; import java.net.URI; import java.util.ConcurrentModificationException; -import java.util.Optional; @RestController @RequestMapping("/api") @@ -77,7 +75,7 @@ public ResponseEntity create(@RequestBody EntityDescriptorRepresentation edRe @Secured("ROLE_ADMIN") @DeleteMapping(value = "/EntityDescriptor/{resourceId}") @Transactional - public ResponseEntity deleteOne(@PathVariable String resourceId) throws ForbiddenException, EntityNotFoundException { + public ResponseEntity deleteOne(@PathVariable String resourceId) throws ForbiddenException, PersistentEntityNotFound { entityDescriptorService.delete(resourceId); return ResponseEntity.noContent().build(); } @@ -90,7 +88,7 @@ public ResponseEntity getAll() throws ForbiddenException { @GetMapping("/EntityDescriptor/{resourceId}/Versions") @Transactional - public ResponseEntity getAllVersions(@PathVariable String resourceId) throws EntityNotFoundException, ForbiddenException { + public ResponseEntity getAllVersions(@PathVariable String resourceId) throws PersistentEntityNotFound, ForbiddenException { // this "get by resource id" verifies that both the ED exists and the user has proper access, so needs to remain EntityDescriptor ed = entityDescriptorService.getEntityDescriptorByResourceId(resourceId); return ResponseEntity.ok(versionService.findVersionsForEntityDescriptor(ed.getResourceId())); @@ -105,21 +103,22 @@ public Iterable getDisabledAndNotOwnedByAdmin() @GetMapping("/EntityDescriptor/{resourceId}") @Transactional - public ResponseEntity getOne(@PathVariable String resourceId) throws EntityNotFoundException, ForbiddenException { + public ResponseEntity getOne(@PathVariable String resourceId) throws PersistentEntityNotFound, ForbiddenException { return ResponseEntity.ok(entityDescriptorService .createRepresentationFromDescriptor(entityDescriptorService.getEntityDescriptorByResourceId(resourceId))); } @GetMapping(value = "/EntityDescriptor/{resourceId}", produces = "application/xml") @Transactional - public ResponseEntity getOneXml(@PathVariable String resourceId) throws MarshallingException, EntityNotFoundException, ForbiddenException { + public ResponseEntity getOneXml(@PathVariable String resourceId) throws MarshallingException, PersistentEntityNotFound, ForbiddenException { EntityDescriptor ed = entityDescriptorService.getEntityDescriptorByResourceId(resourceId); final String xml = this.openSamlObjects.marshalToXmlString(ed); return ResponseEntity.ok(xml); } @GetMapping("/EntityDescriptor/{resourceId}/Versions/{versionId}") - public ResponseEntity getSpecificVersion(@PathVariable String resourceId, @PathVariable String versionId) throws EntityNotFoundException, ForbiddenException { + public ResponseEntity getSpecificVersion(@PathVariable String resourceId, @PathVariable String versionId) throws + PersistentEntityNotFound, ForbiddenException { // this "get by resource id" verifies that both the ED exists and the user has proper access, so needs to remain EntityDescriptor ed = entityDescriptorService.getEntityDescriptorByResourceId(resourceId); EntityDescriptorRepresentation result = versionService.findSpecificVersionOfEntityDescriptor(ed.getResourceId(), versionId); @@ -146,7 +145,7 @@ public void initRestTemplate() { @PutMapping("/EntityDescriptor/{resourceId}") @Transactional public ResponseEntity update(@RequestBody EntityDescriptorRepresentation edRepresentation, @PathVariable String resourceId) - throws ForbiddenException, ConcurrentModificationException, EntityNotFoundException, + throws ForbiddenException, ConcurrentModificationException, PersistentEntityNotFound, InvalidPatternMatchException { edRepresentation.setId(resourceId); // This should be the same already, but just to be safe... EntityDescriptorRepresentation result = entityDescriptorService.update(edRepresentation); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerExceptionHandler.java index 32d3cd4be..e1afe9413 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerExceptionHandler.java @@ -1,6 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; @@ -22,8 +22,8 @@ public ResponseEntity handleConcurrentModificationException(ConcurrentModific return ResponseEntity.status(HttpStatus.CONFLICT).body(new ErrorResponse(HttpStatus.CONFLICT, e.getMessage())); } - @ExceptionHandler({ EntityNotFoundException.class }) - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { + @ExceptionHandler({ PersistentEntityNotFound.class }) + public ResponseEntity handleEntityNotFoundException(PersistentEntityNotFound e, WebRequest request) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(HttpStatus.NOT_FOUND, e.getMessage())); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java index b613c2b4f..b9936633a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesController.java @@ -2,7 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySet; import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySetting; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.service.ShibConfigurationService; import io.swagger.v3.oas.annotations.Operation; @@ -41,8 +41,8 @@ public class ShibPropertiesController { @GetMapping("/properties") @Transactional(readOnly = true) - @Operation(description = "Return all the configuration properties - used to populate the UI with the know configuration properties", - summary = "Return all the configuration properties - used to populate the UI with the know configuration properties", method = "GET") + @Operation(description = "Return all the configuration properties - used to populate the UI with the known configuration properties", + summary = "Return all the configuration properties - used to populate the UI with the known configuration properties", method = "GET") public ResponseEntity getAllConfigurationProperties() { return ResponseEntity.ok(service.getAllConfigurationProperties()); } @@ -62,7 +62,7 @@ public ResponseEntity getAllPropertySets() { @Transactional(readOnly = true) @Operation(description = "Return the property set with the given resourceId", summary = "Return the property set with the given resourceId", method = "GET") - public ResponseEntity getPropertySet(@PathVariable Integer resourceId) throws EntityNotFoundException { + public ResponseEntity getPropertySet(@PathVariable Integer resourceId) throws PersistentEntityNotFound { return ResponseEntity.ok(service.getSet(resourceId)); } @@ -70,7 +70,7 @@ public ResponseEntity getPropertySet(@PathVariable Integer resourceId) throws @Transactional(readOnly = true) @Operation(description = "Return the property set with the given resourceId as a zip file of the properties files", summary = "Return the property set with the given resourceId as a zip file of the properties files", method = "GET") - public ResponseEntity getPropertySetAsZip(@PathVariable Integer resourceId) throws EntityNotFoundException, IOException { + public ResponseEntity getPropertySetAsZip(@PathVariable Integer resourceId) throws PersistentEntityNotFound, IOException { ShibPropertySet set = service.getSet(resourceId); StringBuilder sb = new StringBuilder("attachment; filename=\"").append(set.getName()).append(".zip\""); return ResponseEntity.ok().header("Content-Disposition", sb.toString()).body(prepDownloadAsZip(convertPropertiesToMaps(set.getProperties()))); @@ -80,7 +80,7 @@ public ResponseEntity getPropertySetAsZip(@PathVariable Integer resourceId) t @Transactional(readOnly = true) @Operation(description = "Return the property set with the given resourceId as a zip file of a single properties files", summary = "Return the property set with the given resourceId as a zip file of a single properties files", method = "GET") - public ResponseEntity getPropertySetOneFileAsZip(@PathVariable Integer resourceId) throws EntityNotFoundException, IOException { + public ResponseEntity getPropertySetOneFileAsZip(@PathVariable Integer resourceId) throws PersistentEntityNotFound, IOException { ShibPropertySet set = service.getSet(resourceId); StringBuilder sb = new StringBuilder("attachment; filename=\"").append(set.getName()).append(".zip\""); return ResponseEntity.ok().header("Content-Disposition", sb.toString()).body(prepDownloadAsZipWithSingleFile(convertPropertiesToMaps(set.getProperties()))); @@ -141,7 +141,7 @@ private byte[] prepDownloadAsZip(Map> propertiesFiles @DeleteMapping("/property/set/{resourceId}") @Secured("ROLE_ADMIN") @Transactional - public ResponseEntity deletePropertySet(@PathVariable Integer resourceId) throws EntityNotFoundException { + public ResponseEntity deletePropertySet(@PathVariable Integer resourceId) throws PersistentEntityNotFound { service.delete(resourceId); return ResponseEntity.noContent().build(); } @@ -161,7 +161,8 @@ public ResponseEntity createPropertySet(@RequestBody ShibPropertySet newSet) @Transactional @Operation(description = "Update a property set with with the matching resourceId - must exist", summary = "Update an existing property set with the matching resourceId - must exist", method = "PUT") - public ResponseEntity updatePropertySet(@RequestBody ShibPropertySet setToUpdate, @PathVariable int resourceId) throws EntityNotFoundException { + public ResponseEntity updatePropertySet(@RequestBody ShibPropertySet setToUpdate, @PathVariable int resourceId) throws + PersistentEntityNotFound { ShibPropertySet result = service.update(setToUpdate); return ResponseEntity.status(HttpStatus.OK).body(result); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java index cbc9cb133..c75005a39 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerExceptionHandler.java @@ -1,7 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.controller; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -14,13 +14,13 @@ @ControllerAdvice(assignableTypes = {ShibPropertiesController.class}) public class ShibPropertiesControllerExceptionHandler extends ResponseEntityExceptionHandler { - @ExceptionHandler({ EntityNotFoundException.class }) - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { + @ExceptionHandler({ PersistentEntityNotFound.class }) + public ResponseEntity handleEntityNotFoundException(PersistentEntityNotFound e, WebRequest request) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(HttpStatus.NOT_FOUND, e.getMessage())); } @ExceptionHandler({ IOException.class }) - public ResponseEntity handleIOException(EntityNotFoundException e, WebRequest request) { + public ResponseEntity handleIOException(IOException e, WebRequest request) { return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Error creating file"); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/EntityNotFoundException.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/PersistentEntityNotFound.java similarity index 58% rename from backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/EntityNotFoundException.java rename to backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/PersistentEntityNotFound.java index 212c9f990..b7dc72f33 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/EntityNotFoundException.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/exception/PersistentEntityNotFound.java @@ -3,8 +3,8 @@ /** * Generically meaning - hibernate entity, not SAML entity */ -public class EntityNotFoundException extends Exception { - public EntityNotFoundException(String message) { +public class PersistentEntityNotFound extends Exception { + public PersistentEntityNotFound(String message) { super(message); } } \ 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 c287a14a7..8293c9b04 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,6 +1,6 @@ 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.exception.PersistentEntityNotFound; 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; @@ -40,7 +40,7 @@ public ResponseEntity create(@RequestBody Group group) throws GroupExistsConf @Secured("ROLE_ADMIN") @DeleteMapping("/{resourceId}") @Transactional - public ResponseEntity delete(@PathVariable String resourceId) throws EntityNotFoundException, GroupDeleteException { + public ResponseEntity delete(@PathVariable String resourceId) throws PersistentEntityNotFound, GroupDeleteException { groupService.deleteDefinition(resourceId); return ResponseEntity.noContent().build(); } @@ -53,10 +53,10 @@ public ResponseEntity getAll() { @GetMapping("/{resourceId}") @Transactional(readOnly = true) - public ResponseEntity getOne(@PathVariable String resourceId) throws EntityNotFoundException { + public ResponseEntity getOne(@PathVariable String resourceId) throws PersistentEntityNotFound { Group g = groupService.find(resourceId); if (g == null) { - throw new EntityNotFoundException(String.format("Unable to find group with resource id: [%s]", resourceId)); + throw new PersistentEntityNotFound(String.format("Unable to find group with resource id: [%s]", resourceId)); } return ResponseEntity.ok(g); } @@ -64,7 +64,7 @@ public ResponseEntity getOne(@PathVariable String resourceId) throws EntityNo @Secured("ROLE_ADMIN") @PutMapping @Transactional - public ResponseEntity update(@RequestBody Group group) throws EntityNotFoundException, InvalidGroupRegexException { + public ResponseEntity update(@RequestBody Group group) throws PersistentEntityNotFound, InvalidGroupRegexException { Group result = groupService.updateGroup(group); return ResponseEntity.ok(result); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupControllerExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupControllerExceptionHandler.java index 39778e21a..b382f50ca 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupControllerExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupControllerExceptionHandler.java @@ -11,15 +11,15 @@ 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.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupDeleteException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.GroupExistsConflictException; @ControllerAdvice(assignableTypes = {GroupController.class}) public class GroupControllerExceptionHandler extends ResponseEntityExceptionHandler { - @ExceptionHandler({ EntityNotFoundException.class }) - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { + @ExceptionHandler({ PersistentEntityNotFound.class }) + public ResponseEntity handleEntityNotFoundException(PersistentEntityNotFound e, WebRequest request) { HttpHeaders headers = new HttpHeaders(); headers.setLocation(ServletUriComponentsBuilder.fromCurrentServletMapping().path("/api/admin/groups").build().toUri()); 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 539dc3195..9b549efb3 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 @@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleDeleteException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleExistsConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.model.Role; @@ -42,7 +42,7 @@ public ResponseEntity create(@RequestBody Role role) throws RoleExistsConflic @Secured("ROLE_ADMIN") @DeleteMapping("/{resourceId}") @Transactional - public ResponseEntity delete(@PathVariable String resourceId) throws EntityNotFoundException, RoleDeleteException { + public ResponseEntity delete(@PathVariable String resourceId) throws PersistentEntityNotFound, RoleDeleteException { rolesService.deleteDefinition(resourceId); return ResponseEntity.noContent().build(); } @@ -55,7 +55,7 @@ public ResponseEntity getAll() { @GetMapping("/{resourceId}") @Transactional(readOnly = true) - public ResponseEntity getOne(@PathVariable String resourceId) throws EntityNotFoundException { + public ResponseEntity getOne(@PathVariable String resourceId) throws PersistentEntityNotFound { Role role = rolesService.findByResourceId(resourceId); return ResponseEntity.ok(role); } @@ -63,7 +63,8 @@ public ResponseEntity getOne(@PathVariable String resourceId) throws EntityNo @Secured("ROLE_ADMIN") @PutMapping(path = {"/", "/{resourceId}" }) @Transactional - public ResponseEntity update(@RequestBody Role incomingRoleDetail, @PathVariable Optional resourceId) throws EntityNotFoundException { + public ResponseEntity update(@RequestBody Role incomingRoleDetail, @PathVariable Optional resourceId) throws + PersistentEntityNotFound { Role updateRole; if (resourceId.isPresent()) { updateRole = rolesService.findByResourceId(resourceId.get()); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesExceptionHandler.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesExceptionHandler.java index e4b840f1a..494b1a6b1 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesExceptionHandler.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/controller/RolesExceptionHandler.java @@ -10,15 +10,15 @@ 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.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleDeleteException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleExistsConflictException; @ControllerAdvice(assignableTypes = {RolesController.class}) public class RolesExceptionHandler extends ResponseEntityExceptionHandler { - @ExceptionHandler({ EntityNotFoundException.class }) - public ResponseEntity handleEntityNotFoundException(EntityNotFoundException e, WebRequest request) { + @ExceptionHandler({ PersistentEntityNotFound.class }) + public ResponseEntity handleEntityNotFoundException(PersistentEntityNotFound e, WebRequest request) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorResponse(HttpStatus.NOT_FOUND, e.getMessage())); } @@ -35,4 +35,4 @@ public ResponseEntity handleForbiddenAccess(RoleDeleteException e, WebRequest public ResponseEntity handleRoleExistsConflictException(RoleExistsConflictException e, WebRequest request) { return ResponseEntity.status(HttpStatus.CONFLICT).body(new ErrorResponse(HttpStatus.CONFLICT, e.getMessage())); } -} +} \ 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 a281adc10..ed39250b4 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 @@ -26,7 +26,7 @@ import org.springframework.web.client.HttpClientErrorException; 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.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.security.exception.OwnershipConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.model.User; import edu.internet2.tier.shibboleth.admin.ui.security.repository.UserRepository; @@ -56,7 +56,7 @@ public ResponseEntity deleteOne(@PathVariable String username) { try { userService.delete(username); } - catch (EntityNotFoundException e) { + catch (PersistentEntityNotFound e) { throw new HttpClientErrorException(NOT_FOUND, String.format("User with username [%s] not found", username)); } catch (OwnershipConflictException e) { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/GroupServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/GroupServiceImpl.java index 65ee10764..f329a5be2 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/GroupServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/GroupServiceImpl.java @@ -1,6 +1,6 @@ package edu.internet2.tier.shibboleth.admin.ui.security.service; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; 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; @@ -52,7 +52,7 @@ public Group createGroup(Group group) throws GroupExistsConflictException, Inval @Override @Transactional - public void deleteDefinition(String resourceId) throws EntityNotFoundException, GroupDeleteException { + public void deleteDefinition(String resourceId) throws PersistentEntityNotFound, GroupDeleteException { Group group = find(resourceId); if (!ownershipRepository.findAllByOwner(group).isEmpty()) { throw new GroupDeleteException(String.format( @@ -116,10 +116,10 @@ public List findAll() { } @Override - public Group updateGroup(Group group) throws EntityNotFoundException, InvalidGroupRegexException { + public Group updateGroup(Group group) throws PersistentEntityNotFound, InvalidGroupRegexException { Group g = find(group.getResourceId()); if (g == null) { - throw new EntityNotFoundException(String.format("Unable to find group with resource id: [%s] and name: [%s]", + throw new PersistentEntityNotFound(String.format("Unable to find group with resource id: [%s] and name: [%s]", group.getResourceId(), group.getName())); } validateGroupRegex(group); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IGroupService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IGroupService.java index d6e44e5ec..66fd089a9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IGroupService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IGroupService.java @@ -2,8 +2,7 @@ import java.util.List; -import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; 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; @@ -13,7 +12,7 @@ public interface IGroupService { Group createGroup(Group group) throws GroupExistsConflictException, InvalidGroupRegexException; - void deleteDefinition(String resourceId) throws EntityNotFoundException, GroupDeleteException; + void deleteDefinition(String resourceId) throws PersistentEntityNotFound, GroupDeleteException; void ensureAdminGroupExists(); @@ -21,7 +20,7 @@ public interface IGroupService { List findAll(); - Group updateGroup(Group g) throws EntityNotFoundException, InvalidGroupRegexException; + Group updateGroup(Group g) throws PersistentEntityNotFound, InvalidGroupRegexException; boolean doesStringMatchGroupPattern(String groupId, String uri); } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IRolesService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IRolesService.java index ac30d986a..46d3f81f5 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IRolesService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/IRolesService.java @@ -4,7 +4,7 @@ import java.util.Optional; import java.util.Set; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleDeleteException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleExistsConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.model.Role; @@ -17,13 +17,13 @@ public interface IRolesService { Optional findByName(String roleNone); - Role findByResourceId(String resourceId) throws EntityNotFoundException; + Role findByResourceId(String resourceId) throws PersistentEntityNotFound; Set getAndCreateAllRoles(Set roles); - void deleteDefinition(String resourceId) throws EntityNotFoundException, RoleDeleteException; + void deleteDefinition(String resourceId) throws PersistentEntityNotFound, RoleDeleteException; - Role updateRole(Role role) throws EntityNotFoundException; + Role updateRole(Role role) throws PersistentEntityNotFound; void save(Role newUserRole); } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/RolesServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/RolesServiceImpl.java index 939be59d8..18385084b 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/RolesServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/RolesServiceImpl.java @@ -8,7 +8,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleDeleteException; import edu.internet2.tier.shibboleth.admin.ui.security.exception.RoleExistsConflictException; import edu.internet2.tier.shibboleth.admin.ui.security.model.Role; @@ -31,7 +31,7 @@ public Role createRole(Role role) throws RoleExistsConflictException { } @Override - public void deleteDefinition(String resourceId) throws EntityNotFoundException, RoleDeleteException { + public void deleteDefinition(String resourceId) throws PersistentEntityNotFound, RoleDeleteException { Optional found = roleRepository.findByResourceId(resourceId); if (found.isPresent() && !found.get().getUsers().isEmpty()) { throw new RoleDeleteException(String.format("Unable to delete role with resource id: [%s] - remove role from all users first", resourceId)); @@ -50,10 +50,10 @@ public Optional findByName(String roleName) { } @Override - public Role findByResourceId(String resourceId) throws EntityNotFoundException { + public Role findByResourceId(String resourceId) throws PersistentEntityNotFound { Optional found = roleRepository.findByResourceId(resourceId); if (found.isEmpty()) { - throw new EntityNotFoundException(String.format("Unable to find role with resource id: [%s]", resourceId)); + throw new PersistentEntityNotFound(String.format("Unable to find role with resource id: [%s]", resourceId)); } return found.get(); } @@ -83,10 +83,10 @@ private Role getRoleNone() { } @Override - public Role updateRole(Role role) throws EntityNotFoundException { + public Role updateRole(Role role) throws PersistentEntityNotFound { Optional found = roleRepository.findByName(role.getName()); if (found.isEmpty()) { - throw new EntityNotFoundException(String.format("Unable to find role with name: [%s]", role.getName())); + throw new PersistentEntityNotFound(String.format("Unable to find role with name: [%s]", role.getName())); } return roleRepository.save(role); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/UserService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/UserService.java index df200f482..dfe21708a 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/UserService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/security/service/UserService.java @@ -2,7 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.IActivatable; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; 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.exception.OwnershipConflictException; @@ -82,9 +82,9 @@ public boolean currentUserIsAdmin() { } @Transactional - public void delete(String username) throws EntityNotFoundException, OwnershipConflictException { + public void delete(String username) throws PersistentEntityNotFound, OwnershipConflictException { Optional userToRemove = userRepository.findByUsername(username); - if (userToRemove.isEmpty()) throw new EntityNotFoundException("User does not exist"); + if (userToRemove.isEmpty()) throw new PersistentEntityNotFound("User does not exist"); if (!ownershipRepository.findOwnedByUser(username).isEmpty()) throw new OwnershipConflictException("User ["+username+"] has ownership of entities in the system. Please remove all items before attempting to delete the user."); // ok, user exists and doesn't own anything in the system, so delete them diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java index 916ea99b2..52b869693 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/AttributeBundleService.java @@ -1,7 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.service; import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.repository.AttributeBundleRepository; import org.springframework.beans.factory.annotation.Autowired; @@ -26,17 +26,17 @@ public List findAll() { return attributeBundleRepository.findAll(); } - public void deleteDefinition(String resourceId) throws EntityNotFoundException { + public void deleteDefinition(String resourceId) throws PersistentEntityNotFound { if (attributeBundleRepository.findByResourceId(resourceId).isEmpty()) { - throw new EntityNotFoundException(String.format("Unable to find attribute bundle with resource id: [%s] for deletion", resourceId)); + throw new PersistentEntityNotFound(String.format("Unable to find attribute bundle with resource id: [%s] for deletion", resourceId)); } attributeBundleRepository.deleteById(resourceId); } - public AttributeBundle updateBundle(AttributeBundle bundle) throws EntityNotFoundException { + public AttributeBundle updateBundle(AttributeBundle bundle) throws PersistentEntityNotFound { Optional dbBundle = attributeBundleRepository.findByResourceId(bundle.getResourceId()); if (dbBundle.isEmpty()) { - throw new EntityNotFoundException(String.format("Unable to find attribute bundle with resource id: [%s] for update", bundle.getResourceId())); + throw new PersistentEntityNotFound(String.format("Unable to find attribute bundle with resource id: [%s] for update", bundle.getResourceId())); } AttributeBundle bundleToUpdate = dbBundle.get(); bundleToUpdate.setName(bundle.getName()); @@ -44,10 +44,10 @@ public AttributeBundle updateBundle(AttributeBundle bundle) throws EntityNotFoun return attributeBundleRepository.save(bundleToUpdate); } - public AttributeBundle findByResourceId(String resourceId) throws EntityNotFoundException { + public AttributeBundle findByResourceId(String resourceId) throws PersistentEntityNotFound { Optional result = attributeBundleRepository.findByResourceId(resourceId); if (result.isEmpty()) { - throw new EntityNotFoundException(String.format("Unable to find attribute bundle with resource id: [%s] for deletion", resourceId)); + throw new PersistentEntityNotFound(String.format("Unable to find attribute bundle with resource id: [%s] for deletion", resourceId)); } return result.get(); } diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java index cd5893c42..98454c058 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/CustomEntityAttributesDefinitionServiceImpl.java @@ -17,10 +17,7 @@ public class CustomEntityAttributesDefinitionServiceImpl implements CustomEntityAttributesDefinitionService { @Autowired private ApplicationEventPublisher applicationEventPublisher; - - @Autowired - EntityManager entityManager; // Why is this here - it isn't used - + @Autowired private CustomEntityAttributeDefinitionRepository repository; diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java index 6ecf9073e..6d66732b0 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java @@ -3,7 +3,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute; import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; @@ -55,9 +55,9 @@ EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRepres /** * @param resourceId - id of the JPA EntityDescriptor * @throws ForbiddenException If user is unauthorized to perform this operation - * @throws EntityNotFoundException If the db entity is not found + * @throws PersistentEntityNotFound If the db entity is not found */ - void delete(String resourceId) throws ForbiddenException, EntityNotFoundException; + void delete(String resourceId) throws ForbiddenException, PersistentEntityNotFound; /** * @return - Iterable set of EntityDescriptorRepresentations of those items which are NOT enabled and not owned by @@ -83,9 +83,9 @@ EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRepres * @param resourceId - id of the JPA EntityDescriptor * @return JPA EntityDescriptor * @throws ForbiddenException If user is unauthorized to perform this operation - * @throws EntityNotFoundException If the db entity is not found + * @throws PersistentEntityNotFound If the db entity is not found */ - EntityDescriptor getEntityDescriptorByResourceId(String resourceId) throws EntityNotFoundException, ForbiddenException; + EntityDescriptor getEntityDescriptorByResourceId(String resourceId) throws PersistentEntityNotFound, ForbiddenException; /** * Given a list of attributes, generate a map of relying party overrides @@ -97,12 +97,12 @@ EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRepres /** * @throws ForbiddenException If the user is not permitted to perform the action - * @throws EntityNotFoundException If the entity doesn't already exist in the database + * @throws PersistentEntityNotFound If the entity doesn't already exist in the database * @throws ConcurrentModificationException IF the entity is being modified in another session * @throws InvalidPatternMatchException If the entity id or the ACS location urls don't match the supplied regex */ EntityDescriptorRepresentation update(EntityDescriptorRepresentation edRepresentation) - throws ForbiddenException, EntityNotFoundException, ConcurrentModificationException, + throws ForbiddenException, PersistentEntityNotFound, ConcurrentModificationException, InvalidPatternMatchException; /** @@ -113,7 +113,8 @@ EntityDescriptorRepresentation update(EntityDescriptorRepresentation edRepresent */ void updateDescriptorFromRepresentation(final org.opensaml.saml.saml2.metadata.EntityDescriptor entityDescriptor, final EntityDescriptorRepresentation representation); - EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resourceId, boolean status) throws EntityNotFoundException, ForbiddenException; + EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resourceId, boolean status) throws + PersistentEntityNotFound, ForbiddenException; EntityDescriptorRepresentation createNewEntityDescriptorFromXMLOrigin(EntityDescriptor ed); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java index c8c67fbc8..365fccb80 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorVersionService.java @@ -3,7 +3,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import java.util.List; @@ -12,7 +12,8 @@ */ public interface EntityDescriptorVersionService { - List findVersionsForEntityDescriptor(String resourceId) throws EntityNotFoundException; + List findVersionsForEntityDescriptor(String resourceId) throws PersistentEntityNotFound; - EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) throws EntityNotFoundException; -} + EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) throws + PersistentEntityNotFound; +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java index 99906882b..5857ac283 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EnversEntityDescriptorVersionService.java @@ -4,7 +4,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.versioning.Version; import edu.internet2.tier.shibboleth.admin.ui.envers.EnversVersionServiceSupport; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import java.util.List; @@ -23,20 +23,21 @@ public EnversEntityDescriptorVersionService(EnversVersionServiceSupport enversVe } @Override - public List findVersionsForEntityDescriptor(String resourceId) throws EntityNotFoundException { + public List findVersionsForEntityDescriptor(String resourceId) throws PersistentEntityNotFound { List results = enversVersionServiceSupport.findVersionsForPersistentEntity(resourceId, EntityDescriptor.class); if (results.isEmpty()) { - throw new EntityNotFoundException(String.format("No versions found for entity descriptor with resource id [%s].", resourceId)); + throw new PersistentEntityNotFound(String.format("No versions found for entity descriptor with resource id [%s].", resourceId)); } return results; } @Override - public EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) throws EntityNotFoundException { + public EntityDescriptorRepresentation findSpecificVersionOfEntityDescriptor(String resourceId, String versionId) throws + PersistentEntityNotFound { Object edObject = enversVersionServiceSupport.findSpecificVersionOfPersistentEntity(resourceId, versionId, EntityDescriptor.class); if (edObject == null) { - throw new EntityNotFoundException("Unable to find specific version requested - version: " + versionId); + throw new PersistentEntityNotFound("Unable to find specific version requested - version: " + versionId); } return entityDescriptorService.createRepresentationFromDescriptor((EntityDescriptor) edObject); } -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/FilterService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/FilterService.java index 6d752928b..d5823ef9f 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/FilterService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/FilterService.java @@ -5,7 +5,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; /** @@ -31,5 +31,6 @@ public interface FilterService { */ FilterRepresentation createRepresentationFromFilter(final EntityAttributesFilter entityAttributesFilter); - MetadataFilter updateFilterEnabledStatus(String metadataResolverId, String resourceId, boolean status) throws EntityNotFoundException, ForbiddenException, ScriptException; -} + MetadataFilter updateFilterEnabledStatus(String metadataResolverId, String resourceId, boolean status) throws + PersistentEntityNotFound, ForbiddenException, ScriptException; +} \ 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 ec5c28048..6269020e8 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 @@ -16,7 +16,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.OrganizationRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.SecurityInfoRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.ServiceProviderSsoDescriptorRepresentation; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; @@ -354,7 +354,7 @@ public EntityDescriptorRepresentation createRepresentationFromDescriptor(org.ope } @Override - public void delete(String resourceId) throws ForbiddenException, EntityNotFoundException { + public void delete(String resourceId) throws ForbiddenException, PersistentEntityNotFound { EntityDescriptor ed = getEntityDescriptorByResourceId(resourceId); if (ed.isServiceEnabled()) { throw new ForbiddenException("Deleting an enabled Metadata Source is not allowed. Disable the source and try again."); @@ -398,10 +398,10 @@ public List getAttributeReleaseListFromAttributeList(List att } @Override - public EntityDescriptor getEntityDescriptorByResourceId(String resourceId) throws EntityNotFoundException, ForbiddenException { + public EntityDescriptor getEntityDescriptorByResourceId(String resourceId) throws PersistentEntityNotFound, ForbiddenException { EntityDescriptor ed = entityDescriptorRepository.findByResourceId(resourceId); if (ed == null) { - throw new EntityNotFoundException(String.format("The entity descriptor with entity id [%s] was not found.", resourceId)); + throw new PersistentEntityNotFound(String.format("The entity descriptor with entity id [%s] was not found.", resourceId)); } if (!userService.isAuthorizedFor(ed)) { throw new ForbiddenException(); @@ -416,10 +416,10 @@ public Map getRelyingPartyOverridesRepresentationFromAttributeLi @Override public EntityDescriptorRepresentation update(EntityDescriptorRepresentation edRep) - throws ForbiddenException, EntityNotFoundException, InvalidPatternMatchException { + throws ForbiddenException, PersistentEntityNotFound, InvalidPatternMatchException { EntityDescriptor existingEd = entityDescriptorRepository.findByResourceId(edRep.getId()); if (existingEd == null) { - throw new EntityNotFoundException(String.format("The entity descriptor with entity id [%s] was not found for update.", edRep.getId())); + throw new PersistentEntityNotFound(String.format("The entity descriptor with entity id [%s] was not found for update.", edRep.getId())); } if (edRep.isServiceEnabled() && !userService.currentUserCanEnable(existingEd)) { throw new ForbiddenException("You do not have the permissions necessary to enable this service."); @@ -456,10 +456,11 @@ public void updateDescriptorFromRepresentation(org.opensaml.saml.saml2.metadata. } @Override - public EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resourceId, boolean status) throws EntityNotFoundException, ForbiddenException { + public EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resourceId, boolean status) throws + PersistentEntityNotFound, ForbiddenException { EntityDescriptor ed = entityDescriptorRepository.findByResourceId(resourceId); if (ed == null) { - throw new EntityNotFoundException("Entity with resourceid[" + resourceId + "] was not found for update"); + throw new PersistentEntityNotFound("Entity with resourceid[" + resourceId + "] was not found for update"); } if (!userService.currentUserCanEnable(ed)) { throw new ForbiddenException("You do not have the permissions necessary to change the enable status of this entity descriptor."); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAFilterServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAFilterServiceImpl.java index c42bd7cad..aeab05669 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAFilterServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/JPAFilterServiceImpl.java @@ -1,11 +1,10 @@ package edu.internet2.tier.shibboleth.admin.ui.service; -import edu.internet2.tier.shibboleth.admin.ui.domain.IActivatable; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.EntityAttributesFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.filters.MetadataFilter; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.FilterRepresentation; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.repository.FilterRepository; import edu.internet2.tier.shibboleth.admin.ui.repository.MetadataResolverRepository; @@ -16,7 +15,6 @@ import org.springframework.transaction.interceptor.TransactionAspectSupport; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -108,7 +106,7 @@ private void reloadFiltersAndHandleScriptException(String resolverResourceId) th */ @Override public MetadataFilter updateFilterEnabledStatus(String metadataResolverId, String resourceId, boolean status) - throws EntityNotFoundException, ForbiddenException, ScriptException { + throws PersistentEntityNotFound, ForbiddenException, ScriptException { MetadataResolver metadataResolver = metadataResolverRepository.findByResourceId(metadataResolverId); // Now we operate directly on the filter attached to MetadataResolver, @@ -116,7 +114,7 @@ public MetadataFilter updateFilterEnabledStatus(String metadataResolverId, Strin Optional filterTobeUpdatedOptional = metadataResolver.getMetadataFilters().stream() .filter(it -> it.getResourceId().equals(resourceId)).findFirst(); if (filterTobeUpdatedOptional.isEmpty()) { - throw new EntityNotFoundException("Filter with resource id[" + resourceId + "] not found"); + throw new PersistentEntityNotFound("Filter with resource id[" + resourceId + "] not found"); } MetadataFilter filterTobeUpdated = filterTobeUpdatedOptional.get(); 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 6c921509e..b32e0d9f9 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 @@ -4,13 +4,12 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.exceptions.MetadataFileNotFoundException; import edu.internet2.tier.shibboleth.admin.ui.domain.resolvers.MetadataResolver; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; 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; + public MetadataResolver findByResourceId(String resourceId) throws PersistentEntityNotFound; public Document generateConfiguration(); diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationService.java index 64c029d96..8c1533a6d 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationService.java @@ -2,7 +2,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibConfigurationProperty; import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySet; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.repository.ProjectionIdAndName; @@ -14,7 +14,7 @@ public interface ShibConfigurationService { ShibPropertySet create(ShibPropertySet set) throws ObjectIdExistsException; - void delete(int resourceId) throws EntityNotFoundException; + void delete(int resourceId) throws PersistentEntityNotFound; List getAllConfigurationProperties(); @@ -22,9 +22,9 @@ public interface ShibConfigurationService { List getExistingPropertyNames(); - ShibPropertySet getSet(int resourceId) throws EntityNotFoundException; + ShibPropertySet getSet(int resourceId) throws PersistentEntityNotFound; ShibConfigurationProperty save(ShibConfigurationProperty prop); - ShibPropertySet update(ShibPropertySet setToUpdate) throws EntityNotFoundException; + ShibPropertySet update(ShibPropertySet setToUpdate) throws PersistentEntityNotFound; } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java index 1c3c2a513..21a5605e9 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/ShibConfigurationServiceImpl.java @@ -3,7 +3,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibConfigurationProperty; import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySet; import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySetting; -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.repository.ProjectionIdAndName; import edu.internet2.tier.shibboleth.admin.ui.repository.ShibConfigurationRepository; @@ -39,17 +39,17 @@ public ShibPropertySet create(ShibPropertySet set) throws ObjectIdExistsExceptio getSet(set.getResourceId()); throw new ObjectIdExistsException(Integer.toString(set.getResourceId())); } - catch (EntityNotFoundException e) { + catch (PersistentEntityNotFound e) { // we don't want to find the object } return save(set); } @Override - public void delete(int resourceId) throws EntityNotFoundException { + public void delete(int resourceId) throws PersistentEntityNotFound { ShibPropertySet set = shibPropertySetRepository.findByResourceId(resourceId); if (set == null) { - throw new EntityNotFoundException(String.format("The property set with id [%s] was not found for update.", resourceId)); + throw new PersistentEntityNotFound(String.format("The property set with id [%s] was not found for update.", resourceId)); } shibPropertySettingRepository.deleteAll(set.getProperties()); shibPropertySetRepository.delete(set); @@ -71,10 +71,10 @@ public List getExistingPropertyNames() { } @Override - public ShibPropertySet getSet(int resourceId) throws EntityNotFoundException { + public ShibPropertySet getSet(int resourceId) throws PersistentEntityNotFound { ShibPropertySet result = shibPropertySetRepository.findByResourceId(resourceId); if (result == null) { - throw new EntityNotFoundException((String.format("The property set with id [%s] was not found.", resourceId))); + throw new PersistentEntityNotFound((String.format("The property set with id [%s] was not found.", resourceId))); } return result; } @@ -85,7 +85,7 @@ public ShibConfigurationProperty save(ShibConfigurationProperty prop) { } @Override - public ShibPropertySet update(ShibPropertySet setToUpdate) throws EntityNotFoundException { + public ShibPropertySet update(ShibPropertySet setToUpdate) throws PersistentEntityNotFound { getSet(setToUpdate.getResourceId()); // check that it exists, if not it'll throw an exception return save(setToUpdate); } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestConfiguration.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestConfiguration.groovy index f46eb33d8..1a044baf2 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestConfiguration.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/configuration/TestConfiguration.groovy @@ -61,7 +61,6 @@ class TestConfiguration { @Bean CustomEntityAttributesDefinitionServiceImpl customEntityAttributesDefinitionServiceImpl() { new CustomEntityAttributesDefinitionServiceImpl().with { - it.entityManager = entityManager it.repository = repository return it } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy index 00e624b7e..567639f36 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/AttributeBundleControllerTests.groovy @@ -1,10 +1,10 @@ package edu.internet2.tier.shibboleth.admin.ui.controller -import com.fasterxml.jackson.databind.MapperFeature + import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.configuration.ShibUIConfiguration import edu.internet2.tier.shibboleth.admin.ui.domain.AttributeBundle -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException import edu.internet2.tier.shibboleth.admin.ui.repository.AttributeBundleRepository import edu.internet2.tier.shibboleth.admin.ui.service.AttributeBundleService @@ -148,7 +148,7 @@ class AttributeBundleControllerTests extends Specification { mockMvc.perform(delete("/api/custom/entity/bundles/randomIDValdoesntexist")) false } catch (NestedServletException expected) { - expected instanceof EntityNotFoundException + expected instanceof PersistentEntityNotFound } when: "Delete what does exist" @@ -180,7 +180,7 @@ class AttributeBundleControllerTests extends Specification { mockMvc.perform(put('/api/custom/entity/bundles').contentType(APPLICATION_JSON).content(objectMapper.writeValueAsString(bundle))) false } catch (NestedServletException expected) { - expected.getCause() instanceof EntityNotFoundException + expected.getCause() instanceof PersistentEntityNotFound } when: "update bundle" diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy index 35bd77ea2..3ffbe12e0 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/EntityDescriptorControllerTests.groovy @@ -5,7 +5,7 @@ import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.AssertionConsumerServiceRepresentation import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException @@ -376,7 +376,7 @@ class EntityDescriptorControllerTests extends AbstractBaseDataJpaTest { mockMvc.perform(get("/api/EntityDescriptor/uuid-1")) } catch (Exception e) { - e instanceof EntityNotFoundException + e instanceof PersistentEntityNotFound } } 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 2820533e9..6b54c7a0d 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 @@ -8,7 +8,7 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.exceptions.MetadataFileNotF 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.domain.resolvers.opensaml.OpenSamlChainingMetadataResolver -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException import edu.internet2.tier.shibboleth.admin.ui.exception.InitializationException import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects @@ -107,7 +107,7 @@ class MetadataFiltersControllerTests extends AbstractBaseDataJpaTest { } @Override - MetadataResolver findByResourceId(String resourceId) throws EntityNotFoundException { + MetadataResolver findByResourceId(String resourceId) throws PersistentEntityNotFound { // This won't get called return null } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy index c5ab4a003..8545362c4 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/controller/ShibPropertiesControllerTests.groovy @@ -4,7 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySet import edu.internet2.tier.shibboleth.admin.ui.domain.shib.properties.ShibPropertySetting -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException import edu.internet2.tier.shibboleth.admin.ui.repository.ShibPropertySetRepository import edu.internet2.tier.shibboleth.admin.ui.repository.ShibPropertySettingRepository @@ -18,15 +18,11 @@ import spock.lang.Subject import javax.persistence.EntityManager import javax.transaction.Transactional -import static org.hamcrest.CoreMatchers.containsString import static org.springframework.http.MediaType.APPLICATION_JSON import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @@ -107,7 +103,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { mockMvc.perform(delete("/api/shib/property/set/010")) } catch (Exception e) { - e instanceof EntityNotFoundException + e instanceof PersistentEntityNotFound } when: @@ -128,7 +124,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { mockMvc.perform(get("/api/shib/property/set/0101")) } catch (Exception e) { - e instanceof EntityNotFoundException + e instanceof PersistentEntityNotFound } } @@ -194,7 +190,7 @@ class ShibPropertiesControllerTests extends AbstractBaseDataJpaTest { mockMvc.perform(put('/api/shib/property/set/1234').contentType(APPLICATION_JSON).content(jsonBody)) } catch (Exception e) { - e instanceof EntityNotFoundException + e instanceof PersistentEntityNotFound } } diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepositoryTest.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepositoryTest.groovy index 1635ed35f..1615a81ee 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepositoryTest.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepositoryTest.groovy @@ -122,10 +122,9 @@ class EntityDescriptorRepositoryTest extends AbstractBaseDataJpaTest { @Bean CustomEntityAttributesDefinitionServiceImpl customEntityAttributesDefinitionServiceImpl(EntityManager entityManager, CustomEntityAttributeDefinitionRepository customEntityAttributeDefinitionRepository) { new CustomEntityAttributesDefinitionServiceImpl().with { - it.entityManager = entityManager it.repository = customEntityAttributeDefinitionRepository return it } } } -} +} \ No newline at end of file diff --git a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupsControllerIntegrationTests.groovy b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupsControllerIntegrationTests.groovy index c4a76e832..bb4613f6b 100644 --- a/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupsControllerIntegrationTests.groovy +++ b/backend/src/test/groovy/edu/internet2/tier/shibboleth/admin/ui/security/controller/GroupsControllerIntegrationTests.groovy @@ -1,14 +1,13 @@ package edu.internet2.tier.shibboleth.admin.ui.security.controller import edu.internet2.tier.shibboleth.admin.ui.AbstractBaseDataJpaTest -import edu.internet2.tier.shibboleth.admin.ui.exception.EntityNotFoundException +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound 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.model.Role import edu.internet2.tier.shibboleth.admin.ui.security.model.User import edu.internet2.tier.shibboleth.admin.ui.security.repository.GroupsRepository -import edu.internet2.tier.shibboleth.admin.ui.security.service.IGroupService import edu.internet2.tier.shibboleth.admin.ui.util.WithMockAdmin import groovy.json.JsonOutput import org.springframework.beans.factory.annotation.Autowired @@ -117,7 +116,7 @@ class GroupsControllerIntegrationTests extends AbstractBaseDataJpaTest { .accept(MediaType.APPLICATION_JSON)) false } catch (Throwable expected) { - expected instanceof EntityNotFoundException + expected instanceof PersistentEntityNotFound } } @@ -158,7 +157,7 @@ class GroupsControllerIntegrationTests extends AbstractBaseDataJpaTest { mockMvc.perform(get("$RESOURCE_URI/CCC")) false } catch (Throwable expected) { - expected instanceof EntityNotFoundException + expected instanceof PersistentEntityNotFound } } From 966485bf4250661672ebc377c6371a5245f7be80 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 8 Sep 2022 10:57:51 -0700 Subject: [PATCH 51/71] Added validation for number --- ui/src/app/admin/component/ConfigurationForm.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index 747a70452..d6029481b 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -159,7 +159,9 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, + {...register(`properties.${idx}.propertyValue`, { + valueAsNumber: p.displayType === 'number' + })} /> : Date: Thu, 8 Sep 2022 11:08:36 -0700 Subject: [PATCH 52/71] Updated validation to only allow integers for numbers --- ui/src/app/admin/component/ConfigurationForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index d6029481b..a1560ce42 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -160,7 +160,7 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, type={p.displayType === 'number' ? 'number' : 'text'} placeholder="value" {...register(`properties.${idx}.propertyValue`, { - valueAsNumber: p.displayType === 'number' + setValueAs: v => (p.displayType === 'number' ? parseInt(v) : v), })} /> : From eff2efe56b595298653f3e342b96cdf8108f1dd2 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 8 Sep 2022 11:12:34 -0700 Subject: [PATCH 53/71] Added text displaytype change --- ui/src/app/admin/component/ConfigurationForm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/app/admin/component/ConfigurationForm.js b/ui/src/app/admin/component/ConfigurationForm.js index a1560ce42..bceac7a42 100644 --- a/ui/src/app/admin/component/ConfigurationForm.js +++ b/ui/src/app/admin/component/ConfigurationForm.js @@ -150,7 +150,7 @@ export function ConfigurationForm({ configurations, configuration = {}, loading, { p.propertyName } { p.category } - { p.displayType } + { p.displayType === 'number' ? 'integer' : p.displayType } {p.displayType !== 'boolean' ? Date: Thu, 8 Sep 2022 12:40:29 -0700 Subject: [PATCH 54/71] SHIBUI-2270 Bug fix for ints when no value present --- .../properties/ShibPropertySettingJacksonSerializer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java index 6bd5b926c..c625c9acb 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/domain/shib/properties/ShibPropertySettingJacksonSerializer.java @@ -31,7 +31,11 @@ public void serialize(ShibPropertySetting sps, JsonGenerator generator, Serializ generator.writeBooleanField("propertyValue", Boolean.valueOf(sps.getPropertyValue())); break; case "number": - generator.writeNumberField("propertyValue", Long.parseLong(sps.getPropertyValue())); + try { + generator.writeNumberField("propertyValue", Long.parseLong(sps.getPropertyValue())); + } catch (NumberFormatException notANumber) { + generator.writeStringField("propertyValue", sps.getPropertyValue()); + } break; default: generator.writeStringField("propertyValue", sps.getPropertyValue()); From 51395cd5dffd32fd91c21139cea179cde53d6ba0 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Thu, 8 Sep 2022 13:43:19 -0700 Subject: [PATCH 55/71] SHIBUI-2364 GET ALL for multiple EntityDescriptors doesn't fetch EVERYTHING --- .../EntityDescriptorController.java | 2 +- .../EntityDescriptorProjection.java | 19 +++++++++++++++++++ .../EntityDescriptorRepository.java | 5 ++++- .../ui/repository/ProjectionIdAndName.java | 3 ++- .../ui/service/EntityDescriptorService.java | 7 ++++--- .../JPAEntityDescriptorServiceImpl.java | 11 ++++++----- 6 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorProjection.java 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 f7cfb019a..065e4d9e3 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 @@ -83,7 +83,7 @@ public ResponseEntity deleteOne(@PathVariable String resourceId) throws Forbi @GetMapping("/EntityDescriptors") @Transactional public ResponseEntity getAll() throws ForbiddenException { - return ResponseEntity.ok(entityDescriptorService.getAllRepresentationsBasedOnUserAccess()); + return ResponseEntity.ok(entityDescriptorService.getAllEntityDescriptorProjectionsBasedOnUserAccess()); } @GetMapping("/EntityDescriptor/{resourceId}/Versions") diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorProjection.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorProjection.java new file mode 100644 index 000000000..57cf02ab9 --- /dev/null +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorProjection.java @@ -0,0 +1,19 @@ +package edu.internet2.tier.shibboleth.admin.ui.repository; + +import java.time.LocalDateTime; + +public interface EntityDescriptorProjection { + default String getId() { + return getResourceId(); + } + String getEntityID(); + default String getEntityId() { + return getEntityID(); + } + String getResourceId(); + String getServiceProviderName(); + String getCreatedBy(); + LocalDateTime getCreatedDate(); + boolean getServiceEnabled(); + String getIdOfOwner(); +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepository.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepository.java index 5e28e7d75..bb2b275d6 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepository.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/EntityDescriptorRepository.java @@ -12,6 +12,9 @@ * Repository to manage {@link EntityDescriptor} instances. */ public interface EntityDescriptorRepository extends JpaRepository { + List findAllBy(); + + List findAllByIdOfOwner(String ownerId); EntityDescriptor findByEntityID(String entityId); @@ -34,4 +37,4 @@ public interface EntityDescriptorRepository extends JpaRepository findAllByIdOfOwnerIsNull(); -} +} \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/ProjectionIdAndName.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/ProjectionIdAndName.java index 6731aea86..fca5ae8cd 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/ProjectionIdAndName.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/repository/ProjectionIdAndName.java @@ -1,6 +1,7 @@ package edu.internet2.tier.shibboleth.admin.ui.repository; -public interface ProjectionIdAndName{ +public interface ProjectionIdAndName { String getResourceId(); + String getName(); } \ No newline at end of file diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java index 6d66732b0..a5440b7fa 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java @@ -3,10 +3,11 @@ import edu.internet2.tier.shibboleth.admin.ui.domain.Attribute; import edu.internet2.tier.shibboleth.admin.ui.domain.EntityDescriptor; import edu.internet2.tier.shibboleth.admin.ui.domain.frontend.EntityDescriptorRepresentation; -import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; import edu.internet2.tier.shibboleth.admin.ui.exception.ForbiddenException; import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; +import edu.internet2.tier.shibboleth.admin.ui.exception.PersistentEntityNotFound; +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorProjection; import java.util.ConcurrentModificationException; import java.util.List; @@ -67,9 +68,9 @@ EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRepres Iterable getAllDisabledAndNotOwnedByAdmin() throws ForbiddenException; /** - * @return a list of EntityDescriptorRepresentations that a user has the rights to access + * @return a list of EntityDescriptorProjections that a user has the rights to access */ - List getAllRepresentationsBasedOnUserAccess() throws ForbiddenException; + List getAllEntityDescriptorProjectionsBasedOnUserAccess() throws ForbiddenException; /** * Given a list of attributes, generate an AttributeReleaseList 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 6269020e8..441fa52af 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 @@ -21,6 +21,7 @@ import edu.internet2.tier.shibboleth.admin.ui.exception.InvalidPatternMatchException; import edu.internet2.tier.shibboleth.admin.ui.exception.ObjectIdExistsException; import edu.internet2.tier.shibboleth.admin.ui.opensaml.OpenSamlObjects; +import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorProjection; import edu.internet2.tier.shibboleth.admin.ui.repository.EntityDescriptorRepository; import edu.internet2.tier.shibboleth.admin.ui.security.model.Group; import edu.internet2.tier.shibboleth.admin.ui.security.model.Owner; @@ -373,16 +374,16 @@ public Iterable getAllDisabledAndNotOwnedByAdmin } @Override - public List getAllRepresentationsBasedOnUserAccess() throws ForbiddenException { + public List getAllEntityDescriptorProjectionsBasedOnUserAccess() throws ForbiddenException { switch (userService.getCurrentUserAccess()) { case ADMIN: - return entityDescriptorRepository.findAllStreamByCustomQuery().map(ed -> createRepresentationFromDescriptor(ed)) - .collect(Collectors.toList()); + List o = entityDescriptorRepository.findAllBy();//.map(edProjection -> createRepresentationFromDescriptor(edProjection)).collect(Collectors.toList()); + return o; case GROUP: User user = userService.getCurrentUser(); Group group = user.getGroup(); - return entityDescriptorRepository.findAllStreamByIdOfOwner(group.getOwnerId()) - .map(ed -> createRepresentationFromDescriptor(ed)).collect(Collectors.toList()); + List ed = entityDescriptorRepository.findAllByIdOfOwner(group.getOwnerId());//.map(ed -> createRepresentationFromDescriptor(ed)).collect(Collectors.toList()); + return ed; default: throw new ForbiddenException(); } From d5018e73d84accbaf7439e6ec0eee5e049e03e07 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Thu, 8 Sep 2022 13:49:05 -0700 Subject: [PATCH 56/71] SHIBUI-2364 code cleanup --- .../admin/ui/service/JPAEntityDescriptorServiceImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 441fa52af..55cf3e016 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 @@ -377,12 +377,12 @@ public Iterable getAllDisabledAndNotOwnedByAdmin public List getAllEntityDescriptorProjectionsBasedOnUserAccess() throws ForbiddenException { switch (userService.getCurrentUserAccess()) { case ADMIN: - List o = entityDescriptorRepository.findAllBy();//.map(edProjection -> createRepresentationFromDescriptor(edProjection)).collect(Collectors.toList()); + List o = entityDescriptorRepository.findAllBy(); return o; case GROUP: User user = userService.getCurrentUser(); Group group = user.getGroup(); - List ed = entityDescriptorRepository.findAllByIdOfOwner(group.getOwnerId());//.map(ed -> createRepresentationFromDescriptor(ed)).collect(Collectors.toList()); + List ed = entityDescriptorRepository.findAllByIdOfOwner(group.getOwnerId()); return ed; default: throw new ForbiddenException(); From a4b9907eb1182205228c47e77f3fe500affb7076 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Thu, 8 Sep 2022 15:24:34 -0700 Subject: [PATCH 57/71] Added spinner --- ui/src/app/core/components/Spinner.js | 4 +-- ui/src/app/metadata/hoc/MetadataSelector.js | 28 +++++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/ui/src/app/core/components/Spinner.js b/ui/src/app/core/components/Spinner.js index 880f53d2a..c137bb9ac 100644 --- a/ui/src/app/core/components/Spinner.js +++ b/ui/src/app/core/components/Spinner.js @@ -2,8 +2,8 @@ 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 function Spinner (props) { + return () } export default Spinner; \ No newline at end of file diff --git a/ui/src/app/metadata/hoc/MetadataSelector.js b/ui/src/app/metadata/hoc/MetadataSelector.js index b81db74b2..54a49d4df 100644 --- a/ui/src/app/metadata/hoc/MetadataSelector.js +++ b/ui/src/app/metadata/hoc/MetadataSelector.js @@ -1,5 +1,6 @@ import React from 'react'; import { useLocation, useParams } from 'react-router'; +import Spinner from '../../core/components/Spinner'; import { useMetadataEntity } from '../hooks/api'; export const MetadataTypeContext = React.createContext(); @@ -10,6 +11,7 @@ export const MetadataLoaderContext = React.createContext(); export function MetadataSelector({ children, ...props }) { let { type, id } = useParams(); + const [loading, setLoading] = React.useState(false); const location = useLocation(); if (!type) { @@ -30,25 +32,35 @@ export function MetadataSelector({ children, ...props }) { const source = await get(`/${id}`); if (response.ok) { setMetadata(source); + setLoading(false); } } function reload() { + setLoading(true); loadMetadata(id); + } React.useEffect(() => reload(), [id]); return ( - - {type && - - {metadata && metadata.version && - {children(metadata, reload)} + + {loading &&
+ +
} + + {type && + + {metadata && metadata.version && + + {children(metadata, reload)} + + } + } -
- } -
+ + ); } From 64e4fdd17321fbb763547abd905ec1cdd822d37f Mon Sep 17 00:00:00 2001 From: Charles Hasegawa Date: Thu, 8 Sep 2022 22:57:13 +0000 Subject: [PATCH 58/71] README.md edited online with Bitbucket --- bulk-upload/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/bulk-upload/README.md b/bulk-upload/README.md index c436394e8..23462d5ca 100644 --- a/bulk-upload/README.md +++ b/bulk-upload/README.md @@ -1,8 +1,12 @@ This script can be used to bulk upload metadata files into the Shibboleth IdP UI ### requirements ### -The shibui must be configured without SAML authentication enabled. The API is currently only accessible using Basic auth. -If shibui is using SAML auth, you can temporarily disable it by setting pac4j-enabled: false in application.yml and restarting shibui. +Docker engine - the run script will launch a Docker container which will handle the process. +OR +Bash shell with Perl (and additional Perl libraries - see below). + +The Shib-UI must be configured *without* SAML authentication enabled. The needed API is currently only accessible using Basic auth. If you are using SAML auth, you can return to using it after the bulk upload process is run. +If Shib-UI is using SAML auth, you can temporarily disable it by setting pac4j-enabled: false in application.yml and restarting shibui. After uploading you can re-enable SAML auth by setting pac4j-enabled: true in application.yml and restarting shibui. ### usage ### @@ -34,7 +38,7 @@ attr[0][Value] = false ### docker image ### run.sh will pull the shibui-bulk-upload image from dockerhub and run the script within -If you need to build the image yourself, `cd docker-build;docker build -t unicon/shibui-bulk-upload .` +If you prefer to build the image yourself, `cd docker-build;docker build -t unicon/shibui-bulk-upload .` ### running without docker ### The docker-build/shibui-md-upload.pl script can be run manually. From 7d8b1d879f03bf40d1c8cb4f8624b9d8c9722e78 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Fri, 9 Sep 2022 11:56:09 -0400 Subject: [PATCH 59/71] shibui-2341 fix SQL --- backend/src/main/resources/db/changelog/changelog.sql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/main/resources/db/changelog/changelog.sql b/backend/src/main/resources/db/changelog/changelog.sql index f1494b2ca..af15ca6b8 100644 --- a/backend/src/main/resources/db/changelog/changelog.sql +++ b/backend/src/main/resources/db/changelog/changelog.sql @@ -184,7 +184,7 @@ update resource_backed_metadata_resolver_aud set max_refresh_delay ='PT4H'; ALTER TABLE description ALTER COLUMN descriptionValue LONGTEXT; GO -ALTER TABLE description)aud ALTER COLUMN descriptionValue LONGTEXT; +ALTER TABLE description_aud ALTER COLUMN descriptionValue LONGTEXT; GO -- changeset liquibase:1.13.0.2 dbms:postgresql,mssql @@ -192,7 +192,7 @@ GO -- 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 description ALTER COLUMN descriptionValue TEXT; +ALTER TABLE description ALTER COLUMN descriptionValue TYPE TEXT; GO -ALTER TABLE description_aud ALTER COLUMN descriptionValue TEXT; +ALTER TABLE description_aud ALTER COLUMN descriptionValue TYPE TEXT; GO \ No newline at end of file From bfeda4f3b5863a5007dda37c67b126bcc037fc66 Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Fri, 9 Sep 2022 12:16:51 -0400 Subject: [PATCH 60/71] shibui-2341 exit upload if api is inaccessible --- bulk-upload/docker-build/shibui-md-upload.pl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bulk-upload/docker-build/shibui-md-upload.pl b/bulk-upload/docker-build/shibui-md-upload.pl index 3aae45aa8..160559c6d 100755 --- a/bulk-upload/docker-build/shibui-md-upload.pl +++ b/bulk-upload/docker-build/shibui-md-upload.pl @@ -41,6 +41,11 @@ #create auth token $client->HEAD('/'); + +my $code = $client->responseCode(); +my $res = $client->responseContent(); +die "$res\n" if ($code != 302 && $code != 200); + my $token = &get_cookie_value($cookies, 'XSRF-TOKEN'); $client->addHeader('X-XSRF-TOKEN', $token); ## From 13c512b4df3ce4cfd6c4677e4d100de53ee2a087 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 9 Sep 2022 13:49:34 -0700 Subject: [PATCH 61/71] SHIBUI-2364 code cleanup --- .../ui/controller/EntityDescriptorController.java | 11 +++++++++-- .../admin/ui/service/EntityDescriptorService.java | 2 ++ .../ui/service/JPAEntityDescriptorServiceImpl.java | 8 ++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) 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 065e4d9e3..9952e8842 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 @@ -145,13 +145,20 @@ public void initRestTemplate() { @PutMapping("/EntityDescriptor/{resourceId}") @Transactional public ResponseEntity update(@RequestBody EntityDescriptorRepresentation edRepresentation, @PathVariable String resourceId) - throws ForbiddenException, ConcurrentModificationException, PersistentEntityNotFound, - InvalidPatternMatchException { + throws ForbiddenException, ConcurrentModificationException, PersistentEntityNotFound, InvalidPatternMatchException { edRepresentation.setId(resourceId); // This should be the same already, but just to be safe... EntityDescriptorRepresentation result = entityDescriptorService.update(edRepresentation); return ResponseEntity.ok().body(result); } + @PutMapping("/EntityDescriptor/{resourceId}/changeGroup/{groupId}") + @Transactional + public ResponseEntity updateGroupForEntityDescriptor(@PathVariable String resourceId, String groupId) + throws ForbiddenException, ConcurrentModificationException, PersistentEntityNotFound, InvalidPatternMatchException { + EntityDescriptorRepresentation result = entityDescriptorService.updateGroupForEntityDescriptor(resourceId, groupId); + return ResponseEntity.ok().body(result); + } + @PostMapping(value = "/EntityDescriptor", consumes = "application/xml") @Transactional public ResponseEntity upload(@RequestBody byte[] entityDescriptorXml, @RequestParam String spName) throws Exception { diff --git a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java index a5440b7fa..fa8fc62f8 100644 --- a/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java +++ b/backend/src/main/java/edu/internet2/tier/shibboleth/admin/ui/service/EntityDescriptorService.java @@ -120,4 +120,6 @@ EntityDescriptorRepresentation updateEntityDescriptorEnabledStatus(String resour EntityDescriptorRepresentation createNewEntityDescriptorFromXMLOrigin(EntityDescriptor ed); boolean entityExists(String entityID); + + EntityDescriptorRepresentation updateGroupForEntityDescriptor(String resourceId, String groupId); } \ 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 55cf3e016..291f659f8 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 @@ -119,6 +119,14 @@ public boolean entityExists(String entityID) { return entityDescriptorRepository.findByEntityID(entityID) != null ; } + @Override + public EntityDescriptorRepresentation updateGroupForEntityDescriptor(String resourceId, String groupId) { + EntityDescriptor ed = entityDescriptorRepository.findByResourceId(resourceId); + ed.setIdOfOwner(groupId); + EntityDescriptor savedEntity = entityDescriptorRepository.save(ed); + return createRepresentationFromDescriptor(savedEntity); + } + @Override public EntityDescriptorRepresentation createNew(EntityDescriptorRepresentation edRep) throws ForbiddenException, ObjectIdExistsException, InvalidPatternMatchException { From d4c3cb372d2320a99401f625db59b21f82d13d94 Mon Sep 17 00:00:00 2001 From: Ryan Mathis Date: Fri, 9 Sep 2022 14:32:14 -0700 Subject: [PATCH 62/71] Implemented fix for group change and copy change --- ui/src/app/dashboard/view/SourcesTab.js | 2 +- ui/src/app/metadata/copy/CopySource.js | 30 +++++++++------ ui/src/app/metadata/copy/EntityTypeahead.js | 42 ++++++++++++++++----- 3 files changed, 52 insertions(+), 22 deletions(-) diff --git a/ui/src/app/dashboard/view/SourcesTab.js b/ui/src/app/dashboard/view/SourcesTab.js index 40ff4dd4f..b0d1352d3 100644 --- a/ui/src/app/dashboard/view/SourcesTab.js +++ b/ui/src/app/dashboard/view/SourcesTab.js @@ -37,7 +37,7 @@ export function SourcesTab () { React.useEffect(() => { loadSources() }, []); async function changeSourceGroup(source, group) { - await updater.put(`/${source.id}`, { + await updater.put(`/${source.id}/changeGroup/${group}`, { ...source, idOfOwner: group }); diff --git a/ui/src/app/metadata/copy/CopySource.js b/ui/src/app/metadata/copy/CopySource.js index f3ae6b142..d7d0be54a 100644 --- a/ui/src/app/metadata/copy/CopySource.js +++ b/ui/src/app/metadata/copy/CopySource.js @@ -34,7 +34,7 @@ export function CopySource({ copy, onNext }) { setSelected([]); }; - const { register, handleSubmit, control, formState, setValue, getValues } = useForm({ + const { register, handleSubmit, control, formState, setValue, getValues, watch } = useForm({ mode: 'onChange', reValidateMode: 'onBlur', defaultValues: { @@ -47,6 +47,8 @@ export function CopySource({ copy, onNext }) { shouldUnregister: false, }); + const target = watch('target'); + const { errors, isValid } = formState; React.useEffect(() => { @@ -92,25 +94,28 @@ export function CopySource({ copy, onNext }) {
- - - Select the Entity ID to copy - - - + + + + Select the Entity ID to copy + + + Entity ID to copy is Required - + + Metadata Source Name (Dashboard Display Only) - + + + aria-describedby="serviceProviderName-help" disabled={!target} /> Service Resolver Name is required @@ -118,12 +123,15 @@ export function CopySource({ copy, onNext }) { + New Entity ID - + + !(sourceIds.indexOf(v) > -1) diff --git a/ui/src/app/metadata/copy/EntityTypeahead.js b/ui/src/app/metadata/copy/EntityTypeahead.js index ed8b9a14e..716089039 100644 --- a/ui/src/app/metadata/copy/EntityTypeahead.js +++ b/ui/src/app/metadata/copy/EntityTypeahead.js @@ -1,10 +1,16 @@ +import { faSpinner } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React from 'react'; import { Typeahead } from 'react-bootstrap-typeahead'; import { useController } from 'react-hook-form'; -import { useMetadataSources } from '../hooks/api'; +import { useMetadataEntity, useMetadataSources } from '../hooks/api'; +import Form from 'react-bootstrap/Form'; -export function EntityTypeahead ({id, control, name}) { +export function EntityTypeahead ({id, control, name, children}) { const { data = [] } = useMetadataSources({}, []); + + const { get, response, loading } = useMetadataEntity(); + const entities = React.useMemo(() => data.map(d => d.entityId), [data]); const { @@ -18,14 +24,30 @@ export function EntityTypeahead ({id, control, name}) { defaultValue: "", }); + const loadSelected = async (selected) => { + const toCopy = data.find(e => e.entityId === selected); + + const source = await get(`/${toCopy.id}`); + if (response.ok) { + onChange(source); + } + // + } + return ( - onChange(selected ? data.find(e => e.entityId === selected[0]) : '')} - defaultInputValue={value ? value.entityId : ''} - options={entities} - required={true} - id={id} - /> + + + {children} + {loading && } + + selected && selected.length > 0 ? loadSelected(selected[0]) : null} + defaultInputValue={value ? value.entityId : ''} + options={entities} + required={true} + id={id} + /> + ) } \ No newline at end of file From 999ba4fc94a6ef12ebeedb7d06129f10dd0f4af3 Mon Sep 17 00:00:00 2001 From: chasegawa Date: Fri, 9 Sep 2022 16:03:36 -0700 Subject: [PATCH 63/71] SHIBUI-2364 fixes to group --- .../admin/ui/controller/EntityDescriptorController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9952e8842..e57870cb9 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 @@ -153,7 +153,7 @@ public ResponseEntity update(@RequestBody EntityDescriptorRepresentation edRe @PutMapping("/EntityDescriptor/{resourceId}/changeGroup/{groupId}") @Transactional - public ResponseEntity updateGroupForEntityDescriptor(@PathVariable String resourceId, String groupId) + public ResponseEntity updateGroupForEntityDescriptor(@PathVariable String resourceId, @PathVariable String groupId) throws ForbiddenException, ConcurrentModificationException, PersistentEntityNotFound, InvalidPatternMatchException { EntityDescriptorRepresentation result = entityDescriptorService.updateGroupForEntityDescriptor(resourceId, groupId); return ResponseEntity.ok().body(result); From 1f7a8ff6b116e8c72b5bd6b0b28c873f1cfc5a9c Mon Sep 17 00:00:00 2001 From: Sean Porth Date: Mon, 12 Sep 2022 13:38:40 -0400 Subject: [PATCH 64/71] shibui-2341 better url encoding, utf8 encoding of names --- bulk-upload/README.md | 2 +- bulk-upload/docker-build/Dockerfile | 2 +- bulk-upload/docker-build/shibui-md-upload.pl | 14 +++++++++----- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/bulk-upload/README.md b/bulk-upload/README.md index 23462d5ca..02196fba9 100644 --- a/bulk-upload/README.md +++ b/bulk-upload/README.md @@ -42,6 +42,6 @@ If you prefer to build the image yourself, `cd docker-build;docker build -t unic ### running without docker ### The docker-build/shibui-md-upload.pl script can be run manually. -Depending on OS you may need to install some additional non dist Perl modules. REST::Client , XML::LibXML , JSON , Config::File +Depending on OS you may need to install some additional non dist Perl modules. REST::Client , XML::LibXML , JSON , Config::File , URI::Encode `perl shibui-md-upload.pl -c -m -e (enable metadata source after upload)` diff --git a/bulk-upload/docker-build/Dockerfile b/bulk-upload/docker-build/Dockerfile index dd7384667..8c1efcba9 100644 --- a/bulk-upload/docker-build/Dockerfile +++ b/bulk-upload/docker-build/Dockerfile @@ -3,7 +3,7 @@ MAINTAINER sporth@unicon.net RUN apt-get clean \ && apt-get -y update \ - && apt-get install -y librest-client-perl libconfig-file-perl jq libxml-libxml-perl libjson-perl + && apt-get install -y librest-client-perl libconfig-file-perl jq libxml-libxml-perl libjson-perl liburi-encode-perl WORKDIR /opt COPY shibui-md-upload.pl /opt/shibui-md-upload.pl diff --git a/bulk-upload/docker-build/shibui-md-upload.pl b/bulk-upload/docker-build/shibui-md-upload.pl index 160559c6d..4f24334e3 100755 --- a/bulk-upload/docker-build/shibui-md-upload.pl +++ b/bulk-upload/docker-build/shibui-md-upload.pl @@ -12,6 +12,7 @@ use XML::LibXML::XPathContext; use Encode; use JSON; +use URI::Encode; ##process arguments our ($opt_e,$opt_m,$opt_c); @@ -201,10 +202,13 @@ sub call_api { my $xml = shift; my $enable = shift; my ($params,$code,$result); + my $encoder = URI::Encode->new({encode_reserved => 1}); my $utf8 = encode_utf8($xml); + my $utf8_name = encode_utf8($name); + my $ename = $encoder->encode($name); - $params = "?spName=$name"; + $params = "?spName=$ename"; $params .= "&enableService=true" if ($enable); $client->addHeader('Content-Type', "application/xml; charset='utf8'"); @@ -226,18 +230,18 @@ sub call_api { my $eresult = $client->responseContent(); if ($ecode == 200 || $ecode == 201) { - print "$ecode: entity $name uploaded sucessfully and enabled\n"; + print "$ecode: entity $utf8_name uploaded sucessfully and enabled\n"; } else { - print "$ecode: entity $name uploaded sucessfully but enabling failed:\n"; + print "$ecode: entity $utf8_name uploaded sucessfully but enabling failed:\n"; open(my $pipe, '|-', "jq ."); print $pipe $eresult; } } else { - print "$code: entity $name uploaded sucessfully\n"; + print "$code: entity $utf8_name uploaded sucessfully\n"; } } elsif ($code == 409) { - print "$code: entity $name already exists\n"; + print "$code: entity $utf8_name already exists\n"; } elsif ($code == 500) { print "$code: $result\n"; } else { From fadd43e3579f91d2a54b0a0d7ea4765d4d044f0f Mon Sep 17 00:00:00 2001 From: Charles Hasegawa Date: Mon, 12 Sep 2022 18:43:01 +0000 Subject: [PATCH 65/71] README.md edited online with Bitbucket --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3afd1b078..9f31bc7e4 100644 --- a/README.md +++ b/README.md @@ -6,10 +6,11 @@ ## Running -There are currently 2 ways to run the application: +There are currently 3 ways to run the application: 1. As an executable WAR using Java -1. deployed in a Java Servlet 3.0 container such as Tomcat or Jetty +1. Deployed in a Java Servlet 3.0 container such as Tomcat or Jetty +1. Via Docker container - see instructions at https://spaces.at.internet2.edu/display/SMMU/Shibboleth+IdP+UI+Deployment+Instructions Note that some features require encoded slashes in the URL. In tomcat (which is embedded in the war), this can be allowed with: From c3f7d1fc507aa341644bd6c7634776ffa9189268 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 13 Sep 2022 12:23:43 -0400 Subject: [PATCH 66/71] NOJIRA Fixed a text compare and what looked to be a race condition --- .../integration/resources/SHIBUI-2268.side | 22 +++++++------------ .../integration/resources/SHIBUI-2270-2.side | 7 ++++++ 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/backend/src/integration/resources/SHIBUI-2268.side b/backend/src/integration/resources/SHIBUI-2268.side index a9533b8c8..0dc9a83dd 100644 --- a/backend/src/integration/resources/SHIBUI-2268.side +++ b/backend/src/integration/resources/SHIBUI-2268.side @@ -948,24 +948,18 @@ ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] ], "value": "" - }, { - "id": "6cd2789b-4ec1-4153-8d4e-fb896a1b0e5e", - "comment": "", - "command": "click", - "target": "css=.align-items-end", - "targets": [ - ["css=.align-items-end", "css:finder"], - ["xpath=//div[@id='root']/div/footer/div/div[2]/div", "xpath:idRelative"], - ["xpath=//footer/div/div[2]/div", "xpath:position"] - ], - "value": "" }, { "id": "b9432398-233d-4872-8b56-9aa8fd48ca85", "comment": "", "command": "assertText", - "target": "css=.alert", - "targets": [], - "value": "No FiltersNo filters have been added to this Metadata Provider" + "target": "css=.alert > p", + "targets": [ + ["css=.alert > p", "css:finder"], + ["xpath=//div[@id='filters']/div[2]/p", "xpath:idRelative"], + ["xpath=//section/div/div/div[3]/div[2]/p", "xpath:position"], + ["xpath=//p[contains(.,'No filters have been added to this Metadata Provider')]", "xpath:innerText"] + ], + "value": "No filters have been added to this Metadata Provider" }, { "id": "3543733a-3e14-4f07-9aaa-e29a26fe36b1", "comment": "", diff --git a/backend/src/integration/resources/SHIBUI-2270-2.side b/backend/src/integration/resources/SHIBUI-2270-2.side index 2872ad331..9f1c37d7a 100644 --- a/backend/src/integration/resources/SHIBUI-2270-2.side +++ b/backend/src/integration/resources/SHIBUI-2270-2.side @@ -2114,6 +2114,13 @@ ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] ], "value": "" + }, { + "id": "d7643f3c-f387-4404-8f8b-e73ebfeb0754", + "comment": "", + "command": "pause", + "target": "5000", + "targets": [], + "value": "" }, { "id": "efc6da0e-490c-4c8b-b4d2-07b71059d0ef", "comment": "", From f51aab5fb899b0de195e55b8d384384280ea2fbd Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 13 Sep 2022 13:15:29 -0400 Subject: [PATCH 67/71] NOJIRA Small change to attempt to add test stability. --- backend/src/integration/resources/SHIBUI-1732-1.side | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backend/src/integration/resources/SHIBUI-1732-1.side b/backend/src/integration/resources/SHIBUI-1732-1.side index 5c1d1daec..5ed256172 100644 --- a/backend/src/integration/resources/SHIBUI-1732-1.side +++ b/backend/src/integration/resources/SHIBUI-1732-1.side @@ -630,6 +630,13 @@ ["xpath=//li[3]/button", "xpath:position"] ], "value": "" + }, { + "id": "97d81369-bb35-4f59-b838-ef69e253fc21", + "comment": "", + "command": "waitForElementEditable", + "target": "id=root_xmlId", + "targets": [], + "value": "30000" }, { "id": "14f9bdcf-a54a-4f3b-9c4a-e4e9e94647ba", "comment": "", From 67ea3a9c871538e81b950bc89c360bbed9734746 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 13 Sep 2022 14:29:43 -0400 Subject: [PATCH 68/71] NOJIRA Further attempts at stabilizing tests. --- .../integration/resources/SHIBUI-1407-1.side | 7 ++ .../integration/resources/SHIBUI-2270-2.side | 119 ++---------------- 2 files changed, 16 insertions(+), 110 deletions(-) diff --git a/backend/src/integration/resources/SHIBUI-1407-1.side b/backend/src/integration/resources/SHIBUI-1407-1.side index 46d1c6fa1..dea518e4a 100644 --- a/backend/src/integration/resources/SHIBUI-1407-1.side +++ b/backend/src/integration/resources/SHIBUI-1407-1.side @@ -2415,6 +2415,13 @@ ["xpath=//button[contains(.,'Compare Selected(2)')]", "xpath:innerText"] ], "value": "" + }, { + "id": "4dbf4b6f-7de9-49e1-a23f-ff748f5a986b", + "comment": "", + "command": "pause", + "target": "3000", + "targets": [], + "value": "" }, { "id": "978829e9-fa70-4548-9a55-0e2ffa0df9a4", "comment": "", diff --git a/backend/src/integration/resources/SHIBUI-2270-2.side b/backend/src/integration/resources/SHIBUI-2270-2.side index 9f1c37d7a..9a645405f 100644 --- a/backend/src/integration/resources/SHIBUI-2270-2.side +++ b/backend/src/integration/resources/SHIBUI-2270-2.side @@ -674,7 +674,7 @@ "id": "3aedee37-3445-4679-afe8-62e53b348e52", "comment": "", "command": "click", - "target": "css=.fa-caret-down > path", + "target": "css=.fa-caret-down", "targets": [ ["css=.fa-caret-down > path", "css:finder"] ], @@ -1185,30 +1185,6 @@ ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] ], "value": "" - }, { - "id": "185cd9b2-0f1b-4f64-a4a5-b62f5a881d45", - "comment": "", - "command": "click", - "target": "css=.p-3", - "targets": [ - ["css=.p-3", "css:finder"], - ["xpath=//div[@id='root']/div/main/div", "xpath:idRelative"], - ["xpath=//main/div", "xpath:position"] - ], - "value": "" - }, { - "id": "2a295dc3-422a-436e-8450-03dbcc88a1b0", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[44]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], - ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] - ], - "value": "" }, { "id": "6fdf6ef4-52e8-44a9-8dc5-8126e2ba11b0", "comment": "", @@ -1665,7 +1641,7 @@ "id": "5bf0b70b-e413-49eb-bfcb-f97a4265c70b", "comment": "", "command": "click", - "target": "css=.fa-caret-down > path", + "target": "css=.fa-caret-down", "targets": [ ["css=.fa-caret-down > path", "css:finder"] ], @@ -1699,26 +1675,6 @@ ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] ], "value": "" - }, { - "id": "cd98777e-1800-417f-af35-9f6d531decfa", - "comment": "", - "command": "click", - "target": "css=form", - "targets": [ - ["css=form", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form", "xpath:idRelative"], - ["xpath=//form", "xpath:position"] - ], - "value": "" - }, { - "id": "2ac41455-f406-4e71-88c0-8c30b7c23eab", - "comment": "", - "command": "click", - "target": "css=.fa-caret-down", - "targets": [ - ["css=.fa-caret-down", "css:finder"] - ], - "value": "" }, { "id": "a729126e-0c39-4db6-882c-b506db087119", "comment": "", @@ -1735,18 +1691,6 @@ ["xpath=//a[contains(.,'Status - Add all')]", "xpath:innerText"] ], "value": "" - }, { - "id": "602156fa-9fed-4a42-9182-4aa66338dd24", - "comment": "", - "command": "click", - "target": "css=td", - "targets": [ - ["css=td", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr/td", "xpath:idRelative"], - ["xpath=//td", "xpath:position"], - ["xpath=//td[contains(.,'At least one property is required.')]", "xpath:innerText"] - ], - "value": "" }, { "id": "878447bd-6424-440f-8dcf-461f994a6478", "comment": "", @@ -1884,30 +1828,6 @@ ["xpath=//a[contains(.,'X509InternalAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" - }, { - "id": "2a8c3086-a40d-4e9c-857a-7fda2bd2e8f5", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[68]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], - ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "93a9c033-0fcc-4af9-85b5-7e18d882bf68", - "comment": "", - "command": "click", - "target": "css=.col-12 > .d-flex", - "targets": [ - ["css=.col-12 > .d-flex", "css:finder"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div", "xpath:idRelative"], - ["xpath=//form/div[2]/div/div", "xpath:position"] - ], - "value": "" }, { "id": "d06a3e9a-849f-4b8d-83a1-797f8abf6794", "comment": "", @@ -1920,6 +1840,13 @@ ["xpath=//form/div[2]/div/div/button", "xpath:position"] ], "value": "" + }, { + "id": "546b2382-08c5-4360-baaa-1adb84522a76", + "comment": "", + "command": "waitForElementVisible", + "target": "css=tr:nth-child(653) > td:nth-child(1)", + "targets": [], + "value": "30000" }, { "id": "1e726b4f-8ae7-40eb-ba52-747c88ae2e89", "comment": "", @@ -1960,20 +1887,6 @@ ["xpath=//a[contains(.,'  Edit')]", "xpath:innerText"] ], "value": "" - }, { - "id": "caeb6c0b-c99d-4e4f-87b1-874ac54f30a8", - "comment": "", - "command": "click", - "target": "id=valueInput-idp.resolvertest.accessPolicy", - "targets": [ - ["id=valueInput-idp.resolvertest.accessPolicy", "id"], - ["name=properties.0.propertyValue", "name"], - ["css=#valueInput-idp\\.resolvertest\\.accessPolicy", "css:finder"], - ["xpath=//input[@id='valueInput-idp.resolvertest.accessPolicy']", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr/td[4]/div/input", "xpath:idRelative"], - ["xpath=//td[4]/div/input", "xpath:position"] - ], - "value": "" }, { "id": "812d8a90-f462-470a-9a4d-efd2cca679c2", "comment": "", @@ -1988,20 +1901,6 @@ ["xpath=//td[4]/div/input", "xpath:position"] ], "value": "foo" - }, { - "id": "8c98218b-9d71-42ac-8682-36d2aeb0f39e", - "comment": "", - "command": "click", - "target": "id=valueInput-idp.resolvertest.logging", - "targets": [ - ["id=valueInput-idp.resolvertest.logging", "id"], - ["name=properties.1.propertyValue", "name"], - ["css=#valueInput-idp\\.resolvertest\\.logging", "css:finder"], - ["xpath=//input[@id='valueInput-idp.resolvertest.logging']", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[4]/div/table/tbody/tr[2]/td[4]/div/input", "xpath:idRelative"], - ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] - ], - "value": "" }, { "id": "948ac5c1-aa09-44af-a024-c0dc898616d1", "comment": "", From 3cd6c86efd202a5e835f9dddea169d60c591a113 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 13 Sep 2022 14:47:10 -0400 Subject: [PATCH 69/71] NOJIRA Yet another attempt at getting 2270-2 to exhibit consistent passing behavior. --- .../integration/resources/SHIBUI-2270-2.side | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/backend/src/integration/resources/SHIBUI-2270-2.side b/backend/src/integration/resources/SHIBUI-2270-2.side index 9a645405f..f8941b4b4 100644 --- a/backend/src/integration/resources/SHIBUI-2270-2.side +++ b/backend/src/integration/resources/SHIBUI-2270-2.side @@ -140,7 +140,7 @@ "id": "3fae037d-0e59-4b9d-adf2-dbd624b72613", "comment": "", "command": "click", - "target": "css=.rbt-input-main", + "target": "css=.toggle-button", "targets": [ ["css=.rbt-input-main", "css:finder"], ["xpath=//input[@value='']", "xpath:attributes"], @@ -168,7 +168,7 @@ "id": "be761931-fb77-4030-bc2c-2577d3a99580", "comment": "", "command": "click", - "target": "css=.rbt-input-main", + "target": "css=.toggle-button", "targets": [ ["css=.rbt-input-main", "css:finder"], ["xpath=//input[@value='']", "xpath:attributes"], @@ -225,7 +225,7 @@ "id": "b1cb5ac9-027c-45f2-b7c2-d1a661378928", "comment": "", "command": "click", - "target": "css=.rbt-input-main", + "target": "css=.toggle-button", "targets": [ ["css=.rbt-input-main", "css:finder"], ["xpath=//input[@value='']", "xpath:attributes"], @@ -253,7 +253,7 @@ "id": "ff91bfaf-f6ce-42c2-9dd4-1c52268d140d", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -307,7 +307,7 @@ "id": "384ea0fc-0bc1-4f63-b736-7e1d67277662", "comment": "", "command": "click", - "target": "css=.rbt-input-main", + "target": "css=.toggle-button", "targets": [ ["css=.rbt-input-main", "css:finder"], ["xpath=//input[@value='']", "xpath:attributes"], @@ -451,7 +451,7 @@ "id": "9f2f0c50-7465-4879-bb68-822bca1f0fa3", "comment": "", "command": "click", - "target": "css=.rbt-input-main", + "target": "css=.toggle-button", "targets": [ ["css=.rbt-input-main", "css:finder"], ["xpath=//input[@value='']", "xpath:attributes"], @@ -479,7 +479,7 @@ "id": "3b326c6f-96d3-4f6c-ba82-e9ffd95517f1", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -562,7 +562,7 @@ "id": "c6bfe838-9027-4c25-990e-e451e9d04a4d", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -674,7 +674,7 @@ "id": "3aedee37-3445-4679-afe8-62e53b348e52", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down > path", "css:finder"] ], @@ -815,7 +815,7 @@ "id": "6d5dcd3a-0d08-4140-9634-196e2e2fdb90", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -898,7 +898,7 @@ "id": "c06b4caf-e093-49b4-8cac-f71bda476995", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1097,7 +1097,7 @@ "id": "e8d736c8-be22-4411-87d4-0a1eefcc821e", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1122,7 +1122,7 @@ "id": "ed236cf8-e185-4b41-a47f-2a9219eab773", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1205,7 +1205,7 @@ "id": "614f715d-8fcc-4e84-8d0d-dd947fc7c99f", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1259,7 +1259,7 @@ "id": "b93aed8b-bd95-496a-ad07-b9bfe23f8522", "comment": "", "command": "click", - "target": "css=.fa-caret-down > path", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down > path", "css:finder"] ], @@ -1400,7 +1400,7 @@ "id": "f7c7f42d-b4cb-4f92-997f-d9677a00758f", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1425,7 +1425,7 @@ "id": "5a3ad5c4-37e2-4060-88bd-ed96b94d037e", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1533,7 +1533,7 @@ "id": "10926b24-5952-4685-be81-802f5fc7ca4a", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1558,7 +1558,7 @@ "id": "5558c433-213a-49de-b68d-e6d9ac396b86", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1641,7 +1641,7 @@ "id": "5bf0b70b-e413-49eb-bfcb-f97a4265c70b", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down > path", "css:finder"] ], @@ -1724,7 +1724,7 @@ "id": "eca7bf2d-db81-4cad-873b-eba9440bd0e5", "comment": "", "command": "click", - "target": "css=.fa-caret-down", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down", "css:finder"] ], @@ -1807,7 +1807,7 @@ "id": "a11e93fd-5a1b-4456-a875-f0b8a8582058", "comment": "", "command": "click", - "target": "css=.fa-caret-down > path", + "target": "css=.toggle-button", "targets": [ ["css=.fa-caret-down > path", "css:finder"] ], @@ -2013,6 +2013,30 @@ ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] ], "value": "" + }, { + "id": "f92982ba-8145-490b-999c-ff52ae1ce146", + "comment": "", + "command": "waitForElementVisible", + "target": "css=td", + "targets": [ + ["css=td", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td", "xpath:idRelative"], + ["xpath=//td", "xpath:position"], + ["xpath=//td[contains(.,'No configurations defined.')]", "xpath:innerText"] + ], + "value": "30000" + }, { + "id": "9bc43f09-b4e4-4f98-94d3-d7a9f3fa05c1", + "comment": "", + "command": "assertText", + "target": "css=td", + "targets": [ + ["css=td", "css:finder"], + ["xpath=//div[@id='root']/div/main/div/section/div/div[2]/div[2]/table/tbody/tr/td", "xpath:idRelative"], + ["xpath=//td", "xpath:position"], + ["xpath=//td[contains(.,'No configurations defined.')]", "xpath:innerText"] + ], + "value": "No configurations defined." }, { "id": "d7643f3c-f387-4404-8f8b-e73ebfeb0754", "comment": "", From c7a10c0879f5f54e14c73f082cc167deb9edf93a Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 13 Sep 2022 14:58:31 -0400 Subject: [PATCH 70/71] NOJIRA More 2270 stability. Maybe. --- .../integration/resources/SHIBUI-2270-2.side | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/backend/src/integration/resources/SHIBUI-2270-2.side b/backend/src/integration/resources/SHIBUI-2270-2.side index f8941b4b4..96995251c 100644 --- a/backend/src/integration/resources/SHIBUI-2270-2.side +++ b/backend/src/integration/resources/SHIBUI-2270-2.side @@ -1887,6 +1887,13 @@ ["xpath=//a[contains(.,'  Edit')]", "xpath:innerText"] ], "value": "" + }, { + "id": "10357b31-6f98-4d85-8d42-1ec5fc4906ca", + "comment": "", + "command": "click", + "target": "id=valueInput-idp.resolvertest.accessPolicy", + "targets": [], + "value": "" }, { "id": "812d8a90-f462-470a-9a4d-efd2cca679c2", "comment": "", @@ -1902,7 +1909,7 @@ ], "value": "foo" }, { - "id": "948ac5c1-aa09-44af-a024-c0dc898616d1", + "id": "2b3f457c-5eb6-4df4-a7f5-3f4856a71cc2", "comment": "", "command": "type", "target": "id=valueInput-idp.resolvertest.logging", @@ -1915,6 +1922,13 @@ ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] ], "value": "bar" + }, { + "id": "948ac5c1-aa09-44af-a024-c0dc898616d1", + "comment": "", + "command": "click", + "target": "id=valueInput-idp.resolvertest.logging", + "targets": [], + "value": "" }, { "id": "46d0e1ac-4706-47cf-9336-683b7b6519f2", "comment": "", @@ -2013,6 +2027,13 @@ ["xpath=//div[4]/div/div/div[3]/button", "xpath:position"] ], "value": "" + }, { + "id": "129a0a85-e23e-447c-b1f0-12587ccd7978", + "comment": "", + "command": "pause", + "target": "5000", + "targets": [], + "value": "" }, { "id": "f92982ba-8145-490b-999c-ff52ae1ce146", "comment": "", From 41b4d9154ccdceadbe1542ffe0fba04b10e0f234 Mon Sep 17 00:00:00 2001 From: Bill Smith Date: Tue, 13 Sep 2022 16:30:09 -0400 Subject: [PATCH 71/71] NOJIRA Last attept at stabilizing a lengthy 2270 test. --- .../integration/resources/SHIBUI-2270-2.side | 904 ++++++++++++++++-- 1 file changed, 812 insertions(+), 92 deletions(-) diff --git a/backend/src/integration/resources/SHIBUI-2270-2.side b/backend/src/integration/resources/SHIBUI-2270-2.side index 96995251c..11400b4db 100644 --- a/backend/src/integration/resources/SHIBUI-2270-2.side +++ b/backend/src/integration/resources/SHIBUI-2270-2.side @@ -164,6 +164,18 @@ ["xpath=//a[contains(.,'AACLI - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "161ef892-c85c-43f3-9356-e93a559a44a0", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "be761931-fb77-4030-bc2c-2577d3a99580", "comment": "", @@ -180,7 +192,7 @@ "id": "eb50041f-bf6e-4ef4-92ee-9319f79b8336", "comment": "", "command": "click", - "target": "id=property-selector-item-9", + "target": "id=property-selector-item-2", "targets": [ ["id=property-selector-item-9", "id"], ["linkText=AccountLockoutManagement - Add all", "linkText"], @@ -192,6 +204,18 @@ ["xpath=//a[contains(.,'AccountLockoutManagement - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "32bf713f-ecd2-4b8c-a0bb-e23c397bbd54", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "de63d0c0-9504-4339-b76f-ce21b7c9f5f8", "comment": "", @@ -209,7 +233,7 @@ "id": "9f0ee002-e494-4409-9461-35d70ec30bf3", "comment": "", "command": "click", - "target": "id=property-selector-item-17", + "target": "id=property-selector-item-3", "targets": [ ["id=property-selector-item-17", "id"], ["linkText=AttendedRestartConfiguration - Add all", "linkText"], @@ -221,6 +245,18 @@ ["xpath=//a[contains(.,'AttendedRestartConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "9026ce67-e4e7-4023-943a-13c40955c7c6", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "b1cb5ac9-027c-45f2-b7c2-d1a661378928", "comment": "", @@ -237,7 +273,7 @@ "id": "53354967-a636-428a-8dea-c771e2ee3add", "comment": "", "command": "click", - "target": "id=property-selector-item-25", + "target": "id=property-selector-item-4", "targets": [ ["id=property-selector-item-25", "id"], ["linkText=AttributePostLoginC14NConfiguration - Add all", "linkText"], @@ -249,6 +285,18 @@ ["xpath=//a[contains(.,'AttributePostLoginC14NConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "3a12a054-f507-4e10-b7fb-988fe56a4879", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "ff91bfaf-f6ce-42c2-9dd4-1c52268d140d", "comment": "", @@ -262,7 +310,7 @@ "id": "825680dd-0180-4b92-a2df-40d041c24831", "comment": "", "command": "click", - "target": "id=property-selector-item-33", + "target": "id=property-selector-item-5", "targets": [ ["id=property-selector-item-33", "id"], ["linkText=AuditLoggingConfiguration - Add all", "linkText"], @@ -274,6 +322,18 @@ ["xpath=//a[contains(.,'AuditLoggingConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "a629072e-6d4b-45a9-bcfc-49b7f5ec610e", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "1c671949-1992-4cbd-930c-0153e1fea983", "comment": "", @@ -291,7 +351,7 @@ "id": "7e6f1147-95fa-4f2e-b71c-bdc2265c8537", "comment": "", "command": "click", - "target": "id=property-selector-item-49", + "target": "id=property-selector-item-6", "targets": [ ["id=property-selector-item-49", "id"], ["linkText=AuthenticationConfiguration - Add all", "linkText"], @@ -303,6 +363,18 @@ ["xpath=//a[contains(.,'AuthenticationConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "635ddc4a-f916-4bcd-b7a3-cec6e1a267ca", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "384ea0fc-0bc1-4f63-b736-7e1d67277662", "comment": "", @@ -319,7 +391,7 @@ "id": "2158cbdc-85be-4082-938c-00a14e0d6d63", "comment": "", "command": "click", - "target": "id=property-selector-item-59", + "target": "id=property-selector-item-7", "targets": [ ["id=property-selector-item-59", "id"], ["linkText=CSRF - Add all", "linkText"], @@ -331,6 +403,18 @@ ["xpath=//a[contains(.,'CSRF - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "84e6519a-960d-4c27-a405-395355969ea4", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "a861c6d1-277e-438f-a49c-d47521f67dcc", "comment": "", @@ -348,7 +432,7 @@ "id": "f71b15c0-ff1b-4f26-8630-b755e1af00aa", "comment": "", "command": "click", - "target": "id=property-selector-item-62", + "target": "id=property-selector-item-8", "targets": [ ["id=property-selector-item-62", "id"], ["linkText=CasProtocolConfiguration - Add all", "linkText"], @@ -360,6 +444,18 @@ ["xpath=//a[contains(.,'CasProtocolConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "d6d64aa2-c565-4204-8390-35fb0c2217a9", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "50f0c334-c0ca-43dc-8464-6d5d5b64de3e", "comment": "", @@ -377,7 +473,7 @@ "id": "ab25fbad-3959-4b65-ae5b-cd8cf81679d3", "comment": "", "command": "click", - "target": "id=property-selector-item-66", + "target": "id=property-selector-item-9", "targets": [ ["id=property-selector-item-66", "id"], ["linkText=ConsentConfiguration - Add all", "linkText"], @@ -389,6 +485,18 @@ ["xpath=//a[contains(.,'ConsentConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "1b348c87-d54a-4323-9bb9-9ce5bde493aa", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5b5e0325-1735-4b9a-9920-5dac993cbb13", "comment": "", @@ -406,7 +514,7 @@ "id": "d06957b0-f5fa-4960-ac87-750566eb8484", "comment": "", "command": "click", - "target": "id=property-selector-item-84", + "target": "id=property-selector-item-10", "targets": [ ["id=property-selector-item-84", "id"], ["linkText=Core - Add all", "linkText"], @@ -418,6 +526,18 @@ ["xpath=//a[contains(.,'Core - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "f37bb161-c2fe-458d-b2f1-4c84f17ae1af", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "cf7d85ba-7edc-4bf1-938a-a88fd04c7252", "comment": "", @@ -435,7 +555,7 @@ "id": "630e9dc2-89d6-435e-bd3d-040814109f16", "comment": "", "command": "click", - "target": "id=property-selector-item-100", + "target": "id=property-selector-item-11", "targets": [ ["id=property-selector-item-100", "id"], ["linkText=DuoAuthnConfiguration - Add all", "linkText"], @@ -447,6 +567,18 @@ ["xpath=//a[contains(.,'DuoAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "565f7538-ceb5-46b0-8f95-d67ff41d24e2", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "9f2f0c50-7465-4879-bb68-822bca1f0fa3", "comment": "", @@ -463,7 +595,7 @@ "id": "6f28c9cc-1006-456b-ae72-b70006636829", "comment": "", "command": "click", - "target": "id=property-selector-item-127", + "target": "id=property-selector-item-12", "targets": [ ["id=property-selector-item-127", "id"], ["linkText=DuoOIDCAuthnConfiguration - Add all", "linkText"], @@ -475,6 +607,18 @@ ["xpath=//a[contains(.,'DuoOIDCAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "d6491bae-0111-4831-9a5d-bdd59fd499fd", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "3b326c6f-96d3-4f6c-ba82-e9ffd95517f1", "comment": "", @@ -488,7 +632,7 @@ "id": "ec3ac03f-c46b-4e1c-a89d-e2dc9826ca98", "comment": "", "command": "click", - "target": "id=property-selector-item-169", + "target": "id=property-selector-item-13", "targets": [ ["id=property-selector-item-169", "id"], ["linkText=ErrorHandlingConfiguration - Add all", "linkText"], @@ -500,6 +644,18 @@ ["xpath=//a[contains(.,'ErrorHandlingConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "d111643c-b2f9-43d2-9421-d48e008c6acd", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "ce43ffb1-3979-4381-a155-9a2a59d1ac95", "comment": "", @@ -517,7 +673,7 @@ "id": "62d42fb7-00e2-400d-a1be-adcbf826ce3a", "comment": "", "command": "click", - "target": "id=property-selector-item-175", + "target": "id=property-selector-item-14", "targets": [ ["id=property-selector-item-175", "id"], ["linkText=ExternalAuthnConfiguration - Add all", "linkText"], @@ -529,6 +685,18 @@ ["xpath=//a[contains(.,'ExternalAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "32940f9c-1028-48de-86f5-31b49e098b1c", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "b1c01f80-778c-4ea3-b952-dd84c18e5904", "comment": "", @@ -546,7 +714,7 @@ "id": "8a3757ee-2564-436e-abc5-e0584a59a82e", "comment": "", "command": "click", - "target": "id=property-selector-item-192", + "target": "id=property-selector-item-15", "targets": [ ["id=property-selector-item-192", "id"], ["linkText=FTICKSLoggingConfiguration - Add all", "linkText"], @@ -558,6 +726,18 @@ ["xpath=//a[contains(.,'FTICKSLoggingConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "e5a60d2e-60b2-464e-be45-c73b8717ba2e", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "c6bfe838-9027-4c25-990e-e451e9d04a4d", "comment": "", @@ -571,7 +751,7 @@ "id": "0c462504-cb92-421d-aeb0-8afecac90aec", "comment": "", "command": "click", - "target": "id=property-selector-item-199", + "target": "id=property-selector-item-16", "targets": [ ["id=property-selector-item-199", "id"], ["linkText=FunctionAuthnConfiguration - Add all", "linkText"], @@ -583,6 +763,18 @@ ["xpath=//a[contains(.,'FunctionAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "e44eac9f-47ab-48ec-a821-17c74a00d17b", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "892d14a0-9ab0-4c05-945b-bd96d461eba8", "comment": "", @@ -600,7 +792,7 @@ "id": "9a809145-1f01-4a6b-8eaf-836f91a9bd5a", "comment": "", "command": "click", - "target": "id=property-selector-item-214", + "target": "id=property-selector-item-17", "targets": [ ["id=property-selector-item-214", "id"], ["linkText=HelloWorldConfiguration - Add all", "linkText"], @@ -612,6 +804,18 @@ ["xpath=//a[contains(.,'HelloWorldConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "a2647ee4-f9df-4698-ab1f-02d7b488b835", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "8e3dc610-99f9-4a85-a0c0-cd572ccf0a84", "comment": "", @@ -629,7 +833,7 @@ "id": "fa182a6d-bba7-4f50-a6d8-a5391b592004", "comment": "", "command": "click", - "target": "id=property-selector-item-222", + "target": "id=property-selector-item-18", "targets": [ ["id=property-selector-item-222", "id"], ["linkText=IPAddressAuthnConfiguration - Add all", "linkText"], @@ -641,6 +845,18 @@ ["xpath=//a[contains(.,'IPAddressAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "43df662a-1205-40ca-967e-2473b36eb829", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "17e45a4b-9d00-478f-9add-c1a7138a7959", "comment": "", @@ -658,7 +874,7 @@ "id": "2a3578cb-56d5-4805-8e82-2058e17c3ad5", "comment": "", "command": "click", - "target": "id=property-selector-item-237", + "target": "id=property-selector-item-19", "targets": [ ["id=property-selector-item-237", "id"], ["linkText=JAASAuthnConfiguration - Add all", "linkText"], @@ -670,6 +886,18 @@ ["xpath=//a[contains(.,'JAASAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "f24149b6-8c1e-4ffa-b08a-262f7bc270b0", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "3aedee37-3445-4679-afe8-62e53b348e52", "comment": "", @@ -683,7 +911,7 @@ "id": "fce00a94-ffe3-4771-b33d-e6c8cde6c690", "comment": "", "command": "click", - "target": "id=property-selector-item-240", + "target": "id=property-selector-item-20", "targets": [ ["id=property-selector-item-240", "id"], ["linkText=KerberosAuthnConfiguration - Add all", "linkText"], @@ -695,6 +923,18 @@ ["xpath=//a[contains(.,'KerberosAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "f3fb5c6b-ddcf-4dd5-83c2-4b3f6960e5fc", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "37642e97-2b2a-4cfd-9b71-d150c13b1b2d", "comment": "", @@ -712,7 +952,7 @@ "id": "fdae4c41-909b-44b1-b245-469c430a09a0", "comment": "", "command": "click", - "target": "id=property-selector-item-245", + "target": "id=property-selector-item-21", "targets": [ ["id=property-selector-item-245", "id"], ["linkText=LDAPAuthnConfiguration - Add all", "linkText"], @@ -724,6 +964,18 @@ ["xpath=//a[contains(.,'LDAPAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "fa39c178-50a4-4761-ba14-86c9bb7e146d", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "f34f0217-ff82-441b-a73b-b25f791bc546", "comment": "", @@ -741,7 +993,7 @@ "id": "d30d9da8-65e0-41a1-b27f-c4cc998c97fd", "comment": "", "command": "click", - "target": "id=property-selector-item-281", + "target": "id=property-selector-item-22", "targets": [ ["id=property-selector-item-281", "id"], ["linkText=LogoutConfiguration - Add all", "linkText"], @@ -753,6 +1005,18 @@ ["xpath=//a[contains(.,'LogoutConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "4313bd45-a1f1-43ca-87be-9d173ac965fb", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "cb442dbe-c609-4b8b-ac55-2d32362be80b", "comment": "", @@ -770,7 +1034,7 @@ "id": "19b1de66-7601-4e41-a345-657c5417f23f", "comment": "", "command": "click", - "target": "id=property-selector-item-288", + "target": "id=property-selector-item-23", "targets": [ ["id=property-selector-item-288", "id"], ["linkText=MetadataQuery - Add all", "linkText"], @@ -782,6 +1046,18 @@ ["xpath=//a[contains(.,'MetadataQuery - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "5a58e55d-3351-4ecd-addc-c0d1a74b7c80", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "513c8bd3-cbb4-443f-9a90-8a2ae9d5c0ce", "comment": "", @@ -799,7 +1075,7 @@ "id": "515cc435-61ee-430a-8cdc-ac41e3926fbc", "comment": "", "command": "click", - "target": "id=property-selector-item-296", + "target": "id=property-selector-item-24", "targets": [ ["id=property-selector-item-296", "id"], ["linkText=MetadataReload - Add all", "linkText"], @@ -811,6 +1087,18 @@ ["xpath=//a[contains(.,'MetadataReload - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "4252877a-5ba4-4a08-93a3-865463f8e8ab", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "6d5dcd3a-0d08-4140-9634-196e2e2fdb90", "comment": "", @@ -824,7 +1112,7 @@ "id": "2b2a05d9-4e8b-45cf-882f-08328cb0b6e5", "comment": "", "command": "click", - "target": "id=property-selector-item-304", + "target": "id=property-selector-item-25", "targets": [ ["id=property-selector-item-304", "id"], ["linkText=Metadatagen - Add all", "linkText"], @@ -836,6 +1124,18 @@ ["xpath=//a[contains(.,'Metadatagen - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "1d9b32f7-e71c-414d-a138-d7238ff2cd90", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "f1709162-b102-48da-81b0-5862158fd74d", "comment": "", @@ -853,7 +1153,7 @@ "id": "643c1db8-10f8-4146-94fb-bf920b007c00", "comment": "", "command": "click", - "target": "id=property-selector-item-313", + "target": "id=property-selector-item-26", "targets": [ ["id=property-selector-item-313", "id"], ["linkText=MetricsConfiguration - Add all", "linkText"], @@ -865,6 +1165,18 @@ ["xpath=//a[contains(.,'MetricsConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "5eefe563-90b6-482e-bc3a-a1f001d2f403", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "206468ff-7786-4e32-96dd-4c0e9a2194b7", "comment": "", @@ -882,7 +1194,7 @@ "id": "00f2e151-13aa-4ac0-bb0c-d7e531f422a5", "comment": "", "command": "click", - "target": "id=property-selector-item-320", + "target": "id=property-selector-item-27", "targets": [ ["id=property-selector-item-320", "id"], ["linkText=Misc - Add all", "linkText"], @@ -894,6 +1206,18 @@ ["xpath=//a[contains(.,'Misc - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "419ef781-8332-44e9-9c20-1ac1f680f1cb", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "c06b4caf-e093-49b4-8cac-f71bda476995", "comment": "", @@ -907,7 +1231,7 @@ "id": "031e88e8-bde7-4d25-8aab-919bc8882901", "comment": "", "command": "click", - "target": "id=property-selector-item-326", + "target": "id=property-selector-item-28", "targets": [ ["id=property-selector-item-326", "id"], ["linkText=MultiFactorAuthnConfiguration - Add all", "linkText"], @@ -919,6 +1243,18 @@ ["xpath=//a[contains(.,'MultiFactorAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "7e1bd75f-13e1-4129-8c0b-230abad99d05", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "7ab63a23-e0ab-4a07-8ef8-9fdb6af9f59b", "comment": "", @@ -936,7 +1272,7 @@ "id": "34cbdae8-4b4c-4faa-a38c-f3a9c5475e45", "comment": "", "command": "click", - "target": "id=property-selector-item-342", + "target": "id=property-selector-item-29", "targets": [ ["id=property-selector-item-342", "id"], ["linkText=NameIDConsumptionConfiguration - Add all", "linkText"], @@ -948,6 +1284,18 @@ ["xpath=//a[contains(.,'NameIDConsumptionConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "c7d69437-7bf5-4fb9-8450-47c0aecdae0b", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "15c61405-c967-475f-b494-6bdb461b5283", "comment": "", @@ -965,7 +1313,7 @@ "id": "6e13ab35-510b-4e7b-976c-457d59f65606", "comment": "", "command": "click", - "target": "id=property-selector-item-345", + "target": "id=property-selector-item-30", "targets": [ ["id=property-selector-item-345", "id"], ["linkText=NameIDGenerationConfiguration - Add all", "linkText"], @@ -977,6 +1325,18 @@ ["xpath=//a[contains(.,'NameIDGenerationConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "c2d86012-0b07-4f31-a0a7-47afcd6d5697", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "74505e9c-1a4b-441d-9e21-fce8077576b4", "comment": "", @@ -994,7 +1354,7 @@ "id": "ec03564e-9ff9-4c53-914e-e33e8efec3b8", "comment": "", "command": "click", - "target": "id=property-selector-item-349", + "target": "id=property-selector-item-31", "targets": [ ["id=property-selector-item-349", "id"], ["linkText=OAuth2ClientAuthnConfiguration - Add all", "linkText"], @@ -1006,6 +1366,18 @@ ["xpath=//a[contains(.,'OAuth2ClientAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "f89312e5-6a9c-4bcc-bd98-bade2d380829", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "9bc758f1-8c06-429e-abf4-78fadd181d56", "comment": "", @@ -1023,7 +1395,7 @@ "id": "a81e8d28-41b8-47d1-901b-6d36fb90398d", "comment": "", "command": "click", - "target": "id=property-selector-item-358", + "target": "id=property-selector-item-32", "targets": [ ["id=property-selector-item-358", "id"], ["linkText=OIDC OP - Add all", "linkText"], @@ -1035,6 +1407,18 @@ ["xpath=//a[contains(.,'OIDC OP - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "fee01919-c451-487c-b329-12e715df8d23", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5e1646f3-7841-4b97-96c9-639c6f7ef3ca", "comment": "", @@ -1052,7 +1436,7 @@ "id": "f3865e29-6b36-49ab-99a4-44370b5ed974", "comment": "", "command": "click", - "target": "id=property-selector-item-371", + "target": "id=property-selector-item-33", "targets": [ ["id=property-selector-item-371", "id"], ["linkText=OPAuthorization - Add all", "linkText"], @@ -1064,6 +1448,18 @@ ["xpath=//a[contains(.,'OPAuthorization - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "7dd7a6e4-4b73-4d81-968f-bff6f5688fd4", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "821c3a6d-b9a6-45bf-bda3-46c2f1e87303", "comment": "", @@ -1081,7 +1477,7 @@ "id": "72620249-22a8-436b-b506-670fad77fefa", "comment": "", "command": "click", - "target": "id=property-selector-item-378", + "target": "id=property-selector-item-34", "targets": [ ["id=property-selector-item-378", "id"], ["linkText=OPClientAuthentication - Add all", "linkText"], @@ -1093,6 +1489,18 @@ ["xpath=//a[contains(.,'OPClientAuthentication - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "dc272d77-865b-4dae-bfc4-c64298eece48", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "e8d736c8-be22-4411-87d4-0a1eefcc821e", "comment": "", @@ -1106,7 +1514,7 @@ "id": "d8ef3cf9-1398-4bcd-b976-92a2a471ce1c", "comment": "", "command": "click", - "target": "id=property-selector-item-380", + "target": "id=property-selector-item-35", "targets": [ ["id=property-selector-item-380", "id"], ["linkText=OPClientCredentialsGrant - Add all", "linkText"], @@ -1118,6 +1526,18 @@ ["xpath=//a[contains(.,'OPClientCredentialsGrant - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "7db3f06c-ff54-4312-8f21-8beaec2e64b6", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "ed236cf8-e185-4b41-a47f-2a9219eab773", "comment": "", @@ -1131,7 +1551,7 @@ "id": "d4965727-9cc9-465a-9d4d-9e3a16c9507a", "comment": "", "command": "click", - "target": "id=property-selector-item-383", + "target": "id=property-selector-item-36", "targets": [ ["id=property-selector-item-383", "id"], ["linkText=OPClientResolution - Add all", "linkText"], @@ -1143,6 +1563,18 @@ ["xpath=//a[contains(.,'OPClientResolution - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "942a8de5-3f66-400a-8652-9e77d56cc41e", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "899a5897-0786-4f40-8d1f-2c3cc64f4666", "comment": "", @@ -1150,17 +1582,58 @@ "target": "css=.toggle-button", "targets": [ ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[43]", "xpath:attributes"], + ["xpath=(//button[@type='button'])[43]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], + ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], + ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "a08f536a-166d-45e0-a477-b7aece98a6bc", + "comment": "", + "command": "click", + "target": "id=property-selector-item-37", + "targets": [ + ["id=property-selector-item-387", "id"], + ["linkText=OPCustomFilterRegistration - Add all", "linkText"], + ["css=#property-selector-item-387", "css:finder"], + ["xpath=//a[@id='property-selector-item-387']", "xpath:attributes"], + ["xpath=//div[@id='property-selector']/div[74]/a", "xpath:idRelative"], + ["xpath=(//a[contains(@href, '#')])[387]", "xpath:href"], + ["xpath=//div[74]/a", "xpath:position"], + ["xpath=//a[contains(.,'OPCustomFilterRegistration - Add all')]", "xpath:innerText"] + ], + "value": "" + }, { + "id": "743cfb54-8a45-485f-b99a-69f9ebac1e4c", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" + }, { + "id": "90ec186d-d13c-49a1-9912-744f62873feb", + "comment": "", + "command": "click", + "target": "css=.toggle-button", + "targets": [ + ["css=.toggle-button", "css:finder"], + ["xpath=(//button[@type='button'])[44]", "xpath:attributes"], ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] ], "value": "" }, { - "id": "a08f536a-166d-45e0-a477-b7aece98a6bc", + "id": "5d32be07-b83d-4b24-bfd0-f6c58c3e2228", "comment": "", "command": "click", - "target": "id=property-selector-item-387", + "target": "id=property-selector-item-38", "targets": [ ["id=property-selector-item-387", "id"], ["linkText=OPCustomFilterRegistration - Add all", "linkText"], @@ -1173,32 +1646,15 @@ ], "value": "" }, { - "id": "90ec186d-d13c-49a1-9912-744f62873feb", - "comment": "", - "command": "click", - "target": "css=.toggle-button", - "targets": [ - ["css=.toggle-button", "css:finder"], - ["xpath=(//button[@type='button'])[44]", "xpath:attributes"], - ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/div/div/button", "xpath:idRelative"], - ["xpath=//div[2]/div/div/div/div/button", "xpath:position"], - ["xpath=//button[contains(.,'Options')]", "xpath:innerText"] - ], - "value": "" - }, { - "id": "6fdf6ef4-52e8-44a9-8dc5-8126e2ba11b0", + "id": "998d8862-f79e-4ec4-889e-ce046de3c11c", "comment": "", "command": "click", - "target": "id=property-selector-item-389", + "target": "xpath=//form/div[2]/div/div/button", "targets": [ - ["id=property-selector-item-389", "id"], - ["linkText=OPDiscovery - Add all", "linkText"], - ["css=#property-selector-item-389", "css:finder"], - ["xpath=//a[@id='property-selector-item-389']", "xpath:attributes"], - ["xpath=//div[@id='property-selector']/div[76]/a", "xpath:idRelative"], - ["xpath=(//a[contains(@href, '#')])[389]", "xpath:href"], - ["xpath=//div[76]/a", "xpath:position"], - ["xpath=//a[contains(.,'OPDiscovery - Add all')]", "xpath:innerText"] + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] ], "value": "" }, { @@ -1214,7 +1670,7 @@ "id": "a3bbcc78-ce50-4b17-9419-f228664dc9fc", "comment": "", "command": "click", - "target": "id=property-selector-item-392", + "target": "id=property-selector-item-39", "targets": [ ["id=property-selector-item-392", "id"], ["linkText=OPDynamicClientRegistration - Add all", "linkText"], @@ -1226,6 +1682,18 @@ ["xpath=//a[contains(.,'OPDynamicClientRegistration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "fc0a234c-ee59-4af0-93cf-7994b3cef11f", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "ec8f2a2b-b45d-4345-af4b-dd5965f9dc54", "comment": "", @@ -1243,7 +1711,7 @@ "id": "ba6779d8-9a40-4981-a41f-c8c22df7027a", "comment": "", "command": "click", - "target": "id=property-selector-item-407", + "target": "id=property-selector-item-40", "targets": [ ["id=property-selector-item-407", "id"], ["linkText=OPMetadataPolicies - Add all", "linkText"], @@ -1255,6 +1723,18 @@ ["xpath=//a[contains(.,'OPMetadataPolicies - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "7dbff2cb-b2e1-4054-9411-6a823dffa819", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "b93aed8b-bd95-496a-ad07-b9bfe23f8522", "comment": "", @@ -1268,7 +1748,7 @@ "id": "57fc676c-34fc-4220-915e-be3c30821030", "comment": "", "command": "click", - "target": "id=property-selector-item-409", + "target": "id=property-selector-item-41", "targets": [ ["id=property-selector-item-409", "id"], ["linkText=OPRevocation - Add all", "linkText"], @@ -1280,6 +1760,18 @@ ["xpath=//a[contains(.,'OPRevocation - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "24758ea5-317b-4c0e-9919-d79c2de026a8", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "85efb0c2-9a2b-4816-b77d-4c84816f3499", "comment": "", @@ -1297,7 +1789,7 @@ "id": "0c424441-f80c-4f42-9a4a-2df0be1ad937", "comment": "", "command": "click", - "target": "id=property-selector-item-412", + "target": "id=property-selector-item-42", "targets": [ ["id=property-selector-item-412", "id"], ["linkText=OPSecurity - Add all", "linkText"], @@ -1309,6 +1801,18 @@ ["xpath=//a[contains(.,'OPSecurity - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "3adce77e-2dbb-41c6-9637-bc1db9925f43", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "686dc5ad-4686-4364-865e-e8c95210f7e3", "comment": "", @@ -1326,7 +1830,7 @@ "id": "da318a35-6cdf-4346-b357-3aadeaf46640", "comment": "", "command": "click", - "target": "id=property-selector-item-420", + "target": "id=property-selector-item-43", "targets": [ ["id=property-selector-item-420", "id"], ["linkText=OPSubClaim - Add all", "linkText"], @@ -1338,6 +1842,18 @@ ["xpath=//a[contains(.,'OPSubClaim - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "f1365110-924c-4cd5-9a2d-801e668a8594", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5f8f249d-2052-4b6f-be83-9cdde0f5a06d", "comment": "", @@ -1355,7 +1871,7 @@ "id": "f36fb2c2-bf28-4fb0-8a6e-083b8a7d854e", "comment": "", "command": "click", - "target": "id=property-selector-item-424", + "target": "id=property-selector-item-44", "targets": [ ["id=property-selector-item-424", "id"], ["linkText=OPToken - Add all", "linkText"], @@ -1367,6 +1883,18 @@ ["xpath=//a[contains(.,'OPToken - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "36d15c9b-c948-48d1-b779-6cf5fff7c93a", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5e7fc6cc-c7e3-4d4b-b682-ec939c8a5db1", "comment": "", @@ -1384,7 +1912,7 @@ "id": "24fa8f94-9a62-4e11-9125-a6c576695e77", "comment": "", "command": "click", - "target": "id=property-selector-item-436", + "target": "id=property-selector-item-45", "targets": [ ["id=property-selector-item-436", "id"], ["linkText=PersistentNameIDGenerationConfiguration - Add all", "linkText"], @@ -1396,6 +1924,18 @@ ["xpath=//a[contains(.,'PersistentNameIDGenerationConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "99b294a6-77f5-4d63-96a8-e4a0724e22bf", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "f7c7f42d-b4cb-4f92-997f-d9677a00758f", "comment": "", @@ -1409,7 +1949,7 @@ "id": "7bfdfde0-3399-4161-9cbc-e67f10ae44b5", "comment": "", "command": "click", - "target": "id=property-selector-item-460", + "target": "id=property-selector-item-46", "targets": [ ["id=property-selector-item-460", "id"], ["linkText=ReloadableServices - Add all", "linkText"], @@ -1421,6 +1961,18 @@ ["xpath=//a[contains(.,'ReloadableServices - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "a9c1d8ea-ae21-43d6-adc2-be6696a9d16e", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5a3ad5c4-37e2-4060-88bd-ed96b94d037e", "comment": "", @@ -1434,7 +1986,7 @@ "id": "db192d5c-0857-4059-869d-d1ff40fd8844", "comment": "", "command": "click", - "target": "id=property-selector-item-501", + "target": "id=property-selector-item-47", "targets": [ ["id=property-selector-item-501", "id"], ["linkText=RelyingPartyConfiguration - Add all", "linkText"], @@ -1446,6 +1998,18 @@ ["xpath=//a[contains(.,'RelyingPartyConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "019376a3-6cbc-4dce-b948-9655bc765038", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "46e1fd14-ca91-4f92-a919-695dcff58622", "comment": "", @@ -1463,7 +2027,7 @@ "id": "bf5ba1a6-ba55-4397-91fa-7f1c1cd28e0d", "comment": "", "command": "click", - "target": "id=property-selector-item-507", + "target": "id=property-selector-item-48", "targets": [ ["id=property-selector-item-507", "id"], ["linkText=RemoteUserAuthnConfiguration - Add all", "linkText"], @@ -1475,6 +2039,18 @@ ["xpath=//a[contains(.,'RemoteUserAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "c15a438c-5582-44a0-8d87-70a1034ca0bf", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "fde12162-843c-4425-bc3e-f404f52cd232", "comment": "", @@ -1488,7 +2064,7 @@ "id": "e1313d05-d1ff-4196-8ae7-eb04c1088afd", "comment": "", "command": "click", - "target": "id=property-selector-item-524", + "target": "id=property-selector-item-49", "targets": [ ["id=property-selector-item-524", "id"], ["linkText=RemoteUserInternalAuthnConfiguration - Add all", "linkText"], @@ -1500,6 +2076,18 @@ ["xpath=//a[contains(.,'RemoteUserInternalAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "1e2a6f80-46e4-42d3-b30e-46bcbb07a7b7", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "1b2b7432-6d03-4b84-922c-59b9cee6ccc5", "comment": "", @@ -1517,7 +2105,7 @@ "id": "31fff123-cc89-4473-9943-a7b5d1206de7", "comment": "", "command": "click", - "target": "id=property-selector-item-549", + "target": "id=property-selector-item-50", "targets": [ ["id=property-selector-item-549", "id"], ["linkText=SAML2ProxyTransformPostLoginC14NConfiguration - Add all", "linkText"], @@ -1529,6 +2117,18 @@ ["xpath=//a[contains(.,'SAML2ProxyTransformPostLoginC14NConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "d583a94e-bb04-4c34-ad36-8154af54a05c", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "10926b24-5952-4685-be81-802f5fc7ca4a", "comment": "", @@ -1542,7 +2142,7 @@ "id": "746398e5-d85c-412c-8a64-45c6d2a669ee", "comment": "", "command": "click", - "target": "id=property-selector-item-552", + "target": "id=property-selector-item-51", "targets": [ ["id=property-selector-item-552", "id"], ["linkText=SAMLAuthnConfiguration - Add all", "linkText"], @@ -1554,6 +2154,18 @@ ["xpath=//a[contains(.,'SAMLAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "fd0211b1-c372-487c-9110-e870534cf39c", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5558c433-213a-49de-b68d-e6d9ac396b86", "comment": "", @@ -1567,7 +2179,7 @@ "id": "a85d9957-d3f3-4304-bd85-dd25ae70592b", "comment": "", "command": "click", - "target": "id=property-selector-item-572", + "target": "id=property-selector-item-52", "targets": [ ["id=property-selector-item-572", "id"], ["linkText=SPNEGOAuthnConfiguration - Add all", "linkText"], @@ -1579,6 +2191,18 @@ ["xpath=//a[contains(.,'SPNEGOAuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "cbe5f9bb-b431-4de5-9522-f9a3585839b2", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "62dcb81a-9265-4f8f-ac8e-6ae7027a3601", "comment": "", @@ -1596,7 +2220,7 @@ "id": "18da3cfc-943f-43e5-ab16-6a9070336d5c", "comment": "", "command": "click", - "target": "id=property-selector-item-592", + "target": "id=property-selector-item-53", "targets": [ ["id=property-selector-item-592", "id"], ["linkText=SecurityConfiguration - Add all", "linkText"], @@ -1608,6 +2232,18 @@ ["xpath=//a[contains(.,'SecurityConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "479b0839-b06a-4198-ac33-564b1ed167ad", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "894853a1-2202-4ff4-bc06-f0f7faf32505", "comment": "", @@ -1625,7 +2261,7 @@ "id": "12440bab-1419-4d7d-948c-71811b067df2", "comment": "", "command": "click", - "target": "id=property-selector-item-626", + "target": "id=property-selector-item-54", "targets": [ ["id=property-selector-item-626", "id"], ["linkText=SessionConfiguration - Add all", "linkText"], @@ -1637,6 +2273,18 @@ ["xpath=//a[contains(.,'SessionConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "59eea1df-31ec-424e-a322-788d308372be", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "5bf0b70b-e413-49eb-bfcb-f97a4265c70b", "comment": "", @@ -1650,7 +2298,7 @@ "id": "eb83e85f-6924-44ac-9922-9c5a1fcbcbc5", "comment": "", "command": "click", - "target": "id=property-selector-item-639", + "target": "id=property-selector-item-55", "targets": [ ["id=property-selector-item-639", "id"], ["linkText=SimplePostLoginC14NConfiguration - Add all", "linkText"], @@ -1662,6 +2310,18 @@ ["xpath=//a[contains(.,'SimplePostLoginC14NConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "db50354f-7930-4f07-acae-aabe51699ae0", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "d941d154-a6a3-4684-ad04-ca9d45acf2aa", "comment": "", @@ -1679,7 +2339,7 @@ "id": "a729126e-0c39-4db6-882c-b506db087119", "comment": "", "command": "click", - "target": "id=property-selector-item-643", + "target": "id=property-selector-item-56", "targets": [ ["id=property-selector-item-643", "id"], ["linkText=Status - Add all", "linkText"], @@ -1691,6 +2351,18 @@ ["xpath=//a[contains(.,'Status - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "d57ea24b-ba28-4df9-8bcc-4e2f81fa0a37", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "878447bd-6424-440f-8dcf-461f994a6478", "comment": "", @@ -1708,7 +2380,7 @@ "id": "3b964802-50ee-4a2a-8db6-d24a51a61483", "comment": "", "command": "click", - "target": "id=property-selector-item-651", + "target": "id=property-selector-item-57", "targets": [ ["id=property-selector-item-651", "id"], ["linkText=StorageConfiguration - Add all", "linkText"], @@ -1720,6 +2392,18 @@ ["xpath=//a[contains(.,'StorageConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "74a2c100-4829-443c-8b00-d6e1db73815e", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "eca7bf2d-db81-4cad-873b-eba9440bd0e5", "comment": "", @@ -1733,7 +2417,7 @@ "id": "40ca1af5-e808-4b69-a5dd-3b545c1b233d", "comment": "", "command": "click", - "target": "id=property-selector-item-659", + "target": "id=property-selector-item-58", "targets": [ ["id=property-selector-item-659", "id"], ["linkText=TOTP - Add all", "linkText"], @@ -1745,6 +2429,18 @@ ["xpath=//a[contains(.,'TOTP - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "727b615e-a3e8-4254-b162-970b19aeb2a0", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "d6e986cb-865d-4472-b791-ea9ba459a849", "comment": "", @@ -1762,7 +2458,7 @@ "id": "26be9d61-f3c2-482e-8d0d-759a00c9b28f", "comment": "", "command": "click", - "target": "id=property-selector-item-677", + "target": "id=property-selector-item-59", "targets": [ ["id=property-selector-item-677", "id"], ["linkText=X500PostLoginC14NConfiguration - Add all", "linkText"], @@ -1774,6 +2470,18 @@ ["xpath=//a[contains(.,'X500PostLoginC14NConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "3fd22066-5329-4435-b7ef-ed6f1853e964", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "966c35be-39a4-4fa9-aded-8ba6fa1394a2", "comment": "", @@ -1791,7 +2499,7 @@ "id": "5124a661-4c33-4468-9c08-505268f78ff0", "comment": "", "command": "click", - "target": "id=property-selector-item-683", + "target": "id=property-selector-item-60", "targets": [ ["id=property-selector-item-683", "id"], ["linkText=X509AuthnConfiguration - Add all", "linkText"], @@ -1803,6 +2511,18 @@ ["xpath=//a[contains(.,'X509AuthnConfiguration - Add all')]", "xpath:innerText"] ], "value": "" + }, { + "id": "34c11849-e76a-4169-b63c-4c714912c25f", + "comment": "", + "command": "click", + "target": "xpath=//form/div[2]/div/div/button", + "targets": [ + ["css=.ms-2", "css:finder"], + ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], + ["xpath=//div[@id='root']/div/main/div/section/div[2]/div/form/div[2]/div/div/button", "xpath:idRelative"], + ["xpath=//form/div[2]/div/div/button", "xpath:position"] + ], + "value": "" }, { "id": "a11e93fd-5a1b-4456-a875-f0b8a8582058", "comment": "", @@ -1816,7 +2536,7 @@ "id": "299da229-ce40-43ac-87c6-2bb6c1122d93", "comment": "", "command": "click", - "target": "id=property-selector-item-699", + "target": "id=property-selector-item-61", "targets": [ ["id=property-selector-item-699", "id"], ["linkText=X509InternalAuthnConfiguration - Add all", "linkText"], @@ -1832,7 +2552,7 @@ "id": "d06a3e9a-849f-4b8d-83a1-797f8abf6794", "comment": "", "command": "click", - "target": "css=.ms-2", + "target": "xpath=//form/div[2]/div/div/button", "targets": [ ["css=.ms-2", "css:finder"], ["xpath=(//button[@type='button'])[69]", "xpath:attributes"], @@ -1908,6 +2628,13 @@ ["xpath=//td[4]/div/input", "xpath:position"] ], "value": "foo" + }, { + "id": "948ac5c1-aa09-44af-a024-c0dc898616d1", + "comment": "", + "command": "click", + "target": "id=valueInput-idp.resolvertest.logging", + "targets": [], + "value": "" }, { "id": "2b3f457c-5eb6-4df4-a7f5-3f4856a71cc2", "comment": "", @@ -1922,13 +2649,6 @@ ["xpath=//tr[2]/td[4]/div/input", "xpath:position"] ], "value": "bar" - }, { - "id": "948ac5c1-aa09-44af-a024-c0dc898616d1", - "comment": "", - "command": "click", - "target": "id=valueInput-idp.resolvertest.logging", - "targets": [], - "value": "" }, { "id": "46d0e1ac-4706-47cf-9336-683b7b6519f2", "comment": "",