diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index abadf2aa433f..328062818163 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -5,11 +5,14 @@ body: - type: checkboxes attributes: label: Before reporting an issue - description: Please search to see if the issue is already reported, and try to reproduce the issue on the latest release. + description: | + Please search to see if the issue is already reported, and try to reproduce the issue on the latest release. + + Any reported issues must be reproducible in the [latest](https://github.com/keycloak/keycloak/releases/latest) or [nightly](https://github.com/keycloak/keycloak/releases/nightly) version of Keycloak. + + **⚠️ Failing to follow these guidelines may result in your issue being closed without action. ⚠️** options: - - label: I have searched existing issues - required: true - - label: I have reproduced the issue with the [latest nightly release](https://github.com/keycloak/keycloak/releases/tag/nightly) + - label: I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them. required: true - type: dropdown id: area diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/InfinispanSessionCacheIdMapperUpdater.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/InfinispanSessionCacheIdMapperUpdater.java index 093a85d38dcb..a6ac4fe6cd15 100644 --- a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/InfinispanSessionCacheIdMapperUpdater.java +++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/InfinispanSessionCacheIdMapperUpdater.java @@ -20,7 +20,6 @@ import org.keycloak.adapters.spi.SessionIdMapper; import org.keycloak.adapters.spi.SessionIdMapperUpdater; -import java.util.*; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletContext; @@ -32,6 +31,8 @@ import org.infinispan.persistence.remote.RemoteStore; import org.jboss.logging.Logger; +import java.util.Set; + /** * * @author hmlnarik diff --git a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/SsoSessionCacheListener.java b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/SsoSessionCacheListener.java index c098cdba79d5..c47b1a73f2e6 100644 --- a/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/SsoSessionCacheListener.java +++ b/adapters/saml/wildfly-elytron/src/main/java/org/keycloak/adapters/saml/elytron/infinispan/SsoSessionCacheListener.java @@ -18,7 +18,7 @@ import org.keycloak.adapters.spi.SessionIdMapper; -import java.util.*; +import java.util.Queue; import java.util.concurrent.*; import org.infinispan.Cache; import org.infinispan.client.hotrod.annotation.ClientCacheEntryCreated; diff --git a/common/src/main/java/org/keycloak/common/Profile.java b/common/src/main/java/org/keycloak/common/Profile.java index 7704c171becb..4f52aa927b59 100755 --- a/common/src/main/java/org/keycloak/common/Profile.java +++ b/common/src/main/java/org/keycloak/common/Profile.java @@ -96,7 +96,7 @@ public enum Feature { DEVICE_FLOW("OAuth 2.0 Device Authorization Grant", Type.DEFAULT), - TRANSIENT_USERS("Transient users for brokering", Type.PREVIEW), + TRANSIENT_USERS("Transient users for brokering", Type.EXPERIMENTAL), ; private final Type type; diff --git a/common/src/test/java/org/keycloak/common/ProfileTest.java b/common/src/test/java/org/keycloak/common/ProfileTest.java index 62a750330b1f..003d6a46f982 100644 --- a/common/src/test/java/org/keycloak/common/ProfileTest.java +++ b/common/src/test/java/org/keycloak/common/ProfileTest.java @@ -93,7 +93,7 @@ public void checkDefaults() { disabledFeatures.add(Profile.Feature.KERBEROS); } assertEquals(profile.getDisabledFeatures(), disabledFeatures); - assertEquals(profile.getPreviewFeatures(), Profile.Feature.ACCOUNT3, Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL, Profile.Feature.DPOP, Profile.Feature.TRANSIENT_USERS); + assertEquals(profile.getPreviewFeatures(), Profile.Feature.ACCOUNT3, Profile.Feature.ADMIN_FINE_GRAINED_AUTHZ, Profile.Feature.RECOVERY_CODES, Profile.Feature.SCRIPTS, Profile.Feature.TOKEN_EXCHANGE, Profile.Feature.DECLARATIVE_USER_PROFILE, Profile.Feature.CLIENT_SECRET_ROTATION, Profile.Feature.UPDATE_EMAIL, Profile.Feature.DPOP); } @Test diff --git a/core/src/main/java/org/keycloak/TokenVerifier.java b/core/src/main/java/org/keycloak/TokenVerifier.java index 253f6f7ce613..dc2321a9b2be 100755 --- a/core/src/main/java/org/keycloak/TokenVerifier.java +++ b/core/src/main/java/org/keycloak/TokenVerifier.java @@ -33,7 +33,10 @@ import javax.crypto.SecretKey; import java.security.PublicKey; -import java.util.*; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/docs/documentation/release_notes/topics/23_0_0.adoc b/docs/documentation/release_notes/topics/23_0_0.adoc index d920bb4fb5e8..748f80f985ad 100644 --- a/docs/documentation/release_notes/topics/23_0_0.adoc +++ b/docs/documentation/release_notes/topics/23_0_0.adoc @@ -19,7 +19,43 @@ https://github.com/tnorimat[Takashi Norimatsu] and https://github.com/dteleguin[ Keycloak has preview support for https://fidoalliance.org/passkeys/[Passkeys]. Passkey registration and authentication are realized by the features of WebAuthn. -Therefore, users of Keycloak can do passkey registration and authentication by existing WebAuthn registraton and authentication. +Therefore, users of Keycloak can do passkey registration and authentication by existing WebAuthn registration and authentication. Both synced passkeys and device-bound passkeys can be used for both Same-Device and Cross-Device Authentication. -However, passkeys operations success depends on the user's environment. Make sure which operations can succeed in https://passkeys.dev/device-support/[the environment]. \ No newline at end of file +However, passkeys operations success depends on the user's environment. Make sure which operations can succeed in https://passkeys.dev/device-support/[the environment]. +Thanks to https://github.com/tnorimat[Takashi Norimatsu] for the contribution and thanks to https://github.com/thomasdarimont[Thomas Darimont] for the help with the +ideas and testing of this feature. + += WebAuthn improvements + +WebAuthn policy now includes a new field: `Extra Origins`. It provides better interoperability with non-Web platforms (for example, native mobile applications). +Thanks to https://github.com/akunzai[Charley Wu] for the contribution. + += RESTEasy Reactive + +Keycloak has switched to RESTEasy Reactive. Applications using `quarkus-resteasy-reactive` should still benefit from a better startup time, runtime performance, and memory footprint, even though not using reactive style/semantics. SPI's that depend directly on JAX-RS API should be compatible with this change. SPI's that depend on RESTEasy Classic including `ResteasyClientBuilder` will not be compatible and will require update, this will also be true for other implementation of the JAX-RS API like Jersey. + += More flexibility for introspection endpoint + +In previous versions, introspection endpoint automatically returned most claims, which were available in the access token. Now there is new +switch `Add to token introspection` on most of protocol mappers. This addition allows more flexibility as introspection endpoint can return different +claims than access token. This is first step towards "Lightweight access tokens" support as access tokens can omit lots of the claims, which would be still returned +by the introspection endpoint. When migrating from previous versions, the introspection endpoint should return same claims, which are returned from access token, +so the behavior should be effectively the same by default after the migration. Thanks to https://github.com/skabano[Shigeyuki Kabano] for the contribution. + += Feature flag for OAuth 2.0 device authorization grant flow + +The OAuth 2.0 device authorization grant flow now includes a feature flag, so you can easily disable this feature. This feature is still enabled by default. +Thanks to https://github.com/thomasdarimont[Thomas Darimont] for the contribution. + += Group scalability improvements + +Performance around searching of groups is improved for the use-cases with many groups and subgroups. There are improvements, which allow +paginated lookup of subgroups. Thanks to https://github.com/alice-wondered[Alice] for the contribution. + += User profile improvements + +Declarative user profile is still a preview feature in this release, but we are working hard on promoting it to a supported feature. Feedback is welcome. +If you find any issues or have any improvements in mind, you are welcome to create https://github.com/keycloak/keycloak/issues/new/choose[Github issue], +ideally with label `area/user-profile`. + diff --git a/docs/documentation/server_admin/images/cache-tab.png b/docs/documentation/server_admin/images/cache-tab.png deleted file mode 100644 index 36d0dc5830cc..000000000000 Binary files a/docs/documentation/server_admin/images/cache-tab.png and /dev/null differ diff --git a/docs/documentation/server_admin/topics/admin-console.adoc b/docs/documentation/server_admin/topics/admin-console.adoc index a28eee5c83e6..544437a7c7c9 100644 --- a/docs/documentation/server_admin/topics/admin-console.adoc +++ b/docs/documentation/server_admin/topics/admin-console.adoc @@ -7,9 +7,6 @@ include::realms/proc-using-admin-console.adoc[leveloffset=1] include::realms/master.adoc[leveloffset=2] include::realms/proc-creating-a-realm.adoc[leveloffset=2] include::realms/ssl.adoc[leveloffset=2][] -ifeval::[{project_product}==true] -include::realms/cache.adoc[leveloffset=2][] -endif::[] include::realms/email.adoc[leveloffset=2] include::realms/themes.adoc[leveloffset=2] include::realms/proc-configuring-internationalization.adoc[leveloffset=2] diff --git a/docs/documentation/server_admin/topics/events/login.adoc b/docs/documentation/server_admin/topics/events/login.adoc index 1df417920fcf..899bd797e9d7 100644 --- a/docs/documentation/server_admin/topics/events/login.adoc +++ b/docs/documentation/server_admin/topics/events/login.adoc @@ -171,17 +171,3 @@ You can exclude events by using the `--spi-events-listener-email-exclude-events` kc.[sh|bat] --spi-events-listener-email-exclude-events=UPDATE_TOTP,REMOVE_TOTP ---- -You can set a maximum length of each Event detail in the database by using the `--spi-events-store-jpa-max-detail-length` argument. This setting is useful if a detail (for example, redirect_uri) is long. For example: - -[source,bash] ----- -kc.[sh|bat] --spi-events-store-jpa-max-detail-length=1000 ----- - -Also you can set a maximum length of all Event's details by using the `--spi-events-store-jpa-max-field-length` argument. This setting is useful if you want to adhere to the underlying storage limitation. For example: - -[source,bash] ----- -kc.[sh|bat] --spi-events-store-jpa-max-field-length=2500 ----- - diff --git a/docs/documentation/server_admin/topics/realms/cache.adoc b/docs/documentation/server_admin/topics/realms/cache.adoc deleted file mode 100644 index 0b37cb32673e..000000000000 --- a/docs/documentation/server_admin/topics/realms/cache.adoc +++ /dev/null @@ -1,16 +0,0 @@ -[[_clear-cache]] -= Clearing server caches - -{project_name} caches everything it can in memory within the limits of your JVM and the limits you have configured. If the {project_name} database is modified by a third party, such as a DBA, outside the scope of the server's REST APIs or Admin Console, parts of the in-memory cache could be stale. You can clear the realm cache, user cache or cache of external public keys, such as Public keys of - external clients or Identity providers, which {project_name} may use to verify signatures of particular external entity. - -.Procedure - -. Click *Realm Settings* in the menu. - -. Click the *Cache* tab. - -. Click *Clear* for the cache you want to evict. -+ -.Cache tab -image:images/cache-tab.png[Cache tab] diff --git a/docs/documentation/tests/src/test/java/org/keycloak/documentation/test/utils/LinkUtils.java b/docs/documentation/tests/src/test/java/org/keycloak/documentation/test/utils/LinkUtils.java index 033b72549a1a..912fc524c04b 100644 --- a/docs/documentation/tests/src/test/java/org/keycloak/documentation/test/utils/LinkUtils.java +++ b/docs/documentation/tests/src/test/java/org/keycloak/documentation/test/utils/LinkUtils.java @@ -11,7 +11,13 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; -import java.util.*; +import java.util.Map; +import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.HashMap; +import java.util.Properties; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/docs/documentation/upgrading/topics/keycloak/changes-23_0_0.adoc b/docs/documentation/upgrading/topics/keycloak/changes-23_0_0.adoc index 67697e36dd71..66410d02b5f8 100644 --- a/docs/documentation/upgrading/topics/keycloak/changes-23_0_0.adoc +++ b/docs/documentation/upgrading/topics/keycloak/changes-23_0_0.adoc @@ -135,6 +135,13 @@ Stream getTopLevelGroupsStream(RealmModel realm, Endpoint `GET {keycloak server}/realms/{realm}/groups/{group_id}/children` added as a way to get subgroups of specific groups that support pagination += RESTEeasy Reactive +Relying on RESTEasy Classic is not longer an option because it is not available anymore. Migration will be needed for SPI's and code that is relying on RESTEasy Classic and related packages part of `org.jboss.resteasy.spi.*`. + = Partial export requires manage-realm permission -The endpoint `POST {keycloak server}/realms/{realm}/partial-export` and the corresponding action in the admin console now require `manage-realm` permission for execution instead of `view-realm`. This endpoint exports the realm configuration into a JSON file and the new permission is more appropriate. The parameters `exportGroupsAndRoles` and `exportClients`, which include the realm groups/roles and clients in the export respectively, continue managing the same permissions (`query-groups` and `view-clients`). \ No newline at end of file +The endpoint `POST {keycloak server}/realms/{realm}/partial-export` and the corresponding action in the admin console now require `manage-realm` permission for execution instead of `view-realm`. This endpoint exports the realm configuration into a JSON file and the new permission is more appropriate. The parameters `exportGroupsAndRoles` and `exportClients`, which include the realm groups/roles and clients in the export respectively, continue managing the same permissions (`query-groups` and `view-clients`). + += Removal of the options to trim the event's details length + +Since this release, Keycloak supports long value for `EventEntity` details column. Therefore, it no longer supports options for trimming event detail length `--spi-events-store-jpa-max-detail-length` and `--spi-events-store-jpa-max-field-length`. diff --git a/docs/guides/getting-started/templates/first-app.adoc b/docs/guides/getting-started/templates/first-app.adoc index 5fe07c69d6f2..dc13a30be718 100644 --- a/docs/guides/getting-started/templates/first-app.adoc +++ b/docs/guides/getting-started/templates/first-app.adoc @@ -9,12 +9,11 @@ To secure the first application, you start by registering the application with y . Fill in the form with the following values: ** *Client type*: `OpenID Connect` ** *Client ID*: `myclient` ++ +image::add-client-1.png[Add Client] . Click *Next* . Confirm that *Standard flow* is enabled. . Click *Next*. -+ -image::add-client-1.png[Add Client] - . Make these changes under *Login settings*. * Set *Valid redirect URIs* to `+https://www.keycloak.org/app/*+` * Set *Web origins* to `+https://www.keycloak.org+` diff --git a/docs/guides/operator/customizing-keycloak.adoc b/docs/guides/operator/customizing-keycloak.adoc index 0a324bbc9041..3a64d3e5b8d9 100644 --- a/docs/guides/operator/customizing-keycloak.adoc +++ b/docs/guides/operator/customizing-keycloak.adoc @@ -45,7 +45,7 @@ spec: [NOTE] ==== -With custom images, every build time option passed either through a dedicated field or the `additionalOptions` is ignored. +With custom images, every build time option is passed either through a dedicated field or the `additionalOptions` is ignored. ==== diff --git a/docs/guides/server/caching.adoc b/docs/guides/server/caching.adoc index 4250f593ee98..f88fc00f8e2b 100644 --- a/docs/guides/server/caching.adoc +++ b/docs/guides/server/caching.adoc @@ -14,7 +14,7 @@ The current distributed cache implementation is built on top of https://infinisp == Enable distributed caching When you start Keycloak in production mode, by using the `start` command, caching is enabled and all Keycloak nodes in your network are discovered. -By default, caches are using a `UDP` transport stack so that nodes are discovered using IP multicast transport based on UDP. For most production environments, there are better discovery alternatives to UDP available. Keycloak allows you to either choose from a set of pre-defined default transport stacks, or to define your own custom stack, as you will see later in this {section}. +By default, caches are using a UDP transport stack so that nodes are discovered using IP multicast transport based on UDP. For most production environments, there are better discovery alternatives to UDP available. Keycloak allows you to either choose from a set of pre-defined default transport stacks, or to define your own custom stack, as you will see later in this {section}. To explicitly enable distributed infinispan caching, enter this command: @@ -156,7 +156,7 @@ To apply a specific cache stack, enter this command: <@kc.build parameters="--cache-stack="/> -The default stack is set to `UDP` when distributed caches are enabled. +The default stack is set to `udp` when distributed caches are enabled. === Available transport stacks @@ -181,9 +181,9 @@ The following table shows transport stacks that are available using the `--cache === Additional transport stacks The following table shows transport stacks that are supported by Keycloak, but need some extra steps to work. -Note that _none_ of these stacks are Kubernetes / OpenShift stacks, so no need exists to enable the "google" stack if you want to run Keycloak on top of the Google Kubernetes engine. +Note that _none_ of these stacks are Kubernetes / OpenShift stacks, so no need exists to enable the `google` stack if you want to run Keycloak on top of the Google Kubernetes engine. In that case, use the `kubernetes` stack. -Instead, when you have a distributed cache setup running on AWS EC2 instances, you would need to set the stack to `ec2`, because ec2 does not support a default discovery mechanism such as `UDP`. +Instead, when you have a distributed cache setup running on AWS EC2 instances, you would need to set the stack to `ec2`, because ec2 does not support a default discovery mechanism such as UDP. [%autowidth] |=== @@ -197,7 +197,7 @@ Instead, when you have a distributed cache setup running on AWS EC2 instances, y Cloud vendor specific stacks have additional dependencies for Keycloak. For more information and links to repositories with these dependencies, see the https://infinispan.org/docs/dev/titles/embedding/embedding.html#jgroups-cloud-discovery-protocols_cluster-transport[Infinispan documentation]. -To provide the dependencies to Keycloak, put the respective JAR in the `providers` directory and `build` Keycloak by entering this command: +To provide the dependencies to Keycloak, put the respective JAR in the `providers` directory and build Keycloak by entering this command: <@kc.build parameters="--cache-stack="/> diff --git a/docs/guides/server/fips.adoc b/docs/guides/server/fips.adoc index 91fe16b624c3..1f3605ef8d4c 100644 --- a/docs/guides/server/fips.adoc +++ b/docs/guides/server/fips.adoc @@ -264,7 +264,7 @@ earlier. If you prefer to avoid this option, you can for instance ask all your u == Keycloak FIPS mode on the non-fips system -Keycloak is tested on a FIPS enabled RHEL 8 system and `ubi8` image. It is supported with RHEL 9 (and `ubi9` image) as well. Running on +Keycloak is supported and tested on a FIPS enabled RHEL 8 system and `ubi8` image. It is supported with RHEL 9 (and `ubi9` image) as well. Running on the non-RHEL compatible platform or on the non-FIPS enabled platform, the FIPS compliance cannot be strictly guaranteed and cannot be officially supported. If you are still restricted to running Keycloak on such a system, you can at least update your security providers configured in `java.security` file. This update does not amount to FIPS compliance, but diff --git a/js/apps/account-ui/package.json b/js/apps/account-ui/package.json index 0ba6703cfad7..54a36f96300e 100644 --- a/js/apps/account-ui/package.json +++ b/js/apps/account-ui/package.json @@ -22,14 +22,14 @@ "react-dom": "^18.2.0", "react-hook-form": "^7.47.0", "react-i18next": "^13.3.1", - "react-router-dom": "^6.15.0", + "react-router-dom": "^6.18.0", "ui-shared": "workspace:*" }, "devDependencies": { "@keycloak/keycloak-admin-client": "workspace:*", "@playwright/test": "^1.39.0", "@types/lodash-es": "^4.17.10", - "@types/react": "^18.2.33", + "@types/react": "^18.2.34", "@types/react-dom": "^18.2.14", "@vitejs/plugin-react-swc": "^3.4.1", "lightningcss": "^1.22.0", diff --git a/js/apps/account-ui/playwright.config.ts b/js/apps/account-ui/playwright.config.ts index 5090beec9c40..621511ac45c6 100644 --- a/js/apps/account-ui/playwright.config.ts +++ b/js/apps/account-ui/playwright.config.ts @@ -9,7 +9,7 @@ export default defineConfig({ forbidOnly: !!process.env.CI, retries: process.env.CI ? 2 : 0, workers: 1, - reporter: process.env.CI ? "github" : "list", + reporter: process.env.CI ? [["github"], ["html"]] : "list", use: { baseURL: process.env.CI ? "http://localhost:8080/realms/master/account/" diff --git a/js/apps/account-ui/src/root/ErrorPage.tsx b/js/apps/account-ui/src/root/ErrorPage.tsx index 343113f0c982..79aa3b88b7a3 100644 --- a/js/apps/account-ui/src/root/ErrorPage.tsx +++ b/js/apps/account-ui/src/root/ErrorPage.tsx @@ -50,7 +50,7 @@ function getErrorMessage(error: unknown): string | null { } if (isRouteErrorResponse(error)) { - return error.error ? getErrorMessage(error.error) : null; + return error.statusText; } if (error instanceof Error) { diff --git a/js/apps/admin-ui/cypress/e2e/i18n_test.spec.ts b/js/apps/admin-ui/cypress/e2e/i18n_test.spec.ts index c464d90e0114..9d07d96d3bc2 100644 --- a/js/apps/admin-ui/cypress/e2e/i18n_test.spec.ts +++ b/js/apps/admin-ui/cypress/e2e/i18n_test.spec.ts @@ -134,7 +134,6 @@ describe("i18n tests", () => { goToUserFederationPage(); - // check key "user-federation:addProvider_other" providersPage.assertCardContainsText("ldap", "Add Ldap providers"); }); diff --git a/js/apps/admin-ui/cypress/e2e/realm_settings_user_profile_enabled.spec.ts b/js/apps/admin-ui/cypress/e2e/realm_settings_user_profile_enabled.spec.ts index 3caca7b27850..8db687cd3ecb 100644 --- a/js/apps/admin-ui/cypress/e2e/realm_settings_user_profile_enabled.spec.ts +++ b/js/apps/admin-ui/cypress/e2e/realm_settings_user_profile_enabled.spec.ts @@ -213,7 +213,6 @@ describe("User profile tabs", () => { cy.get(".pf-c-form__label-text") .contains("newAttribute2") .should("not.exist"); - cy.findByTestId("firstName").type("testuser9"); cy.findByTestId("email").clear(); cy.findByTestId("email").type("testuser9@gmail.com"); cy.findByTestId("save-user").click(); diff --git a/js/apps/admin-ui/package.json b/js/apps/admin-ui/package.json index f01cdd54f8ee..d2b6e3b2202a 100644 --- a/js/apps/admin-ui/package.json +++ b/js/apps/admin-ui/package.json @@ -83,7 +83,7 @@ "react-error-boundary": "^3.1.4", "react-hook-form": "^7.47.0", "react-i18next": "^13.3.1", - "react-router-dom": "^6.15.0", + "react-router-dom": "^6.18.0", "reactflow": "^11.9.4", "ui-shared": "workspace:*", "use-react-router-breadcrumbs": "^4.0.1" @@ -96,7 +96,7 @@ "@types/dagre": "^0.7.51", "@types/file-saver": "^2.0.6", "@types/lodash-es": "^4.17.10", - "@types/react": "^18.2.33", + "@types/react": "^18.2.34", "@types/react-dom": "^18.2.14", "@types/uuid": "^9.0.6", "@vitejs/plugin-react-swc": "^3.4.1", diff --git a/js/apps/admin-ui/src/authentication/AuthenticationSection.tsx b/js/apps/admin-ui/src/authentication/AuthenticationSection.tsx index b3ee06022d6d..c9c2ae9dceb1 100644 --- a/js/apps/admin-ui/src/authentication/AuthenticationSection.tsx +++ b/js/apps/admin-ui/src/authentication/AuthenticationSection.tsx @@ -1,3 +1,4 @@ +import { fetchWithError } from "@keycloak/keycloak-admin-client"; import type AuthenticationFlowRepresentation from "@keycloak/keycloak-admin-client/lib/defs/authenticationFlowRepresentation"; import RealmRepresentation from "@keycloak/keycloak-admin-client/lib/defs/realmRepresentation"; import { @@ -101,7 +102,7 @@ export default function AuthenticationSection() { ]); const loader = async () => { - const flowsRequest = await fetch( + const flowsRequest = await fetchWithError( `${addTrailingSlash( adminClient.baseUrl, )}admin/realms/${realmName}/ui-ext/authentication-management/flows`, diff --git a/js/apps/admin-ui/src/authentication/EmptyExecutionState.tsx b/js/apps/admin-ui/src/authentication/EmptyExecutionState.tsx index dc529f3fa33b..1bfe9c5ae963 100644 --- a/js/apps/admin-ui/src/authentication/EmptyExecutionState.tsx +++ b/js/apps/admin-ui/src/authentication/EmptyExecutionState.tsx @@ -69,7 +69,7 @@ export const EmptyExecutionState = ({ {t(`${section}Title`)} -

{t(`authentication-help:${section}`)}

+

{t(section)}

diff --git a/js/apps/admin-ui/src/authentication/policies/PolicyRow.tsx b/js/apps/admin-ui/src/authentication/policies/PolicyRow.tsx index 2b429d46fca0..fc0d31520b67 100644 --- a/js/apps/admin-ui/src/authentication/policies/PolicyRow.tsx +++ b/js/apps/admin-ui/src/authentication/policies/PolicyRow.tsx @@ -45,7 +45,7 @@ export const PolicyRow = ({ labelIcon={ } > diff --git a/js/apps/admin-ui/src/clients/add/SamlConfig.tsx b/js/apps/admin-ui/src/clients/add/SamlConfig.tsx index 415297082aa4..a1fb1c3a31dc 100644 --- a/js/apps/admin-ui/src/clients/add/SamlConfig.tsx +++ b/js/apps/admin-ui/src/clients/add/SamlConfig.tsx @@ -27,12 +27,7 @@ export const Toggle = ({ name, label }: ToggleProps) => { hasNoPaddingTop label={t(label)} fieldId={label} - labelIcon={ - - } + labelIcon={} > - } + labelIcon={} > { - } + labelIcon={} > diff --git a/js/apps/admin-ui/src/clients/credentials/Credentials.tsx b/js/apps/admin-ui/src/clients/credentials/Credentials.tsx index a77f968fa280..34f5b8c9cb70 100644 --- a/js/apps/admin-ui/src/clients/credentials/Credentials.tsx +++ b/js/apps/admin-ui/src/clients/credentials/Credentials.tsx @@ -91,7 +91,7 @@ export const Credentials = ({ client, save, refresh }: CredentialsProps) => { addAlert(t(`${message}Success`), AlertVariant.success); return data; } catch (error) { - addError(`clients:${message}Error`, error); + addError(`${message}Error`, error); } } diff --git a/js/apps/admin-ui/src/clients/import/ImportForm.tsx b/js/apps/admin-ui/src/clients/import/ImportForm.tsx index 6d555ebe2116..efad92534761 100644 --- a/js/apps/admin-ui/src/clients/import/ImportForm.tsx +++ b/js/apps/admin-ui/src/clients/import/ImportForm.tsx @@ -1,3 +1,4 @@ +import { fetchWithError } from "@keycloak/keycloak-admin-client"; import type ClientRepresentation from "@keycloak/keycloak-admin-client/lib/defs/clientRepresentation"; import { Language } from "@patternfly/react-code-editor"; import { @@ -61,7 +62,7 @@ export default function ImportForm() { return JSON.parse(contents); } - const response = await fetch( + const response = await fetchWithError( `${addTrailingSlash( adminClient.baseUrl, )}admin/realms/${realm}/client-description-converter`, diff --git a/js/apps/admin-ui/src/clients/keys/Certificate.tsx b/js/apps/admin-ui/src/clients/keys/Certificate.tsx index cbfd4592824d..c9a29e8cc516 100644 --- a/js/apps/admin-ui/src/clients/keys/Certificate.tsx +++ b/js/apps/admin-ui/src/clients/keys/Certificate.tsx @@ -39,12 +39,7 @@ export const Certificate = ({ keyInfo, plain = false }: CertificateProps) => { - } + labelIcon={} > diff --git a/js/apps/admin-ui/src/clients/keys/SamlKeys.tsx b/js/apps/admin-ui/src/clients/keys/SamlKeys.tsx index ee11479598b9..1244ee2fceea 100644 --- a/js/apps/admin-ui/src/clients/keys/SamlKeys.tsx +++ b/js/apps/admin-ui/src/clients/keys/SamlKeys.tsx @@ -95,10 +95,7 @@ const KeySection = ({ + } label={t(key)} fieldId={key} diff --git a/js/apps/admin-ui/src/clients/scopes/ClientScopes.tsx b/js/apps/admin-ui/src/clients/scopes/ClientScopes.tsx index 18f980632e33..b4c69a885a73 100644 --- a/js/apps/admin-ui/src/clients/scopes/ClientScopes.tsx +++ b/js/apps/admin-ui/src/clients/scopes/ClientScopes.tsx @@ -241,7 +241,7 @@ export const ClientScopes = ({ { if (selectedConfig?.mediaType === "application/zip") { - const response = await fetch( + const response = await fetchWithError( `${addTrailingSlash( adminClient.baseUrl, )}admin/realms/${realm}/clients/${id}/installation/providers/${selected}`, diff --git a/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx b/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx index 514ae40b5bc5..b46916915a16 100644 --- a/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx +++ b/js/apps/admin-ui/src/components/group/GroupPickerDialog.tsx @@ -90,7 +90,7 @@ export const GroupPickerDialog = ({ if (!navigation.map(({ id }) => id).includes(groupId)) { group = await adminClient.groups.findOne({ id: groupId }); if (!group) { - throw new Error(t("common:notFound")); + throw new Error(t("notFound")); } } if (group?.id) { diff --git a/js/apps/admin-ui/src/components/users/UserSelect.tsx b/js/apps/admin-ui/src/components/users/UserSelect.tsx index 63154fae16e4..dd03ea72a33d 100644 --- a/js/apps/admin-ui/src/components/users/UserSelect.tsx +++ b/js/apps/admin-ui/src/components/users/UserSelect.tsx @@ -81,9 +81,7 @@ export const UserSelect = ({ - } + labelIcon={} fieldId={name!} validated={errors[name!] ? "error" : "default"} helperTextInvalid={t("required")} diff --git a/js/apps/admin-ui/src/context/auth/admin-ui-endpoint.ts b/js/apps/admin-ui/src/context/auth/admin-ui-endpoint.ts index e3e3e91c639d..9b298cfcfbea 100644 --- a/js/apps/admin-ui/src/context/auth/admin-ui-endpoint.ts +++ b/js/apps/admin-ui/src/context/auth/admin-ui-endpoint.ts @@ -1,3 +1,4 @@ +import { fetchWithError } from "@keycloak/keycloak-admin-client"; import { adminClient } from "../../admin-client"; import { getAuthorizationHeaders } from "../../utils/getAuthorizationHeaders"; import { joinPath } from "../../utils/joinPath"; @@ -9,7 +10,7 @@ export async function fetchAdminUI( const accessToken = await adminClient.getAccessToken(); const baseUrl = adminClient.baseUrl; - const response = await fetch( + const response = await fetchWithError( joinPath(baseUrl, "admin/realms", adminClient.realmName, endpoint) + (query ? "?" + new URLSearchParams(query) : ""), { diff --git a/js/apps/admin-ui/src/events/EventsSection.tsx b/js/apps/admin-ui/src/events/EventsSection.tsx index ea2f19bbbd91..ac32d5a8ed62 100644 --- a/js/apps/admin-ui/src/events/EventsSection.tsx +++ b/js/apps/admin-ui/src/events/EventsSection.tsx @@ -312,7 +312,7 @@ export default function EventsSection() { ); }} > - {t(`realm-settings:eventTypes.${chip}.name`)} + {t(`eventTypes.${chip}.name`)} ))} @@ -320,7 +320,7 @@ export default function EventsSection() { > {events?.enabledEventTypes?.map((option) => ( - {t(`realm-settings:eventTypes.${option}.name`)} + {t(`eventTypes.${option}.name`)} ))} @@ -437,7 +437,7 @@ export default function EventsSection() { key={entry} onClick={() => removeFilterValue(key, entry)} > - {t(`realm-settings:eventTypes.${entry}.name`)} + {t(`eventTypes.${entry}.name`)} )) )} diff --git a/js/apps/admin-ui/src/identity-providers/add/SamlConnectSettings.tsx b/js/apps/admin-ui/src/identity-providers/add/SamlConnectSettings.tsx index be0ba324dae5..ad5541f18569 100644 --- a/js/apps/admin-ui/src/identity-providers/add/SamlConnectSettings.tsx +++ b/js/apps/admin-ui/src/identity-providers/add/SamlConnectSettings.tsx @@ -1,3 +1,4 @@ +import { fetchWithError } from "@keycloak/keycloak-admin-client"; import type IdentityProviderRepresentation from "@keycloak/keycloak-admin-client/lib/defs/identityProviderRepresentation"; import { FormGroup, Title } from "@patternfly/react-core"; import { useFormContext } from "react-hook-form"; @@ -47,7 +48,7 @@ export const SamlConnectSettings = () => { formData.append("file", new Blob([xml])); try { - const response = await fetch( + const response = await fetchWithError( `${addTrailingSlash( adminClient.baseUrl, )}admin/realms/${realm}/identity-provider/import-config`, diff --git a/js/apps/admin-ui/src/realm-settings/DefaultGroupsTab.tsx b/js/apps/admin-ui/src/realm-settings/DefaultGroupsTab.tsx index 5abd2b6c2c82..000f1d0e5b68 100644 --- a/js/apps/admin-ui/src/realm-settings/DefaultGroupsTab.tsx +++ b/js/apps/admin-ui/src/realm-settings/DefaultGroupsTab.tsx @@ -132,7 +132,7 @@ export const DefaultsGroupsTab = () => { {enabled && ( + {" "} . diff --git a/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx b/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx index 05edcaf8fbd9..689a8fd10b22 100644 --- a/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx +++ b/js/apps/admin-ui/src/realm-settings/GeneralTab.tsx @@ -94,7 +94,7 @@ export const RealmSettingsGeneralTab = ({ required: { value: true, message: t("required") }, pattern: { value: /^[a-zA-Z0-9-_]+$/, - message: t("realm:invalidRealmName"), + message: t("invalidRealmName"), }, }} defaultValue="" diff --git a/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx b/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx index d2dbe21d1407..78a4636b990d 100644 --- a/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx +++ b/js/apps/admin-ui/src/realm-settings/NewClientPolicyCondition.tsx @@ -229,9 +229,7 @@ export default function NewClientPolicyCondition() { } > diff --git a/js/apps/admin-ui/src/realm-settings/event-config/EventsTab.tsx b/js/apps/admin-ui/src/realm-settings/event-config/EventsTab.tsx index bb37e6e50c72..c146c4fa021c 100644 --- a/js/apps/admin-ui/src/realm-settings/event-config/EventsTab.tsx +++ b/js/apps/admin-ui/src/realm-settings/event-config/EventsTab.tsx @@ -78,7 +78,7 @@ export const EventsTab = ({ realm }: EventsTabProps) => { } addAlert(t(`${type}-events-cleared`), AlertVariant.success); } catch (error) { - addError(`realm-settings:${type}-events-cleared-error`, error); + addError(`${type}-events-cleared-error`, error); } }, }); diff --git a/js/apps/admin-ui/src/realm-settings/security-defences/Time.tsx b/js/apps/admin-ui/src/realm-settings/security-defences/Time.tsx index be9e50282da5..49b4467f6771 100644 --- a/js/apps/admin-ui/src/realm-settings/security-defences/Time.tsx +++ b/js/apps/admin-ui/src/realm-settings/security-defences/Time.tsx @@ -23,12 +23,7 @@ export const Time = ({ style={style} label={t(name)} fieldId={name} - labelIcon={ - - } + labelIcon={} validated={ errors[name] ? ValidatedOptions.error : ValidatedOptions.default } diff --git a/js/apps/admin-ui/src/realm/routes/AddRealm.tsx b/js/apps/admin-ui/src/realm/routes/AddRealm.tsx index 9655d4a1e9c6..6c3fe30c5f13 100644 --- a/js/apps/admin-ui/src/realm/routes/AddRealm.tsx +++ b/js/apps/admin-ui/src/realm/routes/AddRealm.tsx @@ -10,7 +10,7 @@ const NewRealmForm = lazy(() => import("../add/NewRealmForm")); export const AddRealmRoute: AppRouteObject = { path: "/:realm/add-realm", element: , - breadcrumb: (t) => t("realm:createRealm"), + breadcrumb: (t) => t("createRealm"), handle: { access: "view-realm", }, diff --git a/js/apps/admin-ui/src/user/UserForm.tsx b/js/apps/admin-ui/src/user/UserForm.tsx index ec53ac1437f1..5fab8b87dd0b 100644 --- a/js/apps/admin-ui/src/user/UserForm.tsx +++ b/js/apps/admin-ui/src/user/UserForm.tsx @@ -187,11 +187,40 @@ export const UserForm = ({ )} {userProfileMetadata ? ( - + <> + + } + > + ( + field.onChange(value)} + isChecked={field.value} + label={t("yes")} + labelOff={t("no")} + /> + )} + /> + + + ) : ( <> {!realm.registrationEmailAsUsername && ( diff --git a/js/libs/keycloak-admin-client/package.json b/js/libs/keycloak-admin-client/package.json index dab56cbb391f..e25a62ecbd7f 100644 --- a/js/libs/keycloak-admin-client/package.json +++ b/js/libs/keycloak-admin-client/package.json @@ -47,7 +47,7 @@ "@types/chai": "^4.3.9", "@types/lodash-es": "^4.17.10", "@types/mocha": "^10.0.3", - "@types/node": "^20.8.9", + "@types/node": "^20.8.10", "chai": "^4.3.10", "mocha": "^10.2.0", "ts-node": "^10.9.1" diff --git a/js/libs/keycloak-admin-client/src/index.ts b/js/libs/keycloak-admin-client/src/index.ts index 4829e2ded730..dae9760a23e2 100644 --- a/js/libs/keycloak-admin-client/src/index.ts +++ b/js/libs/keycloak-admin-client/src/index.ts @@ -3,5 +3,5 @@ import { RequiredActionAlias } from "./defs/requiredActionProviderRepresentation export const requiredAction = RequiredActionAlias; export default KeycloakAdminClient; -export { NetworkError } from "./utils/fetchWithError.js"; +export { NetworkError, fetchWithError } from "./utils/fetchWithError.js"; export type { NetworkErrorOptions } from "./utils/fetchWithError.js"; diff --git a/js/libs/keycloak-admin-client/src/utils/stringifyQueryParams.ts b/js/libs/keycloak-admin-client/src/utils/stringifyQueryParams.ts index 2c58d4ca9913..be526d77daa1 100644 --- a/js/libs/keycloak-admin-client/src/utils/stringifyQueryParams.ts +++ b/js/libs/keycloak-admin-client/src/utils/stringifyQueryParams.ts @@ -1,21 +1,29 @@ export function stringifyQueryParams(params: Record) { - return new URLSearchParams( - Object.entries(params).filter((param): param is [string, string] => { - const [, value] = param; + const searchParams = new URLSearchParams(); - if (typeof value === "undefined" || value === null) { - return false; - } + for (const [key, value] of Object.entries(params)) { + // Ignore undefined and null values. + if (value === undefined || value === null) { + continue; + } - if (typeof value === "string" && value.length === 0) { - return false; - } + // Ignore empty strings. + if (typeof value === "string" && value.length === 0) { + continue; + } - if (Array.isArray(value) && value.length === 0) { - return false; - } + // Ignore empty arrays. + if (Array.isArray(value) && value.length === 0) { + continue; + } - return true; - }), - ).toString(); + // Append each entry of an array as a separate parameter, or the value itself otherwise. + if (Array.isArray(value)) { + value.forEach((item) => searchParams.append(key, item.toString())); + } else { + searchParams.append(key, value.toString()); + } + } + + return searchParams.toString(); } diff --git a/js/libs/keycloak-admin-client/test/auth.spec.ts b/js/libs/keycloak-admin-client/test/auth.spec.ts index 2e3514178184..e39be8bd8d70 100644 --- a/js/libs/keycloak-admin-client/test/auth.spec.ts +++ b/js/libs/keycloak-admin-client/test/auth.spec.ts @@ -42,6 +42,6 @@ describe("Authorization", () => { "idToken", ); - expect(data.scope).to.equal("openid profile email"); + expect(data.scope).to.equal("openid email profile"); }); }); diff --git a/js/libs/keycloak-admin-client/test/authenticationManagement.spec.ts b/js/libs/keycloak-admin-client/test/authenticationManagement.spec.ts index 8e472e05cb76..470f2392af7d 100644 --- a/js/libs/keycloak-admin-client/test/authenticationManagement.spec.ts +++ b/js/libs/keycloak-admin-client/test/authenticationManagement.spec.ts @@ -176,7 +176,6 @@ describe("Authentication management", () => { "clients", "first broker login", "docker auth", - "http challenge", ]); }); diff --git a/js/libs/keycloak-admin-client/test/stringifyQueryParams.spec.ts b/js/libs/keycloak-admin-client/test/stringifyQueryParams.spec.ts index 582cf8d98c21..323698296109 100644 --- a/js/libs/keycloak-admin-client/test/stringifyQueryParams.spec.ts +++ b/js/libs/keycloak-admin-client/test/stringifyQueryParams.spec.ts @@ -23,9 +23,10 @@ describe("stringifyQueryParams", () => { numZero: 0, numNegative: -1, str: "Hello World!", + arr: ["foo", "bar"], }), ).to.equal( - "boolTrue=true&boolFalse=false&numPositive=1&numZero=0&numNegative=-1&str=Hello+World%21", + "boolTrue=true&boolFalse=false&numPositive=1&numZero=0&numNegative=-1&str=Hello+World%21&arr=foo&arr=bar", ); }); }); diff --git a/js/libs/keycloak-js/package.json b/js/libs/keycloak-js/package.json index fdc558e5271a..3faea8825bb6 100644 --- a/js/libs/keycloak-js/package.json +++ b/js/libs/keycloak-js/package.json @@ -48,7 +48,7 @@ "@rollup/plugin-terser": "^0.4.4", "@rollup/plugin-typescript": "^11.1.5", "es6-promise": "^4.2.8", - "rollup": "^4.1.5" + "rollup": "^4.2.0" }, "dependencies": { "base64-js": "^1.5.1", diff --git a/js/libs/keycloak-masthead/package.json b/js/libs/keycloak-masthead/package.json index 8ac1fd810364..30f4c4aaf1e8 100644 --- a/js/libs/keycloak-masthead/package.json +++ b/js/libs/keycloak-masthead/package.json @@ -47,7 +47,7 @@ "react-dom": "^18.2.0" }, "devDependencies": { - "@types/react": "^18.2.33", + "@types/react": "^18.2.34", "@types/react-dom": "^18.2.14", "@vitejs/plugin-react-swc": "^3.4.1", "rollup-plugin-peer-deps-external": "^2.2.4", diff --git a/js/libs/ui-shared/package.json b/js/libs/ui-shared/package.json index 807f0abd7f6e..d9584f67496c 100644 --- a/js/libs/ui-shared/package.json +++ b/js/libs/ui-shared/package.json @@ -41,7 +41,7 @@ "react-hook-form": "7.47.0" }, "devDependencies": { - "@types/react": "^18.2.33", + "@types/react": "^18.2.34", "@types/react-dom": "^18.2.14", "@vitejs/plugin-react-swc": "^3.4.1", "rollup-plugin-peer-deps-external": "^2.2.4", diff --git a/js/package.json b/js/package.json index a9f5b969f03e..045e172169e5 100644 --- a/js/package.json +++ b/js/package.json @@ -4,7 +4,7 @@ "prepare": "cd .. && husky install js/.husky" }, "devDependencies": { - "@types/node": "^20.8.9", + "@types/node": "^20.8.10", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", "eslint": "^8.52.0", diff --git a/js/pnpm-lock.yaml b/js/pnpm-lock.yaml index 10af2193feb4..49de0e831e9d 100644 --- a/js/pnpm-lock.yaml +++ b/js/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@types/node': - specifier: ^20.8.9 - version: 20.8.9 + specifier: ^20.8.10 + version: 20.8.10 '@typescript-eslint/eslint-plugin': specifier: ^6.9.1 version: 6.9.1(@typescript-eslint/parser@6.9.1)(eslint@8.52.0)(typescript@5.2.2) @@ -70,16 +70,16 @@ importers: dependencies: '@patternfly/patternfly': specifier: ^4.224.2 - version: 4.224.2 + version: 4.224.5 '@patternfly/react-core': specifier: ^4.276.8 - version: 4.276.8(react-dom@18.2.0)(react@18.2.0) + version: 4.278.0(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-icons': specifier: ^4.93.6 - version: 4.93.6(react-dom@18.2.0)(react@18.2.0) + version: 4.93.7(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-table': specifier: ^4.113.0 - version: 4.113.0(react-dom@18.2.0)(react@18.2.0) + version: 4.113.6(react-dom@18.2.0)(react@18.2.0) i18next: specifier: ^23.6.0 version: 23.6.0 @@ -108,8 +108,8 @@ importers: specifier: ^13.3.1 version: 13.3.1(i18next@23.6.0)(react-dom@18.2.0)(react@18.2.0) react-router-dom: - specifier: ^6.15.0 - version: 6.15.0(react-dom@18.2.0)(react@18.2.0) + specifier: ^6.18.0 + version: 6.18.0(react-dom@18.2.0)(react@18.2.0) ui-shared: specifier: workspace:* version: link:../../libs/ui-shared @@ -124,8 +124,8 @@ importers: specifier: ^4.17.10 version: 4.17.10 '@types/react': - specifier: ^18.2.33 - version: 18.2.33 + specifier: ^18.2.34 + version: 18.2.34 '@types/react-dom': specifier: ^18.2.14 version: 18.2.14 @@ -137,7 +137,7 @@ importers: version: 1.22.0 vite: specifier: ^4.5.0 - version: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + version: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) vite-plugin-checker: specifier: ^0.6.2 version: 0.6.2(eslint@8.52.0)(typescript@5.2.2)(vite@4.5.0) @@ -149,25 +149,25 @@ importers: version: link:../../libs/keycloak-admin-client '@patternfly/patternfly': specifier: ^4.224.2 - version: 4.224.2 + version: 4.224.5 '@patternfly/react-code-editor': specifier: ^4.82.115 - version: 4.82.115(react-dom@18.2.0)(react-monaco-editor@0.51.0)(react@18.2.0) + version: 4.82.121(react-dom@18.2.0)(react-monaco-editor@0.51.0)(react@18.2.0) '@patternfly/react-core': specifier: ^4.276.8 - version: 4.276.8(react-dom@18.2.0)(react@18.2.0) + version: 4.278.0(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-icons': specifier: ^4.93.6 - version: 4.93.6(react-dom@18.2.0)(react@18.2.0) + version: 4.93.7(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-styles': specifier: ^4.92.6 - version: 4.92.6 + version: 4.92.8 '@patternfly/react-table': specifier: ^4.113.0 - version: 4.113.0(react-dom@18.2.0)(react@18.2.0) + version: 4.113.6(react-dom@18.2.0)(react@18.2.0) admin-ui: specifier: 'file:' - version: file:apps/admin-ui(@types/react@18.2.33)(react-monaco-editor@0.51.0) + version: file:apps/admin-ui(@types/react@18.2.34)(react-monaco-editor@0.51.0) dagre: specifier: ^0.8.5 version: 0.8.5 @@ -214,17 +214,17 @@ importers: specifier: ^13.3.1 version: 13.3.1(i18next@23.6.0)(react-dom@18.2.0)(react@18.2.0) react-router-dom: - specifier: ^6.15.0 - version: 6.15.0(react-dom@18.2.0)(react@18.2.0) + specifier: ^6.18.0 + version: 6.18.0(react-dom@18.2.0)(react@18.2.0) reactflow: specifier: ^11.9.4 - version: 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + version: 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) ui-shared: specifier: workspace:* version: link:../../libs/ui-shared use-react-router-breadcrumbs: specifier: ^4.0.1 - version: 4.0.1(react-router-dom@6.15.0)(react@18.2.0) + version: 4.0.1(react-router-dom@6.18.0)(react@18.2.0) devDependencies: '@4tw/cypress-drag-drop': specifier: ^2.2.5 @@ -248,8 +248,8 @@ importers: specifier: ^4.17.10 version: 4.17.10 '@types/react': - specifier: ^18.2.33 - version: 18.2.33 + specifier: ^18.2.34 + version: 18.2.34 '@types/react-dom': specifier: ^18.2.14 version: 18.2.14 @@ -264,7 +264,7 @@ importers: version: 13.4.0 cypress-axe: specifier: ^1.5.0 - version: 1.5.0(axe-core@4.7.2)(cypress@13.4.0) + version: 1.5.0(axe-core@4.8.2)(cypress@13.4.0) jsdom: specifier: ^22.1.0 version: 22.1.0 @@ -276,13 +276,13 @@ importers: version: 1.22.0 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@20.8.9)(typescript@5.2.2) + version: 10.9.1(@types/node@20.8.10)(typescript@5.2.2) uuid: specifier: ^9.0.1 version: 9.0.1 vite: specifier: ^4.5.0 - version: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + version: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) vite-plugin-checker: specifier: ^0.6.2 version: 0.6.2(eslint@8.52.0)(typescript@5.2.2)(vite@4.5.0) @@ -339,8 +339,8 @@ importers: specifier: ^10.0.3 version: 10.0.3 '@types/node': - specifier: ^20.8.9 - version: 20.8.9 + specifier: ^20.8.10 + version: 20.8.10 chai: specifier: ^4.3.10 version: 4.3.10 @@ -349,7 +349,7 @@ importers: version: 10.2.0 ts-node: specifier: ^10.9.1 - version: 10.9.1(@types/node@20.8.9)(typescript@5.2.2) + version: 10.9.1(@types/node@20.8.10)(typescript@5.2.2) libs/keycloak-js: dependencies: @@ -365,34 +365,34 @@ importers: devDependencies: '@rollup/plugin-commonjs': specifier: ^25.0.7 - version: 25.0.7(rollup@4.1.5) + version: 25.0.7(rollup@4.2.0) '@rollup/plugin-inject': specifier: ^5.0.5 - version: 5.0.5(rollup@4.1.5) + version: 5.0.5(rollup@4.2.0) '@rollup/plugin-node-resolve': specifier: ^15.2.3 - version: 15.2.3(rollup@4.1.5) + version: 15.2.3(rollup@4.2.0) '@rollup/plugin-terser': specifier: ^0.4.4 - version: 0.4.4(rollup@4.1.5) + version: 0.4.4(rollup@4.2.0) '@rollup/plugin-typescript': specifier: ^11.1.5 - version: 11.1.5(rollup@4.1.5)(tslib@2.6.2)(typescript@5.2.2) + version: 11.1.5(rollup@4.2.0)(tslib@2.6.2)(typescript@5.2.2) es6-promise: specifier: ^4.2.8 version: 4.2.8 rollup: - specifier: ^4.1.5 - version: 4.1.5 + specifier: ^4.2.0 + version: 4.2.0 libs/keycloak-masthead: dependencies: '@patternfly/react-core': specifier: ^4.276.8 - version: 4.276.8(react-dom@18.2.0)(react@18.2.0) + version: 4.278.0(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-styles': specifier: ^4.11.8 - version: 4.92.6 + version: 4.92.8 keycloak-js: specifier: workspace:* version: link:../keycloak-js @@ -404,8 +404,8 @@ importers: version: 18.2.0(react@18.2.0) devDependencies: '@types/react': - specifier: ^18.2.33 - version: 18.2.33 + specifier: ^18.2.34 + version: 18.2.34 '@types/react-dom': specifier: ^18.2.14 version: 18.2.14 @@ -414,25 +414,25 @@ importers: version: 3.4.1(vite@4.5.0) rollup-plugin-peer-deps-external: specifier: ^2.2.4 - version: 2.2.4(rollup@4.1.5) + version: 2.2.4(rollup@4.2.0) vite: specifier: ^4.5.0 - version: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + version: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) vite-plugin-checker: specifier: ^0.6.2 version: 0.6.2(eslint@8.52.0)(typescript@5.2.2)(vite@4.5.0) vite-plugin-dts: specifier: ^3.6.3 - version: 3.6.3(@types/node@20.8.9)(rollup@4.1.5)(typescript@5.2.2)(vite@4.5.0) + version: 3.6.3(@types/node@20.8.10)(rollup@4.2.0)(typescript@5.2.2)(vite@4.5.0) libs/ui-shared: dependencies: '@patternfly/react-core': specifier: ^4.276.8 - version: 4.276.8(react-dom@18.2.0)(react@18.2.0) + version: 4.278.0(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-icons': specifier: ^4.93.6 - version: 4.93.6(react-dom@18.2.0)(react@18.2.0) + version: 4.93.7(react-dom@18.2.0)(react@18.2.0) react: specifier: ^18.2.0 version: 18.2.0 @@ -444,8 +444,8 @@ importers: version: 7.47.0(react@18.2.0) devDependencies: '@types/react': - specifier: ^18.2.33 - version: 18.2.33 + specifier: ^18.2.34 + version: 18.2.34 '@types/react-dom': specifier: ^18.2.14 version: 18.2.14 @@ -454,19 +454,19 @@ importers: version: 3.4.1(vite@4.5.0) rollup-plugin-peer-deps-external: specifier: ^2.2.4 - version: 2.2.4(rollup@4.1.5) + version: 2.2.4(rollup@4.2.0) vite: specifier: ^4.5.0 - version: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + version: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) vite-plugin-checker: specifier: ^0.6.2 version: 0.6.2(eslint@8.52.0)(typescript@5.2.2)(vite@4.5.0) vite-plugin-dts: specifier: ^3.6.3 - version: 3.6.3(@types/node@20.8.9)(rollup@4.1.5)(typescript@5.2.2)(vite@4.5.0) + version: 3.6.3(@types/node@20.8.10)(rollup@4.2.0)(typescript@5.2.2)(vite@4.5.0) vitest: specifier: ^0.34.6 - version: 0.34.6 + version: 0.34.6(jsdom@22.1.0)(lightningcss@1.22.0) packages: @@ -491,7 +491,7 @@ packages: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} dependencies: - '@babel/highlight': 7.22.13 + '@babel/highlight': 7.22.20 chalk: 2.4.2 dev: true @@ -500,40 +500,40 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-validator-identifier@7.22.5: - resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} dev: true - /@babel/highlight@7.22.13: - resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} + /@babel/highlight@7.22.20: + resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 chalk: 2.4.2 js-tokens: 4.0.0 dev: true - /@babel/parser@7.22.13: - resolution: {integrity: sha512-3l6+4YOvc9wx7VlCSw4yQfcBo01ECA8TicQfbnCPuCEpRQrf+gTUyGdxNw+pyTUyywp6JRD1w0YQs9TpBXYlkw==} + /@babel/parser@7.23.0: + resolution: {integrity: sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==} engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.22.11 + '@babel/types': 7.23.0 dev: true - /@babel/runtime@7.22.11: - resolution: {integrity: sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==} + /@babel/runtime@7.23.2: + resolution: {integrity: sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==} engines: {node: '>=6.9.0'} dependencies: regenerator-runtime: 0.14.0 - /@babel/types@7.22.11: - resolution: {integrity: sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==} + /@babel/types@7.23.0: + resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 dev: true @@ -551,8 +551,8 @@ packages: '@jridgewell/trace-mapping': 0.3.9 dev: true - /@cypress/request@3.0.0: - resolution: {integrity: sha512-GKFCqwZwMYmL3IBoNeR2MM1SnxRIGERsQOTWeQKoYBt2JLqcqiy7JXqO894FLrpjZYqGxW92MNwRH2BN56obdQ==} + /@cypress/request@3.0.1: + resolution: {integrity: sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==} engines: {node: '>= 6'} dependencies: aws-sign2: 0.7.0 @@ -792,8 +792,8 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@eslint-community/regexpp@4.8.0: - resolution: {integrity: sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==} + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true @@ -804,7 +804,7 @@ packages: ajv: 6.12.6 debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 - globals: 13.21.0 + globals: 13.23.0 ignore: 5.2.4 import-fresh: 3.3.0 js-yaml: 4.1.0 @@ -857,7 +857,7 @@ packages: dependencies: '@jridgewell/set-array': 1.1.2 '@jridgewell/sourcemap-codec': 1.4.15 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 dev: true /@jridgewell/resolve-uri@3.1.1: @@ -874,15 +874,15 @@ packages: resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} dependencies: '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 + '@jridgewell/trace-mapping': 0.3.20 dev: true /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} dev: true - /@jridgewell/trace-mapping@0.3.19: - resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==} + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} dependencies: '@jridgewell/resolve-uri': 3.1.1 '@jridgewell/sourcemap-codec': 1.4.15 @@ -895,29 +895,29 @@ packages: '@jridgewell/sourcemap-codec': 1.4.15 dev: true - /@microsoft/api-extractor-model@7.28.2(@types/node@20.8.9): + /@microsoft/api-extractor-model@7.28.2(@types/node@20.8.10): resolution: {integrity: sha512-vkojrM2fo3q4n4oPh4uUZdjJ2DxQ2+RnDQL/xhTWSRUNPF6P4QyrvY357HBxbnltKcYu+nNNolVqc6TIGQ73Ig==} dependencies: '@microsoft/tsdoc': 0.14.2 '@microsoft/tsdoc-config': 0.16.2 - '@rushstack/node-core-library': 3.61.0(@types/node@20.8.9) + '@rushstack/node-core-library': 3.61.0(@types/node@20.8.10) transitivePeerDependencies: - '@types/node' dev: true - /@microsoft/api-extractor@7.38.0(@types/node@20.8.9): - resolution: {integrity: sha512-e1LhZYnfw+JEebuY2bzhw0imDCl1nwjSThTrQqBXl40hrVo6xm3j/1EpUr89QyzgjqmAwek2ZkIVZbrhaR+cqg==} + /@microsoft/api-extractor@7.38.2(@types/node@20.8.10): + resolution: {integrity: sha512-JOARuhTwOcOMIU0O2czscoJy3ddVzIRhSA9/7T1ALuZSNphgWsPk+Bv4E7AnBDmTV4pP4lBNLtCxEHjjpWaytQ==} hasBin: true dependencies: - '@microsoft/api-extractor-model': 7.28.2(@types/node@20.8.9) + '@microsoft/api-extractor-model': 7.28.2(@types/node@20.8.10) '@microsoft/tsdoc': 0.14.2 '@microsoft/tsdoc-config': 0.16.2 - '@rushstack/node-core-library': 3.61.0(@types/node@20.8.9) + '@rushstack/node-core-library': 3.61.0(@types/node@20.8.10) '@rushstack/rig-package': 0.5.1 - '@rushstack/ts-command-line': 4.16.1 + '@rushstack/ts-command-line': 4.17.1 colors: 1.2.5 lodash: 4.17.21 - resolve: 1.22.4 + resolve: 1.22.8 semver: 7.5.4 source-map: 0.6.1 typescript: 5.0.4 @@ -964,90 +964,86 @@ packages: engines: {node: '>= 18'} dev: false - /@octokit/core@5.0.0: - resolution: {integrity: sha512-YbAtMWIrbZ9FCXbLwT9wWB8TyLjq9mxpKdgB3dUNxQcIVTf9hJ70gRPwAcqGZdY6WdJPZ0I7jLaaNDCiloGN2A==} + /@octokit/core@5.0.1: + resolution: {integrity: sha512-lyeeeZyESFo+ffI801SaBKmCfsvarO+dgV8/0gD8u1d87clbEdWsP5yC+dSj3zLhb2eIf5SJrn6vDz9AheETHw==} engines: {node: '>= 18'} dependencies: '@octokit/auth-token': 4.0.0 - '@octokit/graphql': 7.0.1 - '@octokit/request': 8.1.1 - '@octokit/request-error': 5.0.0 - '@octokit/types': 11.1.0 + '@octokit/graphql': 7.0.2 + '@octokit/request': 8.1.4 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 before-after-hook: 2.2.3 universal-user-agent: 6.0.0 dev: false - /@octokit/endpoint@9.0.0: - resolution: {integrity: sha512-szrQhiqJ88gghWY2Htt8MqUDO6++E/EIXqJ2ZEp5ma3uGS46o7LZAzSLt49myB7rT+Hfw5Y6gO3LmOxGzHijAQ==} + /@octokit/endpoint@9.0.2: + resolution: {integrity: sha512-qhKW8YLIi+Kmc92FQUFGr++DYtkx/1fBv+Thua6baqnjnOsgBYJDCvWZR1YcINuHGOEQt416WOfE+A/oG60NBQ==} engines: {node: '>= 18'} dependencies: - '@octokit/types': 11.1.0 + '@octokit/types': 12.1.1 is-plain-object: 5.0.0 universal-user-agent: 6.0.0 dev: false - /@octokit/graphql@7.0.1: - resolution: {integrity: sha512-T5S3oZ1JOE58gom6MIcrgwZXzTaxRnxBso58xhozxHpOqSTgDS6YNeEUvZ/kRvXgPrRz/KHnZhtb7jUMRi9E6w==} + /@octokit/graphql@7.0.2: + resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} engines: {node: '>= 18'} dependencies: - '@octokit/request': 8.1.1 - '@octokit/types': 11.1.0 + '@octokit/request': 8.1.4 + '@octokit/types': 12.1.1 universal-user-agent: 6.0.0 dev: false - /@octokit/openapi-types@18.0.0: - resolution: {integrity: sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==} - dev: false - - /@octokit/openapi-types@19.0.0: - resolution: {integrity: sha512-PclQ6JGMTE9iUStpzMkwLCISFn/wDeRjkZFIKALpvJQNBGwDoYYi2fFvuHwssoQ1rXI5mfh6jgTgWuddeUzfWw==} + /@octokit/openapi-types@19.0.2: + resolution: {integrity: sha512-8li32fUDUeml/ACRp/njCWTsk5t17cfTM1jp9n08pBrqs5cDFJubtjsSnuz56r5Tad6jdEPJld7LxNp9dNcyjQ==} dev: false - /@octokit/plugin-paginate-rest@9.0.0(@octokit/core@5.0.0): - resolution: {integrity: sha512-oIJzCpttmBTlEhBmRvb+b9rlnGpmFgDtZ0bB6nq39qIod6A5DP+7RkVLMOixIgRCYSHDTeayWqmiJ2SZ6xgfdw==} + /@octokit/plugin-paginate-rest@9.1.2(@octokit/core@5.0.1): + resolution: {integrity: sha512-euDbNV6fxX6btsCDnZoZM4vw3zO1nj1Z7TskHAulO6mZ9lHoFTpwll6farf+wh31mlBabgU81bBYdflp0GLVAQ==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=5' dependencies: - '@octokit/core': 5.0.0 - '@octokit/types': 12.0.0 + '@octokit/core': 5.0.1 + '@octokit/types': 12.1.1 dev: false - /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.0): + /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.1): resolution: {integrity: sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=5' dependencies: - '@octokit/core': 5.0.0 + '@octokit/core': 5.0.1 dev: false - /@octokit/plugin-rest-endpoint-methods@10.0.0(@octokit/core@5.0.0): - resolution: {integrity: sha512-16VkwE2v6rXU+/gBsYC62M8lKWOphY5Lg4wpjYnVE9Zbu0J6IwiT5kILoj1YOB53XLmcJR+Nqp8DmifOPY4H3g==} + /@octokit/plugin-rest-endpoint-methods@10.1.2(@octokit/core@5.0.1): + resolution: {integrity: sha512-JztgZ82CY4JNlPTuF0jh4iWuuGpEi5czFCoXyAbMg4F2XyFBbG5DWAKfa3odRvdZww6Df1tQgBKnqpd9X0WF9g==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=5' dependencies: - '@octokit/core': 5.0.0 - '@octokit/types': 12.0.0 + '@octokit/core': 5.0.1 + '@octokit/types': 12.1.1 dev: false - /@octokit/request-error@5.0.0: - resolution: {integrity: sha512-1ue0DH0Lif5iEqT52+Rf/hf0RmGO9NWFjrzmrkArpG9trFfDM/efx00BJHdLGuro4BR/gECxCU2Twf5OKrRFsQ==} + /@octokit/request-error@5.0.1: + resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} engines: {node: '>= 18'} dependencies: - '@octokit/types': 11.1.0 + '@octokit/types': 12.1.1 deprecation: 2.3.1 once: 1.4.0 dev: false - /@octokit/request@8.1.1: - resolution: {integrity: sha512-8N+tdUz4aCqQmXl8FpHYfKG9GelDFd7XGVzyN8rc6WxVlYcfpHECnuRkgquzz+WzvHTK62co5di8gSXnzASZPQ==} + /@octokit/request@8.1.4: + resolution: {integrity: sha512-M0aaFfpGPEKrg7XoA/gwgRvc9MSXHRO2Ioki1qrPDbl1e9YhjIwVoHE7HIKmv/m3idzldj//xBujcFNqGX6ENA==} engines: {node: '>= 18'} dependencies: - '@octokit/endpoint': 9.0.0 - '@octokit/request-error': 5.0.0 - '@octokit/types': 11.1.0 + '@octokit/endpoint': 9.0.2 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.1.1 is-plain-object: 5.0.0 universal-user-agent: 6.0.0 dev: false @@ -1056,52 +1052,46 @@ packages: resolution: {integrity: sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==} engines: {node: '>= 18'} dependencies: - '@octokit/core': 5.0.0 - '@octokit/plugin-paginate-rest': 9.0.0(@octokit/core@5.0.0) - '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.0) - '@octokit/plugin-rest-endpoint-methods': 10.0.0(@octokit/core@5.0.0) - dev: false - - /@octokit/types@11.1.0: - resolution: {integrity: sha512-Fz0+7GyLm/bHt8fwEqgvRBWwIV1S6wRRyq+V6exRKLVWaKGsuy6H9QFYeBVDV7rK6fO3XwHgQOPxv+cLj2zpXQ==} - dependencies: - '@octokit/openapi-types': 18.0.0 + '@octokit/core': 5.0.1 + '@octokit/plugin-paginate-rest': 9.1.2(@octokit/core@5.0.1) + '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.1) + '@octokit/plugin-rest-endpoint-methods': 10.1.2(@octokit/core@5.0.1) dev: false - /@octokit/types@12.0.0: - resolution: {integrity: sha512-EzD434aHTFifGudYAygnFlS1Tl6KhbTynEWELQXIbTY8Msvb5nEqTZIm7sbPEt4mQYLZwu3zPKVdeIrw0g7ovg==} + /@octokit/types@12.1.1: + resolution: {integrity: sha512-qnJTldJ1NyGT5MTsCg/Zi+y2IFHZ1Jo5+njNCjJ9FcainV7LjuHgmB697kA0g4MjZeDAJsM3B45iqCVsCLVFZg==} dependencies: - '@octokit/openapi-types': 19.0.0 + '@octokit/openapi-types': 19.0.2 dev: false - /@patternfly/patternfly@4.224.2: - resolution: {integrity: sha512-HGNV26uyHSIECuhjPg/WGn0mXbAotcs6ODfhAOkfYjIgGylddgiwElxUe1rpEHV5mQJJ2rMn4OdeJIIpzRX61g==} + /@patternfly/patternfly@4.224.5: + resolution: {integrity: sha512-io0huj+LCP5FgDZJDaLv1snxktTYs8iCFz/W1VDRneYoebNHLmGfQdF7Yn8bS6PF7qmN6oJKEBlq3AjmmE8vdA==} dev: false - /@patternfly/react-code-editor@4.82.115(react-dom@18.2.0)(react-monaco-editor@0.51.0)(react@18.2.0): - resolution: {integrity: sha512-mwHj5r+HGEUppFKzw8vKPG140LAZAuyAKmCIjgmtCH2sUWkujtOS2BMId3BZI7mwdYt9vjwdbiUIHls0TP/HhQ==} + /@patternfly/react-code-editor@4.82.121(react-dom@18.2.0)(react-monaco-editor@0.51.0)(react@18.2.0): + resolution: {integrity: sha512-c6RYoXK4vlU6jBnshVx8zw/MHeUU37/WdnO3e5n5tf7Vxkhv/0H+YwMZ2YR6zuCq8UD4dG0+cl7W6HUC1ZgBVA==} peerDependencies: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 react-monaco-editor: ^0.51.0 dependencies: - '@patternfly/react-core': 4.276.8(react-dom@18.2.0)(react@18.2.0) - '@patternfly/react-icons': 4.93.6(react-dom@18.2.0)(react@18.2.0) - '@patternfly/react-styles': 4.92.6 + '@patternfly/react-core': 4.278.0(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-icons': 4.93.7(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-styles': 4.92.8 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) react-dropzone: 9.0.0(react@18.2.0) - react-monaco-editor: 0.51.0(@types/react@18.2.33)(monaco-editor@0.44.0)(react@18.2.0) + react-monaco-editor: 0.51.0(@types/react@18.2.34)(monaco-editor@0.44.0)(react@18.2.0) tslib: 2.6.2 dev: false - /@patternfly/react-core@4.276.8(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-dn322rEzBeiVztZEuCZMUUittNb8l1hk30h9ZN31FLZLLVtXGlThFNV9ieqOJYA9zrYxYZrHMkTnOxSWVacMZg==} + /@patternfly/react-core@4.278.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-w+0WgSa5O64yi50PpkYuuIt5N5S9svkJKxrhV4LQzOhAtSRTtbraOBRwEKodppT/oUeKMlAdDUWep1O3QluF3Q==} peerDependencies: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 dependencies: - '@patternfly/react-icons': 4.93.6(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-icons': 4.93.7(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-styles': 4.92.8 '@patternfly/react-tokens': 4.94.7 focus-trap: 6.9.2 @@ -1112,8 +1102,8 @@ packages: tslib: 2.6.2 dev: false - /@patternfly/react-icons@4.93.6(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-ZrXegc/81oiuTIeWvoHb3nG/eZODbB4rYmekBEsrbiysyO7m/sUFoi/RLvgFINrRoh6YCJqL5fj06Jg6d7jX1g==} + /@patternfly/react-icons@4.93.7(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-3kr35dgba7Qz5CSzmfH0rIjSvBC5xkmiknf3SvVUVxaiVA7KRowID8viYHeZlf3v/Oa3sEewaH830Q0t+nWsZQ==} peerDependencies: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 @@ -1122,22 +1112,18 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /@patternfly/react-styles@4.92.6: - resolution: {integrity: sha512-b8uQdEReMyeoMzjpMri845QxqtupY/tIFFYfVeKoB2neno8gkcW1RvDdDe62LF88q45OktCwAe/8A99ker10Iw==} - dev: false - /@patternfly/react-styles@4.92.8: resolution: {integrity: sha512-K4lUU8O4HiCX9NeuNUIrPgN3wlGERCxJVio+PAjd8hpJD/PKnjFfOJ9u6/Cii3qLy/5ZviWPRNHbGiwA/+YUhg==} dev: false - /@patternfly/react-table@4.113.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-qxa3NWCdYasqQQL1rqEd8DyNa8oWr6HNveNW5YJRakE7imWZhUPG2Nd6Op60+KYX8kbCSl7gwSmgAZAYMBMZkQ==} + /@patternfly/react-table@4.113.6(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-09TfJISmJVsCH0pTSFtHY0PBWVJpffT0DJT8WvMNttU/vpC7XJVdeXi+yWaIUoqfgZvL0c7Cmu5rUT97zUODJQ==} peerDependencies: react: ^16.8 || ^17 || ^18 react-dom: ^16.8 || ^17 || ^18 dependencies: - '@patternfly/react-core': 4.276.8(react-dom@18.2.0)(react@18.2.0) - '@patternfly/react-icons': 4.93.6(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-core': 4.278.0(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-icons': 4.93.7(react-dom@18.2.0)(react@18.2.0) '@patternfly/react-styles': 4.92.8 '@patternfly/react-tokens': 4.94.7 lodash: 4.17.21 @@ -1170,120 +1156,120 @@ packages: playwright: 1.39.0 dev: true - /@reactflow/background@11.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /@reactflow/background@11.3.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-bgwvqWxF09chwmdkyClpYEMaewBspdwjgLbbFlLf4SpWPFMYyuvCBQrcISsvy/EDEWO9i3Uj9ktgGAhvtSQsmA==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/core': 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) classcat: 5.0.4 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.1(@types/react@18.2.33)(react@18.2.0) + zustand: 4.4.6(@types/react@18.2.34)(react@18.2.0) transitivePeerDependencies: - '@types/react' - immer dev: false - /@reactflow/controls@11.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /@reactflow/controls@11.2.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-x6e5p9iHjC6gd+4SoZ3DOOp0F1MefGKQ8hT6yPVdqxfo1+rV2WhrWvrX/MCoEu12Dp7457LdLfa0giy3aho8tQ==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/core': 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) classcat: 5.0.4 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.1(@types/react@18.2.33)(react@18.2.0) + zustand: 4.4.6(@types/react@18.2.34)(react@18.2.0) transitivePeerDependencies: - '@types/react' - immer dev: false - /@reactflow/core@11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /@reactflow/core@11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Ko7nKPOYalwDTTbRHi2+QXDiidSAcpUzGN3G+0B+QysLZkcaPCkpkMjjHiDC4c/Z1BJBzs1FRJg/T6BXaBnYkg==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@types/d3': 7.4.0 - '@types/d3-drag': 3.0.3 - '@types/d3-selection': 3.0.6 - '@types/d3-zoom': 3.0.4 + '@types/d3': 7.4.2 + '@types/d3-drag': 3.0.5 + '@types/d3-selection': 3.0.8 + '@types/d3-zoom': 3.0.6 classcat: 5.0.4 d3-drag: 3.0.0 d3-selection: 3.0.0 d3-zoom: 3.0.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.1(@types/react@18.2.33)(react@18.2.0) + zustand: 4.4.6(@types/react@18.2.34)(react@18.2.0) transitivePeerDependencies: - '@types/react' - immer dev: false - /@reactflow/minimap@11.7.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /@reactflow/minimap@11.7.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-Jo1R+uDey9IV7O2s3m0gK2+cZpg9M8hq2EZJb3NGfOSzMAPhj3mby0fNJIgTzycreuht0TpA51c2YfjGI3YIOw==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@types/d3-selection': 3.0.6 - '@types/d3-zoom': 3.0.4 + '@reactflow/core': 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) + '@types/d3-selection': 3.0.8 + '@types/d3-zoom': 3.0.6 classcat: 5.0.4 d3-selection: 3.0.0 d3-zoom: 3.0.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.1(@types/react@18.2.33)(react@18.2.0) + zustand: 4.4.6(@types/react@18.2.34)(react@18.2.0) transitivePeerDependencies: - '@types/react' - immer dev: false - /@reactflow/node-resizer@2.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /@reactflow/node-resizer@2.2.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-+p271/hAsM5M1+RQTWW/02pbNkCHeGXwxGimIlL1tMIagyuko0NX2vOz2B8jxJnPKlF09Wj18BcXBNUm3nDcSg==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/core': 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) classcat: 5.0.4 d3-drag: 3.0.0 d3-selection: 3.0.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.1(@types/react@18.2.33)(react@18.2.0) + zustand: 4.4.6(@types/react@18.2.34)(react@18.2.0) transitivePeerDependencies: - '@types/react' - immer dev: false - /@reactflow/node-toolbar@1.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /@reactflow/node-toolbar@1.3.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-TfcmpXHRBb2mUfzKGjburiU6FWqRME9pPFs1OwIC1z5e9BjupQhNDEKEk8XHi7PKL/mAiDfwuGXaM1BVVFuPqw==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/core': 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) classcat: 5.0.4 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - zustand: 4.4.1(@types/react@18.2.33)(react@18.2.0) + zustand: 4.4.6(@types/react@18.2.34)(react@18.2.0) transitivePeerDependencies: - '@types/react' - immer dev: false - /@remix-run/router@1.8.0: - resolution: {integrity: sha512-mrfKqIHnSZRyIzBcanNJmVQELTnX+qagEDlcKO90RgRBVOZGSGvZKeDihTRfWcqoDn5N/NkUcwWTccnpN18Tfg==} + /@remix-run/router@1.11.0: + resolution: {integrity: sha512-BHdhcWgeiudl91HvVa2wxqZjSHbheSgIiDvxrF1VjFzBzpTtuDPkOdOi3Iqvc08kXtFkLjhbS+ML9aM8mJS+wQ==} engines: {node: '>=14.0.0'} dev: false - /@rollup/plugin-commonjs@25.0.7(rollup@4.1.5): + /@rollup/plugin-commonjs@25.0.7(rollup@4.2.0): resolution: {integrity: sha512-nEvcR+LRjEjsaSsc4x3XZfCCvZIaSMenZu/OiwOKGN2UhQpAYI7ru7czFvyWbErlpoGjnSX3D5Ch5FcMA3kRWQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1292,16 +1278,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.4(rollup@4.1.5) + '@rollup/pluginutils': 5.0.5(rollup@4.2.0) commondir: 1.0.1 estree-walker: 2.0.2 glob: 8.1.0 is-reference: 1.2.1 - magic-string: 0.30.3 - rollup: 4.1.5 + magic-string: 0.30.5 + rollup: 4.2.0 dev: true - /@rollup/plugin-inject@5.0.5(rollup@4.1.5): + /@rollup/plugin-inject@5.0.5(rollup@4.2.0): resolution: {integrity: sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1310,13 +1296,13 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.4(rollup@4.1.5) + '@rollup/pluginutils': 5.0.5(rollup@4.2.0) estree-walker: 2.0.2 - magic-string: 0.30.3 - rollup: 4.1.5 + magic-string: 0.30.5 + rollup: 4.2.0 dev: true - /@rollup/plugin-node-resolve@15.2.3(rollup@4.1.5): + /@rollup/plugin-node-resolve@15.2.3(rollup@4.2.0): resolution: {integrity: sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1325,16 +1311,16 @@ packages: rollup: optional: true dependencies: - '@rollup/pluginutils': 5.0.4(rollup@4.1.5) + '@rollup/pluginutils': 5.0.5(rollup@4.2.0) '@types/resolve': 1.20.2 deepmerge: 4.3.1 is-builtin-module: 3.2.1 is-module: 1.0.0 - resolve: 1.22.4 - rollup: 4.1.5 + resolve: 1.22.8 + rollup: 4.2.0 dev: true - /@rollup/plugin-terser@0.4.4(rollup@4.1.5): + /@rollup/plugin-terser@0.4.4(rollup@4.2.0): resolution: {integrity: sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1343,13 +1329,13 @@ packages: rollup: optional: true dependencies: - rollup: 4.1.5 + rollup: 4.2.0 serialize-javascript: 6.0.1 - smob: 1.4.0 - terser: 5.19.2 + smob: 1.4.1 + terser: 5.24.0 dev: true - /@rollup/plugin-typescript@11.1.5(rollup@4.1.5)(tslib@2.6.2)(typescript@5.2.2): + /@rollup/plugin-typescript@11.1.5(rollup@4.2.0)(tslib@2.6.2)(typescript@5.2.2): resolution: {integrity: sha512-rnMHrGBB0IUEv69Q8/JGRD/n4/n6b3nfpufUu26axhUcboUzv/twfZU8fIBbTOphRAe0v8EyxzeDpKXqGHfyDA==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1362,29 +1348,14 @@ packages: tslib: optional: true dependencies: - '@rollup/pluginutils': 5.0.4(rollup@4.1.5) - resolve: 1.22.4 - rollup: 4.1.5 + '@rollup/pluginutils': 5.0.5(rollup@4.2.0) + resolve: 1.22.8 + rollup: 4.2.0 tslib: 2.6.2 typescript: 5.2.2 dev: true - /@rollup/pluginutils@5.0.4(rollup@4.1.5): - resolution: {integrity: sha512-0KJnIoRI8A+a1dqOYLxH8vBf8bphDmty5QvIm2hqm7oFCFYKCAZWWd2hXgMibaPsNDhI0AtpYfQZJG47pt/k4g==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.1 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 4.1.5 - dev: true - - /@rollup/pluginutils@5.0.5(rollup@4.1.5): + /@rollup/pluginutils@5.0.5(rollup@4.2.0): resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==} engines: {node: '>=14.0.0'} peerDependencies: @@ -1393,109 +1364,109 @@ packages: rollup: optional: true dependencies: - '@types/estree': 1.0.1 + '@types/estree': 1.0.4 estree-walker: 2.0.2 picomatch: 2.3.1 - rollup: 4.1.5 + rollup: 4.2.0 dev: true - /@rollup/rollup-android-arm-eabi@4.1.5: - resolution: {integrity: sha512-/fwx6GS8cIbM2rTNyLMxjSCOegHywOdXO+kN9yFy018iCULcKZCyA3xvzw4bxyKbYfdSxQgdhbsl0egNcxerQw==} + /@rollup/rollup-android-arm-eabi@4.2.0: + resolution: {integrity: sha512-8PlggAxGxavr+pkCNeV1TM2wTb2o+cUWDg9M1cm9nR27Dsn287uZtSLYXoQqQcmq+sYfF7lHfd3sWJJinH9GmA==} cpu: [arm] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-android-arm64@4.1.5: - resolution: {integrity: sha512-tmXh7dyEt+JEz/NgDJlB1UeL/1gFV0v8qYzUAU42WZH4lmUJ5rp6/HkR2qUNC5jCgYEwd8/EfbHKtGIEfS4CUg==} + /@rollup/rollup-android-arm64@4.2.0: + resolution: {integrity: sha512-+71T85hbMFrJI+zKQULNmSYBeIhru55PYoF/u75MyeN2FcxE4HSPw20319b+FcZ4lWx2Nx/Ql9tN+hoaD3GH/A==} cpu: [arm64] os: [android] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-arm64@4.1.5: - resolution: {integrity: sha512-lTDmLxdEVhzI3KCesZUrNbl3icBvPrDv/85JasY5gh4P2eAuDFmM4uj9HC5DdH0anLC0fwJ+1Uzasr4qOXcjRQ==} + /@rollup/rollup-darwin-arm64@4.2.0: + resolution: {integrity: sha512-IIIQLuG43QIElT1JZqUP/zqIdiJl4t9U/boa0GZnQTw9m1X0k3mlBuysbgYXeloLT1RozdL7bgw4lpSaI8GOXw==} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-darwin-x64@4.1.5: - resolution: {integrity: sha512-v6qEHZyjWnIgcc4oiy8AIeFsUJAx+Kg0sLj+RE7ICwv3u7YC/+bSClxAiBASRjMzqsq0Z+I/pfxj+OD8mjBYxg==} + /@rollup/rollup-darwin-x64@4.2.0: + resolution: {integrity: sha512-BXcXvnLaea1Xz900omrGJhxHFJfH9jZ0CpJuVsbjjhpniJ6qiLXz3xA8Lekaa4MuhFcJd4f0r+Ky1G4VFbYhWw==} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm-gnueabihf@4.1.5: - resolution: {integrity: sha512-WngCfwPEDUNbZR1FNO2TCROYUwJvRlbvPi3AS85bDUkkoRDBcjUIz42cuB1j4PKilmnZascL5xTMF/yU8YFayA==} + /@rollup/rollup-linux-arm-gnueabihf@4.2.0: + resolution: {integrity: sha512-f4K3MKw9Y4AKi4ANGnmPIglr+S+8tO858YrGVuqAHXxJdVghBmz9CPU9kDpOnGvT4g4vg5uNyIFpOOFvffXyMA==} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-gnu@4.1.5: - resolution: {integrity: sha512-Q2A/PEP/UTPTOBwgar3mmCaApahoezai/8e/7f4GCLV6XWCpnU4YwkQQtla7d7nUnc792Ps7g1G0WMovzIknrA==} + /@rollup/rollup-linux-arm64-gnu@4.2.0: + resolution: {integrity: sha512-bNsTYQBgp4H7w6cT7FZhesxpcUPahsSIy4NgdZjH1ZwEoZHxi4XKglj+CsSEkhsKi+x6toVvMylhjRKhEMYfnA==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-arm64-musl@4.1.5: - resolution: {integrity: sha512-84aBKNAVzTU/eG3tb2+kR4NGRAtm2YVW/KHwkGGDR4z1k4hyrDbuImsfs/6J74t6y0YLOe9HOSu7ejRjzUBGVQ==} + /@rollup/rollup-linux-arm64-musl@4.2.0: + resolution: {integrity: sha512-Jp1NxBJpGLuxRU2ihrQk4IZ+ia5nffobG6sOFUPW5PMYkF0kQtxEbeDuCa69Xif211vUOcxlOnf5IOEIpTEySA==} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-gnu@4.1.5: - resolution: {integrity: sha512-mldtP9UEBurIq2+GYMdNeiqCLW1fdgf4KdkMR/QegAeXk4jFHkKQl7p0NITrKFVyVqzISGXH5gR6GSTBH4wszw==} + /@rollup/rollup-linux-x64-gnu@4.2.0: + resolution: {integrity: sha512-3p3iRtQmv2aXw+vtKNyZMLOQ+LSRsqArXjKAh2Oj9cqwfIRe7OXvdkOzWfZOIp1F/x5KJzVAxGxnniF4cMbnsQ==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-linux-x64-musl@4.1.5: - resolution: {integrity: sha512-36p+nMcSxjAEzfU47+by102HolUtf/EfgBAidocTKAofJMTqG5QD50qzaFLk4QO+z7Qvg4qd0wr99jGAwnKOig==} + /@rollup/rollup-linux-x64-musl@4.2.0: + resolution: {integrity: sha512-atih7IF/reUZe4LBLC5Izd44hth2tfDIG8LaPp4/cQXdHh9jabcZEvIeRPrpDq0i/Uu487Qu5gl5KwyAnWajnw==} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-arm64-msvc@4.1.5: - resolution: {integrity: sha512-5oxhubo0A3J8aF/tG+6jHBg785HF8/88kl1YnfbDKmnqMxz/EFiAQDH9cq6lbnxofjn8tlq5KiTf0crJGOGThg==} + /@rollup/rollup-win32-arm64-msvc@4.2.0: + resolution: {integrity: sha512-vYxF3tKJeUE4ceYzpNe2p84RXk/fGK30I8frpRfv/MyPStej/mRlojztkN7Jtd1014HHVeq/tYaMBz/3IxkxZw==} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-ia32-msvc@4.1.5: - resolution: {integrity: sha512-uVQyBREKX9ErofL8KAZ4iVlqzSZOXSIG+BOLYuz5FD+Cg6jh1eLIeUa3Q4SgX0QaTRFeeAgSNqCC+8kZrZBpSw==} + /@rollup/rollup-win32-ia32-msvc@4.2.0: + resolution: {integrity: sha512-1LZJ6zpl93SaPQvas618bMFarVwufWTaczH4ESAbFcwiC4OtznA6Ym+hFPyIGaJaGEB8uMWWac0uXGPXOg5FGA==} cpu: [ia32] os: [win32] requiresBuild: true dev: true optional: true - /@rollup/rollup-win32-x64-msvc@4.1.5: - resolution: {integrity: sha512-FQ5qYqRJ2vUBSom3Fos8o/6UvAMOvlus4+HGCAifH1TagbbwVnVVe0o01J1V52EWnQ8kmfpJDJ0FMrfM5yzcSA==} + /@rollup/rollup-win32-x64-msvc@4.2.0: + resolution: {integrity: sha512-dgQfFdHCNg08nM5zBmqxqc9vrm0DVzhWotpavbPa0j4//MAOKZEB75yGAfzQE9fUJ+4pvM1239Y4IhL8f6sSog==} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true - /@rushstack/node-core-library@3.61.0(@types/node@20.8.9): + /@rushstack/node-core-library@3.61.0(@types/node@20.8.10): resolution: {integrity: sha512-tdOjdErme+/YOu4gPed3sFS72GhtWCgNV9oDsHDnoLY5oDfwjKUc9Z+JOZZ37uAxcm/OCahDHfuu2ugqrfWAVQ==} peerDependencies: '@types/node': '*' @@ -1503,12 +1474,12 @@ packages: '@types/node': optional: true dependencies: - '@types/node': 20.8.9 + '@types/node': 20.8.10 colors: 1.2.5 fs-extra: 7.0.1 import-lazy: 4.0.0 jju: 1.4.0 - resolve: 1.22.4 + resolve: 1.22.8 semver: 7.5.4 z-schema: 5.0.5 dev: true @@ -1516,12 +1487,12 @@ packages: /@rushstack/rig-package@0.5.1: resolution: {integrity: sha512-pXRYSe29TjRw7rqxD4WS3HN/sRSbfr+tJs4a9uuaSIBAITbUggygdhuG0VrO0EO+QqH91GhYMN4S6KRtOEmGVA==} dependencies: - resolve: 1.22.4 + resolve: 1.22.8 strip-json-comments: 3.1.1 dev: true - /@rushstack/ts-command-line@4.16.1: - resolution: {integrity: sha512-+OCsD553GYVLEmz12yiFjMOzuPeCiZ3f8wTiFHL30ZVXexTyPmgjwXEhg2K2P0a2lVf+8YBy7WtPoflB2Fp8/A==} + /@rushstack/ts-command-line@4.17.1: + resolution: {integrity: sha512-2jweO1O57BYP5qdBGl6apJLB+aRIn5ccIRTPDyULh0KMwVzFqWtw6IZWt1qtUoZD/pD2RNkIOosH6Cq45rIYeg==} dependencies: '@types/argparse': 1.0.38 argparse: 1.0.10 @@ -1633,7 +1604,7 @@ packages: '@swc/helpers': optional: true dependencies: - '@swc/counter': 0.1.1 + '@swc/counter': 0.1.2 '@swc/types': 0.1.5 optionalDependencies: '@swc/core-darwin-arm64': 1.3.95 @@ -1648,8 +1619,8 @@ packages: '@swc/core-win32-x64-msvc': 1.3.95 dev: true - /@swc/counter@0.1.1: - resolution: {integrity: sha512-xVRaR4u9hcYjFvcSg71Lz5Bo4//CyjAAfMxa7UsaDSYxAshflUkVJWiyVWrfxC59z2kP1IzI4/1BEpnhI9o3Mw==} + /@swc/counter@0.1.2: + resolution: {integrity: sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==} dev: true /@swc/types@0.1.5: @@ -1662,18 +1633,18 @@ packages: peerDependencies: cypress: ^12.0.0 || ^13.0.0 dependencies: - '@babel/runtime': 7.22.11 - '@testing-library/dom': 9.3.1 + '@babel/runtime': 7.23.2 + '@testing-library/dom': 9.3.3 cypress: 13.4.0 dev: true - /@testing-library/dom@9.3.1: - resolution: {integrity: sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==} + /@testing-library/dom@9.3.3: + resolution: {integrity: sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==} engines: {node: '>=14'} dependencies: '@babel/code-frame': 7.22.13 - '@babel/runtime': 7.22.11 - '@types/aria-query': 5.0.1 + '@babel/runtime': 7.23.2 + '@types/aria-query': 5.0.3 aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.16 @@ -1700,7 +1671,7 @@ packages: optional: true dependencies: '@adobe/css-tools': 4.3.1 - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.23.2 aria-query: 5.3.0 chalk: 3.0.0 css.escape: 1.5.1 @@ -1717,8 +1688,8 @@ packages: react: ^18.0.0 react-dom: ^18.0.0 dependencies: - '@babel/runtime': 7.22.11 - '@testing-library/dom': 9.3.1 + '@babel/runtime': 7.23.2 + '@testing-library/dom': 9.3.3 '@types/react-dom': 18.2.14 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) @@ -1749,227 +1720,223 @@ packages: resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} dev: true - /@types/aria-query@5.0.1: - resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} + /@types/aria-query@5.0.3: + resolution: {integrity: sha512-0Z6Tr7wjKJIk4OUEjVUQMtyunLDy339vcMaj38Kpj6jM2OE1p3S4kXExKZ7a3uXQAPCoy3sbrP1wibDKaf39oA==} dev: true - /@types/chai-subset@1.3.3: - resolution: {integrity: sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==} + /@types/chai-subset@1.3.4: + resolution: {integrity: sha512-CCWNXrJYSUIojZ1149ksLl3AN9cmZ5djf+yUoVVV+NuYrtydItQVlL2ZDqyC6M6O9LWRnVf8yYDxbXHO2TfQZg==} dependencies: '@types/chai': 4.3.9 dev: true - /@types/chai@4.3.8: - resolution: {integrity: sha512-yW/qTM4mRBBcsA9Xw9FbcImYtFPY7sgr+G/O5RDYVmxiy9a+pE5FyoFUi8JYCZY5nicj8atrr1pcfPiYpeNGOA==} - dev: true - /@types/chai@4.3.9: resolution: {integrity: sha512-69TtiDzu0bcmKQv3yg1Zx409/Kd7r0b5F1PfpYJfSHzLGtB53547V4u+9iqKYsTu/O2ai6KTb0TInNpvuQ3qmg==} dev: true - /@types/d3-array@3.0.7: - resolution: {integrity: sha512-4/Q0FckQ8TBjsB0VdGFemJOG8BLXUB2KKlL0VmZ+eOYeOnTb/wDRQqYWpBmQ6IlvWkXwkYiot+n9Px2aTJ7zGQ==} + /@types/d3-array@3.2.0: + resolution: {integrity: sha512-tjU8juPSfhMnu6mJZPOCVVGba4rZoE0tjHDPb81PYwA8CzbaFscGjgkUM7juUJu6iWA1cCVWNEVwxZ5HN9Jj8Q==} dev: false - /@types/d3-axis@3.0.3: - resolution: {integrity: sha512-SE3x/pLO/+GIHH17mvs1uUVPkZ3bHquGzvZpPAh4yadRy71J93MJBpgK/xY8l9gT28yTN1g9v3HfGSFeBMmwZw==} + /@types/d3-axis@3.0.5: + resolution: {integrity: sha512-ufDAV3SQzju+uB3Jlty7SUb/jMigjpIlvDDcSGvGmmO6OT/sNO93UE0dRzwWOZeBLzrLSA0CQM4bf3iq1std3A==} dependencies: - '@types/d3-selection': 3.0.6 + '@types/d3-selection': 3.0.8 dev: false - /@types/d3-brush@3.0.3: - resolution: {integrity: sha512-MQ1/M/B5ifTScHSe5koNkhxn2mhUPqXjGuKjjVYckplAPjP9t2I2sZafb/YVHDwhoXWZoSav+Q726eIbN3qprA==} + /@types/d3-brush@3.0.5: + resolution: {integrity: sha512-JROQXZNq1X6QdWstESDUv1VilwZ2hBCQnWB91yal+5yZvYwGQvYsGCjrkHGfKK/8/AcX1JnERmpQzdDDuLRUsA==} dependencies: - '@types/d3-selection': 3.0.6 + '@types/d3-selection': 3.0.8 dev: false - /@types/d3-chord@3.0.3: - resolution: {integrity: sha512-keuSRwO02c7PBV3JMWuctIfdeJrVFI7RpzouehvBWL4/GGUB3PBNg/9ZKPZAgJphzmS2v2+7vr7BGDQw1CAulw==} + /@types/d3-chord@3.0.5: + resolution: {integrity: sha512-rs26AIhJjtc+XLR4YQU8IjPTLOlDVO4PR1y+pVFYEHzKh2tE5tYz3MF4QV6iz7HboXQEaYpJQt8dH9uUkne8yA==} dev: false - /@types/d3-color@3.1.0: - resolution: {integrity: sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==} + /@types/d3-color@3.1.2: + resolution: {integrity: sha512-At+Ski7dL8Bs58E8g8vPcFJc8tGcaC12Z4m07+p41+DRqnZQcAlp3NfYjLrhNYv+zEyQitU1CUxXNjqUyf+c0g==} dev: false - /@types/d3-contour@3.0.3: - resolution: {integrity: sha512-x7G/tdDZt4m09XZnG2SutbIuQqmkNYqR9uhDMdPlpJbcwepkEjEWG29euFcgVA1k6cn92CHdDL9Z+fOnxnbVQw==} + /@types/d3-contour@3.0.5: + resolution: {integrity: sha512-wLvjwdOQVd1NL1IcW90CCt1VtpeZ3V20p/OTXlkT8uAiprrJnq2PNNnRNe1QCez4U9aMU29Z14zpJQVLW1+Lcg==} dependencies: - '@types/d3-array': 3.0.7 - '@types/geojson': 7946.0.10 + '@types/d3-array': 3.2.0 + '@types/geojson': 7946.0.12 dev: false - /@types/d3-delaunay@6.0.1: - resolution: {integrity: sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==} + /@types/d3-delaunay@6.0.3: + resolution: {integrity: sha512-+Lf5NPKZ4JBC9tbudVkKceQXRxU3jJs0el9aKQvinMtdnFSOG84eVXyhCNgIFuXNQO3iIcYs7sgzN359FEOZnQ==} dev: false - /@types/d3-dispatch@3.0.3: - resolution: {integrity: sha512-Df7KW3Re7G6cIpIhQtqHin8yUxUHYAqiE41ffopbmU5+FifYUNV7RVyTg8rQdkEagg83m14QtS8InvNb95Zqug==} + /@types/d3-dispatch@3.0.5: + resolution: {integrity: sha512-hxvq2kc+9hydVppo21JCGfcM0tLTh1DXnG3MLN0KlxsNZJH4bsdl1iXDuWtXFpWWlBrCMwSqlnoLPDxNAZU3Bg==} dev: false - /@types/d3-drag@3.0.3: - resolution: {integrity: sha512-82AuQMpBQjuXeIX4tjCYfWjpm3g7aGCfx6dFlxX2JlRaiME/QWcHzBsINl7gbHCODA2anPYlL31/Trj/UnjK9A==} + /@types/d3-drag@3.0.5: + resolution: {integrity: sha512-arHyAGvO0NEGGPCU2jTb31TlXeSxwty1bIxr5wOFOCVqVjgriXloLWXoRp39Oa0Y/qXxcAVMIonAWLrtLxUZAQ==} dependencies: - '@types/d3-selection': 3.0.6 + '@types/d3-selection': 3.0.8 dev: false - /@types/d3-dsv@3.0.2: - resolution: {integrity: sha512-DooW5AOkj4AGmseVvbwHvwM/Ltu0Ks0WrhG6r5FG9riHT5oUUTHz6xHsHqJSVU8ZmPkOqlUEY2obS5C9oCIi2g==} + /@types/d3-dsv@3.0.5: + resolution: {integrity: sha512-73WZR3QFOaSRVz9iOrebTbTnbo7xjcgS/i0Cq5zy0jMXPO3v/JbkTD3Zqii1eYE6v4EJ78g5VP407rm+p8fdlA==} dev: false - /@types/d3-ease@3.0.0: - resolution: {integrity: sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==} + /@types/d3-ease@3.0.1: + resolution: {integrity: sha512-VZofjpEt8HWv3nxUAosj5o/+4JflnJ7Bbv07k17VO3T2WRuzGdZeookfaF60iVh5RdhVG49LE5w6LIshVUC6rg==} dev: false - /@types/d3-fetch@3.0.3: - resolution: {integrity: sha512-/EsDKRiQkby3Z/8/AiZq8bsuLDo/tYHnNIZkUpSeEHWV7fHUl6QFBjvMPbhkKGk9jZutzfOkGygCV7eR/MkcXA==} + /@types/d3-fetch@3.0.5: + resolution: {integrity: sha512-Rc8pb6H0RRLpAV2hEXduykUgcDUOhjSLTLmCIeo6ejzgs4SaITh/EteMb3p5Env3Hqjsqw0fCksyqopHHzMkMg==} dependencies: - '@types/d3-dsv': 3.0.2 + '@types/d3-dsv': 3.0.5 dev: false - /@types/d3-force@3.0.5: - resolution: {integrity: sha512-EGG+IWx93ESSXBwfh/5uPuR9Hp8M6o6qEGU7bBQslxCvrdUBQZha/EFpu/VMdLU4B0y4Oe4h175nSm7p9uqFug==} + /@types/d3-force@3.0.7: + resolution: {integrity: sha512-rsok4CEvPLyVWRPsFiBhanJc3up03H/EARVz4d8soPh8drv82YMuAckYy4yv8g4/81JwCng5U5/o9aj9d0T6bQ==} dev: false - /@types/d3-format@3.0.1: - resolution: {integrity: sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==} + /@types/d3-format@3.0.3: + resolution: {integrity: sha512-kxuLXSAEJykTeL/EI3tUiEfGqru7PRdqEy099YBnqFl+fF167UVSB4+wntlZv86ZdoYf0DHjsRHnTIm8kcH7qw==} dev: false - /@types/d3-geo@3.0.4: - resolution: {integrity: sha512-kmUK8rVVIBPKJ1/v36bk2aSgwRj2N/ZkjDT+FkMT5pgedZoPlyhaG62J+9EgNIgUXE6IIL0b7bkLxCzhE6U4VQ==} + /@types/d3-geo@3.0.6: + resolution: {integrity: sha512-wblAES3b+C3hvp4VakwECEKtHquT/xc6K4HOna95LM1j1fd7s7WmU4V+JMQZfKhNCMkV2vWD+ZUgY2Uj6gqfuA==} dependencies: - '@types/geojson': 7946.0.10 + '@types/geojson': 7946.0.12 dev: false - /@types/d3-hierarchy@3.1.3: - resolution: {integrity: sha512-GpSK308Xj+HeLvogfEc7QsCOcIxkDwLhFYnOoohosEzOqv7/agxwvJER1v/kTC+CY1nfazR0F7gnHo7GE41/fw==} + /@types/d3-hierarchy@3.1.5: + resolution: {integrity: sha512-DEcBUj1IL3WyPLDlh4m2nsNXnMLITXM5Vwcu4G85yJHtf2cVGPBjgky3L11WBnT+ayHKf06Tchk5mY1eGmd4WQ==} dev: false - /@types/d3-interpolate@3.0.1: - resolution: {integrity: sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==} + /@types/d3-interpolate@3.0.3: + resolution: {integrity: sha512-6OZ2EIB4lLj+8cUY7I/Cgn9Q+hLdA4DjJHYOQDiHL0SzqS1K9DL5xIOVBSIHgF+tiuO9MU1D36qvdIvRDRPh+Q==} dependencies: - '@types/d3-color': 3.1.0 + '@types/d3-color': 3.1.2 dev: false - /@types/d3-path@3.0.0: - resolution: {integrity: sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==} + /@types/d3-path@3.0.1: + resolution: {integrity: sha512-blRhp7ki7pVznM8k6lk5iUU9paDbVRVq+/xpf0RRgSJn5gr6SE7RcFtxooYGMBOc1RZiGyqRpVdu5AD0z0ooMA==} dev: false - /@types/d3-polygon@3.0.0: - resolution: {integrity: sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==} + /@types/d3-polygon@3.0.1: + resolution: {integrity: sha512-nrcWPk7B9qs6xnpq60Cls44zm9eDmFAv65qi/N/emh/oftnG6uYz49aIS0mdFaGeJxVN8H3pHneMuZMV8EwFdw==} dev: false - /@types/d3-quadtree@3.0.2: - resolution: {integrity: sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==} + /@types/d3-quadtree@3.0.4: + resolution: {integrity: sha512-B725MopFDIOQ6njFbeOxIEf42HVO2Xv+FmcxQISdOKErvLbFqWz3Riu+OWujUYoogreqqyHBHcGGL/JzzXQYsw==} dev: false - /@types/d3-random@3.0.1: - resolution: {integrity: sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==} + /@types/d3-random@3.0.2: + resolution: {integrity: sha512-8QhsqkKs6mymAZMrg3ZFXPxKA34rdgp3ZrtB8o6mhFsKAd1gOvR1gocWnca+kmXypQdwgnzKm9gZE2Uw8NjjKw==} dev: false - /@types/d3-scale-chromatic@3.0.0: - resolution: {integrity: sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==} + /@types/d3-scale-chromatic@3.0.1: + resolution: {integrity: sha512-Ob7OrwiTeQXY/WBBbRHGZBOn6rH1h7y3jjpTSKYqDEeqFjktql6k2XSgNwLrLDmAsXhEn8P9NHDY4VTuo0ZY1w==} dev: false - /@types/d3-scale@4.0.4: - resolution: {integrity: sha512-eq1ZeTj0yr72L8MQk6N6heP603ubnywSDRfNpi5enouR112HzGLS6RIvExCzZTraFF4HdzNpJMwA/zGiMoHUUw==} + /@types/d3-scale@4.0.6: + resolution: {integrity: sha512-lo3oMLSiqsQUovv8j15X4BNEDOsnHuGjeVg7GRbAuB2PUa1prK5BNSOu6xixgNf3nqxPl4I1BqJWrPvFGlQoGQ==} dependencies: - '@types/d3-time': 3.0.0 + '@types/d3-time': 3.0.2 dev: false - /@types/d3-selection@3.0.6: - resolution: {integrity: sha512-2ACr96USZVjXR9KMD9IWi1Epo4rSDKnUtYn6q2SPhYxykvXTw9vR77lkFNruXVg4i1tzQtBxeDMx0oNvJWbF1w==} + /@types/d3-selection@3.0.8: + resolution: {integrity: sha512-pxCZUfQyedq/DIlPXIR5wE1mIH37omOdx1yxRudL3KZ4AC+156jMjOv1z5RVlGq62f8WX2kyO0hTVgEx627QFg==} dev: false - /@types/d3-shape@3.1.2: - resolution: {integrity: sha512-NN4CXr3qeOUNyK5WasVUV8NCSAx/CRVcwcb0BuuS1PiTqwIm6ABi1SyasLZ/vsVCFDArF+W4QiGzSry1eKYQ7w==} + /@types/d3-shape@3.1.4: + resolution: {integrity: sha512-M2/xsWPsjaZc5ifMKp1EBp0gqJG0eO/zlldJNOC85Y/5DGsBQ49gDkRJ2h5GY7ZVD6KUumvZWsylSbvTaJTqKg==} dependencies: - '@types/d3-path': 3.0.0 + '@types/d3-path': 3.0.1 dev: false - /@types/d3-time-format@4.0.0: - resolution: {integrity: sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==} + /@types/d3-time-format@4.0.2: + resolution: {integrity: sha512-wr08C1Gh77qaN8JIkrn5Rz/bdt5M9bdEqFmEOcYhUSq2t2sHvLTBfb4XAtGB3D4hm0ubj50NXWWXoXyp5tPXDg==} dev: false - /@types/d3-time@3.0.0: - resolution: {integrity: sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==} + /@types/d3-time@3.0.2: + resolution: {integrity: sha512-kbdRXTmUgNfw5OTE3KZnFQn6XdIc4QGroN5UixgdrXATmYsdlPQS6pEut9tVlIojtzuFD4txs/L+Rq41AHtLpg==} dev: false - /@types/d3-timer@3.0.0: - resolution: {integrity: sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==} + /@types/d3-timer@3.0.1: + resolution: {integrity: sha512-GGTvzKccVEhxmRfJEB6zhY9ieT4UhGVUIQaBzFpUO9OXy2ycAlnPCSJLzmGGgqt3KVjqN3QCQB4g1rsZnHsWhg==} dev: false - /@types/d3-transition@3.0.4: - resolution: {integrity: sha512-512a4uCOjUzsebydItSXsHrPeQblCVk8IKjqCUmrlvBWkkVh3donTTxmURDo1YPwIVDh5YVwCAO6gR4sgimCPQ==} + /@types/d3-transition@3.0.6: + resolution: {integrity: sha512-K0To23B5UxNwFtKORnS5JoNYvw/DnknU5MzhHIS9czJ/lTqFFDeU6w9lArOdoTl0cZFNdNrMJSFCbRCEHccH2w==} dependencies: - '@types/d3-selection': 3.0.6 + '@types/d3-selection': 3.0.8 dev: false - /@types/d3-zoom@3.0.4: - resolution: {integrity: sha512-cqkuY1ah9ZQre2POqjSLcM8g40UVya/qwEUrNYP2/rCVljbmqKCVcv+ebvwhlI5azIbSEL7m+os6n+WlYA43aA==} + /@types/d3-zoom@3.0.6: + resolution: {integrity: sha512-dGZQaXEu7aNcCL71LPpjB58IjoQNM9oDPfQuMUJ7N/fbkcIWGX2PnmUWO1jPJ+RLbZBpRUggJUX8twKRvo2hKQ==} dependencies: - '@types/d3-interpolate': 3.0.1 - '@types/d3-selection': 3.0.6 + '@types/d3-interpolate': 3.0.3 + '@types/d3-selection': 3.0.8 dev: false - /@types/d3@7.4.0: - resolution: {integrity: sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==} + /@types/d3@7.4.2: + resolution: {integrity: sha512-Y4g2Yb30ZJmmtqAJTqMRaqXwRawfvpdpVmyEYEcyGNhrQI/Zvkq3k7yE1tdN07aFSmNBfvmegMQ9Fe2qy9ZMhw==} dependencies: - '@types/d3-array': 3.0.7 - '@types/d3-axis': 3.0.3 - '@types/d3-brush': 3.0.3 - '@types/d3-chord': 3.0.3 - '@types/d3-color': 3.1.0 - '@types/d3-contour': 3.0.3 - '@types/d3-delaunay': 6.0.1 - '@types/d3-dispatch': 3.0.3 - '@types/d3-drag': 3.0.3 - '@types/d3-dsv': 3.0.2 - '@types/d3-ease': 3.0.0 - '@types/d3-fetch': 3.0.3 - '@types/d3-force': 3.0.5 - '@types/d3-format': 3.0.1 - '@types/d3-geo': 3.0.4 - '@types/d3-hierarchy': 3.1.3 - '@types/d3-interpolate': 3.0.1 - '@types/d3-path': 3.0.0 - '@types/d3-polygon': 3.0.0 - '@types/d3-quadtree': 3.0.2 - '@types/d3-random': 3.0.1 - '@types/d3-scale': 4.0.4 - '@types/d3-scale-chromatic': 3.0.0 - '@types/d3-selection': 3.0.6 - '@types/d3-shape': 3.1.2 - '@types/d3-time': 3.0.0 - '@types/d3-time-format': 4.0.0 - '@types/d3-timer': 3.0.0 - '@types/d3-transition': 3.0.4 - '@types/d3-zoom': 3.0.4 + '@types/d3-array': 3.2.0 + '@types/d3-axis': 3.0.5 + '@types/d3-brush': 3.0.5 + '@types/d3-chord': 3.0.5 + '@types/d3-color': 3.1.2 + '@types/d3-contour': 3.0.5 + '@types/d3-delaunay': 6.0.3 + '@types/d3-dispatch': 3.0.5 + '@types/d3-drag': 3.0.5 + '@types/d3-dsv': 3.0.5 + '@types/d3-ease': 3.0.1 + '@types/d3-fetch': 3.0.5 + '@types/d3-force': 3.0.7 + '@types/d3-format': 3.0.3 + '@types/d3-geo': 3.0.6 + '@types/d3-hierarchy': 3.1.5 + '@types/d3-interpolate': 3.0.3 + '@types/d3-path': 3.0.1 + '@types/d3-polygon': 3.0.1 + '@types/d3-quadtree': 3.0.4 + '@types/d3-random': 3.0.2 + '@types/d3-scale': 4.0.6 + '@types/d3-scale-chromatic': 3.0.1 + '@types/d3-selection': 3.0.8 + '@types/d3-shape': 3.1.4 + '@types/d3-time': 3.0.2 + '@types/d3-time-format': 4.0.2 + '@types/d3-timer': 3.0.1 + '@types/d3-transition': 3.0.6 + '@types/d3-zoom': 3.0.6 dev: false /@types/dagre@0.7.51: resolution: {integrity: sha512-OJtLXov4mK9wZ4/TkBqUM5OBCpIQvv+sT9FZFnM1Ais5yqHEMnDObGGPYYrQhkLVIKik/bD8o9WWn7YQfPkDlQ==} dev: true - /@types/estree@1.0.1: - resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} + /@types/estree@1.0.4: + resolution: {integrity: sha512-2JwWnHK9H+wUZNorf2Zr6ves96WHoWDJIftkcxPKsS7Djta6Zu519LarhRNljPXkpsZR2ZMwNCPeW7omW07BJw==} dev: true /@types/file-saver@2.0.6: resolution: {integrity: sha512-Mw671DVqoMHbjw0w4v2iiOro01dlT/WhWp5uwecBa0Wg8c+bcZOjgF1ndBnlaxhtvFCgTRBtsGivSVhrK/vnag==} dev: true - /@types/geojson@7946.0.10: - resolution: {integrity: sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==} + /@types/geojson@7946.0.12: + resolution: {integrity: sha512-uK2z1ZHJyC0nQRbuovXFt4mzXDwf27vQeUWNhfKGwRcWW429GOhP8HxUHlM6TLH4bzmlv/HlEjpvJh3JfmGsAA==} dev: false /@types/gunzip-maybe@1.4.1: resolution: {integrity: sha512-FAxzVI4EbR3bsvsvtNsJ6kqaxQftN1wD/F6A+51m85oo1oRoZn15rQwbedJY2GmzyUKl6EjG9wKkgShwcTQgTA==} dependencies: - '@types/node': 20.8.8 + '@types/node': 20.8.10 dev: false - /@types/json-schema@7.0.12: - resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} + /@types/json-schema@7.0.14: + resolution: {integrity: sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==} dev: true /@types/json5@0.0.29: @@ -1979,88 +1946,85 @@ packages: /@types/lodash-es@4.17.10: resolution: {integrity: sha512-YJP+w/2khSBwbUSFdGsSqmDvmnN3cCKoPOL7Zjle6s30ZtemkkqhjVfFqGwPN7ASil5VyjE2GtyU/yqYY6mC0A==} dependencies: - '@types/lodash': 4.14.197 + '@types/lodash': 4.14.200 dev: true - /@types/lodash@4.14.197: - resolution: {integrity: sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==} + /@types/lodash@4.14.200: + resolution: {integrity: sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==} dev: true /@types/mocha@10.0.3: resolution: {integrity: sha512-RsOPImTriV/OE4A9qKjMtk2MnXiuLLbcO3nCXK+kvq4nr0iMfFgpjaX3MPLb6f7+EL1FGSelYvuJMV6REH+ZPQ==} dev: true - /@types/node@18.17.15: - resolution: {integrity: sha512-2yrWpBk32tvV/JAd3HNHWuZn/VDN1P+72hWirHnvsvTGSqbANi+kSeuQR9yAHnbvaBvHDsoTdXV0Fe+iRtHLKA==} - dev: true - - /@types/node@20.8.8: - resolution: {integrity: sha512-YRsdVxq6OaLfmR9Hy816IMp33xOBjfyOgUd77ehqg96CFywxAPbDbXvAsuN2KVg2HOT8Eh6uAfU+l4WffwPVrQ==} + /@types/node@18.18.8: + resolution: {integrity: sha512-OLGBaaK5V3VRBS1bAkMVP2/W9B+H8meUfl866OrMNQqt7wDgdpWPp5o6gmIc9pB+lIQHSq4ZL8ypeH1vPxcPaQ==} dependencies: - undici-types: 5.25.3 + undici-types: 5.26.5 + dev: true - /@types/node@20.8.9: - resolution: {integrity: sha512-UzykFsT3FhHb1h7yD4CA4YhBHq545JC0YnEz41xkipN88eKQtL6rSgocL5tbAP6Ola9Izm/Aw4Ora8He4x0BHg==} + /@types/node@20.8.10: + resolution: {integrity: sha512-TlgT8JntpcbmKUFzjhsyhGfP2fsiz1Mv56im6enJ905xG1DAYesxJaeSbGqQmAw8OWPdhyJGhGSQGKRNJ45u9w==} dependencies: undici-types: 5.26.5 - /@types/prop-types@15.7.5: - resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + /@types/prop-types@15.7.9: + resolution: {integrity: sha512-n1yyPsugYNSmHgxDFjicaI2+gCNjsBck8UX9kuofAKlc0h1bL+20oSF72KeNaW2DUlesbEVCFgyV2dPGTiY42g==} /@types/react-dom@18.2.14: resolution: {integrity: sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==} dependencies: - '@types/react': 18.2.33 + '@types/react': 18.2.34 dev: true - /@types/react@18.2.33: - resolution: {integrity: sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==} + /@types/react@18.2.34: + resolution: {integrity: sha512-U6eW/alrRk37FU/MS2RYMjx0Va2JGIVXELTODaTIYgvWGCV4Y4TfTUzG8DdmpDNIT0Xpj/R7GfyHOJJrDttcvg==} dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.3 + '@types/prop-types': 15.7.9 + '@types/scheduler': 0.16.5 csstype: 3.1.2 /@types/resolve@1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: true - /@types/scheduler@0.16.3: - resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + /@types/scheduler@0.16.5: + resolution: {integrity: sha512-s/FPdYRmZR8SjLWGMCuax7r3qCWQw9QKHzXVukAuuIJkXkDRwp+Pu5LMIVFi0Fxbav35WURicYr8u1QsoybnQw==} - /@types/semver@7.5.1: - resolution: {integrity: sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==} + /@types/semver@7.5.4: + resolution: {integrity: sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==} dev: true /@types/sinonjs__fake-timers@8.1.1: resolution: {integrity: sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==} dev: true - /@types/sizzle@2.3.3: - resolution: {integrity: sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==} + /@types/sizzle@2.3.5: + resolution: {integrity: sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ==} dev: true /@types/tar-fs@2.0.3: resolution: {integrity: sha512-ADS99HAnztB8MD+LSOdzDrDLcSe5oBIg+SUQwwsgnsOgZobWoSqYmg9ZJWdvLppoKV8R8kZinX6Om+LlsNuIlQ==} dependencies: - '@types/node': 20.8.8 - '@types/tar-stream': 2.2.2 + '@types/node': 20.8.10 + '@types/tar-stream': 3.1.2 dev: false - /@types/tar-stream@2.2.2: - resolution: {integrity: sha512-1AX+Yt3icFuU6kxwmPakaiGrJUwG44MpuiqPg4dSolRFk6jmvs4b3IbUol9wKDLIgU76gevn3EwE8y/DkSJCZQ==} + /@types/tar-stream@3.1.2: + resolution: {integrity: sha512-qnIpUItVb5u8jl3kbrHofkM40ggO3YKSzc7TWqLYjDdwlrL7CiEAkDySaGfeUBLtC50RTfh2acdz51ItUbV7pQ==} dependencies: - '@types/node': 20.8.9 + '@types/node': 20.8.10 dev: false /@types/uuid@9.0.6: resolution: {integrity: sha512-BT2Krtx4xaO6iwzwMFUYvWBWkV2pr37zD68Vmp1CDV196MzczBRxuEpD6Pr395HAgebC/co7hOphs53r8V7jew==} dev: true - /@types/yauzl@2.10.0: - resolution: {integrity: sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==} + /@types/yauzl@2.10.2: + resolution: {integrity: sha512-Km7XAtUIduROw7QPgvcft0lIupeG8a8rdKL8RiSyKvlE7dYY31fEn41HVuQsRFDuROA8tA4K2UVL+WdfFmErBA==} requiresBuild: true dependencies: - '@types/node': 20.8.9 + '@types/node': 20.8.10 dev: true optional: true @@ -2075,7 +2039,7 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.8.0 + '@eslint-community/regexpp': 4.10.0 '@typescript-eslint/parser': 6.9.1(eslint@8.52.0)(typescript@5.2.2) '@typescript-eslint/scope-manager': 6.9.1 '@typescript-eslint/type-utils': 6.9.1(eslint@8.52.0)(typescript@5.2.2) @@ -2087,7 +2051,7 @@ packages: ignore: 5.2.4 natural-compare: 1.4.0 semver: 7.5.4 - ts-api-utils: 1.0.2(typescript@5.2.2) + ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color @@ -2136,7 +2100,7 @@ packages: '@typescript-eslint/utils': 6.9.1(eslint@8.52.0)(typescript@5.2.2) debug: 4.3.4(supports-color@8.1.1) eslint: 8.52.0 - ts-api-utils: 1.0.2(typescript@5.2.2) + ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color @@ -2162,7 +2126,7 @@ packages: globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 - ts-api-utils: 1.0.2(typescript@5.2.2) + ts-api-utils: 1.0.3(typescript@5.2.2) typescript: 5.2.2 transitivePeerDependencies: - supports-color @@ -2175,8 +2139,8 @@ packages: eslint: ^7.0.0 || ^8.0.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) - '@types/json-schema': 7.0.12 - '@types/semver': 7.5.1 + '@types/json-schema': 7.0.14 + '@types/semver': 7.5.4 '@typescript-eslint/scope-manager': 6.9.1 '@typescript-eslint/types': 6.9.1 '@typescript-eslint/typescript-estree': 6.9.1(typescript@5.2.2) @@ -2205,7 +2169,7 @@ packages: vite: ^4 dependencies: '@swc/core': 1.3.95 - vite: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + vite: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) transitivePeerDependencies: - '@swc/helpers' dev: true @@ -2229,89 +2193,81 @@ packages: /@vitest/snapshot@0.34.6: resolution: {integrity: sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==} dependencies: - magic-string: 0.30.3 + magic-string: 0.30.5 pathe: 1.1.1 - pretty-format: 29.6.3 + pretty-format: 29.7.0 dev: true /@vitest/spy@0.34.6: resolution: {integrity: sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==} dependencies: - tinyspy: 2.1.1 + tinyspy: 2.2.0 dev: true /@vitest/utils@0.34.6: resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==} dependencies: diff-sequences: 29.6.3 - loupe: 2.3.6 - pretty-format: 29.6.3 + loupe: 2.3.7 + pretty-format: 29.7.0 dev: true - /@volar/language-core@1.10.4: - resolution: {integrity: sha512-Na69qA6uwVIdA0rHuOc2W3pHtVQQO8hCNim7FOaKNpRJh0oAFnu5r9i7Oopo5C4cnELZkPNjTrbmpcCTiW+CMQ==} + /@volar/language-core@1.10.10: + resolution: {integrity: sha512-nsV1o3AZ5n5jaEAObrS3MWLBWaGwUj/vAsc15FVNIv+DbpizQRISg9wzygsHBr56ELRH8r4K75vkYNMtsSNNWw==} dependencies: - '@volar/source-map': 1.10.4 + '@volar/source-map': 1.10.10 dev: true - /@volar/source-map@1.10.4: - resolution: {integrity: sha512-RxZdUEL+pV8p+SMqnhVjzy5zpb1QRZTlcwSk4bdcBO7yOu4rtEWqDGahVCEj4CcXour+0yJUMrMczfSCpP9Uxg==} + /@volar/source-map@1.10.10: + resolution: {integrity: sha512-GVKjLnifV4voJ9F0vhP56p4+F3WGf+gXlRtjFZsv6v3WxBTWU3ZVeaRaEHJmWrcv5LXmoYYpk/SC25BKemPRkg==} dependencies: muggle-string: 0.3.1 dev: true - /@volar/typescript@1.10.4: - resolution: {integrity: sha512-BCCUEBASBEMCrz7qmNSi2hBEWYsXD0doaktRKpmmhvb6XntM2sAWYu6gbyK/MluLDgluGLFiFRpWgobgzUqolg==} + /@volar/typescript@1.10.10: + resolution: {integrity: sha512-4a2r5bdUub2m+mYVnLu2wt59fuoYWe7nf0uXtGHU8QQ5LDNfzAR0wK7NgDiQ9rcl2WT3fxT2AA9AylAwFtj50A==} dependencies: - '@volar/language-core': 1.10.4 + '@volar/language-core': 1.10.10 + path-browserify: 1.0.1 dev: true - /@vue/compiler-core@3.3.4: - resolution: {integrity: sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==} + /@vue/compiler-core@3.3.7: + resolution: {integrity: sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==} dependencies: - '@babel/parser': 7.22.13 - '@vue/shared': 3.3.4 + '@babel/parser': 7.23.0 + '@vue/shared': 3.3.7 estree-walker: 2.0.2 source-map-js: 1.0.2 dev: true - /@vue/compiler-dom@3.3.4: - resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} + /@vue/compiler-dom@3.3.7: + resolution: {integrity: sha512-0LwkyJjnUPssXv/d1vNJ0PKfBlDoQs7n81CbO6Q0zdL7H1EzqYRrTVXDqdBVqro0aJjo/FOa1qBAPVI4PGSHBw==} dependencies: - '@vue/compiler-core': 3.3.4 - '@vue/shared': 3.3.4 + '@vue/compiler-core': 3.3.7 + '@vue/shared': 3.3.7 dev: true - /@vue/language-core@1.8.20(typescript@5.2.2): - resolution: {integrity: sha512-vNJaqjCTSrWEr+erSq6Rq0CqDC8MOAwyxirxwK8esOxd+1LmAUJUTG2p7I84Mj1Izy5uHiHQAkRTVR2QxMBY+A==} + /@vue/language-core@1.8.22(typescript@5.2.2): + resolution: {integrity: sha512-bsMoJzCrXZqGsxawtUea1cLjUT9dZnDsy5TuZ+l1fxRMzUGQUG9+Ypq4w//CqpWmrx7nIAJpw2JVF/t258miRw==} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: - '@volar/language-core': 1.10.4 - '@volar/source-map': 1.10.4 - '@vue/compiler-dom': 3.3.4 - '@vue/shared': 3.3.4 + '@volar/language-core': 1.10.10 + '@volar/source-map': 1.10.10 + '@vue/compiler-dom': 3.3.7 + '@vue/shared': 3.3.7 computeds: 0.0.1 minimatch: 9.0.3 muggle-string: 0.3.1 typescript: 5.2.2 - vue-template-compiler: 2.7.14 - dev: true - - /@vue/shared@3.3.4: - resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} + vue-template-compiler: 2.7.15 dev: true - /@vue/typescript@1.8.20(typescript@5.2.2): - resolution: {integrity: sha512-F0XX1wK71Fo9ewtzLSCSo5dfOuwKrSi/dR2AlI00iTJ4Bfk0wq1BNTRgnlvfx4kz/vQovaGXqwpIkif14W9KrA==} - dependencies: - '@volar/typescript': 1.10.4 - '@vue/language-core': 1.8.20(typescript@5.2.2) - transitivePeerDependencies: - - typescript + /@vue/shared@3.3.7: + resolution: {integrity: sha512-N/tbkINRUDExgcPTBvxNkvHGu504k8lzlNQRITVnm6YjOjwa4r0nnbd4Jb01sNpur5hAllyRJzSK5PvB9PPwRg==} dev: true /abab@2.0.6: @@ -2322,21 +2278,21 @@ packages: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} dev: true - /acorn-jsx@5.3.2(acorn@8.10.0): + /acorn-jsx@5.3.2(acorn@8.11.2): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: - acorn: 8.10.0 + acorn: 8.11.2 dev: true - /acorn-walk@8.2.0: - resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} + /acorn-walk@8.3.0: + resolution: {integrity: sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==} engines: {node: '>=0.4.0'} dev: true - /acorn@8.10.0: - resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==} + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} engines: {node: '>=0.4.0'} hasBin: true dev: true @@ -2466,29 +2422,18 @@ packages: /array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 is-array-buffer: 3.0.2 dev: true - /array-includes@3.1.6: - resolution: {integrity: sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 - is-string: 1.0.7 - dev: true - /array-includes@3.1.7: resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 is-string: 1.0.7 dev: true @@ -2501,71 +2446,52 @@ packages: resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 - dev: true - - /array.prototype.flat@1.3.1: - resolution: {integrity: sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 dev: true /array.prototype.flat@1.3.2: resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - dev: true - - /array.prototype.flatmap@1.3.1: - resolution: {integrity: sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 dev: true /array.prototype.flatmap@1.3.2: resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 dev: true - /array.prototype.tosorted@1.1.1: - resolution: {integrity: sha512-pZYPXPRl2PqWcsUs6LOMn+1f1532nEoPTYowBtqLwAW+W8vSVhkIGnmOX1t/UQjD6YGI0vcD2B1U7ZFGQH9jnQ==} + /array.prototype.tosorted@1.1.2: + resolution: {integrity: sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-shim-unscopables: 1.0.0 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 dev: true - /arraybuffer.prototype.slice@1.0.1: - resolution: {integrity: sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==} + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 - call-bind: 1.0.2 - define-properties: 1.2.0 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 dev: true @@ -2634,8 +2560,8 @@ packages: resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} dev: true - /axe-core@4.7.2: - resolution: {integrity: sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==} + /axe-core@4.8.2: + resolution: {integrity: sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==} engines: {node: '>=4'} dev: true @@ -2758,11 +2684,12 @@ packages: engines: {node: '>=6'} dev: true - /call-bind@1.0.2: - resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} dependencies: function-bind: 1.1.2 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 + set-function-length: 1.1.1 dev: true /callsites@3.1.0: @@ -2792,7 +2719,7 @@ packages: check-error: 1.0.3 deep-eql: 4.1.3 get-func-name: 2.0.2 - loupe: 2.3.6 + loupe: 2.3.7 pathval: 1.1.1 type-detect: 4.0.8 dev: true @@ -2853,8 +2780,8 @@ packages: fsevents: 2.3.3 dev: true - /ci-info@3.8.0: - resolution: {integrity: sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==} + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} dev: true @@ -3043,14 +2970,14 @@ packages: /csstype@3.1.2: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} - /cypress-axe@1.5.0(axe-core@4.7.2)(cypress@13.4.0): + /cypress-axe@1.5.0(axe-core@4.8.2)(cypress@13.4.0): resolution: {integrity: sha512-Hy/owCjfj+25KMsecvDgo4fC/781ccL+e8p+UUYoadGVM2ogZF9XIKbiM6KI8Y3cEaSreymdD6ZzccbI2bY0lQ==} engines: {node: '>=10'} peerDependencies: axe-core: ^3 || ^4 cypress: ^10 || ^11 || ^12 || ^13 dependencies: - axe-core: 4.7.2 + axe-core: 4.8.2 cypress: 13.4.0 dev: true @@ -3060,11 +2987,11 @@ packages: hasBin: true requiresBuild: true dependencies: - '@cypress/request': 3.0.0 + '@cypress/request': 3.0.1 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/node': 18.17.15 + '@types/node': 18.18.8 '@types/sinonjs__fake-timers': 8.1.1 - '@types/sizzle': 2.3.3 + '@types/sizzle': 2.3.5 arch: 2.2.0 blob-util: 2.0.2 bluebird: 3.7.2 @@ -3076,7 +3003,7 @@ packages: cli-table3: 0.6.3 commander: 6.2.1 common-tags: 1.8.2 - dayjs: 1.11.9 + dayjs: 1.11.10 debug: 4.3.4(supports-color@8.1.1) enquirer: 2.4.1 eventemitter2: 6.4.7 @@ -3193,8 +3120,8 @@ packages: whatwg-url: 12.0.1 dev: true - /dayjs@1.11.9: - resolution: {integrity: sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA==} + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} dev: true /de-indent@1.0.2: @@ -3246,9 +3173,9 @@ packages: resolution: {integrity: sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==} dependencies: array-buffer-byte-length: 1.0.0 - call-bind: 1.0.2 + call-bind: 1.0.5 es-get-iterator: 1.1.3 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 is-arguments: 1.1.1 is-array-buffer: 3.0.2 is-date-object: 1.0.5 @@ -3258,11 +3185,11 @@ packages: object-is: 1.1.5 object-keys: 1.1.1 object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 + regexp.prototype.flags: 1.5.1 side-channel: 1.0.4 which-boxed-primitive: 1.0.2 which-collection: 1.0.1 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /deep-is@0.1.4: @@ -3292,16 +3219,26 @@ packages: titleize: 3.0.0 dev: true + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + /define-lazy-prop@3.0.0: resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} engines: {node: '>=12'} dev: true - /define-properties@1.2.0: - resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} dependencies: - has-property-descriptors: 1.0.0 + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 object-keys: 1.1.1 dev: true @@ -3426,26 +3363,26 @@ packages: engines: {node: '>=0.12'} dev: true - /es-abstract@1.22.1: - resolution: {integrity: sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==} + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} engines: {node: '>= 0.4'} dependencies: array-buffer-byte-length: 1.0.0 - arraybuffer.prototype.slice: 1.0.1 + arraybuffer.prototype.slice: 1.0.2 available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-set-tostringtag: 2.0.1 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 es-to-primitive: 1.2.1 function.prototype.name: 1.1.6 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 get-symbol-description: 1.0.0 globalthis: 1.0.3 gopd: 1.0.1 - has: 1.0.3 - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.1 has-proto: 1.0.1 has-symbols: 1.0.3 - internal-slot: 1.0.5 + hasown: 2.0.0 + internal-slot: 1.0.6 is-array-buffer: 3.0.2 is-callable: 1.2.7 is-negative-zero: 2.0.2 @@ -3454,28 +3391,28 @@ packages: is-string: 1.0.7 is-typed-array: 1.1.12 is-weakref: 1.0.2 - object-inspect: 1.12.3 + object-inspect: 1.13.1 object-keys: 1.1.1 object.assign: 4.1.4 - regexp.prototype.flags: 1.5.0 - safe-array-concat: 1.0.0 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.0.1 safe-regex-test: 1.0.0 - string.prototype.trim: 1.2.7 - string.prototype.trimend: 1.0.6 - string.prototype.trimstart: 1.0.6 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 typed-array-buffer: 1.0.0 typed-array-byte-length: 1.0.0 typed-array-byte-offset: 1.0.0 typed-array-length: 1.0.4 unbox-primitive: 1.0.2 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /es-get-iterator@1.1.3: resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 is-arguments: 1.1.1 is-map: 2.0.2 @@ -3485,38 +3422,38 @@ packages: stop-iteration-iterator: 1.0.0 dev: true - /es-iterator-helpers@1.0.14: - resolution: {integrity: sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==} + /es-iterator-helpers@1.0.15: + resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} dependencies: asynciterator.prototype: 1.0.0 - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - es-set-tostringtag: 2.0.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-set-tostringtag: 2.0.2 function-bind: 1.1.2 - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 globalthis: 1.0.3 - has-property-descriptors: 1.0.0 + has-property-descriptors: 1.0.1 has-proto: 1.0.1 has-symbols: 1.0.3 - internal-slot: 1.0.5 - iterator.prototype: 1.1.0 - safe-array-concat: 1.0.0 + internal-slot: 1.0.6 + iterator.prototype: 1.1.2 + safe-array-concat: 1.0.1 dev: true - /es-set-tostringtag@2.0.1: - resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 + get-intrinsic: 1.2.2 has-tostringtag: 1.0.0 + hasown: 2.0.0 dev: true - /es-shim-unscopables@1.0.0: - resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} dependencies: - has: 1.0.3 + hasown: 2.0.0 dev: true /es-to-primitive@1.2.1: @@ -3591,7 +3528,7 @@ packages: dependencies: debug: 3.2.7(supports-color@8.1.1) is-core-module: 2.13.1 - resolve: 1.22.4 + resolve: 1.22.8 transitivePeerDependencies: - supports-color dev: true @@ -3609,8 +3546,8 @@ packages: eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) eslint-plugin-import: 2.29.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0) fast-glob: 3.3.1 - get-tsconfig: 4.7.0 - is-core-module: 2.13.0 + get-tsconfig: 4.7.2 + is-core-module: 2.13.1 is-glob: 4.0.3 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -3655,7 +3592,7 @@ packages: eslint: '>= 3.2.1' dependencies: eslint: 8.52.0 - globals: 13.21.0 + globals: 13.23.0 dev: true /eslint-plugin-import@2.29.0(@typescript-eslint/parser@6.9.1)(eslint-import-resolver-typescript@3.6.1)(eslint@8.52.0): @@ -3750,11 +3687,11 @@ packages: peerDependencies: eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 dependencies: - array-includes: 3.1.6 - array.prototype.flatmap: 1.3.1 - array.prototype.tosorted: 1.1.1 + array-includes: 3.1.7 + array.prototype.flatmap: 1.3.2 + array.prototype.tosorted: 1.1.2 doctrine: 2.1.0 - es-iterator-helpers: 1.0.14 + es-iterator-helpers: 1.0.15 eslint: 8.52.0 estraverse: 5.3.0 jsx-ast-utils: 3.3.5 @@ -3764,9 +3701,9 @@ packages: object.hasown: 1.1.3 object.values: 1.1.7 prop-types: 15.8.1 - resolve: 2.0.0-next.4 + resolve: 2.0.0-next.5 semver: 6.3.1 - string.prototype.matchall: 4.0.9 + string.prototype.matchall: 4.0.10 dev: true /eslint-scope@7.2.2: @@ -3803,7 +3740,7 @@ packages: hasBin: true dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.52.0) - '@eslint-community/regexpp': 4.8.0 + '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.2 '@eslint/js': 8.52.0 '@humanwhocodes/config-array': 0.11.13 @@ -3825,7 +3762,7 @@ packages: file-entry-cache: 6.0.1 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.21.0 + globals: 13.23.0 graphemer: 1.4.0 ignore: 5.2.4 imurmurhash: 0.1.4 @@ -3848,8 +3785,8 @@ packages: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: - acorn: 8.10.0 - acorn-jsx: 5.3.2(acorn@8.10.0) + acorn: 8.11.2 + acorn-jsx: 5.3.2(acorn@8.11.2) eslint-visitor-keys: 3.4.3 dev: true @@ -3969,7 +3906,7 @@ packages: get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: - '@types/yauzl': 2.10.0 + '@types/yauzl': 2.10.2 transitivePeerDependencies: - supports-color dev: true @@ -4038,7 +3975,7 @@ packages: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: - flat-cache: 3.1.0 + flat-cache: 3.1.1 dev: true /file-saver@2.0.5: @@ -4074,12 +4011,12 @@ packages: path-exists: 4.0.0 dev: true - /flat-cache@3.1.0: - resolution: {integrity: sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==} + /flat-cache@3.1.1: + resolution: {integrity: sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==} engines: {node: '>=12.0.0'} dependencies: - flatted: 3.2.7 - keyv: 4.5.3 + flatted: 3.2.9 + keyv: 4.5.4 rimraf: 3.0.2 dev: true @@ -4094,8 +4031,8 @@ packages: hasBin: true dev: false - /flatted@3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true /focus-trap@6.9.2: @@ -4138,7 +4075,7 @@ packages: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 - universalify: 2.0.0 + universalify: 2.0.1 dev: true /fs-extra@7.0.1: @@ -4157,7 +4094,7 @@ packages: at-least-node: 1.0.0 graceful-fs: 4.2.11 jsonfile: 6.1.0 - universalify: 2.0.0 + universalify: 2.0.1 dev: true /fs.realpath@1.0.0: @@ -4188,9 +4125,9 @@ packages: resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 functions-have-names: 1.2.3 dev: true @@ -4207,13 +4144,13 @@ packages: resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} dev: true - /get-intrinsic@1.2.1: - resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} dependencies: function-bind: 1.1.2 - has: 1.0.3 has-proto: 1.0.1 has-symbols: 1.0.3 + hasown: 2.0.0 dev: true /get-stream@5.2.0: @@ -4237,12 +4174,12 @@ packages: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 dev: true - /get-tsconfig@4.7.0: - resolution: {integrity: sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==} + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} dependencies: resolve-pkg-maps: 1.0.0 dev: true @@ -4313,8 +4250,8 @@ packages: ini: 2.0.0 dev: true - /globals@13.21.0: - resolution: {integrity: sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==} + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 @@ -4324,7 +4261,7 @@ packages: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} dependencies: - define-properties: 1.2.0 + define-properties: 1.2.1 dev: true /globby@11.1.0: @@ -4342,7 +4279,7 @@ packages: /gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 dev: true /graceful-fs@4.2.11: @@ -4385,10 +4322,10 @@ packages: engines: {node: '>=8'} dev: true - /has-property-descriptors@1.0.0: - resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} dependencies: - get-intrinsic: 1.2.1 + get-intrinsic: 1.2.2 dev: true /has-proto@1.0.1: @@ -4408,13 +4345,6 @@ packages: has-symbols: 1.0.3 dev: true - /has@1.0.3: - resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} - engines: {node: '>= 0.4.0'} - dependencies: - function-bind: 1.1.2 - dev: true - /hasown@2.0.0: resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} engines: {node: '>= 0.4'} @@ -4457,7 +4387,7 @@ packages: dependencies: assert-plus: 1.0.0 jsprim: 2.0.2 - sshpk: 1.17.0 + sshpk: 1.18.0 dev: true /https-proxy-agent@5.0.1: @@ -4507,7 +4437,7 @@ packages: /i18next@23.6.0: resolution: {integrity: sha512-z0Cxr0MGkt+kli306WS4nNNM++9cgt2b2VCMprY92j+AIab/oclgPxdwtTZVLP1zn5t5uo8M6uLsZmYrcjr3HA==} dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.23.2 dev: false /iconv-lite@0.6.3: @@ -4564,12 +4494,12 @@ packages: engines: {node: '>=10'} dev: true - /internal-slot@1.0.5: - resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.2.1 - has: 1.0.3 + get-intrinsic: 1.2.2 + hasown: 2.0.0 side-channel: 1.0.4 dev: true @@ -4577,15 +4507,15 @@ packages: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-tostringtag: 1.0.0 dev: true /is-array-buffer@3.0.2: resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 is-typed-array: 1.1.12 dev: true @@ -4613,7 +4543,7 @@ packages: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-tostringtag: 1.0.0 dev: true @@ -4633,13 +4563,7 @@ packages: resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==} hasBin: true dependencies: - ci-info: 3.8.0 - dev: true - - /is-core-module@2.13.0: - resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} - dependencies: - has: 1.0.3 + ci-info: 3.9.0 dev: true /is-core-module@2.13.1: @@ -4679,7 +4603,7 @@ packages: /is-finalizationregistry@1.0.2: resolution: {integrity: sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 dev: true /is-fullwidth-code-point@3.0.0: @@ -4774,14 +4698,14 @@ packages: /is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: - '@types/estree': 1.0.1 + '@types/estree': 1.0.4 dev: true /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-tostringtag: 1.0.0 dev: true @@ -4792,7 +4716,7 @@ packages: /is-shared-array-buffer@1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 dev: true /is-stream@2.0.1: @@ -4823,7 +4747,7 @@ packages: resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} engines: {node: '>= 0.4'} dependencies: - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /is-typedarray@1.0.0: @@ -4842,14 +4766,14 @@ packages: /is-weakref@1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 dev: true /is-weakset@2.0.2: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 dev: true /is-wsl@2.2.0: @@ -4875,14 +4799,14 @@ packages: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} dev: true - /iterator.prototype@1.1.0: - resolution: {integrity: sha512-rjuhAk1AJ1fssphHD0IFV6TWL40CwRZ53FrztKx43yk2v6rguBYsY4Bj1VU4HmoMmKwZUlx7mfnhDf9cOp4YTw==} + /iterator.prototype@1.1.2: + resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} dependencies: - define-properties: 1.2.0 - get-intrinsic: 1.2.1 + define-properties: 1.2.1 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 - has-tostringtag: 1.0.0 - reflect.getprototypeof: 1.0.3 + reflect.getprototypeof: 1.0.4 + set-function-name: 2.0.1 dev: true /jju@1.4.0: @@ -4937,7 +4861,7 @@ packages: whatwg-encoding: 2.0.0 whatwg-mimetype: 3.0.0 whatwg-url: 12.0.1 - ws: 8.13.0 + ws: 8.14.2 xml-name-validator: 4.0.0 transitivePeerDependencies: - bufferutil @@ -4985,7 +4909,7 @@ packages: /jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: - universalify: 2.0.0 + universalify: 2.0.1 optionalDependencies: graceful-fs: 4.2.11 dev: true @@ -5004,8 +4928,8 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} dependencies: - array-includes: 3.1.6 - array.prototype.flat: 1.3.1 + array-includes: 3.1.7 + array.prototype.flat: 1.3.2 object.assign: 4.1.4 object.values: 1.1.7 dev: true @@ -5015,8 +4939,8 @@ packages: engines: {node: '>=18'} dev: false - /keyv@4.5.3: - resolution: {integrity: sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==} + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: json-buffer: 3.0.1 dev: true @@ -5300,8 +5224,8 @@ packages: dependencies: js-tokens: 4.0.0 - /loupe@2.3.6: - resolution: {integrity: sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==} + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} dependencies: get-func-name: 2.0.2 dev: true @@ -5318,8 +5242,8 @@ packages: hasBin: true dev: true - /magic-string@0.30.3: - resolution: {integrity: sha512-B7xGbll2fG/VjP+SWg4sX3JynwIU0mjoTc6MPpKNuIvftk6u6vqhDnk1R80b8C2GBR6ywqy+1DcKBrevBg+bmw==} + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} engines: {node: '>=12'} dependencies: '@jridgewell/sourcemap-codec': 1.4.15 @@ -5408,13 +5332,13 @@ packages: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} dev: false - /mlly@1.4.1: - resolution: {integrity: sha512-SCDs78Q2o09jiZiE2WziwVBEqXQ02XkGdUy45cbJf+BpYRIjArXRJ1Wbowxkb+NaM9DWvS3UC9GiO/6eqvQ/pg==} + /mlly@1.4.2: + resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} dependencies: - acorn: 8.10.0 + acorn: 8.11.2 pathe: 1.1.1 pkg-types: 1.0.3 - ufo: 1.3.0 + ufo: 1.3.1 dev: true /mocha@10.2.0: @@ -5516,16 +5440,16 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} - /object-inspect@1.12.3: - resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} dev: true /object-is@1.1.5: resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 + call-bind: 1.0.5 + define-properties: 1.2.1 dev: true /object-keys@1.1.1: @@ -5537,8 +5461,8 @@ packages: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 + call-bind: 1.0.5 + define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 dev: true @@ -5547,43 +5471,43 @@ packages: resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true /object.fromentries@2.0.7: resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true /object.groupby@1.0.1: resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 dev: true /object.hasown@1.1.3: resolution: {integrity: sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==} dependencies: - define-properties: 1.2.0 - es-abstract: 1.22.1 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true /object.values@1.1.7: resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true /once@1.4.0: @@ -5676,6 +5600,10 @@ packages: entities: 4.5.0 dev: true + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: true + /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} @@ -5753,7 +5681,7 @@ packages: resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} dependencies: jsonc-parser: 3.2.0 - mlly: 1.4.1 + mlly: 1.4.2 pathe: 1.1.1 dev: true @@ -5778,8 +5706,8 @@ packages: deprecated: You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1 dev: false - /postcss@8.4.28: - resolution: {integrity: sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==} + /postcss@8.4.31: + resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} dependencies: nanoid: 3.3.6 @@ -5824,8 +5752,8 @@ packages: react-is: 17.0.2 dev: true - /pretty-format@29.6.3: - resolution: {integrity: sha512-ZsBgjVhFAj5KeK+nHfF1305/By3lechHQSMWCTl8iHSbfOm2TN5nHEtFc/+W7fAyUeCs2n5iow72gld4gW0xDw==} + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: '@jest/schemas': 29.6.3 @@ -5896,8 +5824,8 @@ packages: pump: 2.0.1 dev: false - /punycode@2.3.0: - resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} dev: true @@ -5970,7 +5898,7 @@ packages: peerDependencies: react: '>=16.13.1' dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.23.2 react: 18.2.0 dev: false @@ -5996,7 +5924,7 @@ packages: react-native: optional: true dependencies: - '@babel/runtime': 7.22.11 + '@babel/runtime': 7.23.2 html-parse-stringify: 3.0.1 i18next: 23.6.0 react: 18.2.0 @@ -6014,39 +5942,39 @@ packages: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} dev: true - /react-monaco-editor@0.51.0(@types/react@18.2.33)(monaco-editor@0.44.0)(react@18.2.0): + /react-monaco-editor@0.51.0(@types/react@18.2.34)(monaco-editor@0.44.0)(react@18.2.0): resolution: {integrity: sha512-6jx1V8p6gHVKJHFaTvicOtmlhFjOJhekobeNd92ZAo7F5UvAin1cF7bxWLCKgtxClYZ7CB3Ar284Kpbhj22FpQ==} peerDependencies: '@types/react': '>=17 <= 18' monaco-editor: ^0.34.1 react: '>=17 <= 18' dependencies: - '@types/react': 18.2.33 + '@types/react': 18.2.34 monaco-editor: 0.44.0 prop-types: 15.8.1 react: 18.2.0 dev: false - /react-router-dom@6.15.0(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-aR42t0fs7brintwBGAv2+mGlCtgtFQeOzK0BM1/OiqEzRejOZtpMZepvgkscpMUnKb8YO84G7s3LsHnnDNonbQ==} + /react-router-dom@6.18.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-Ubrue4+Ercc/BoDkFQfc6og5zRQ4A8YxSO3Knsne+eRbZ+IepAsK249XBH/XaFuOYOYr3L3r13CXTLvYt5JDjw==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' react-dom: '>=16.8' dependencies: - '@remix-run/router': 1.8.0 + '@remix-run/router': 1.11.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) - react-router: 6.15.0(react@18.2.0) + react-router: 6.18.0(react@18.2.0) dev: false - /react-router@6.15.0(react@18.2.0): - resolution: {integrity: sha512-NIytlzvzLwJkCQj2HLefmeakxxWHWAP+02EGqWEZy+DgfHHKQMUoBBjUQLOtFInBMhWtb3hiUy6MfFgwLjXhqg==} + /react-router@6.18.0(react@18.2.0): + resolution: {integrity: sha512-vk2y7Dsy8wI02eRRaRmOs9g2o+aE72YCx5q9VasT1N9v+lrdB79tIqrjMfByHiY5+6aYkH2rUa5X839nwWGPDg==} engines: {node: '>=14.0.0'} peerDependencies: react: '>=16.8' dependencies: - '@remix-run/router': 1.8.0 + '@remix-run/router': 1.11.0 react: 18.2.0 dev: false @@ -6056,18 +5984,18 @@ packages: dependencies: loose-envify: 1.4.0 - /reactflow@11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0): + /reactflow@11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-IHAKBkJngNvU9y1vZ5Nw9rvA3Z+zc9geTgQQIi9qq9Y9knGLlDDr9KfsjbFMew9AycAAgVg8TvBEakF4IT5lqg==} peerDependencies: react: '>=17' react-dom: '>=17' dependencies: - '@reactflow/background': 11.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@reactflow/controls': 11.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@reactflow/core': 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@reactflow/minimap': 11.7.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@reactflow/node-resizer': 2.2.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) - '@reactflow/node-toolbar': 1.3.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/background': 11.3.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/controls': 11.2.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/core': 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/minimap': 11.7.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/node-resizer': 2.2.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) + '@reactflow/node-toolbar': 1.3.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) react: 18.2.0 react-dom: 18.2.0(react@18.2.0) transitivePeerDependencies: @@ -6102,14 +6030,14 @@ packages: strip-indent: 3.0.0 dev: true - /reflect.getprototypeof@1.0.3: - resolution: {integrity: sha512-TTAOZpkJ2YLxl7mVHWrNo3iDMEkYlva/kgFcXndqMgbo/AZUmmavEkdXV+hXtE4P8xdyEKRzalaFqZVuwIk/Nw==} + /reflect.getprototypeof@1.0.4: + resolution: {integrity: sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 globalthis: 1.0.3 which-builtin-type: 1.1.3 dev: true @@ -6117,13 +6045,13 @@ packages: /regenerator-runtime@0.14.0: resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==} - /regexp.prototype.flags@1.5.0: - resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - functions-have-names: 1.2.3 + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 dev: true /request-progress@3.0.0: @@ -6157,8 +6085,8 @@ packages: path-parse: 1.0.7 dev: true - /resolve@1.22.4: - resolution: {integrity: sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==} + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true dependencies: is-core-module: 2.13.1 @@ -6166,8 +6094,8 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true - /resolve@2.0.0-next.4: - resolution: {integrity: sha512-iMDbmAWtfU+MHpxt/I5iWI7cY6YVEZUQ3MBgPQ++XD1PELuJHIl82xBmObyP2KyQmkNB2dsqF7seoQQiAn5yDQ==} + /resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} hasBin: true dependencies: is-core-module: 2.13.1 @@ -6212,12 +6140,12 @@ packages: glob: 7.2.3 dev: true - /rollup-plugin-peer-deps-external@2.2.4(rollup@4.1.5): + /rollup-plugin-peer-deps-external@2.2.4(rollup@4.2.0): resolution: {integrity: sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g==} peerDependencies: rollup: '*' dependencies: - rollup: 4.1.5 + rollup: 4.2.0 dev: true /rollup@3.29.4: @@ -6228,23 +6156,23 @@ packages: fsevents: 2.3.3 dev: true - /rollup@4.1.5: - resolution: {integrity: sha512-AEw14/q4NHYQkQlngoSae2yi7hDBeT9w84aEzdgCr39+2RL+iTG84lGTkgC1Wp5igtquN64cNzuzZKVz+U6jOg==} + /rollup@4.2.0: + resolution: {integrity: sha512-deaMa9Z+jPVeBD2dKXv+h7EbdKte9++V2potc/ADqvVgEr6DEJ3ia9u0joarjC2lX/ubaCRYz3QVx0TzuVqAJA==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.1.5 - '@rollup/rollup-android-arm64': 4.1.5 - '@rollup/rollup-darwin-arm64': 4.1.5 - '@rollup/rollup-darwin-x64': 4.1.5 - '@rollup/rollup-linux-arm-gnueabihf': 4.1.5 - '@rollup/rollup-linux-arm64-gnu': 4.1.5 - '@rollup/rollup-linux-arm64-musl': 4.1.5 - '@rollup/rollup-linux-x64-gnu': 4.1.5 - '@rollup/rollup-linux-x64-musl': 4.1.5 - '@rollup/rollup-win32-arm64-msvc': 4.1.5 - '@rollup/rollup-win32-ia32-msvc': 4.1.5 - '@rollup/rollup-win32-x64-msvc': 4.1.5 + '@rollup/rollup-android-arm-eabi': 4.2.0 + '@rollup/rollup-android-arm64': 4.2.0 + '@rollup/rollup-darwin-arm64': 4.2.0 + '@rollup/rollup-darwin-x64': 4.2.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.2.0 + '@rollup/rollup-linux-arm64-gnu': 4.2.0 + '@rollup/rollup-linux-arm64-musl': 4.2.0 + '@rollup/rollup-linux-x64-gnu': 4.2.0 + '@rollup/rollup-linux-x64-musl': 4.2.0 + '@rollup/rollup-win32-arm64-msvc': 4.2.0 + '@rollup/rollup-win32-ia32-msvc': 4.2.0 + '@rollup/rollup-win32-x64-msvc': 4.2.0 fsevents: 2.3.3 dev: true @@ -6271,12 +6199,12 @@ packages: tslib: 2.6.2 dev: true - /safe-array-concat@1.0.0: - resolution: {integrity: sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==} + /safe-array-concat@1.0.1: + resolution: {integrity: sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==} engines: {node: '>=0.4'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 isarray: 2.0.5 dev: true @@ -6292,8 +6220,8 @@ packages: /safe-regex-test@1.0.0: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 is-regex: 1.1.4 dev: true @@ -6338,6 +6266,25 @@ packages: randombytes: 2.1.0 dev: true + /set-function-length@1.1.1: + resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -6353,9 +6300,9 @@ packages: /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 - object-inspect: 1.12.3 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 dev: true /siginfo@2.0.0: @@ -6402,8 +6349,8 @@ packages: is-fullwidth-code-point: 4.0.0 dev: true - /smob@1.4.0: - resolution: {integrity: sha512-MqR3fVulhjWuRNSMydnTlweu38UhQ0HXM4buStD/S3mc/BzX3CuM9OmhyQpmtYCvoYdl5ris6TI0ZqH355Ymqg==} + /smob@1.4.1: + resolution: {integrity: sha512-9LK+E7Hv5R9u4g4C3p+jjLstaLe11MDsL21UpYaCNmapvMkYhqCV4A/f/3gyH8QjMyh6l68q9xC85vihY9ahMQ==} dev: true /source-map-js@1.0.2: @@ -6427,8 +6374,8 @@ packages: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} dev: true - /sshpk@1.17.0: - resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + /sshpk@1.18.0: + resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} hasBin: true dependencies: @@ -6455,15 +6402,15 @@ packages: resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} engines: {node: '>= 0.4'} dependencies: - internal-slot: 1.0.5 + internal-slot: 1.0.6 dev: true /stream-shift@1.0.1: resolution: {integrity: sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==} dev: false - /streamx@2.15.1: - resolution: {integrity: sha512-fQMzy2O/Q47rgwErk/eGeLu/roaFWV0jVsogDmrszM9uIw8L5OA+t+V93MgYlufNptfjmYR1tOMWhei/Eh7TQA==} + /streamx@2.15.2: + resolution: {integrity: sha512-b62pAV/aeMjUoRN2C/9F0n+G8AfcJjNC0zw/ZmOHeFsIe4m4GzjVW9m6VHXVjk536NbdU9JRwKMJRfkc+zUFTg==} dependencies: fast-fifo: 1.3.2 queue-tick: 1.0.1 @@ -6492,42 +6439,43 @@ packages: strip-ansi: 7.1.0 dev: true - /string.prototype.matchall@4.0.9: - resolution: {integrity: sha512-6i5hL3MqG/K2G43mWXWgP+qizFW/QH/7kCNN13JrJS5q48FN5IKksLDscexKP3dnmB6cdm9jlNgAsWNLpSykmA==} + /string.prototype.matchall@4.0.10: + resolution: {integrity: sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 has-symbols: 1.0.3 - internal-slot: 1.0.5 - regexp.prototype.flags: 1.5.0 + internal-slot: 1.0.6 + regexp.prototype.flags: 1.5.1 + set-function-name: 2.0.1 side-channel: 1.0.4 dev: true - /string.prototype.trim@1.2.7: - resolution: {integrity: sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==} + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true - /string.prototype.trimend@1.0.6: - resolution: {integrity: sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==} + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true - /string.prototype.trimstart@1.0.6: - resolution: {integrity: sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==} + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} dependencies: - call-bind: 1.0.2 - define-properties: 1.2.0 - es-abstract: 1.22.1 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 dev: true /string_decoder@1.1.1: @@ -6580,7 +6528,7 @@ packages: /strip-literal@1.3.0: resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} dependencies: - acorn: 8.10.0 + acorn: 8.11.2 dev: true /supports-color@5.5.0: @@ -6643,16 +6591,16 @@ packages: dependencies: b4a: 1.6.4 fast-fifo: 1.3.2 - streamx: 2.15.1 + streamx: 2.15.2 dev: false - /terser@5.19.2: - resolution: {integrity: sha512-qC5+dmecKJA4cpYxRa5aVkKehYsQKc+AHeKl0Oe62aYjBL8ZA33tTljktDHJSaxxMnbI5ZYw+o/S2DxxLu8OfA==} + /terser@5.24.0: + resolution: {integrity: sha512-ZpGR4Hy3+wBEzVEnHvstMvqpD/nABNelQn/z2r0fjVWGQsN3bpOLzQlqDxmb4CDZnXq5lpjnQ+mHQLAOpfM5iw==} engines: {node: '>=10'} hasBin: true dependencies: '@jridgewell/source-map': 0.3.5 - acorn: 8.10.0 + acorn: 8.11.2 commander: 2.20.3 source-map-support: 0.5.21 dev: true @@ -6680,8 +6628,8 @@ packages: resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} dev: true - /tinybench@2.5.0: - resolution: {integrity: sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==} + /tinybench@2.5.1: + resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} dev: true /tinypool@0.7.0: @@ -6689,8 +6637,8 @@ packages: engines: {node: '>=14.0.0'} dev: true - /tinyspy@2.1.1: - resolution: {integrity: sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==} + /tinyspy@2.2.0: + resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} engines: {node: '>=14.0.0'} dev: true @@ -6729,7 +6677,7 @@ packages: engines: {node: '>=6'} dependencies: psl: 1.9.0 - punycode: 2.3.0 + punycode: 2.3.1 universalify: 0.2.0 url-parse: 1.5.10 dev: true @@ -6742,11 +6690,11 @@ packages: resolution: {integrity: sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==} engines: {node: '>=14'} dependencies: - punycode: 2.3.0 + punycode: 2.3.1 dev: true - /ts-api-utils@1.0.2(typescript@5.2.2): - resolution: {integrity: sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==} + /ts-api-utils@1.0.3(typescript@5.2.2): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} engines: {node: '>=16.13.0'} peerDependencies: typescript: '>=4.2.0' @@ -6754,7 +6702,7 @@ packages: typescript: 5.2.2 dev: true - /ts-node@10.9.1(@types/node@20.8.9)(typescript@5.2.2): + /ts-node@10.9.1(@types/node@20.8.10)(typescript@5.2.2): resolution: {integrity: sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==} hasBin: true peerDependencies: @@ -6773,9 +6721,9 @@ packages: '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.8.9 - acorn: 8.10.0 - acorn-walk: 8.2.0 + '@types/node': 20.8.10 + acorn: 8.11.2 + acorn-walk: 8.3.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 @@ -6838,8 +6786,8 @@ packages: resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 - get-intrinsic: 1.2.1 + call-bind: 1.0.5 + get-intrinsic: 1.2.2 is-typed-array: 1.1.12 dev: true @@ -6847,7 +6795,7 @@ packages: resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} engines: {node: '>= 0.4'} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 @@ -6858,7 +6806,7 @@ packages: engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 @@ -6867,7 +6815,7 @@ packages: /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 is-typed-array: 1.1.12 dev: true @@ -6884,22 +6832,19 @@ packages: hasBin: true dev: true - /ufo@1.3.0: - resolution: {integrity: sha512-bRn3CsoojyNStCZe0BG0Mt4Nr/4KF+rhFlnNXybgqt5pXHNFRlqinSoQaTrGyzE4X8aHplSb+TorH+COin9Yxw==} + /ufo@1.3.1: + resolution: {integrity: sha512-uY/99gMLIOlJPwATcMVYfqDSxUR9//AUcgZMzwfSTJPDKzA1S8mX4VLqa+fiAtveraQUBCz4FFcwVZBGbwBXIw==} dev: true /unbox-primitive@1.0.2: resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} dependencies: - call-bind: 1.0.2 + call-bind: 1.0.5 has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 dev: true - /undici-types@5.25.3: - resolution: {integrity: sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA==} - /undici-types@5.26.5: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} @@ -6917,8 +6862,8 @@ packages: engines: {node: '>= 4.0.0'} dev: true - /universalify@2.0.0: - resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} dev: true @@ -6930,7 +6875,7 @@ packages: /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: - punycode: 2.3.0 + punycode: 2.3.1 dev: true /url-join@5.0.0: @@ -6950,14 +6895,14 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false - /use-react-router-breadcrumbs@4.0.1(react-router-dom@6.15.0)(react@18.2.0): + /use-react-router-breadcrumbs@4.0.1(react-router-dom@6.18.0)(react@18.2.0): resolution: {integrity: sha512-Zbcy0KvWt1JePFcUHJAnTr7Z+AeO9WxmPs6A5Q/xqOVoi8edPKzpqHF87WB2opXwie/QjCxrEyTB7kFg7fgXvQ==} peerDependencies: react: '>=16.8' react-router-dom: '>=6.0.0' dependencies: react: 18.2.0 - react-router-dom: 6.15.0(react-dom@18.2.0)(react@18.2.0) + react-router-dom: 6.18.0(react-dom@18.2.0)(react@18.2.0) dev: false /use-sync-external-store@1.2.0(react@18.2.0): @@ -7016,39 +6961,17 @@ packages: extsprintf: 1.4.1 dev: true - /vite-node@0.34.6(@types/node@20.8.8)(lightningcss@1.22.0): + /vite-node@0.34.6(@types/node@20.8.10)(lightningcss@1.22.0): resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==} engines: {node: '>=v14.18.0'} hasBin: true dependencies: cac: 6.7.14 debug: 4.3.4(supports-color@8.1.1) - mlly: 1.4.1 + mlly: 1.4.2 pathe: 1.1.1 picocolors: 1.0.0 - vite: 4.5.0(@types/node@20.8.8)(lightningcss@1.22.0) - transitivePeerDependencies: - - '@types/node' - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - - /vite-node@0.34.6(@types/node@20.8.9): - resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==} - engines: {node: '>=v14.18.0'} - hasBin: true - dependencies: - cac: 6.7.14 - debug: 4.3.4(supports-color@8.1.1) - mlly: 1.4.1 - pathe: 1.1.1 - picocolors: 1.0.0 - vite: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + vite: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) transitivePeerDependencies: - '@types/node' - less @@ -7106,14 +7029,14 @@ packages: strip-ansi: 6.0.1 tiny-invariant: 1.3.1 typescript: 5.2.2 - vite: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) + vite: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) vscode-languageclient: 7.0.0 vscode-languageserver: 7.0.0 - vscode-languageserver-textdocument: 1.0.8 - vscode-uri: 3.0.7 + vscode-languageserver-textdocument: 1.0.11 + vscode-uri: 3.0.8 dev: true - /vite-plugin-dts@3.6.3(@types/node@20.8.9)(rollup@4.1.5)(typescript@5.2.2)(vite@4.5.0): + /vite-plugin-dts@3.6.3(@types/node@20.8.10)(rollup@4.2.0)(typescript@5.2.2)(vite@4.5.0): resolution: {integrity: sha512-NyRvgobl15rYj65coi/gH7UAEH+CpSjh539DbGb40DfOTZSvDLNYTzc8CK4460W+LqXuMK7+U3JAxRB3ksrNPw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -7123,58 +7046,21 @@ packages: vite: optional: true dependencies: - '@microsoft/api-extractor': 7.38.0(@types/node@20.8.9) - '@rollup/pluginutils': 5.0.5(rollup@4.1.5) - '@vue/language-core': 1.8.20(typescript@5.2.2) + '@microsoft/api-extractor': 7.38.2(@types/node@20.8.10) + '@rollup/pluginutils': 5.0.5(rollup@4.2.0) + '@vue/language-core': 1.8.22(typescript@5.2.2) debug: 4.3.4(supports-color@8.1.1) kolorist: 1.8.0 typescript: 5.2.2 - vite: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) - vue-tsc: 1.8.20(typescript@5.2.2) + vite: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) + vue-tsc: 1.8.22(typescript@5.2.2) transitivePeerDependencies: - '@types/node' - rollup - supports-color dev: true - /vite@4.5.0(@types/node@20.8.8)(lightningcss@1.22.0): - resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} - engines: {node: ^14.18.0 || >=16.0.0} - hasBin: true - peerDependencies: - '@types/node': '>= 14' - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - dependencies: - '@types/node': 20.8.8 - esbuild: 0.18.20 - lightningcss: 1.22.0 - postcss: 8.4.28 - rollup: 3.29.4 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /vite@4.5.0(@types/node@20.8.9)(lightningcss@1.22.0): + /vite@4.5.0(@types/node@20.8.10)(lightningcss@1.22.0): resolution: {integrity: sha512-ulr8rNLA6rkyFAlVWw2q5YJ91v098AFQ2R0PRFwPzREXOUJQPtFUG0t+/ZikhaOCDqFoDhN6/v8Sq0o4araFAw==} engines: {node: ^14.18.0 || >=16.0.0} hasBin: true @@ -7202,80 +7088,15 @@ packages: terser: optional: true dependencies: - '@types/node': 20.8.9 + '@types/node': 20.8.10 esbuild: 0.18.20 lightningcss: 1.22.0 - postcss: 8.4.28 + postcss: 8.4.31 rollup: 3.29.4 optionalDependencies: fsevents: 2.3.3 dev: true - /vitest@0.34.6: - resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} - engines: {node: '>=v14.18.0'} - hasBin: true - peerDependencies: - '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' - happy-dom: '*' - jsdom: '*' - playwright: '*' - safaridriver: '*' - webdriverio: '*' - peerDependenciesMeta: - '@edge-runtime/vm': - optional: true - '@vitest/browser': - optional: true - '@vitest/ui': - optional: true - happy-dom: - optional: true - jsdom: - optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true - dependencies: - '@types/chai': 4.3.9 - '@types/chai-subset': 1.3.3 - '@types/node': 20.8.9 - '@vitest/expect': 0.34.6 - '@vitest/runner': 0.34.6 - '@vitest/snapshot': 0.34.6 - '@vitest/spy': 0.34.6 - '@vitest/utils': 0.34.6 - acorn: 8.10.0 - acorn-walk: 8.2.0 - cac: 6.7.14 - chai: 4.3.10 - debug: 4.3.4(supports-color@8.1.1) - local-pkg: 0.4.3 - magic-string: 0.30.3 - pathe: 1.1.1 - picocolors: 1.0.0 - std-env: 3.4.3 - strip-literal: 1.3.0 - tinybench: 2.5.0 - tinypool: 0.7.0 - vite: 4.5.0(@types/node@20.8.9)(lightningcss@1.22.0) - vite-node: 0.34.6(@types/node@20.8.9) - why-is-node-running: 2.2.2 - transitivePeerDependencies: - - less - - lightningcss - - sass - - stylus - - sugarss - - supports-color - - terser - dev: true - /vitest@0.34.6(jsdom@22.1.0)(lightningcss@1.22.0): resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} @@ -7307,30 +7128,30 @@ packages: webdriverio: optional: true dependencies: - '@types/chai': 4.3.8 - '@types/chai-subset': 1.3.3 - '@types/node': 20.8.8 + '@types/chai': 4.3.9 + '@types/chai-subset': 1.3.4 + '@types/node': 20.8.10 '@vitest/expect': 0.34.6 '@vitest/runner': 0.34.6 '@vitest/snapshot': 0.34.6 '@vitest/spy': 0.34.6 '@vitest/utils': 0.34.6 - acorn: 8.10.0 - acorn-walk: 8.2.0 + acorn: 8.11.2 + acorn-walk: 8.3.0 cac: 6.7.14 chai: 4.3.10 debug: 4.3.4(supports-color@8.1.1) jsdom: 22.1.0 local-pkg: 0.4.3 - magic-string: 0.30.3 + magic-string: 0.30.5 pathe: 1.1.1 picocolors: 1.0.0 std-env: 3.4.3 strip-literal: 1.3.0 - tinybench: 2.5.0 + tinybench: 2.5.1 tinypool: 0.7.0 - vite: 4.5.0(@types/node@20.8.8)(lightningcss@1.22.0) - vite-node: 0.34.6(@types/node@20.8.8)(lightningcss@1.22.0) + vite: 4.5.0(@types/node@20.8.10)(lightningcss@1.22.0) + vite-node: 0.34.6(@types/node@20.8.10)(lightningcss@1.22.0) why-is-node-running: 2.2.2 transitivePeerDependencies: - less @@ -7368,8 +7189,8 @@ packages: vscode-languageserver-types: 3.16.0 dev: true - /vscode-languageserver-textdocument@1.0.8: - resolution: {integrity: sha512-1bonkGqQs5/fxGT5UchTgjGVnfysL0O8v1AYMBjqTbWQTFn721zaPGDYFkOKtfDgFiSgXM3KwaG3FMGfW4Ed9Q==} + /vscode-languageserver-textdocument@1.0.11: + resolution: {integrity: sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA==} dev: true /vscode-languageserver-types@3.16.0: @@ -7383,25 +7204,25 @@ packages: vscode-languageserver-protocol: 3.16.0 dev: true - /vscode-uri@3.0.7: - resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==} + /vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} dev: true - /vue-template-compiler@2.7.14: - resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} + /vue-template-compiler@2.7.15: + resolution: {integrity: sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==} dependencies: de-indent: 1.0.2 he: 1.2.0 dev: true - /vue-tsc@1.8.20(typescript@5.2.2): - resolution: {integrity: sha512-bIADlyxJl+1ZWQQHAi47NZoi2iTiw/lBwQLL98wXROcQlUuGVtyroAIiqvto9pJotcyhtU0JbGvsHN6JN0fYfg==} + /vue-tsc@1.8.22(typescript@5.2.2): + resolution: {integrity: sha512-j9P4kHtW6eEE08aS5McFZE/ivmipXy0JzrnTgbomfABMaVKx37kNBw//irL3+LlE3kOo63XpnRigyPC3w7+z+A==} hasBin: true peerDependencies: typescript: '*' dependencies: - '@vue/language-core': 1.8.20(typescript@5.2.2) - '@vue/typescript': 1.8.20(typescript@5.2.2) + '@volar/typescript': 1.10.10 + '@vue/language-core': 1.8.22(typescript@5.2.2) semver: 7.5.4 typescript: 5.2.2 dev: true @@ -7480,7 +7301,7 @@ packages: isarray: 2.0.5 which-boxed-primitive: 1.0.2 which-collection: 1.0.1 - which-typed-array: 1.1.11 + which-typed-array: 1.1.13 dev: true /which-collection@1.0.1: @@ -7492,12 +7313,12 @@ packages: is-weakset: 2.0.2 dev: true - /which-typed-array@1.1.11: - resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 - call-bind: 1.0.2 + call-bind: 1.0.5 for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 @@ -7566,8 +7387,8 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - /ws@8.13.0: - resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==} + /ws@8.14.2: + resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -7669,8 +7490,8 @@ packages: commander: 9.5.0 dev: true - /zustand@4.4.1(@types/react@18.2.33)(react@18.2.0): - resolution: {integrity: sha512-QCPfstAS4EBiTQzlaGP1gmorkh/UL1Leaj2tdj+zZCZ/9bm0WS7sI2wnfD5lpOszFqWJ1DcPnGoY8RDL61uokw==} + /zustand@4.4.6(@types/react@18.2.34)(react@18.2.0): + resolution: {integrity: sha512-Rb16eW55gqL4W2XZpJh0fnrATxYEG3Apl2gfHTyDSE965x/zxslTikpNch0JgNjJA9zK6gEFW8Fl6d1rTZaqgg==} engines: {node: '>=12.7.0'} peerDependencies: '@types/react': '>=16.8' @@ -7684,23 +7505,23 @@ packages: react: optional: true dependencies: - '@types/react': 18.2.33 + '@types/react': 18.2.34 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) dev: false - file:apps/admin-ui(@types/react@18.2.33)(react-monaco-editor@0.51.0): + file:apps/admin-ui(@types/react@18.2.34)(react-monaco-editor@0.51.0): resolution: {directory: apps/admin-ui, type: directory} id: file:apps/admin-ui name: admin-ui dependencies: '@keycloak/keycloak-admin-client': link:libs/keycloak-admin-client - '@patternfly/patternfly': 4.224.2 - '@patternfly/react-code-editor': 4.82.115(react-dom@18.2.0)(react-monaco-editor@0.51.0)(react@18.2.0) - '@patternfly/react-core': 4.276.8(react-dom@18.2.0)(react@18.2.0) - '@patternfly/react-icons': 4.93.6(react-dom@18.2.0)(react@18.2.0) - '@patternfly/react-styles': 4.92.6 - '@patternfly/react-table': 4.113.0(react-dom@18.2.0)(react@18.2.0) + '@patternfly/patternfly': 4.224.5 + '@patternfly/react-code-editor': 4.82.121(react-dom@18.2.0)(react-monaco-editor@0.51.0)(react@18.2.0) + '@patternfly/react-core': 4.278.0(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-icons': 4.93.7(react-dom@18.2.0)(react@18.2.0) + '@patternfly/react-styles': 4.92.8 + '@patternfly/react-table': 4.113.6(react-dom@18.2.0)(react@18.2.0) dagre: 0.8.5 file-saver: 2.0.5 file-selector: 0.6.0 @@ -7716,10 +7537,10 @@ packages: react-error-boundary: 3.1.4(react@18.2.0) react-hook-form: 7.47.0(react@18.2.0) react-i18next: 13.3.1(i18next@23.6.0)(react-dom@18.2.0)(react@18.2.0) - react-router-dom: 6.15.0(react-dom@18.2.0)(react@18.2.0) - reactflow: 11.9.4(@types/react@18.2.33)(react-dom@18.2.0)(react@18.2.0) + react-router-dom: 6.18.0(react-dom@18.2.0)(react@18.2.0) + reactflow: 11.9.4(@types/react@18.2.34)(react-dom@18.2.0)(react@18.2.0) ui-shared: link:libs/ui-shared - use-react-router-breadcrumbs: 4.0.1(react-router-dom@6.15.0)(react@18.2.0) + use-react-router-breadcrumbs: 4.0.1(react-router-dom@6.18.0)(react@18.2.0) transitivePeerDependencies: - '@types/react' - encoding diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/AdminEventEntity.java b/model/jpa/src/main/java/org/keycloak/events/jpa/AdminEventEntity.java index f5be1d5d029f..76655a624658 100644 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/AdminEventEntity.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/AdminEventEntity.java @@ -60,7 +60,7 @@ public class AdminEventEntity { @Column(name="RESOURCE_PATH") private String resourcePath; - @Column(name="REPRESENTATION", length = 25500) + @Column(name="REPRESENTATION") private String representation; @Column(name="ERROR") diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java b/model/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java index 1e26a486dac3..38cab319a097 100644 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/EventEntity.java @@ -57,9 +57,13 @@ public class EventEntity { @Column(name="ERROR") private String error; + // This is the legacy field which is kept here to be able to read old events without the need to migrate them @Column(name="DETAILS_JSON", length = 2550) private String detailsJson; + @Column(name="DETAILS_JSON_LONG_VALUE") + private String detailsJsonLongValue; + public String getId() { return id; } @@ -133,11 +137,11 @@ public void setError(String error) { } public String getDetailsJson() { - return detailsJson; + return detailsJsonLongValue != null ? detailsJsonLongValue : detailsJson; } public void setDetailsJson(String detailsJson) { - this.detailsJson = detailsJson; + this.detailsJsonLongValue = detailsJson; } } diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java index e1a1690f7ddf..28e3ff6af906 100755 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProvider.java @@ -39,7 +39,6 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.TypedQuery; import java.io.IOException; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -57,14 +56,10 @@ public class JpaEventStoreProvider implements EventStoreProvider { private final KeycloakSession session; private final EntityManager em; - private final int maxDetailLength; - private final int maxFieldLength; - public JpaEventStoreProvider(KeycloakSession session, EntityManager em, int maxDetailLength, int maxFieldLength) { + public JpaEventStoreProvider(KeycloakSession session, EntityManager em) { this.session = session; this.em = em; - this.maxDetailLength = maxDetailLength; - this.maxFieldLength = maxFieldLength; } @Override @@ -165,40 +160,13 @@ private EventEntity convertEvent(Event event) { eventEntity.setIpAddress(event.getIpAddress()); eventEntity.setError(event.getError()); try { - if (maxDetailLength > 0 && event.getDetails() != null) { - Map result = new HashMap<>(event.getDetails()); - result.entrySet().forEach(t -> t.setValue(trimToMaxDetailLength(t.getValue()))); - - eventEntity.setDetailsJson(trimToMaxFieldLength(mapper.writeValueAsString(result))); - } else { - eventEntity.setDetailsJson(mapper.writeValueAsString(event.getDetails())); - } + eventEntity.setDetailsJson(mapper.writeValueAsString(event.getDetails())); } catch (IOException ex) { logger.error("Failed to write log details", ex); } return eventEntity; } - private String trimToMaxDetailLength(String detail) { - if (detail != null && detail.length() > maxDetailLength) { - logger.warnf("Detail '%s' will be truncated.", detail); - // (maxDetailLength - 3) takes "..." into account - return detail.substring(0, maxDetailLength - 3).concat("..."); - } else { - return detail; - } - } - - private String trimToMaxFieldLength(String field) { - if (maxFieldLength > 0 && field != null && field.length() > maxFieldLength) { - logger.warnf("Field '%s' will be truncated.", field); - // (maxFieldLength - 3) takes "..." into account - return field.substring(0, maxFieldLength - 3).concat("..."); - } else { - return field; - } - } - static Event convertEvent(EventEntity eventEntity) { Event event = new Event(); event.setId(eventEntity.getId() == null ? UUID.randomUUID().toString() : eventEntity.getId()); @@ -234,8 +202,8 @@ private AdminEventEntity convertAdminEvent(AdminEvent adminEvent, boolean includ adminEventEntity.setResourcePath(adminEvent.getResourcePath()); adminEventEntity.setError(adminEvent.getError()); - if(includeRepresentation) { - adminEventEntity.setRepresentation(trimToMaxFieldLength(adminEvent.getRepresentation())); + if (includeRepresentation) { + adminEventEntity.setRepresentation(adminEvent.getRepresentation()); } return adminEventEntity; } @@ -255,7 +223,7 @@ static AdminEvent convertAdminEvent(AdminEventEntity adminEventEntity) { adminEvent.setResourcePath(adminEventEntity.getResourcePath()); adminEvent.setError(adminEventEntity.getError()); - if(adminEventEntity.getRepresentation() != null) { + if (adminEventEntity.getRepresentation() != null) { adminEvent.setRepresentation(adminEventEntity.getRepresentation()); } return adminEvent; diff --git a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProviderFactory.java b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProviderFactory.java index 49506c7b00e3..24868b3037c4 100755 --- a/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProviderFactory.java +++ b/model/jpa/src/main/java/org/keycloak/events/jpa/JpaEventStoreProviderFactory.java @@ -32,21 +32,15 @@ public class JpaEventStoreProviderFactory implements EventStoreProviderFactory, InvalidationHandler { public static final String ID = "jpa"; - private int maxDetailLength; - private int maxFieldLength; @Override public EventStoreProvider create(KeycloakSession session) { JpaConnectionProvider connection = session.getProvider(JpaConnectionProvider.class); - return new JpaEventStoreProvider(session, connection.getEntityManager(), maxDetailLength, maxFieldLength); + return new JpaEventStoreProvider(session, connection.getEntityManager()); } @Override public void init(Config.Scope config) { - maxDetailLength = config.getInt("max-detail-length", -1); - maxFieldLength = config.getInt("max-field-length", -1); - if (maxDetailLength != -1 && maxDetailLength < 3) throw new IllegalArgumentException("max-detail-length cannot be less that 3."); - if (maxFieldLength != -1 && maxFieldLength < 3) throw new IllegalArgumentException("max-field-length cannot be less that 3."); } @Override diff --git a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java index cff752cce093..174290a40505 100755 --- a/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java +++ b/model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java @@ -35,7 +35,18 @@ import jakarta.persistence.EntityManager; import jakarta.persistence.LockModeType; import jakarta.persistence.TypedQuery; -import java.util.*; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.Collections; +import java.util.Collection; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Arrays; +import java.util.Optional; import java.util.function.Predicate; import java.util.stream.Stream; diff --git a/model/jpa/src/main/resources/META-INF/jpa-changelog-23.0.0.xml b/model/jpa/src/main/resources/META-INF/jpa-changelog-23.0.0.xml index 4f35cc440dc6..4c499231a40f 100644 --- a/model/jpa/src/main/resources/META-INF/jpa-changelog-23.0.0.xml +++ b/model/jpa/src/main/resources/META-INF/jpa-changelog-23.0.0.xml @@ -30,4 +30,11 @@ + + + + + + + diff --git a/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java b/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java index 23ba52cb33a0..3c11de21afb3 100644 --- a/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java +++ b/operator/src/test/java/org/keycloak/operator/testsuite/integration/KeycloakDeploymentTest.java @@ -107,7 +107,7 @@ public void testKeycloakDeploymentBeforeSecret() { Resource stsResource = k8sclient.resources(StatefulSet.class).withName(deploymentName); Resource keycloakResource = k8sclient.resources(Keycloak.class).withName(deploymentName); // expect no errors and not ready, which means we'll keep reconciling - Awaitility.await().untilAsserted(() -> { + Awaitility.await().ignoreExceptions().untilAsserted(() -> { assertThat(stsResource.get()).isNotNull(); Keycloak keycloak = keycloakResource.get(); CRAssert.assertKeycloakStatusCondition(keycloak, KeycloakStatusCondition.HAS_ERRORS, false); diff --git a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java index f3108366fcd4..5ab946220a43 100644 --- a/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java +++ b/quarkus/tests/integration/src/test/java/org/keycloak/it/cli/dist/FeaturesDistTest.java @@ -28,7 +28,7 @@ @LegacyStore public class FeaturesDistTest { - private static final String PREVIEW_FEATURES_EXPECTED_LOG = "Preview features enabled: account3, admin-fine-grained-authz, client-secret-rotation, declarative-user-profile, dpop, recovery-codes, scripts, token-exchange, transient-users, update-email"; + private static final String PREVIEW_FEATURES_EXPECTED_LOG = "Preview features enabled: account3, admin-fine-grained-authz, client-secret-rotation, declarative-user-profile, dpop, recovery-codes, scripts, token-exchange, update-email"; @Test public void testEnableOnBuild(KeycloakDistribution dist) { diff --git a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java index 5477514a5a29..27bb1d16de16 100755 --- a/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java +++ b/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java @@ -24,7 +24,12 @@ import org.keycloak.models.RequiredCredentialModel; import org.keycloak.representations.idm.IdentityProviderRepresentation; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.LinkedList; + /** * @author Bill Burke diff --git a/server-spi-private/src/main/java/org/keycloak/validate/BuiltinValidators.java b/server-spi-private/src/main/java/org/keycloak/validate/BuiltinValidators.java new file mode 100644 index 000000000000..7b80aa100370 --- /dev/null +++ b/server-spi-private/src/main/java/org/keycloak/validate/BuiltinValidators.java @@ -0,0 +1,82 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.keycloak.validate; + +import org.keycloak.validate.validators.DoubleValidator; +import org.keycloak.validate.validators.EmailValidator; +import org.keycloak.validate.validators.IntegerValidator; +import org.keycloak.validate.validators.LengthValidator; +import org.keycloak.validate.validators.LocalDateValidator; +import org.keycloak.validate.validators.NotBlankValidator; +import org.keycloak.validate.validators.NotEmptyValidator; +import org.keycloak.validate.validators.OptionsValidator; +import org.keycloak.validate.validators.PatternValidator; +import org.keycloak.validate.validators.UriValidator; +import org.keycloak.validate.validators.ValidatorConfigValidator; + +/** + * @author Marek Posolda + */ +public class BuiltinValidators { + + public static NotBlankValidator notBlankValidator() { + return NotBlankValidator.INSTANCE; + } + + public static NotEmptyValidator notEmptyValidator() { + return NotEmptyValidator.INSTANCE; + } + + public static LengthValidator lengthValidator() { + return LengthValidator.INSTANCE; + } + + public static UriValidator uriValidator() { + return UriValidator.INSTANCE; + } + + public static EmailValidator emailValidator() { + return EmailValidator.INSTANCE; + } + + public static PatternValidator patternValidator() { + return PatternValidator.INSTANCE; + } + + public static DoubleValidator doubleValidator() { + return DoubleValidator.INSTANCE; + } + + public static IntegerValidator integerValidator() { + return IntegerValidator.INSTANCE; + } + + public static LocalDateValidator dateValidator() { + return LocalDateValidator.INSTANCE; + } + + public static OptionsValidator optionsValidator() { + return OptionsValidator.INSTANCE; + } + + public static ValidatorConfigValidator validatorConfigValidator() { + return ValidatorConfigValidator.INSTANCE; + } +} diff --git a/server-spi-private/src/main/java/org/keycloak/validate/Validators.java b/server-spi-private/src/main/java/org/keycloak/validate/Validators.java deleted file mode 100644 index 2311a779807c..000000000000 --- a/server-spi-private/src/main/java/org/keycloak/validate/Validators.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright 2021 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.validate; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; - -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.KeycloakSessionFactory; -import org.keycloak.validate.validators.LocalDateValidator; -import org.keycloak.validate.validators.EmailValidator; -import org.keycloak.validate.validators.IntegerValidator; -import org.keycloak.validate.validators.LengthValidator; -import org.keycloak.validate.validators.NotBlankValidator; -import org.keycloak.validate.validators.NotEmptyValidator; -import org.keycloak.validate.validators.OptionsValidator; -import org.keycloak.validate.validators.DoubleValidator; -import org.keycloak.validate.validators.PatternValidator; -import org.keycloak.validate.validators.UriValidator; -import org.keycloak.validate.validators.ValidatorConfigValidator; - -/** - * Facade for Validation functions with support for {@link Validator} implementation lookup by id. - */ -public class Validators { - - /** - * Holds a mapping of internal {@link SimpleValidator} to allow look-up via provider id. - */ - private static final Map INTERNAL_VALIDATORS; - - static { - List list = Arrays.asList( - LengthValidator.INSTANCE, - NotEmptyValidator.INSTANCE, - UriValidator.INSTANCE, - EmailValidator.INSTANCE, - NotBlankValidator.INSTANCE, - PatternValidator.INSTANCE, - DoubleValidator.INSTANCE, - IntegerValidator.INSTANCE, - ValidatorConfigValidator.INSTANCE, - OptionsValidator.INSTANCE - ); - - INTERNAL_VALIDATORS = list.stream().collect(Collectors.toMap(SimpleValidator::getId, v -> v)); - } - - /** - * Holds the {@link KeycloakSession}. - */ - private final KeycloakSession session; - - /** - * Creates a new {@link Validators} instance with the given {@link KeycloakSession}. - * - * @param session - */ - public Validators(KeycloakSession session) { - this.session = session; - } - - /** - * Look-up for a built-in or registered {@link Validator} with the given provider {@code id}. - * - * @param id - * @return - * @see #validator(KeycloakSession, String) - */ - public Validator validator(String id) { - return validator(session, id); - } - - /** - * Look-up for a built-in or registered {@link ValidatorFactory} with the given provider {@code id}. - * - * @param id - * @return - * @see #validatorFactory(KeycloakSession, String) - */ - public ValidatorFactory validatorFactory(String id) { - return validatorFactory(session, id); - } - - /** - * Validates the {@link ValidatorConfig} of {@link Validator} referenced by the given provider {@code id}. - * - * @param id - * @param config - * @return - * @see #validateConfig(KeycloakSession, String, ValidatorConfig) - */ - public ValidationResult validateConfig(String id, ValidatorConfig config) { - return validateConfig(session, id, config); - } - - /* static import friendly accessor methods for built-in validators */ - - public static Validator getInternalValidatorById(String id) { - return INTERNAL_VALIDATORS.get(id); - } - - public static ValidatorFactory getInternalValidatorFactoryById(String id) { - return INTERNAL_VALIDATORS.get(id); - } - - public static Map getInternalValidators() { - return Collections.unmodifiableMap(INTERNAL_VALIDATORS); - } - - public static NotBlankValidator notBlankValidator() { - return NotBlankValidator.INSTANCE; - } - - public static NotEmptyValidator notEmptyValidator() { - return NotEmptyValidator.INSTANCE; - } - - public static LengthValidator lengthValidator() { - return LengthValidator.INSTANCE; - } - - public static UriValidator uriValidator() { - return UriValidator.INSTANCE; - } - - public static EmailValidator emailValidator() { - return EmailValidator.INSTANCE; - } - - public static PatternValidator patternValidator() { - return PatternValidator.INSTANCE; - } - - public static DoubleValidator doubleValidator() { - return DoubleValidator.INSTANCE; - } - - public static IntegerValidator integerValidator() { - return IntegerValidator.INSTANCE; - } - - public static LocalDateValidator dateValidator() { - return LocalDateValidator.INSTANCE; - } - - public static OptionsValidator optionsValidator() { - return OptionsValidator.INSTANCE; - } - - public static ValidatorConfigValidator validatorConfigValidator() { - return ValidatorConfigValidator.INSTANCE; - } - - /** - * Look-up up for a built-in or registered {@link Validator} with the given validatorId. - * - * @param session the {@link KeycloakSession} - * @param id the id of the validator - * @return the {@link Validator} or {@literal null} - */ - public static Validator validator(KeycloakSession session, String id) { - - // Fast-path for internal Validators - Validator validator = getInternalValidatorById(id); - if (validator != null) { - return validator; - } - - if (session == null) { - return null; - } - - // Lookup validator in registry - return session.getProvider(Validator.class, id); - } - - /** - * Look-up for a built-in or registered {@link ValidatorFactory} with the given validatorId. - *

- * This is intended for users who want to dynamically create new {@link Validator} instances, validate - * {@link ValidatorConfig} configurations or create default configurations for a {@link Validator}. - * - * @param session the {@link KeycloakSession} - * @param id the id of the validator - * @return the {@link Validator} or {@literal null} - */ - public static ValidatorFactory validatorFactory(KeycloakSession session, String id) { - - // Fast-path for internal Validators - ValidatorFactory factory = getInternalValidatorFactoryById(id); - if (factory != null) { - return factory; - } - - if (session == null) { - return null; - } - - // Lookup factory in registry - KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); - return (ValidatorFactory) sessionFactory.getProviderFactory(Validator.class, id); - } - - /** - * Validates the {@link ValidatorConfig} of {@link Validator} referenced by the given provider {@code id}. - * - * @param session - * @param id of the validator - * @param config to be validated - * @return - */ - public static ValidationResult validateConfig(KeycloakSession session, String id, ValidatorConfig config) { - - ValidatorFactory validatorFactory = validatorFactory(session, id); - if (validatorFactory != null) { - return validatorFactory.validateConfig(session, config); - } - - // We could not find a ValidationFactory to validate that config, so we assume the config is valid. - return ValidationResult.OK; - } -} diff --git a/server-spi-private/src/main/java/org/keycloak/validate/validators/ValidatorConfigValidator.java b/server-spi-private/src/main/java/org/keycloak/validate/validators/ValidatorConfigValidator.java index 1eb3144b6b48..a49631834719 100644 --- a/server-spi-private/src/main/java/org/keycloak/validate/validators/ValidatorConfigValidator.java +++ b/server-spi-private/src/main/java/org/keycloak/validate/validators/ValidatorConfigValidator.java @@ -57,7 +57,7 @@ public class ValidatorConfigValidator implements SimpleValidator { public static final ValidatorConfigValidator INSTANCE = new ValidatorConfigValidator(); - private ValidatorConfigValidator() { + public ValidatorConfigValidator() { } @Override diff --git a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.validate.ValidatorFactory b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.validate.ValidatorFactory index 5694637d6871..48378941f57d 100644 --- a/server-spi-private/src/main/resources/META-INF/services/org.keycloak.validate.ValidatorFactory +++ b/server-spi-private/src/main/resources/META-INF/services/org.keycloak.validate.ValidatorFactory @@ -7,4 +7,4 @@ org.keycloak.validate.validators.PatternValidator org.keycloak.validate.validators.DoubleValidator org.keycloak.validate.validators.IntegerValidator org.keycloak.validate.validators.LocalDateValidator -org.keycloak.validate.validators.OptionsValidator \ No newline at end of file +org.keycloak.validate.validators.OptionsValidator diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/AttributeContext.java b/server-spi/src/main/java/org/keycloak/userprofile/AttributeContext.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/AttributeContext.java rename to server-spi/src/main/java/org/keycloak/userprofile/AttributeContext.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/AttributeGroupMetadata.java b/server-spi/src/main/java/org/keycloak/userprofile/AttributeGroupMetadata.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/AttributeGroupMetadata.java rename to server-spi/src/main/java/org/keycloak/userprofile/AttributeGroupMetadata.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/AttributeMetadata.java b/server-spi/src/main/java/org/keycloak/userprofile/AttributeMetadata.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/AttributeMetadata.java rename to server-spi/src/main/java/org/keycloak/userprofile/AttributeMetadata.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/AttributeValidatorMetadata.java b/server-spi/src/main/java/org/keycloak/userprofile/AttributeValidatorMetadata.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/AttributeValidatorMetadata.java rename to server-spi/src/main/java/org/keycloak/userprofile/AttributeValidatorMetadata.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/Attributes.java b/server-spi/src/main/java/org/keycloak/userprofile/Attributes.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/Attributes.java rename to server-spi/src/main/java/org/keycloak/userprofile/Attributes.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileAttributeValidationContext.java b/server-spi/src/main/java/org/keycloak/userprofile/UserProfileAttributeValidationContext.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileAttributeValidationContext.java rename to server-spi/src/main/java/org/keycloak/userprofile/UserProfileAttributeValidationContext.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileContext.java b/server-spi/src/main/java/org/keycloak/userprofile/UserProfileContext.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileContext.java rename to server-spi/src/main/java/org/keycloak/userprofile/UserProfileContext.java diff --git a/server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileMetadata.java b/server-spi/src/main/java/org/keycloak/userprofile/UserProfileMetadata.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/userprofile/UserProfileMetadata.java rename to server-spi/src/main/java/org/keycloak/userprofile/UserProfileMetadata.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/AbstractSimpleValidator.java b/server-spi/src/main/java/org/keycloak/validate/AbstractSimpleValidator.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/AbstractSimpleValidator.java rename to server-spi/src/main/java/org/keycloak/validate/AbstractSimpleValidator.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/AbstractStringValidator.java b/server-spi/src/main/java/org/keycloak/validate/AbstractStringValidator.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/AbstractStringValidator.java rename to server-spi/src/main/java/org/keycloak/validate/AbstractStringValidator.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/SimpleValidator.java b/server-spi/src/main/java/org/keycloak/validate/SimpleValidator.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/SimpleValidator.java rename to server-spi/src/main/java/org/keycloak/validate/SimpleValidator.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/ValidationContext.java b/server-spi/src/main/java/org/keycloak/validate/ValidationContext.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/ValidationContext.java rename to server-spi/src/main/java/org/keycloak/validate/ValidationContext.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/ValidationError.java b/server-spi/src/main/java/org/keycloak/validate/ValidationError.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/ValidationError.java rename to server-spi/src/main/java/org/keycloak/validate/ValidationError.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/ValidationResult.java b/server-spi/src/main/java/org/keycloak/validate/ValidationResult.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/ValidationResult.java rename to server-spi/src/main/java/org/keycloak/validate/ValidationResult.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/Validator.java b/server-spi/src/main/java/org/keycloak/validate/Validator.java similarity index 75% rename from server-spi-private/src/main/java/org/keycloak/validate/Validator.java rename to server-spi/src/main/java/org/keycloak/validate/Validator.java index dfd08a76525f..41e3042605ca 100644 --- a/server-spi-private/src/main/java/org/keycloak/validate/Validator.java +++ b/server-spi/src/main/java/org/keycloak/validate/Validator.java @@ -1,18 +1,20 @@ /* - * Copyright 2021 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. */ package org.keycloak.validate; @@ -40,17 +42,6 @@ default ValidationContext validate(Object input) { return validate(input, "input", new ValidationContext(), ValidatorConfig.EMPTY); } - /** - * Validates the given {@code input} with an additional {@code config}. - * - * @param input the value to validate - * @param config parameterization for the current validation - * @return the validation context with the outcome of the validation - */ - default ValidationContext validate(Object input, ValidatorConfig config) { - return validate(input, "input", new ValidationContext(), config); - } - /** * Validates the given {@code input}. * diff --git a/server-spi-private/src/main/java/org/keycloak/validate/ValidatorConfig.java b/server-spi/src/main/java/org/keycloak/validate/ValidatorConfig.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/ValidatorConfig.java rename to server-spi/src/main/java/org/keycloak/validate/ValidatorConfig.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/ValidatorFactory.java b/server-spi/src/main/java/org/keycloak/validate/ValidatorFactory.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/ValidatorFactory.java rename to server-spi/src/main/java/org/keycloak/validate/ValidatorFactory.java diff --git a/server-spi-private/src/main/java/org/keycloak/validate/ValidatorSPI.java b/server-spi/src/main/java/org/keycloak/validate/ValidatorSPI.java similarity index 100% rename from server-spi-private/src/main/java/org/keycloak/validate/ValidatorSPI.java rename to server-spi/src/main/java/org/keycloak/validate/ValidatorSPI.java diff --git a/server-spi/src/main/java/org/keycloak/validate/Validators.java b/server-spi/src/main/java/org/keycloak/validate/Validators.java new file mode 100644 index 000000000000..07d62d81fd19 --- /dev/null +++ b/server-spi/src/main/java/org/keycloak/validate/Validators.java @@ -0,0 +1,131 @@ +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +package org.keycloak.validate; + +import org.keycloak.models.KeycloakSession; +import org.keycloak.models.KeycloakSessionFactory; + +/** + * Facade for Validation functions with support for {@link Validator} implementation lookup by id. + */ +public class Validators { + + /** + * Holds the {@link KeycloakSession}. + */ + private final KeycloakSession session; + + /** + * Creates a new {@link Validators} instance with the given {@link KeycloakSession}. + * + * @param session + */ + public Validators(KeycloakSession session) { + this.session = session; + } + + /** + * Look-up for a built-in or registered {@link Validator} with the given provider {@code id}. + * + * @param id + * @return + * @see #validator(KeycloakSession, String) + */ + public Validator validator(String id) { + return validator(session, id); + } + + /** + * Look-up for a built-in or registered {@link ValidatorFactory} with the given provider {@code id}. + * + * @param id + * @return + * @see #validatorFactory(KeycloakSession, String) + */ + public ValidatorFactory validatorFactory(String id) { + return validatorFactory(session, id); + } + + /** + * Validates the {@link ValidatorConfig} of {@link Validator} referenced by the given provider {@code id}. + * + * @param id + * @param config + * @return + * @see #validateConfig(KeycloakSession, String, ValidatorConfig) + */ + public ValidationResult validateConfig(String id, ValidatorConfig config) { + return validateConfig(session, id, config); + } + + /** + * Look-up up for a built-in or registered {@link Validator} with the given validatorId. + * + * @param session the {@link KeycloakSession} + * @param id the id of the validator + * @return the {@link Validator} or {@literal null} + */ + public static Validator validator(KeycloakSession session, String id) { + if (session == null) { + throw new IllegalArgumentException("KeycloakSession must be not null"); + } + + // Lookup validator in registry + return session.getProvider(Validator.class, id); + } + + /** + * Look-up for a built-in or registered {@link ValidatorFactory} with the given validatorId. + *

+ * This is intended for users who want to dynamically create new {@link Validator} instances, validate + * {@link ValidatorConfig} configurations or create default configurations for a {@link Validator}. + * + * @param session the {@link KeycloakSession} + * @param id the id of the validator + * @return the {@link Validator} or {@literal null} + */ + public static ValidatorFactory validatorFactory(KeycloakSession session, String id) { + if (session == null) { + throw new IllegalArgumentException("KeycloakSession must be not null"); + } + + // Lookup factory in registry + KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory(); + return (ValidatorFactory) sessionFactory.getProviderFactory(Validator.class, id); + } + + /** + * Validates the {@link ValidatorConfig} of {@link Validator} referenced by the given provider {@code id}. + * + * @param session + * @param id of the validator + * @param config to be validated + * @return + */ + public static ValidationResult validateConfig(KeycloakSession session, String id, ValidatorConfig config) { + + ValidatorFactory validatorFactory = validatorFactory(session, id); + if (validatorFactory != null) { + return validatorFactory.validateConfig(session, config); + } + + // We could not find a ValidationFactory to validate that config, so we assume the config is valid. + return ValidationResult.OK; + } +} diff --git a/services/src/main/java/org/keycloak/partialimport/UsersPartialImport.java b/services/src/main/java/org/keycloak/partialimport/UsersPartialImport.java index 7820462cd1e2..d7d3eb1abf24 100755 --- a/services/src/main/java/org/keycloak/partialimport/UsersPartialImport.java +++ b/services/src/main/java/org/keycloak/partialimport/UsersPartialImport.java @@ -110,7 +110,9 @@ public void remove(RealmModel realm, KeycloakSession session, UserRepresentation @Override public void create(RealmModel realm, KeycloakSession session, UserRepresentation user) { - user.setId(KeycloakModelUtils.generateId()); + if (user.getId() == null) { + user.setId(KeycloakModelUtils.generateId()); + } UserModel userModel = RepresentationToModel.createUser(session, realm, user); if (userModel == null) throw new RuntimeException("Unable to create user " + getName(user)); createdIds.put(getName(user), userModel.getId()); diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java index 2f371513917e..dbd61ed4428c 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java @@ -75,10 +75,7 @@ protected static void setClaim(IDToken token, ProtocolMapperModel mappingModel, } - private static final Pattern CLIENT_ID_PATTERN = Pattern.compile("\\$\\{client_id\\}"); - - private static final Pattern DOT_PATTERN = Pattern.compile("\\."); - private static final String DOT_REPLACEMENT = "\\\\\\\\."; + private static final Pattern CLIENT_ID_PATTERN = Pattern.compile(Pattern.quote("${client_id}")); private static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue, String clientId) { attributeValue = OIDCAttributeMapperHelper.mapAttributeValue(mappingModel, attributeValue); @@ -90,11 +87,10 @@ private static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Ob } if (clientId != null) { - // case when clientId contains dots - clientId = DOT_PATTERN.matcher(clientId).replaceAll(DOT_REPLACEMENT); Matcher matcher = CLIENT_ID_PATTERN.matcher(protocolClaim); if (matcher.find()) { - protocolClaim = matcher.replaceAll(clientId); + // dots and backslashes in clientId should be escaped first for the claim + protocolClaim = matcher.replaceAll(Matcher.quoteReplacement(clientId.replace("\\", "\\\\").replace(".", "\\."))); } } diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/ScriptBasedMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/ScriptBasedMapper.java index 5e0b00685742..a6cf95ad455e 100644 --- a/services/src/main/java/org/keycloak/protocol/saml/mappers/ScriptBasedMapper.java +++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/ScriptBasedMapper.java @@ -12,7 +12,11 @@ import org.keycloak.scripting.ScriptCompilationException; import org.keycloak.scripting.ScriptingProvider; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + /** * This class provides a mapper that uses javascript to attach a value to an attribute for SAML tokens. diff --git a/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java b/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java index 211c6d8972ad..8d17a2267e1b 100644 --- a/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java +++ b/services/src/main/java/org/keycloak/userprofile/DeclarativeUserProfileProvider.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Optional; @@ -448,6 +449,10 @@ private boolean isBuiltInAttribute(String attributeName) { return UserModel.USERNAME.equals(attributeName) || UserModel.EMAIL.equals(attributeName); } + private boolean isOptionalBuiltInAttribute(String attributeName) { + return UserModel.FIRST_NAME.equals(attributeName) || UserModel.LAST_NAME.equals(attributeName); + } + private Predicate createViewAllowedPredicate(Predicate canEdit, Set viewRoles) { return ac -> UPConfigUtils.isRoleForContext(ac.getContext(), viewRoles) || canEdit.test(ac); @@ -521,7 +526,11 @@ private Function createUserDefinedProfi throw new RuntimeException("UserProfile configuration for realm '" + session.getContext().getRealm().getName() + "' is invalid: " + errors.toString()); } - for (AttributeMetadata metadata : decoratedMetadata.getAttributes()) { + Iterator attributes = decoratedMetadata.getAttributes().iterator(); + + while (attributes.hasNext()) { + AttributeMetadata metadata = attributes.next(); + String attributeName = metadata.getName(); if (isBuiltInAttribute(attributeName)) { @@ -534,6 +543,10 @@ private Function createUserDefinedProfi // user-defined configuration will add its own validators validators.removeIf(m -> m.getValidatorId().equals(id)); } + } else if (isOptionalBuiltInAttribute(attributeName)) { + // removes optional default attributes in favor of user-defined configuration + // make sure any attribute other than username and email are removed from the metadata + attributes.remove(); } } diff --git a/services/src/main/java/org/keycloak/userprofile/validator/ImmutableAttributeValidator.java b/services/src/main/java/org/keycloak/userprofile/validator/ImmutableAttributeValidator.java index 3b588adbff1d..d76d5575eb9a 100644 --- a/services/src/main/java/org/keycloak/userprofile/validator/ImmutableAttributeValidator.java +++ b/services/src/main/java/org/keycloak/userprofile/validator/ImmutableAttributeValidator.java @@ -17,23 +17,20 @@ package org.keycloak.userprofile.validator; import static org.keycloak.common.util.CollectionUtil.collectionEquals; -import static org.keycloak.validate.Validators.notBlankValidator; +import static org.keycloak.validate.BuiltinValidators.notBlankValidator; import java.util.List; import java.util.Objects; import java.util.stream.Collectors; -import org.keycloak.common.util.CollectionUtil; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.userprofile.AttributeContext; -import org.keycloak.userprofile.AttributeValidatorMetadata; import org.keycloak.userprofile.UserProfileAttributeValidationContext; import org.keycloak.validate.SimpleValidator; import org.keycloak.validate.ValidationContext; import org.keycloak.validate.ValidationError; import org.keycloak.validate.ValidatorConfig; -import org.keycloak.validate.Validators; /** * A validator that fails when the attribute is marked as read only and its value has changed. diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java index c99534bb9934..f6f25c043c6e 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java @@ -556,8 +556,9 @@ public String createUser(String realm, String username, String password, String return ApiUtil.createUserWithAdminClient(adminClient.realm(realm), homer); } - public static UserRepresentation createUserRepresentation(String username, String email, String firstName, String lastName, List groups, boolean enabled) { + public static UserRepresentation createUserRepresentation(String id, String username, String email, String firstName, String lastName, List groups, boolean enabled) { UserRepresentation user = new UserRepresentation(); + user.setId(id); user.setUsername(username); user.setEmail(email); user.setFirstName(firstName); @@ -567,6 +568,10 @@ public static UserRepresentation createUserRepresentation(String username, Strin return user; } + public static UserRepresentation createUserRepresentation(String username, String email, String firstName, String lastName, List groups, boolean enabled) { + return createUserRepresentation(null, username, email, firstName, lastName, groups, enabled); + } + public static UserRepresentation createUserRepresentation(String username, String email, String firstName, String lastName, boolean enabled) { return createUserRepresentation(username, email, firstName, lastName, null, enabled); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java index b99518cca88d..23d08e05d83f 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java @@ -17,6 +17,7 @@ package org.keycloak.testsuite.admin.event; +import org.apache.commons.lang3.RandomStringUtils; import org.junit.Before; import org.junit.Test; import org.keycloak.admin.client.resource.RealmResource; @@ -45,6 +46,7 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; import static org.junit.Assert.assertNull; import static org.keycloak.testsuite.auth.page.AuthRealm.MASTER; @@ -167,6 +169,23 @@ public void defaultMaxResults() { assertThat(realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 1000).size(), is(greaterThanOrEqualTo(110))); } + @Test + public void adminEventRepresentationLenght() { + RealmResource realm = adminClient.realms().realm("test"); + AdminEventRepresentation event = new AdminEventRepresentation(); + event.setOperationType(OperationType.CREATE.toString()); + event.setAuthDetails(new AuthDetailsRepresentation()); + event.setRealmId(realm.toRepresentation().getId()); + String longValue = RandomStringUtils.random(30000, true, true); + event.setRepresentation(longValue); + + testingClient.testing("test").onAdminEvent(event, true); + List adminEvents = realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null); + + assertThat(adminEvents, hasSize(1)); + assertThat(adminEvents.get(0).getRepresentation(), equalTo(longValue)); + } + @Test public void orderResultsTest() { RealmResource realm = adminClient.realms().realm("test"); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java index e5cd2344ea05..b1c6503d25de 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/partialimport/PartialImportTest.java @@ -57,6 +57,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import java.util.UUID; import static org.hamcrest.CoreMatchers.hasItem; import static org.hamcrest.CoreMatchers.startsWith; @@ -247,6 +248,17 @@ private void addUsers() { piRep.setUsers(users); } + private void addUsersWithIds() { + List users = new ArrayList<>(); + + for (int i = 0; i < NUM_ENTITIES; i++) { + UserRepresentation user = createUserRepresentation(UUID.randomUUID().toString(), USER_PREFIX + i, USER_PREFIX + i + "@foo.com", "foo", "bar", null, true); + users.add(user); + } + + piRep.setUsers(users); + } + private void addUsersWithTermsAndConditions() { List users = new ArrayList<>(); List requiredActions = new ArrayList<>(); @@ -418,6 +430,46 @@ public void testAddUsers() { } } + @Test + public void testAddUsersWithIds() { + assertAdminEvents.clear(); + + setFail(); + addUsersWithIds(); + + Set userRepIds = new HashSet<>(); + for (UserRepresentation userRep : piRep.getUsers()) { + userRepIds.add(userRep.getId()); + } + + PartialImportResults results = doImport(); + assertEquals(NUM_ENTITIES, results.getAdded()); + + // Need to do this way as admin events from partial import are unsorted + Set userIds = new HashSet<>(); + for (int i=0 ; i> att assertNull(user.getEmail()); assertEquals(upAttributes.getFirstValue(UserModel.FIRST_NAME), attributes.get(UserModel.FIRST_NAME).get(0)); } + + @Test + public void testRemoveOptionalAttributesFromDefaultConfigIfNotSet() { + getTestingClient().server(TEST_REALM_NAME).run((RunOnServer) UserProfileTest::testRemoveOptionalAttributesFromDefaultConfigIfNotSet); + } + + private static void testRemoveOptionalAttributesFromDefaultConfigIfNotSet(KeycloakSession session) throws IOException { + UPConfig config = new UPConfig(); + UPAttribute attribute = new UPAttribute(); + + attribute.setName("foo"); + + config.addAttribute(attribute); + + UserProfileProvider provider = getUserProfileProvider(session); + provider.setConfiguration(JsonSerialization.writeValueAsString(config)); + + Map attributes = new HashMap<>(); + + attributes.put(UserModel.USERNAME, org.keycloak.models.utils.KeycloakModelUtils.generateId() + "@keycloak.org"); + attributes.put(UserModel.EMAIL, org.keycloak.models.utils.KeycloakModelUtils.generateId() + "@keycloak.org"); + attributes.put("foo", "foo"); + + UserProfile profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes); + UserModel user = profile.create(); + + assertFalse(profile.getAttributes().contains(UserModel.FIRST_NAME)); + assertFalse(profile.getAttributes().contains(UserModel.LAST_NAME)); + + UPAttribute firstName = new UPAttribute(); + firstName.setName(UserModel.FIRST_NAME); + config.addAttribute(firstName); + UPAttribute lastName = new UPAttribute(); + lastName.setName(UserModel.LAST_NAME); + config.addAttribute(lastName); + provider.setConfiguration(JsonSerialization.writeValueAsString(config)); + profile = provider.create(UserProfileContext.UPDATE_PROFILE, attributes, user); + assertTrue(profile.getAttributes().contains(UserModel.FIRST_NAME)); + assertTrue(profile.getAttributes().contains(UserModel.LAST_NAME)); + } } diff --git a/server-spi-private/src/test/java/org/keycloak/validate/BuiltinValidatorsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/BuiltinValidatorsTest.java similarity index 81% rename from server-spi-private/src/test/java/org/keycloak/validate/BuiltinValidatorsTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/BuiltinValidatorsTest.java index 7bbacd4fc393..5834f8953cdd 100644 --- a/server-spi-private/src/test/java/org/keycloak/validate/BuiltinValidatorsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/BuiltinValidatorsTest.java @@ -1,4 +1,23 @@ -package org.keycloak.validate; +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.keycloak.testsuite.validation; import static org.keycloak.validate.ValidatorConfig.configFromMap; @@ -11,24 +30,39 @@ import org.junit.Assert; import org.junit.Test; +import org.keycloak.models.KeycloakSession; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.AbstractKeycloakTest; +import org.keycloak.testsuite.arquillian.annotation.ModelTest; +import org.keycloak.validate.AbstractSimpleValidator; +import org.keycloak.validate.ValidationContext; +import org.keycloak.validate.ValidationError; +import org.keycloak.validate.ValidationResult; +import org.keycloak.validate.Validator; +import org.keycloak.validate.ValidatorConfig; import org.keycloak.validate.validators.DoubleValidator; import org.keycloak.validate.validators.EmailValidator; import org.keycloak.validate.validators.IntegerValidator; import org.keycloak.validate.validators.LengthValidator; import org.keycloak.validate.validators.OptionsValidator; import org.keycloak.validate.validators.PatternValidator; +import org.keycloak.validate.BuiltinValidators; import org.keycloak.validate.validators.UriValidator; import com.google.common.collect.ImmutableMap; -public class BuiltinValidatorsTest { +public class BuiltinValidatorsTest extends AbstractKeycloakTest { private static final ValidatorConfig valConfigIgnoreEmptyValues = ValidatorConfig.builder().config(AbstractSimpleValidator.IGNORE_EMPTY_VALUE, true).build(); + @Override + public void addTestRealms(List testRealms) { + } + @Test public void testLengthValidator() { - Validator validator = Validators.lengthValidator(); + Validator validator = BuiltinValidators.lengthValidator(); // null and empty values handling Assert.assertFalse(validator.validate(null, "name", configFromMap(ImmutableMap.of(LengthValidator.KEY_MIN, 1))).isValid()); @@ -84,12 +118,13 @@ public void testLengthValidator() { } @Test - public void testLengthValidator_ConfigValidation() { + @ModelTest + public void testLengthValidator_ConfigValidation(KeycloakSession session) { // invalid min and max config values ValidatorConfig config = new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, new Object(), LengthValidator.KEY_MAX, "invalid")); - ValidationResult result = Validators.validatorConfigValidator().validate(config, LengthValidator.ID).toResult(); + ValidationResult result = BuiltinValidators.validatorConfigValidator().validate(config, LengthValidator.ID, new ValidationContext(session)).toResult(); Assert.assertFalse(result.isValid()); ValidationError[] errors = result.getErrors().toArray(new ValidationError[0]); @@ -105,25 +140,25 @@ public void testLengthValidator_ConfigValidation() { Assert.assertEquals(LengthValidator.KEY_MAX, error1.getInputHint()); // empty config - result = Validators.validatorConfigValidator().validate(null, LengthValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(null, LengthValidator.ID, new ValidationContext(session)).toResult(); Assert.assertEquals(2, result.getErrors().size()); - result = Validators.validatorConfigValidator().validate(ValidatorConfig.EMPTY, LengthValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(ValidatorConfig.EMPTY, LengthValidator.ID, new ValidationContext(session)).toResult(); Assert.assertEquals(2, result.getErrors().size()); // correct config - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, "10")), LengthValidator.ID).toResult().isValid()); - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MAX, "10")), LengthValidator.ID).toResult().isValid()); - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, "10", LengthValidator.KEY_MAX, "10")), LengthValidator.ID).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, "10")), LengthValidator.ID, new ValidationContext(session)).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MAX, "10")), LengthValidator.ID, new ValidationContext(session)).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, "10", LengthValidator.KEY_MAX, "10")), LengthValidator.ID, new ValidationContext(session)).toResult().isValid()); // max is smaller than min - Assert.assertFalse(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, "10", LengthValidator.KEY_MAX, "9")), LengthValidator.ID).toResult().isValid()); + Assert.assertFalse(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(LengthValidator.KEY_MIN, "10", LengthValidator.KEY_MAX, "9")), LengthValidator.ID, new ValidationContext(session)).toResult().isValid()); } @Test public void testEmailValidator() { // this also validates StringFormatValidatorBase for simple values - Validator validator = Validators.emailValidator(); + Validator validator = BuiltinValidators.emailValidator(); Assert.assertFalse(validator.validate(null, "email").isValid()); Assert.assertFalse(validator.validate("", "email").isValid()); @@ -156,7 +191,7 @@ public void testEmailValidator() { @Test public void testAbstractSimpleValidatorSupportForCollections() { - Validator validator = Validators.emailValidator(); + Validator validator = BuiltinValidators.emailValidator(); List valuesCollection = new ArrayList<>(); @@ -180,7 +215,7 @@ public void testAbstractSimpleValidatorSupportForCollections() { @Test public void testNotBlankValidator() { - Validator validator = Validators.notBlankValidator(); + Validator validator = BuiltinValidators.notBlankValidator(); // simple String value Assert.assertTrue(validator.validate("tester", "username").isValid()); @@ -203,7 +238,7 @@ public void testNotBlankValidator() { @Test public void testNotEmptyValidator() { - Validator validator = Validators.notEmptyValidator(); + Validator validator = BuiltinValidators.notEmptyValidator(); Assert.assertTrue(validator.validate("tester", "username").isValid()); Assert.assertTrue(validator.validate(" ", "username").isValid()); @@ -221,7 +256,7 @@ public void testNotEmptyValidator() { @Test public void testDoubleValidator() { - Validator validator = Validators.doubleValidator(); + Validator validator = BuiltinValidators.doubleValidator(); // null value and empty String Assert.assertFalse(validator.validate(null, "null").isValid()); @@ -285,12 +320,13 @@ public void testDoubleValidator() { } @Test - public void testDoubleValidator_ConfigValidation() { + @ModelTest + public void testDoubleValidator_ConfigValidation(KeycloakSession session) { // invalid min and max config values ValidatorConfig config = new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, new Object(), DoubleValidator.KEY_MAX, "invalid")); - ValidationResult result = Validators.validatorConfigValidator().validate(config, DoubleValidator.ID).toResult(); + ValidationResult result = BuiltinValidators.validatorConfigValidator().validate(config, DoubleValidator.ID, new ValidationContext(session)).toResult(); Assert.assertFalse(result.isValid()); ValidationError[] errors = result.getErrors().toArray(new ValidationError[0]); @@ -306,23 +342,23 @@ public void testDoubleValidator_ConfigValidation() { Assert.assertEquals(DoubleValidator.KEY_MAX, error1.getInputHint()); // empty config - result = Validators.validatorConfigValidator().validate(null, DoubleValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(null, DoubleValidator.ID, new ValidationContext(session)).toResult(); Assert.assertEquals(0, result.getErrors().size()); - result = Validators.validatorConfigValidator().validate(ValidatorConfig.EMPTY, DoubleValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(ValidatorConfig.EMPTY, DoubleValidator.ID, new ValidationContext(session)).toResult(); Assert.assertEquals(0, result.getErrors().size()); // correct config - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, "10.1")), DoubleValidator.ID).toResult().isValid()); - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MAX, "10.1")), DoubleValidator.ID).toResult().isValid()); - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, "10.1", DoubleValidator.KEY_MAX, "11")), DoubleValidator.ID).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, "10.1")), DoubleValidator.ID, new ValidationContext(session)).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MAX, "10.1")), DoubleValidator.ID, new ValidationContext(session)).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, "10.1", DoubleValidator.KEY_MAX, "11")), DoubleValidator.ID, new ValidationContext(session)).toResult().isValid()); // max is smaller than min - Assert.assertFalse(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, "10.1", DoubleValidator.KEY_MAX, "10.1")), DoubleValidator.ID).toResult().isValid()); + Assert.assertFalse(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(DoubleValidator.KEY_MIN, "10.1", DoubleValidator.KEY_MAX, "10.1")), DoubleValidator.ID, new ValidationContext(session)).toResult().isValid()); } @Test public void testIntegerValidator() { - Validator validator = Validators.integerValidator(); + Validator validator = BuiltinValidators.integerValidator(); // null value and empty String Assert.assertFalse(validator.validate(null, "null").isValid()); @@ -387,12 +423,13 @@ public void testIntegerValidator() { } @Test - public void testIntegerValidator_ConfigValidation() { + @ModelTest + public void testIntegerValidator_ConfigValidation(KeycloakSession session) { // invalid min and max config values ValidatorConfig config = new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, new Object(), IntegerValidator.KEY_MAX, "invalid")); - ValidationResult result = Validators.validatorConfigValidator().validate(config, IntegerValidator.ID).toResult(); + ValidationResult result = BuiltinValidators.validatorConfigValidator().validate(config, IntegerValidator.ID, new ValidationContext(session)).toResult(); Assert.assertFalse(result.isValid()); ValidationError[] errors = result.getErrors().toArray(new ValidationError[0]); @@ -408,24 +445,24 @@ public void testIntegerValidator_ConfigValidation() { Assert.assertEquals(IntegerValidator.KEY_MAX, error1.getInputHint()); // empty config - result = Validators.validatorConfigValidator().validate(null, IntegerValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(null, IntegerValidator.ID, new ValidationContext(session)).toResult(); Assert.assertEquals(0, result.getErrors().size()); - result = Validators.validatorConfigValidator().validate(ValidatorConfig.EMPTY, IntegerValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(ValidatorConfig.EMPTY, IntegerValidator.ID, new ValidationContext(session)).toResult(); Assert.assertEquals(0, result.getErrors().size()); // correct config - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, "10")), IntegerValidator.ID).toResult().isValid()); - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MAX, "10")), IntegerValidator.ID).toResult().isValid()); - Assert.assertTrue(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, "10", IntegerValidator.KEY_MAX, "11")), IntegerValidator.ID).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, "10")), IntegerValidator.ID, new ValidationContext(session)).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MAX, "10")), IntegerValidator.ID, new ValidationContext(session)).toResult().isValid()); + Assert.assertTrue(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, "10", IntegerValidator.KEY_MAX, "11")), IntegerValidator.ID, new ValidationContext(session)).toResult().isValid()); // max is smaller than min - Assert.assertFalse(Validators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, "10", IntegerValidator.KEY_MAX, "10")), IntegerValidator.ID).toResult().isValid()); + Assert.assertFalse(BuiltinValidators.validatorConfigValidator().validate(new ValidatorConfig(ImmutableMap.of(IntegerValidator.KEY_MIN, "10", IntegerValidator.KEY_MAX, "10")), IntegerValidator.ID, new ValidationContext(session)).toResult().isValid()); } @Test public void testPatternValidator() { - Validator validator = Validators.patternValidator(); + Validator validator = BuiltinValidators.patternValidator(); // Pattern object in the configuration ValidatorConfig config = configFromMap(Collections.singletonMap(PatternValidator.CFG_PATTERN, Pattern.compile("^start-.*-end$"))); @@ -456,7 +493,7 @@ public void testPatternValidator() { @Test public void testUriValidator() throws Exception { - Validator validator = Validators.uriValidator(); + Validator validator = BuiltinValidators.uriValidator(); Assert.assertTrue(validator.validate(null, "baseUrl").isValid()); Assert.assertTrue(validator.validate("", "baseUrl").isValid()); @@ -472,14 +509,14 @@ public void testUriValidator() throws Exception { Assert.assertFalse(validator.validate("https://localhost:3000/#someFragment", "baseUrl", config).isValid()); // it is also possible to call dedicated validation methods on a built-in validator - Assert.assertTrue(Validators.uriValidator().validateUri(new URI("https://customurl"), Collections.singleton("https"), true, true)); + Assert.assertTrue(BuiltinValidators.uriValidator().validateUri(new URI("https://customurl"), Collections.singleton("https"), true, true)); - Assert.assertFalse(Validators.uriValidator().validateUri(new URI("http://customurl"), Collections.singleton("https"), true, true)); + Assert.assertFalse(BuiltinValidators.uriValidator().validateUri(new URI("http://customurl"), Collections.singleton("https"), true, true)); } @Test public void testOptionsValidator(){ - Validator validator = Validators.optionsValidator(); + Validator validator = BuiltinValidators.optionsValidator(); // options not configured - always invalid Assert.assertFalse(validator.validate(null, "test", ValidatorConfig.builder().config(OptionsValidator.KEY_OPTIONS, null).build()).isValid()); @@ -517,16 +554,17 @@ public void testOptionsValidator(){ } @Test - public void testOptionsValidator_Config_Validation() { + @ModelTest + public void testOptionsValidator_Config_Validation(KeycloakSession session) { - ValidationResult result = Validators.validatorConfigValidator().validate(ValidatorConfig.builder().build(), OptionsValidator.ID).toResult(); + ValidationResult result = BuiltinValidators.validatorConfigValidator().validate(ValidatorConfig.builder().build(), OptionsValidator.ID, new ValidationContext(session)).toResult(); Assert.assertFalse(result.isValid()); // invalid type of the config value - result = Validators.validatorConfigValidator().validate(ValidatorConfig.builder().config(OptionsValidator.KEY_OPTIONS, "a").build(), OptionsValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(ValidatorConfig.builder().config(OptionsValidator.KEY_OPTIONS, "a").build(), OptionsValidator.ID, new ValidationContext(session)).toResult(); Assert.assertFalse(result.isValid()); - result = Validators.validatorConfigValidator().validate(ValidatorConfig.builder().config(OptionsValidator.KEY_OPTIONS, Arrays.asList("opt1")).build(), OptionsValidator.ID).toResult(); + result = BuiltinValidators.validatorConfigValidator().validate(ValidatorConfig.builder().config(OptionsValidator.KEY_OPTIONS, Arrays.asList("opt1")).build(), OptionsValidator.ID, new ValidationContext(session)).toResult(); Assert.assertTrue(result.isValid()); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorTest.java index b0404723a72f..39f58172af9c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorTest.java @@ -25,7 +25,6 @@ import java.util.Collections; import java.util.Locale; -import org.junit.Assert; import org.junit.Test; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; @@ -34,7 +33,7 @@ import org.keycloak.testsuite.AbstractTestRealmKeycloakTest; import org.keycloak.testsuite.runonserver.RunOnServer; import org.keycloak.validate.ValidationContext; -import org.keycloak.validate.Validators; +import org.keycloak.validate.BuiltinValidators; /** * @author Pedro Igor @@ -51,21 +50,21 @@ public void testDateValidator() { } private static void testDateValidator(KeycloakSession session) { - assertTrue(Validators.dateValidator().validate(null, new ValidationContext(session)).isValid()); - assertTrue(Validators.dateValidator().validate("", new ValidationContext(session)).isValid()); + assertTrue(BuiltinValidators.dateValidator().validate(null, new ValidationContext(session)).isValid()); + assertTrue(BuiltinValidators.dateValidator().validate("", new ValidationContext(session)).isValid()); // defaults to Locale.ENGLISH as per default locale selector - assertFalse(Validators.dateValidator().validate("13/12/2021", new ValidationContext(session)).isValid()); - assertFalse(Validators.dateValidator().validate("13/12/21", new ValidationContext(session)).isValid()); - assertTrue(Validators.dateValidator().validate("12/13/2021", new ValidationContext(session)).isValid()); + assertFalse(BuiltinValidators.dateValidator().validate("13/12/2021", new ValidationContext(session)).isValid()); + assertFalse(BuiltinValidators.dateValidator().validate("13/12/21", new ValidationContext(session)).isValid()); + assertTrue(BuiltinValidators.dateValidator().validate("12/13/2021", new ValidationContext(session)).isValid()); RealmModel realm = session.getContext().getRealm(); realm.setInternationalizationEnabled(true); realm.setDefaultLocale(Locale.FRANCE.getLanguage()); - assertTrue(Validators.dateValidator().validate("13/12/21", new ValidationContext(session)).isValid()); - assertTrue(Validators.dateValidator().validate("13/12/2021", new ValidationContext(session)).isValid()); - assertFalse(Validators.dateValidator().validate("12/13/2021", new ValidationContext(session)).isValid()); + assertTrue(BuiltinValidators.dateValidator().validate("13/12/21", new ValidationContext(session)).isValid()); + assertTrue(BuiltinValidators.dateValidator().validate("13/12/2021", new ValidationContext(session)).isValid()); + assertFalse(BuiltinValidators.dateValidator().validate("12/13/2021", new ValidationContext(session)).isValid()); UserModel alice = session.users().getUserByUsername(realm, "alice"); @@ -75,6 +74,6 @@ private static void testDateValidator(KeycloakSession session) { context.getAttributes().put(UserModel.class.getName(), alice); - assertFalse(Validators.dateValidator().validate("13/12/2021", context).isValid()); + assertFalse(BuiltinValidators.dateValidator().validate("13/12/2021", context).isValid()); } } diff --git a/server-spi-private/src/test/java/org/keycloak/validate/ValidatorTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorsTest.java similarity index 76% rename from server-spi-private/src/test/java/org/keycloak/validate/ValidatorTest.java rename to testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorsTest.java index f4d7952e14bf..1e8d1012470c 100644 --- a/server-spi-private/src/test/java/org/keycloak/validate/ValidatorTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/validation/ValidatorsTest.java @@ -1,4 +1,23 @@ -package org.keycloak.validate; +/* + * Copyright 2023 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.keycloak.testsuite.validation; import static org.keycloak.validate.ValidatorConfig.configFromMap; @@ -14,28 +33,42 @@ import org.junit.Assert; import org.junit.Test; import org.keycloak.models.KeycloakSession; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.AbstractKeycloakTest; +import org.keycloak.testsuite.arquillian.annotation.ModelTest; +import org.keycloak.validate.SimpleValidator; +import org.keycloak.validate.ValidationContext; +import org.keycloak.validate.ValidationError; +import org.keycloak.validate.ValidationResult; +import org.keycloak.validate.Validator; +import org.keycloak.validate.ValidatorConfig; +import org.keycloak.validate.Validators; import org.keycloak.validate.validators.EmailValidator; import org.keycloak.validate.validators.LengthValidator; import org.keycloak.validate.validators.NotBlankValidator; +import org.keycloak.validate.BuiltinValidators; import org.keycloak.validate.validators.ValidatorConfigValidator; -public class ValidatorTest { +public class ValidatorsTest extends AbstractKeycloakTest { - KeycloakSession session = null; + @Override + public void addTestRealms(List testRealms) { + } @Test public void simpleValidation() { - Validator validator = Validators.notEmptyValidator(); + Validator validator = BuiltinValidators.notEmptyValidator(); Assert.assertTrue(validator.validate("a").isValid()); Assert.assertFalse(validator.validate("").isValid()); } @Test - public void simpleValidationWithContext() { + @ModelTest + public void simpleValidationWithContext(KeycloakSession session) { - Validator validator = Validators.lengthValidator(); + Validator validator = BuiltinValidators.lengthValidator(); ValidationContext context = new ValidationContext(session); validator.validate("a", "username", context); @@ -45,17 +78,19 @@ public void simpleValidationWithContext() { } @Test - public void simpleValidationFluent() { + @ModelTest + public void simpleValidationFluent(KeycloakSession session) { ValidationContext context = new ValidationContext(session); - ValidationResult result = Validators.lengthValidator().validate("a", "username", context).toResult(); + ValidationResult result = BuiltinValidators.lengthValidator().validate("a", "username", context).toResult(); Assert.assertTrue(result.isValid()); } @Test - public void simpleValidationLookup() { + @ModelTest + public void simpleValidationLookup(KeycloakSession session) { // later: session.validators().validator(LengthValidator.ID); Validator validator = Validators.validator(session, LengthValidator.ID); @@ -68,7 +103,8 @@ public void simpleValidationLookup() { } @Test - public void simpleValidationError() { + @ModelTest + public void simpleValidationError(KeycloakSession session) { Validator validator = LengthValidator.INSTANCE; @@ -104,20 +140,21 @@ public void simpleValidationError() { public void acceptOnError() { AtomicBoolean bool1 = new AtomicBoolean(); - Validators.notEmptyValidator().validate("a").toResult().ifNotValidAccept(r -> bool1.set(true)); + BuiltinValidators.notEmptyValidator().validate("a").toResult().ifNotValidAccept(r -> bool1.set(true)); Assert.assertFalse(bool1.get()); AtomicBoolean bool2 = new AtomicBoolean(); - Validators.notEmptyValidator().validate("").toResult().ifNotValidAccept(r -> bool2.set(true)); + BuiltinValidators.notEmptyValidator().validate("").toResult().ifNotValidAccept(r -> bool2.set(true)); Assert.assertTrue(bool2.get()); } @Test - public void forEachError() { + @ModelTest + public void forEachError(KeycloakSession session) { List errors = new ArrayList<>(); MockAddress faultyAddress = new MockAddress("", "Saint-Maur-des-Fossés", null, "Germany"); - MockAddressValidator.INSTANCE.validate(faultyAddress, "address").toResult().forEachError(e -> { + MockAddressValidator.INSTANCE.validate(faultyAddress, "address", new ValidationContext(session)).toResult().forEachError(e -> { errors.add(e.getMessage()); }); @@ -125,7 +162,8 @@ public void forEachError() { } @Test - public void formatError() { + @ModelTest + public void formatError(KeycloakSession session) { Map miniResourceBundle = new HashMap<>(); miniResourceBundle.put("error-invalid-blank", "{0} is blank: <{1}>"); @@ -133,7 +171,7 @@ public void formatError() { List errors = new ArrayList<>(); MockAddress faultyAddress = new MockAddress("", "Saint-Maur-des-Fossés", null, "Germany"); - MockAddressValidator.INSTANCE.validate(faultyAddress, "address").toResult().forEachError(e -> { + MockAddressValidator.INSTANCE.validate(faultyAddress, "address", new ValidationContext(session)).toResult().forEachError(e -> { errors.add(e.formatMessage((message, args) -> MessageFormat.format(miniResourceBundle.getOrDefault(message, message), args))); }); @@ -141,15 +179,16 @@ public void formatError() { } @Test - public void multipleValidations() { + @ModelTest + public void multipleValidations(KeycloakSession session) { ValidationContext context = new ValidationContext(session); String input = "aaa"; String inputHint = "username"; - Validators.lengthValidator().validate(input, inputHint, context); - Validators.notEmptyValidator().validate(input, inputHint, context); + BuiltinValidators.lengthValidator().validate(input, inputHint, context); + BuiltinValidators.notEmptyValidator().validate(input, inputHint, context); ValidationResult result = context.toResult(); @@ -157,15 +196,16 @@ public void multipleValidations() { } @Test - public void multipleValidationsError() { + @ModelTest + public void multipleValidationsError(KeycloakSession session) { ValidationContext context = new ValidationContext(session); String input = " "; String inputHint = "username"; - Validators.lengthValidator().validate(input, inputHint, context, configFromMap(Collections.singletonMap(LengthValidator.KEY_MIN, 1))); - Validators.notBlankValidator().validate(input, inputHint, context); + BuiltinValidators.lengthValidator().validate(input, inputHint, context, configFromMap(Collections.singletonMap(LengthValidator.KEY_MIN, 1))); + BuiltinValidators.notBlankValidator().validate(input, inputHint, context); ValidationResult result = context.toResult(); @@ -184,7 +224,8 @@ public void multipleValidationsError() { } @Test - public void validateValidatorConfigSimple() { + @ModelTest + public void validateValidatorConfigSimple(KeycloakSession session) { SimpleValidator validator = LengthValidator.INSTANCE; @@ -197,8 +238,9 @@ public void validateValidatorConfigSimple() { } @Test - public void validateEmailValidator() { - SimpleValidator validator = Validators.emailValidator(); + @ModelTest + public void validateEmailValidator(KeycloakSession session) { + SimpleValidator validator = BuiltinValidators.emailValidator(); Assert.assertTrue(validator.validateConfig(session, null).isValid()); Assert.assertTrue(validator.validateConfig(session, ValidatorConfig.EMPTY).isValid()); @@ -215,7 +257,8 @@ public void validateEmailValidator() { } @Test - public void validateValidatorConfigMultipleOptions() { + @ModelTest + public void validateValidatorConfigMultipleOptions(KeycloakSession session) { SimpleValidator validator = LengthValidator.INSTANCE; @@ -229,7 +272,8 @@ public void validateValidatorConfigMultipleOptions() { } @Test - public void validateValidatorConfigMultipleOptionsInvalidValues() { + @ModelTest + public void validateValidatorConfigMultipleOptionsInvalidValues(KeycloakSession session) { SimpleValidator validator = LengthValidator.INSTANCE; @@ -253,7 +297,8 @@ public void validateValidatorConfigMultipleOptionsInvalidValues() { } @Test - public void validateValidatorConfigViaValidatorFactory() { + @ModelTest + public void validateValidatorConfigViaValidatorFactory(KeycloakSession session) { Map config = new HashMap<>(); config.put("min", "a"); @@ -275,15 +320,16 @@ public void validateValidatorConfigViaValidatorFactory() { } @Test - public void nestedValidation() { + @ModelTest + public void nestedValidation(KeycloakSession session) { Assert.assertTrue(MockAddressValidator.INSTANCE.validate( new MockAddress("4848 Arcu St.", "Saint-Maur-des-Fossés", "02206", "Germany") - , "address").isValid()); + , "address", new ValidationContext(session)).isValid()); ValidationResult result = MockAddressValidator.INSTANCE.validate( new MockAddress("", "Saint-Maur-des-Fossés", null, "Germany") - , "address").toResult(); + , "address", new ValidationContext(session)).toResult(); Assert.assertFalse(result.isValid()); Assert.assertEquals(2, result.getErrors().size()); diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_en.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_en.properties index da90117b3123..ccf4342cdee6 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_en.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_en.properties @@ -1,3 +1,2 @@ -#encoding: utf-8 locale_test=Přísný jazyk client_localized-client=Přespříliš lokalizovaný klient diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_test.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_test.properties index 41173f4cc4a0..b2cc17b5a0b5 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_test.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme-preview/account/messages/messages_test.properties @@ -1,4 +1,3 @@ -#encoding: utf-8 locale_test=Přísný jazyk accountManagementWelcomeMessage=Vítejte v Keycloaku personalInfoHtmlTitle=Osobní údaje \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_en.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_en.properties index da90117b3123..ccf4342cdee6 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_en.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_en.properties @@ -1,3 +1,2 @@ -#encoding: utf-8 locale_test=Přísný jazyk client_localized-client=Přespříliš lokalizovaný klient diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_test.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_test.properties index 41173f4cc4a0..b2cc17b5a0b5 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_test.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/account/messages/messages_test.properties @@ -1,4 +1,3 @@ -#encoding: utf-8 locale_test=Přísný jazyk accountManagementWelcomeMessage=Vítejte v Keycloaku personalInfoHtmlTitle=Osobní údaje \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_en.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_en.properties index d5ac3fa3ad00..fc49db6b0a4c 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_en.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_en.properties @@ -1,2 +1 @@ -#encoding: utf-8 locale_test=Přísný jazyk diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_test.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_test.properties index 363f47efd009..0eda2dc94ce6 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_test.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/email/messages/messages_test.properties @@ -1,2 +1 @@ -#encoding: utf-8 locale_test=Přísný jazyk \ No newline at end of file diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_en.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_en.properties index d5ac3fa3ad00..fc49db6b0a4c 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_en.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_en.properties @@ -1,2 +1 @@ -#encoding: utf-8 locale_test=Přísný jazyk diff --git a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_test.properties b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_test.properties index 42f3e4a00ca5..555e51305d54 100644 --- a/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_test.properties +++ b/testsuite/integration-arquillian/tests/other/base-ui/src/main/resources/themes/localized-theme/login/messages/messages_test.properties @@ -1,4 +1,3 @@ -#encoding: utf-8 locale_test=Přísný jazyk termsText=[TEST LOCALE] souhlas s podmínkami notMatchPasswordMessage=[TEST LOCALE] hesla se neshodují diff --git a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AccountLinkSpringBootTest.java b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AccountLinkSpringBootTest.java index e5255cef4e7e..7311bd1ba623 100644 --- a/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AccountLinkSpringBootTest.java +++ b/testsuite/integration-arquillian/tests/other/springboot-tests/src/test/java/org/keycloak/testsuite/springboot/AccountLinkSpringBootTest.java @@ -466,7 +466,7 @@ public void testLinkOnlyProvider() throws Exception { links = realm.users().get(childUserId).getFederatedIdentity(); assertThat(links, is(empty())); - pause(500) + pause(500); logoutAll(); diff --git a/testsuite/model/README.md b/testsuite/model/README.md index 45fc693701a6..e992cd433cac 100644 --- a/testsuite/model/README.md +++ b/testsuite/model/README.md @@ -49,76 +49,4 @@ mvn test -Pjpa -Dtest=ClientModelTest \ The results are available in the `target/profile.html` file. -Usage of Testcontainers ------------------------ - -Some profiles within model tests require running 3rd party software, for -example, database or Infinispan. For running these we are using -[Testcontainers](https://www.testcontainers.org/). This may require some -additional configuration of your container engine. - -#### Podman settings - -For more details see the following [Podman guide from Quarkus webpage](https://quarkus.io/guides/podman). - -Specifically, these steps are required: -```shell -# Enable the podman socket with Docker REST API (only needs to be done once) -systemctl --user enable podman.socket --now - -# Set the required environment variables (need to be run everytime or added to profile) -export DOCKER_HOST=unix:///run/user/${UID}/podman/podman.sock -``` - -Testcontainers are using [ryuk](https://hub.docker.com/r/testcontainers/ryuk) -to cleanup containers after tests. To make this work with Podman add the -following line to `~/.testcontainers.properties` -```shell -ryuk.container.privileged=true -``` -Alternatively, disable usage of ryuk (using this may result in stale containers -still running after tests finish. This is not recommended especially if you are -executing tests from Intellij IDE as it [may not stop](https://youtrack.jetbrains.com/issue/IDEA-190385) -the containers created during test run). -```shell -export TESTCONTAINERS_RYUK_DISABLED=true #not recommended - see above! -``` - -#### Docker settings - -To use Testcontainers with Docker it is necessary to -[make Docker available for non-root users](https://docs.docker.com/engine/install/linux-postinstall/). - -Running HotRod tests with external Infinispan ---------------------------------------------- - -By default, Model tests with `hot-rod` profile spawn a new Infinispan container -with each test execution. It is also possible, to configure Model tests to -connect to an external instance of Infinispan. To do so, execute tests with -the following command: -```shell -mvn test -Phot-rod \ - -Dkeycloak.testsuite.start-hotrod-container=false \ - -Dkeycloak.connectionsHotRod.host= \ - -Dkeycloak.connectionsHotRod.port= \ - -Dkeycloak.connectionsHotRod.username= \ - -Dkeycloak.connectionsHotRod.password= -``` - -Running tests with `map-jpa` profile using external Postgres database ---------------------------------------------- - -By default, Model tests with `map-jpa` profile spawns a new Postgres container -with each test execution. Default image used is "postgres:alpine". To spawn different -version, it can be used "keycloak.map.storage.postgres.docker.image" system property. - -It is also possible, to configure Model tests to connect to an external instance -of Postgres. To do so, execute tests with the following command: -```shell -mvn test -Pmap-jpa \ - -Dpostgres.start-container=false \ - -Dkeycloak.map.storage.connectionsJpa.url= \ - -Dkeycloak.map.storage.connectionsJpa.user= \ - -Dkeycloak.map.storage.connectionsJpa.password= -``` diff --git a/testsuite/model/pom.xml b/testsuite/model/pom.xml index a94e48310857..f866f1b54131 100644 --- a/testsuite/model/pom.xml +++ b/testsuite/model/pom.xml @@ -29,7 +29,6 @@ ${h2.version} file:${project.build.directory}/dependency/log4j.properties true - disabled false @@ -93,23 +92,11 @@ org.keycloak keycloak-model-infinispan - - org.keycloak - keycloak-model-map - org.keycloak.testsuite integration-arquillian-testsuite-providers ${project.version} - - org.keycloak - keycloak-model-map-hot-rod - - - org.keycloak - keycloak-model-map-ldap - org.infinispan infinispan-core-jakarta @@ -119,18 +106,6 @@ postgresql ${postgresql-jdbc.version} - - org.testcontainers - testcontainers - ${testcontainers.version} - test - - - org.testcontainers - postgresql - ${testcontainers.version} - test - org.infinispan @@ -181,11 +156,7 @@ ${keycloak.connectionsJpa.user} ${keycloak.connectionsJpa.password} ${keycloak.connectionsJpa.url} - ${keycloak.map.storage.connectionsJpa.url} - ${keycloak.map.storage.connectionsJpa.user} - ${keycloak.map.storage.connectionsJpa.password} file:${project.build.directory}/test-classes/log4j.properties - ${keycloak.profile.feature.map_storage} ${keycloak.userSessions.infinispan.preloadOfflineSessionsFromDatabase} org.jboss.logmanager.LogManager log4j @@ -200,26 +171,6 @@ - - org.apache.maven.plugins - maven-antrun-plugin - - - process-test-resources - - run - - - - - - - - - - - - maven-dependency-plugin @@ -341,46 +292,6 @@ - - map - - enabled - Map,ConcurrentHashMapStorage - - - - - file - - enabled - Map,FileMapStorage - - - - - hot-rod - - enabled - Map,HotRodMapStorage - - - - - map-ldap - - enabled - Map,LdapMapStorage - - - - - map-jpa - - enabled - Map,JpaMapStorage - - - .asyncProfiler diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/ConcurrentHashMapStorageTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/ConcurrentHashMapStorageTest.java deleted file mode 100644 index b64c1901cd9e..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/ConcurrentHashMapStorageTest.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright 2020 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model; - -import org.hamcrest.Matchers; -import org.jboss.logging.Logger; -import org.junit.Before; -import org.junit.Test; -import org.keycloak.component.ComponentModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.ClientProvider; -import org.keycloak.models.Constants; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.map.client.MapClientEntity; -import org.keycloak.models.map.client.MapClientEntityImpl; -import org.keycloak.models.map.client.MapClientProviderFactory; -import org.keycloak.models.map.common.DeepCloner; -import org.keycloak.models.map.common.StringKeyConverter; -import org.keycloak.models.map.storage.MapStorage; -import org.keycloak.models.map.storage.MapStorageProvider; -import org.keycloak.models.map.storage.MapStorageProviderFactory; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorage; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.utils.KeycloakModelUtils; -import org.keycloak.provider.InvalidationHandler; - -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.nullValue; - - -/** - * - * @author hmlnarik - */ -@RequireProvider(value = ClientProvider.class, only = {MapClientProviderFactory.PROVIDER_ID}) -@RequireProvider(RealmProvider.class) -@RequireProvider(value = MapStorageProvider.class, only = {ConcurrentHashMapStorageProviderFactory.PROVIDER_ID}) -public class ConcurrentHashMapStorageTest extends KeycloakModelTest { - - private static final Logger LOG = Logger.getLogger(ConcurrentHashMapStorageTest.class.getName()); - - private String realmId; - - private String mapStorageProviderId; - - @Before - public void initMapStorageProviderId() { - MapStorageProviderFactory ms = (MapStorageProviderFactory) getFactory().getProviderFactory(MapStorageProvider.class, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID); - mapStorageProviderId = ms.getId(); - assertThat(mapStorageProviderId, Matchers.notNullValue()); - } - - @Override - public void createEnvironment(KeycloakSession s) { - RealmModel realm = createRealm(s, "realm"); - realm.setDefaultRole(s.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName())); - this.realmId = realm.getId(); - } - - @Override - public void cleanEnvironment(KeycloakSession s) { - s.realms().removeRealm(realmId); - } - - @Test - @SuppressWarnings("unchecked") - public void testStorageSeparation() { - String component1Id = createMapStorageComponent("component1", "keyType", "ulong"); - String component2Id = createMapStorageComponent("component2", "keyType", "string"); - - String[] ids = withRealm(realmId, (session, realm) -> { - ConcurrentHashMapStorage storageMain = (ConcurrentHashMapStorage) (MapStorage) session.getProvider(MapStorageProvider.class, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID).getMapStorage(ClientModel.class); - ConcurrentHashMapStorage storage1 = (ConcurrentHashMapStorage) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getMapStorage(ClientModel.class); - ConcurrentHashMapStorage storage2 = (ConcurrentHashMapStorage) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getMapStorage(ClientModel.class); - - // Assert that the map storage can be used both as a standalone store and a component - assertThat(storageMain, notNullValue()); - assertThat(storage1, notNullValue()); - assertThat(storage2, notNullValue()); - - final StringKeyConverter kcMain = (StringKeyConverter) StringKeyConverter.UUIDKey.INSTANCE; - final StringKeyConverter kc1 = (StringKeyConverter) StringKeyConverter.ULongKey.INSTANCE; - final StringKeyConverter kc2 = (StringKeyConverter) StringKeyConverter.StringKey.INSTANCE; - - String idMain = kcMain.keyToString(kcMain.yieldNewUniqueKey()); - String id1 = kc1.keyToString(kc1.yieldNewUniqueKey()); - String id2 = kc2.keyToString(kc2.yieldNewUniqueKey()); - - assertThat(idMain, notNullValue()); - assertThat(id1, notNullValue()); - assertThat(id2, notNullValue()); - - // Assert that the stores do not contain the to-be-created clients - assertThat(storageMain.read(idMain), nullValue()); - assertThat(storage1.read(id1), nullValue()); - assertThat(storage2.read(id2), nullValue()); - - assertClientDoesNotExist(storageMain, id1, kc1, kcMain); - assertClientDoesNotExist(storageMain, id2, kc2, kcMain); - assertClientDoesNotExist(storage1, idMain, kcMain, kc1); - assertClientDoesNotExist(storage1, id2, kc2, kc1); - assertClientDoesNotExist(storage2, idMain, kcMain, kc2); - assertClientDoesNotExist(storage2, id1, kc1, kc2); - - MapClientEntity clientMain = new MapClientEntityImpl(DeepCloner.DUMB_CLONER); - clientMain.setId(idMain); - clientMain.setRealmId(realmId); - MapClientEntity client1 = new MapClientEntityImpl(DeepCloner.DUMB_CLONER); - client1.setId(id1); - client1.setRealmId(realmId); - MapClientEntity client2 = new MapClientEntityImpl(DeepCloner.DUMB_CLONER); - client2.setId(id2); - client2.setRealmId(realmId); - - clientMain = storageMain.create(clientMain); - client1 = storage1.create(client1); - client2 = storage2.create(client2); - - return new String[] {clientMain.getId(), client1.getId(), client2.getId()}; - }); - - String idMain = ids[0]; - String id1 = ids[1]; - String id2 = ids[2]; - - LOG.debugf("Object IDs: %s, %s, %s", idMain, id1, id2); - - assertClientsPersisted(component1Id, component2Id, idMain, id1, id2); - - // Invalidate one component and check that the storage still contains what it should - getFactory().invalidate(null, InvalidationHandler.ObjectType.COMPONENT, component1Id); - assertClientsPersisted(component1Id, component2Id, idMain, id1, id2); - - // Invalidate whole realm and check that the storage still contains what it should - getFactory().invalidate(null, InvalidationHandler.ObjectType.REALM, realmId); - assertClientsPersisted(component1Id, component2Id, idMain, id1, id2); - - // Refresh factory (akin server restart) and check that the storage still contains what it should - reinitializeKeycloakSessionFactory(); - assertClientsPersisted(component1Id, component2Id, idMain, id1, id2); - } - - private void assertClientDoesNotExist(ConcurrentHashMapStorage storage, String id, final StringKeyConverter kc, final StringKeyConverter kcStorage) { - // Assert that the other stores do not contain the to-be-created clients (if they use compatible key format) - try { - assertThat(storage.read(id), nullValue()); - } catch (Exception ex) { - // If the format is incompatible then the object does not exist in the store - } - } - - private void assertClientsPersisted(String component1Id, String component2Id, String idMain, String id1, String id2) { - // Check that in the next transaction, the objects are still there - withRealm(realmId, (session, realm) -> { - @SuppressWarnings("unchecked") - ConcurrentHashMapStorage storageMain = (ConcurrentHashMapStorage) (MapStorage) session.getProvider(MapStorageProvider.class, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID).getMapStorage(ClientModel.class); - @SuppressWarnings("unchecked") - ConcurrentHashMapStorage storage1 = (ConcurrentHashMapStorage) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component1Id).getMapStorage(ClientModel.class); - @SuppressWarnings("unchecked") - ConcurrentHashMapStorage storage2 = (ConcurrentHashMapStorage) (MapStorage) session.getComponentProvider(MapStorageProvider.class, component2Id).getMapStorage(ClientModel.class); - - final StringKeyConverter kcMain = (StringKeyConverter) StringKeyConverter.UUIDKey.INSTANCE; - final StringKeyConverter kc1 = (StringKeyConverter) StringKeyConverter.ULongKey.INSTANCE; - final StringKeyConverter kc2 = (StringKeyConverter) StringKeyConverter.StringKey.INSTANCE; - - // Assert that the stores contain the created clients - assertThat(storageMain.read(idMain), notNullValue()); - assertThat(storage1.read(id1), notNullValue()); - assertThat(storage2.read(id2), notNullValue()); - - // Assert that the other stores do not contain the to-be-created clients (if they use compatible key format) - assertClientDoesNotExist(storageMain, id1, kc1, kcMain); - assertClientDoesNotExist(storageMain, id2, kc2, kcMain); - assertClientDoesNotExist(storage1, idMain, kcMain, kc1); - assertClientDoesNotExist(storage1, id2, kc2, kc1); - assertClientDoesNotExist(storage2, idMain, kcMain, kc2); - assertClientDoesNotExist(storage2, id1, kc1, kc2); - assertThat(storageMain.read(idMain), notNullValue()); - - return null; - }); - } - - private String createMapStorageComponent(String name, String... config) { - ComponentModel c1 = KeycloakModelUtils.createComponentModel(name, realmId, mapStorageProviderId, MapStorageProvider.class.getName(), config); - - return withRealm(realmId, (s, r) -> r.addComponentModel(c1).getId()); - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/client/ClientModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/client/ClientModelTest.java index 596ff38d1a01..0824644f2543 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/client/ClientModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/client/ClientModelTest.java @@ -16,10 +16,7 @@ */ package org.keycloak.testsuite.model.client; -import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; @@ -28,23 +25,17 @@ import org.junit.Test; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientProvider; -import org.keycloak.models.ClientScopeModel; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.RoleModel; import org.keycloak.models.RoleProvider; -import org.keycloak.models.map.client.MapClientProvider; -import org.keycloak.models.map.client.MapClientProviderFactory; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; /** * @@ -154,23 +145,6 @@ public void testClientsBasics() { } } - @Test - @RequireProvider(value = ClientProvider.class, only = MapClientProviderFactory.PROVIDER_ID) - public void testDeleteClientUsingQueryParameters() { - final String CLIENT_ID = "createDeleteClientId"; - // Create client - withRealm(realmId, (session, realm) -> session.clients().addClient(realm, CLIENT_ID)); - - // Check if exists - assertThat(withRealm(realmId, (session, realm) -> session.clients().getClientByClientId(realm, CLIENT_ID)), notNullValue()); - - // Remove - withRealm(realmId, (session, realm) -> {((MapClientProvider)session.clients()).preRemove(realm); return null;}); - - // Check is null - assertThat(withRealm(realmId, (session, realm) -> session.clients().getClientByClientId(realm, CLIENT_ID)), nullValue()); - } - @Test public void testScopeMappingRoleRemoval() { // create two clients, one realm role and one client role and assign both to one of the clients diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/AdminEventQueryTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/AdminEventQueryTest.java index aa411e1210fc..bc961c1e14e8 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/AdminEventQueryTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/AdminEventQueryTest.java @@ -17,8 +17,11 @@ package org.keycloak.testsuite.model.events; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; +import org.apache.commons.lang3.RandomStringUtils; import org.junit.Test; import org.keycloak.common.ClientConnection; import org.keycloak.events.EventStoreProvider; @@ -38,6 +41,7 @@ import org.keycloak.testsuite.model.RequireProvider; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @RequireProvider(EventStoreProvider.class) @@ -113,6 +117,30 @@ public void testQueryOrder() { }); } + @Test + public void testAdminEventRepresentationLongValue() { + String longValue = RandomStringUtils.random(30000, true, true); + + withRealm(realmId, (session, realm) -> { + + AdminEvent event = createClientEvent(realm, OperationType.CREATE); + event.setRepresentation(longValue); + + session.getProvider(EventStoreProvider.class).onEvent(event, true); + + return null; + }); + + withRealm(realmId, (session, realm) -> { + List events = session.getProvider(EventStoreProvider.class).createAdminQuery().realm(realmId).getResultStream().collect(Collectors.toList()); + assertThat(events, hasSize(1)); + + assertThat(events.get(0).getRepresentation(), equalTo(longValue)); + + return null; + }); + } + private AdminEvent createClientEvent(RealmModel realm, OperationType operation) { return new AdminEventBuilder(realm, new DummyAuth(realm), null, DummyClientConnection.DUMMY_CONNECTION) .resource(ResourceType.CLIENT).operation(operation).getEvent(); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/EventQueryTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/EventQueryTest.java index 7d9f86bd5243..ffadf60ce9ee 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/EventQueryTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/events/EventQueryTest.java @@ -20,26 +20,21 @@ import org.keycloak.events.Event; import org.keycloak.events.EventBuilder; import org.keycloak.events.EventStoreProvider; -import org.keycloak.events.EventStoreSpi; import org.keycloak.events.EventType; -import org.keycloak.events.admin.AdminEvent; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; -import org.keycloak.models.map.events.MapEventStoreProviderFactory; -import org.keycloak.models.map.storage.file.FileMapStorageProviderFactory; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; import java.util.List; -import java.util.Set; -import java.util.function.Consumer; +import java.util.Map; import java.util.stream.Collectors; +import org.apache.commons.lang3.RandomStringUtils; import org.junit.Test; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; -import static org.junit.Assume.assumeFalse; /** * @@ -64,12 +59,6 @@ public void cleanEnvironment(KeycloakSession s) { @Test public void testClear() { - // Skip the test if EventProvider == File - String evProvider = CONFIG.getConfig().get(EventStoreSpi.NAME + ".provider"); - String evMapStorageProvider = CONFIG.getConfig().get(EventStoreSpi.NAME + ".map.storage-auth-events.provider"); - assumeFalse(MapEventStoreProviderFactory.PROVIDER_ID.equals(evProvider) && - (evMapStorageProvider == null || FileMapStorageProviderFactory.PROVIDER_ID.equals(evMapStorageProvider))); - inRolledBackTransaction(null, (session, t) -> { EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); eventStore.clear(); @@ -149,81 +138,35 @@ public void testQueryOrder() { }); } - @Test - @RequireProvider(value = EventStoreProvider.class, only = "map") - public void testEventExpiration() { - withRealm(realmId, (session, realm) -> { - EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); - - // Set expiration so no event is valid - realm.setEventsExpiration(5); - Event e = createAuthEventForUser(session, realm, "u1"); - eventStore.onEvent(e); - - // Set expiration to 1000 seconds - realm.setEventsExpiration(1000); - e = createAuthEventForUser(session, realm, "u2"); - eventStore.onEvent(e); - - return null; - }); - - setTimeOffset(10); - - try { - withRealm(realmId, (session, realm) -> { - EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); - - Set events = eventStore.createQuery() - .realm(realmId) - .getResultStream().collect(Collectors.toSet()); - - assertThat(events, hasSize(1)); - assertThat(events.iterator().next().getUserId(), equalTo("u2")); - return null; - }); - } finally { - setTimeOffset(0); - } + public void testEventDetailsLongValue() { + String v1 = RandomStringUtils.random(1000, true, true); + String v2 = RandomStringUtils.random(1000, true, true); + String v3 = RandomStringUtils.random(1000, true, true); + String v4 = RandomStringUtils.random(1000, true, true); + withRealm(realmId, (session, realm) -> { - } - - @Test - @RequireProvider(value = EventStoreProvider.class, only = "map") - public void testEventsClearedOnRealmRemoval() { - // Create another realm - String newRealmId = inComittedTransaction(null, (session, t) -> { - RealmModel realm = session.realms().createRealm("events-realm"); - realm.setDefaultRole(session.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName())); - - EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); - Event e = createAuthEventForUser(session, realm, "u1"); - eventStore.onEvent(e); + Map details = Map.of("k1", v1, "k2", v2, "k3", v3, "k4", v4); - AdminEvent ae = new AdminEvent(); - ae.setRealmId(realm.getId()); - eventStore.onEvent(ae, false); + Event event = createAuthEventForUser(session, realm, "u1"); + event.setDetails(details); - return realm.getId(); - }); + session.getProvider(EventStoreProvider.class).onEvent(event); - // Check if events were created - inComittedTransaction(session -> { - EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); - assertThat(eventStore.createQuery().realm(newRealmId).getResultStream().count(), is(1L)); - assertThat(eventStore.createAdminQuery().realm(newRealmId).getResultStream().count(), is(1L)); + return null; }); - // Remove realm - inComittedTransaction((Consumer) session -> session.realms().removeRealm(newRealmId)); - - // Check events were removed - inComittedTransaction(session -> { - EventStoreProvider eventStore = session.getProvider(EventStoreProvider.class); - assertThat(eventStore.createQuery().realm(newRealmId).getResultStream().count(), is(0L)); - assertThat(eventStore.createAdminQuery().realm(newRealmId).getResultStream().count(), is(0L)); + withRealm(realmId, (session, realm) -> { + List events = session.getProvider(EventStoreProvider.class).createQuery().realm(realmId).getResultStream().collect(Collectors.toList()); + assertThat(events, hasSize(1)); + Map details = events.get(0).getDetails(); + + assertThat(details.get("k1"), equalTo(v1)); + assertThat(details.get("k2"), equalTo(v2)); + assertThat(details.get("k3"), equalTo(v3)); + assertThat(details.get("k4"), equalTo(v4)); + return null; }); } diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java deleted file mode 100644 index 71f7ac34e073..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/ConcurrentHashMapStorage.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import org.keycloak.common.crypto.CryptoIntegration; -import org.keycloak.common.crypto.CryptoProvider; -import org.keycloak.exportimport.ExportSpi; -import org.keycloak.exportimport.ImportSpi; -import org.keycloak.exportimport.dir.DirExportProviderFactory; -import org.keycloak.exportimport.dir.DirImportProviderFactory; -import org.keycloak.exportimport.singlefile.SingleFileExportProviderFactory; -import org.keycloak.exportimport.singlefile.SingleFileImportProviderFactory; -import org.keycloak.keys.KeyProviderFactory; -import org.keycloak.keys.KeySpi; -import org.keycloak.models.ClientScopeSpi; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.services.clientpolicy.ClientPolicyManagerFactory; -import org.keycloak.services.clientpolicy.ClientPolicyManagerSpi; -import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicyFactory; -import org.keycloak.services.clientregistration.policy.ClientRegistrationPolicySpi; -import org.keycloak.testsuite.model.KeycloakModelParameters; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.testsuite.model.Config; -import com.google.common.collect.ImmutableSet; -import java.util.Set; - -/** - * - * @author hmlnarik - */ -public class ConcurrentHashMapStorage extends KeycloakModelParameters { - - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .add(ExportSpi.class) - .add(ClientPolicyManagerSpi.class) - .add(ImportSpi.class) - .add(ClientRegistrationPolicySpi.class) - .add(ClientScopeSpi.class) - .add(KeySpi.class) - .build(); - - static { - // CryptoIntegration needed for import of realms - CryptoIntegration.init(CryptoProvider.class.getClassLoader()); - } - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(ConcurrentHashMapStorageProviderFactory.class) - // start providers needed for export - .add(SingleFileExportProviderFactory.class) - .add(DirExportProviderFactory.class) - .add(ClientPolicyManagerFactory.class) - // end providers needed for export - // start providers needed for import - .add(SingleFileImportProviderFactory.class) - .add(DirImportProviderFactory.class) - .add(ClientRegistrationPolicyFactory.class) - .add(KeyProviderFactory.class) - // end providers needed for import - .build(); - - @Override - public void updateConfig(Config cf) { - cf.spi(MapStorageSpi.NAME) - .defaultProvider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target}"); - } - - public ConcurrentHashMapStorage() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/FileMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/FileMapStorage.java deleted file mode 100644 index f3c4b55749af..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/FileMapStorage.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import org.keycloak.authorization.store.StoreFactorySpi; -import org.keycloak.events.EventStoreSpi; -import org.keycloak.models.DeploymentStateSpi; -import org.keycloak.models.SingleUseObjectSpi; -import org.keycloak.models.UserLoginFailureSpi; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.map.authSession.MapRootAuthenticationSessionProviderFactory; -import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory; -import org.keycloak.models.map.client.MapClientProviderFactory; -import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory; -import org.keycloak.models.map.deploymentState.MapDeploymentStateProviderFactory; -import org.keycloak.models.map.events.MapEventStoreProviderFactory; -import org.keycloak.models.map.group.MapGroupProviderFactory; -import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory; -import org.keycloak.models.map.loginFailure.MapUserLoginFailureProviderFactory; -import org.keycloak.models.map.realm.MapRealmProviderFactory; -import org.keycloak.models.map.role.MapRoleProviderFactory; -import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.storage.file.FileMapStorageProviderFactory; -import org.keycloak.models.map.user.MapUserProviderFactory; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.sessions.AuthenticationSessionSpi; -import org.keycloak.testsuite.model.Config; -import org.keycloak.testsuite.model.KeycloakModelParameters; - -public class FileMapStorage extends KeycloakModelParameters { - - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .build(); - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(FileMapStorageProviderFactory.class) - .add(ConcurrentHashMapStorageProviderFactory.class) - .build(); - - public FileMapStorage() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - - @Override - public void updateConfig(Config cf) { - cf.spi(MapStorageSpi.NAME) - .provider(FileMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target/file}") - .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target/chm}") - - .spi(AuthenticationSessionSpi.PROVIDER_ID).provider(MapRootAuthenticationSessionProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi("client").provider(MapClientProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi("clientScope").provider(MapClientScopeProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi("group").provider(MapGroupProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi("role").provider(MapRoleProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi("user").provider(MapUserProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi(UserLoginFailureSpi.NAME).provider(MapUserLoginFailureProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi(SingleUseObjectSpi.NAME).provider(MapSingleUseObjectProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("publicKeyStorage").provider(MapPublicKeyStorageProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(UserSessionSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, FileMapStorageProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).provider(MapEventStoreProviderFactory.PROVIDER_ID) .config("storage-admin-events.provider", FileMapStorageProviderFactory.PROVIDER_ID) - .config("storage-auth-events.provider", FileMapStorageProviderFactory.PROVIDER_ID); - } - -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java deleted file mode 100644 index d894ea41a7c5..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/HotRodMapStorage.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2020 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import com.google.common.collect.ImmutableSet; -import org.jboss.logging.Logger; -import org.keycloak.authorization.store.StoreFactorySpi; -import org.keycloak.events.EventStoreSpi; -import org.keycloak.models.DeploymentStateSpi; -import org.keycloak.models.SingleUseObjectSpi; -import org.keycloak.models.UserLoginFailureSpi; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.locking.GlobalLockProviderSpi; -import org.keycloak.models.locking.NoneGlobalLockProviderFactory; -import org.keycloak.models.map.authSession.MapRootAuthenticationSessionProviderFactory; -import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory; -import org.keycloak.models.map.client.MapClientProviderFactory; -import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory; -import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory; -import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.DefaultHotRodConnectionProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.HotRodConnectionProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.HotRodConnectionSpi; -import org.keycloak.models.map.deploymentState.MapDeploymentStateProviderFactory; -import org.keycloak.models.map.group.MapGroupProviderFactory; -import org.keycloak.models.map.loginFailure.MapUserLoginFailureProviderFactory; -import org.keycloak.models.map.realm.MapRealmProviderFactory; -import org.keycloak.models.map.role.MapRoleProviderFactory; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.storage.hotRod.HotRodMapStorageProviderFactory; -import org.keycloak.models.map.storage.hotRod.locking.HotRodGlobalLockProviderFactory; -import org.keycloak.models.map.user.MapUserProviderFactory; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.sessions.AuthenticationSessionSpi; -import org.keycloak.testsuite.model.Config; -import org.keycloak.testsuite.model.KeycloakModelParameters; -import org.keycloak.testsuite.util.InfinispanContainer; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.Wait; - -import java.time.Duration; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import static org.keycloak.testsuite.model.transaction.StorageTransactionTest.LOCK_TIMEOUT_SYSTEM_PROPERTY; - -/** - * - * @author hmlnarik - */ -public class HotRodMapStorage extends KeycloakModelParameters { - - private final Logger LOG = Logger.getLogger(getClass()); - public static final Boolean START_CONTAINER = Boolean.valueOf(System.getProperty("keycloak.testsuite.start-hotrod-container", "true")); - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .add(HotRodConnectionSpi.class) - .build(); - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(HotRodMapStorageProviderFactory.class) - .add(HotRodConnectionProviderFactory.class) - .add(HotRodGlobalLockProviderFactory.class) - .build(); - - private final InfinispanContainer hotRodContainer = new InfinispanContainer(); - - @Override - public void updateConfig(Config cf) { - cf.spi(AuthenticationSessionSpi.PROVIDER_ID).provider(MapRootAuthenticationSessionProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi(SingleUseObjectSpi.NAME).provider(MapSingleUseObjectProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi("publicKeyStorage").provider(MapPublicKeyStorageProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("client").provider(MapClientProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi("clientScope").provider(MapClientScopeProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi("group").provider(MapGroupProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi("role").provider(MapRoleProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi("user").provider(MapUserProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi(UserSessionSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi(UserLoginFailureSpi.NAME).provider(MapUserLoginFailureProviderFactory.PROVIDER_ID).config(STORAGE_CONFIG, HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID).config("storage-admin-events.provider", HotRodMapStorageProviderFactory.PROVIDER_ID) - .config("storage-auth-events.provider", HotRodMapStorageProviderFactory.PROVIDER_ID) - .spi(GlobalLockProviderSpi.GLOBAL_LOCK).defaultProvider(HotRodGlobalLockProviderFactory.PROVIDER_ID); - - cf.spi(MapStorageSpi.NAME) - .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target}") - .config("keyType.single-use-objects", "string"); - - cf.spi(HotRodConnectionSpi.NAME).provider(DefaultHotRodConnectionProviderFactory.PROVIDER_ID) - .config("host", hotRodContainer.getHost()) - .config("port", hotRodContainer.getPort()) - .config("username", hotRodContainer.getUsername()) - .config("password", hotRodContainer.getPassword()) - .config("configureRemoteCaches", "true") - .config("lockTimeout", "${" + LOCK_TIMEOUT_SYSTEM_PROPERTY + ":}"); - } - - @Override - public void beforeSuite(Config cf) { - if (START_CONTAINER) { - hotRodContainer.start(); - } - } - - @Override - public void afterSuite() { - if (START_CONTAINER) { - hotRodContainer.stop(); - } - } - - public HotRodMapStorage() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/JpaMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/JpaMapStorage.java deleted file mode 100644 index 913e496c2928..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/JpaMapStorage.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2020 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import com.google.common.collect.ImmutableSet; -import java.util.Set; -import org.jboss.logging.Logger; -import org.keycloak.authorization.store.StoreFactorySpi; -import org.keycloak.events.EventStoreSpi; -import org.keycloak.models.DeploymentStateSpi; -import org.keycloak.models.SingleUseObjectSpi; -import org.keycloak.models.UserLoginFailureSpi; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.locking.GlobalLockProviderSpi; -import org.keycloak.models.map.authSession.MapRootAuthenticationSessionProviderFactory; -import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory; -import org.keycloak.models.map.client.MapClientProviderFactory; -import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory; -import org.keycloak.models.map.deploymentState.MapDeploymentStateProviderFactory; -import org.keycloak.models.map.events.MapEventStoreProviderFactory; -import org.keycloak.models.map.group.MapGroupProviderFactory; -import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory; -import org.keycloak.models.map.loginFailure.MapUserLoginFailureProviderFactory; -import org.keycloak.models.map.realm.MapRealmProviderFactory; -import org.keycloak.models.map.role.MapRoleProviderFactory; -import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.lock.MapGlobalLockProviderFactory; -import org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory; -import org.keycloak.models.map.storage.jpa.liquibase.connection.MapLiquibaseConnectionProviderFactory; -import org.keycloak.models.map.storage.jpa.liquibase.connection.MapLiquibaseConnectionSpi; -import org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterProviderFactory; -import org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterSpi; -import org.keycloak.models.map.user.MapUserProviderFactory; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.sessions.AuthenticationSessionSpi; -import org.keycloak.testsuite.model.Config; -import org.keycloak.testsuite.model.KeycloakModelParameters; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.utility.DockerImageName; - -import static org.keycloak.testsuite.model.transaction.StorageTransactionTest.LOCK_TIMEOUT_SYSTEM_PROPERTY; - -public class JpaMapStorage extends KeycloakModelParameters { - - private static final Logger LOG = Logger.getLogger(JpaMapStorage.class.getName()); - - private static final Boolean START_CONTAINER = Boolean.valueOf(System.getProperty("postgres.start-container", "true")); - private static final String POSTGRES_DOCKER_IMAGE_NAME = System.getProperty("keycloak.map.storage.postgres.docker.image", "postgres:alpine"); - private static final PostgreSQLContainer POSTGRES_CONTAINER = new PostgreSQLContainer(DockerImageName.parse(POSTGRES_DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("postgres")); - private static final String POSTGRES_DB_DEFAULT_NAME = System.getProperty("keycloak.map.storage.connectionsJpa.databaseName", "keycloak"); - private static final String POSTGRES_DB_USER = System.getProperty("keycloak.map.storage.connectionsJpa.user", "keycloak"); - private static final String POSTGRES_DB_PASSWORD = System.getProperty("keycloak.map.storage.connectionsJpa.password", "pass"); - - private static String POSTGRES_DB_JDBC_URL = System.getProperty("keycloak.map.storage.connectionsJpa.url"); - - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .add(MapJpaUpdaterSpi.class) - .add(MapLiquibaseConnectionSpi.class) - .build(); - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(ConcurrentHashMapStorageProviderFactory.class) - .add(JpaMapStorageProviderFactory.class) - .add(MapJpaUpdaterProviderFactory.class) - .add(MapLiquibaseConnectionProviderFactory.class) - .add(MapGlobalLockProviderFactory.class) - .build(); - - public JpaMapStorage() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - - @Override - public void updateConfig(Config cf) { - cf.spi(MapStorageSpi.NAME) - .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target}"); - - cf.spi(MapStorageSpi.NAME) - .provider(JpaMapStorageProviderFactory.PROVIDER_ID) - .config("url", POSTGRES_DB_JDBC_URL) - .config("user", POSTGRES_DB_USER) - .config("password", POSTGRES_DB_PASSWORD) - .config("driver", "org.postgresql.Driver") - .config("lockTimeout", "${" + LOCK_TIMEOUT_SYSTEM_PROPERTY + ":}"); - - cf.spi(AuthenticationSessionSpi.PROVIDER_ID).provider(MapRootAuthenticationSessionProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("client").provider(MapClientProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("clientScope").provider(MapClientScopeProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("group").provider(MapGroupProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("role").provider(MapRoleProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("user").provider(MapUserProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(UserLoginFailureSpi.NAME).provider(MapUserLoginFailureProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(SingleUseObjectSpi.NAME).provider(MapSingleUseObjectProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("publicKeyStorage").provider(MapPublicKeyStorageProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(UserSessionSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).provider(MapEventStoreProviderFactory.PROVIDER_ID) .config("storage-admin-events.provider", JpaMapStorageProviderFactory.PROVIDER_ID) - .config("storage-auth-events.provider", JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(GlobalLockProviderSpi.GLOBAL_LOCK) .config("provider", MapGlobalLockProviderFactory.PROVIDER_ID) - .spi(GlobalLockProviderSpi.GLOBAL_LOCK).provider(MapGlobalLockProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID); - } - - @Override - public void beforeSuite(Config cf) { - if (START_CONTAINER) { - POSTGRES_CONTAINER - .withDatabaseName(POSTGRES_DB_DEFAULT_NAME) - .withUsername(POSTGRES_DB_USER) - .withPassword(POSTGRES_DB_PASSWORD) - .start(); - - POSTGRES_DB_JDBC_URL = POSTGRES_CONTAINER.getJdbcUrl(); - } - } - - @Override - public void afterSuite() { - if (START_CONTAINER) { - POSTGRES_CONTAINER.stop(); - } - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/JpaMapStorageCockroachdb.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/JpaMapStorageCockroachdb.java deleted file mode 100644 index f5c8e17c2a53..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/JpaMapStorageCockroachdb.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2022 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import com.google.common.collect.ImmutableSet; -import org.keycloak.authorization.store.StoreFactorySpi; -import org.keycloak.events.EventStoreSpi; -import org.keycloak.models.DeploymentStateSpi; -import org.keycloak.models.SingleUseObjectSpi; -import org.keycloak.models.UserLoginFailureSpi; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.locking.GlobalLockProviderSpi; -import org.keycloak.models.map.authSession.MapRootAuthenticationSessionProviderFactory; -import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory; -import org.keycloak.models.map.client.MapClientProviderFactory; -import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory; -import org.keycloak.models.map.deploymentState.MapDeploymentStateProviderFactory; -import org.keycloak.models.map.events.MapEventStoreProviderFactory; -import org.keycloak.models.map.group.MapGroupProviderFactory; -import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory; -import org.keycloak.models.map.lock.MapGlobalLockProviderFactory; -import org.keycloak.models.map.loginFailure.MapUserLoginFailureProviderFactory; -import org.keycloak.models.map.realm.MapRealmProviderFactory; -import org.keycloak.models.map.role.MapRoleProviderFactory; -import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory; -import org.keycloak.models.map.storage.jpa.liquibase.connection.MapLiquibaseConnectionProviderFactory; -import org.keycloak.models.map.storage.jpa.liquibase.connection.MapLiquibaseConnectionSpi; -import org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterProviderFactory; -import org.keycloak.models.map.storage.jpa.updater.MapJpaUpdaterSpi; -import org.keycloak.models.map.user.MapUserProviderFactory; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.sessions.AuthenticationSessionSpi; -import org.keycloak.testsuite.model.Config; -import org.keycloak.testsuite.model.KeycloakModelParameters; -import org.keycloak.testsuite.model.KeycloakModelTest; -import org.testcontainers.containers.CockroachContainer; -import org.testcontainers.utility.DockerImageName; - -import java.util.Set; - -import static org.keycloak.testsuite.model.transaction.StorageTransactionTest.LOCK_TIMEOUT_SYSTEM_PROPERTY; - -public class JpaMapStorageCockroachdb extends KeycloakModelParameters { - - private static final Boolean START_CONTAINER = Boolean.valueOf(System.getProperty("cockroachdb.start-container", "true")); - private static final String COCKROACHDB_DOCKER_IMAGE_NAME = System.getProperty("keycloak.map.storage.cockroachdb.docker.image", "cockroachdb/cockroach:v22.1.0"); - private static final CockroachContainer COCKROACHDB_CONTAINER = new CockroachContainer(DockerImageName.parse(COCKROACHDB_DOCKER_IMAGE_NAME).asCompatibleSubstituteFor("cockroachdb")); - private static final String COCKROACHDB_DB_USER = System.getProperty("keycloak.map.storage.connectionsJpa.user", "keycloak"); - private static final String COCKROACHDB_DB_PASSWORD = System.getProperty("keycloak.map.storage.connectionsJpa.password", "pass"); - - private static String COCKROACHDB_DB_JDBC_URL = System.getProperty("keycloak.map.storage.connectionsJpa.url"); - - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .add(MapJpaUpdaterSpi.class) - .add(MapLiquibaseConnectionSpi.class) - .build(); - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(ConcurrentHashMapStorageProviderFactory.class) - .add(JpaMapStorageProviderFactory.class) - .add(MapJpaUpdaterProviderFactory.class) - .add(MapLiquibaseConnectionProviderFactory.class) - .add(MapGlobalLockProviderFactory.class) - .build(); - - public JpaMapStorageCockroachdb() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - - @Override - public void updateConfig(Config cf) { - cf.spi(MapStorageSpi.NAME) - .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target}"); - - cf.spi(MapStorageSpi.NAME) - .provider(JpaMapStorageProviderFactory.PROVIDER_ID) - .config("url", COCKROACHDB_DB_JDBC_URL) - .config("user", COCKROACHDB_DB_USER) - .config("password", COCKROACHDB_DB_PASSWORD) - .config("driver", "org.postgresql.Driver") - .config("lockTimeout", "${" + LOCK_TIMEOUT_SYSTEM_PROPERTY + ":}"); - - cf.spi(AuthenticationSessionSpi.PROVIDER_ID).provider(MapRootAuthenticationSessionProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("client").provider(MapClientProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("clientScope").provider(MapClientScopeProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("group").provider(MapGroupProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("realm").provider(MapRealmProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("role").provider(MapRoleProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(DeploymentStateSpi.NAME).provider(MapDeploymentStateProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).provider(MapAuthorizationStoreFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("user").provider(MapUserProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(UserLoginFailureSpi.NAME).provider(MapUserLoginFailureProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(SingleUseObjectSpi.NAME).provider(MapSingleUseObjectProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi("publicKeyStorage").provider(MapPublicKeyStorageProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(UserSessionSpi.NAME).provider(MapUserSessionProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).provider(MapEventStoreProviderFactory.PROVIDER_ID) .config("storage-admin-events.provider", JpaMapStorageProviderFactory.PROVIDER_ID) - .config("storage-auth-events.provider", JpaMapStorageProviderFactory.PROVIDER_ID) - .spi(GlobalLockProviderSpi.GLOBAL_LOCK) .config("provider", MapGlobalLockProviderFactory.PROVIDER_ID) - .spi(GlobalLockProviderSpi.GLOBAL_LOCK).provider(MapGlobalLockProviderFactory.PROVIDER_ID) .config(STORAGE_CONFIG, JpaMapStorageProviderFactory.PROVIDER_ID); - } - - @Override - public void beforeSuite(Config cf) { - if (START_CONTAINER) { - COCKROACHDB_CONTAINER - // Using the environment variables for now where using the withXXX() method is not supported, yet. - // https://github.com/testcontainers/testcontainers-java/issues/6299 - .withEnv("COCKROACH_DATABASE", "keycloak") - .withEnv("COCKROACH_USER", COCKROACHDB_DB_USER) - // password is not used/supported in insecure mode - .withCommand("start-single-node", "--insecure") - .start(); - - COCKROACHDB_DB_JDBC_URL = COCKROACHDB_CONTAINER.getJdbcUrl(); - } - System.setProperty(KeycloakModelTest.KEYCLOAK_MODELTESTS_RETRY_TRANSACTIONS, "true"); - } - - @Override - public void afterSuite() { - if (START_CONTAINER) { - COCKROACHDB_CONTAINER.stop(); - } - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/LdapMapStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/LdapMapStorage.java deleted file mode 100644 index f5a6041d4bbe..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/LdapMapStorage.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2020 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import com.google.common.collect.ImmutableSet; -import org.jboss.logging.Logger; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; -import org.keycloak.authorization.store.StoreFactorySpi; -import org.keycloak.events.EventStoreSpi; -import org.keycloak.models.DeploymentStateSpi; -import org.keycloak.models.LDAPConstants; -import org.keycloak.models.SingleUseObjectSpi; -import org.keycloak.models.UserLoginFailureSpi; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.storage.ldap.LdapMapStorageProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.testsuite.model.Config; -import org.keycloak.testsuite.model.KeycloakModelParameters; -import org.keycloak.testsuite.util.LDAPRule; -import org.keycloak.util.ldap.LDAPEmbeddedServer; - -import java.util.Set; - -/** - * @author Alexander Schwartz - */ -public class LdapMapStorage extends KeycloakModelParameters { - - private static final Logger LOG = Logger.getLogger(LdapMapStorage.class.getName()); - - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .build(); - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(ConcurrentHashMapStorageProviderFactory.class) - .add(LdapMapStorageProviderFactory.class) - .build(); - - private final LDAPRule ldapRule = new LDAPRule(); - - public LdapMapStorage() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - - @Override - public void updateConfig(Config cf) { - cf.spi(MapStorageSpi.NAME) - .provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .config("dir", "${project.build.directory:target}"); - - cf.spi(MapStorageSpi.NAME) - .provider(LdapMapStorageProviderFactory.PROVIDER_ID) - .config("vendor", "other") - .config("usernameLDAPAttribute", "uid") - .config("rdnLDAPAttribute", "uid") - .config("uuidLDAPAttribute", "entryUUID") - .config("userObjectClasses", "inetOrgPerson, organizationalPerson") - .config("connectionUrl", "ldap://localhost:10389") - .config("usersDn", "ou=People,dc=keycloak,dc=org") - .config("bindDn", "uid=admin,ou=system") - .config("bindCredential", "secret") - .config("roles.realm.dn", "ou=RealmRoles,dc=keycloak,dc=org") - .config("roles.client.dn", "ou={0},dc=keycloak,dc=org") - .config("roles.common.dn", "dc=keycloak,dc=org") // this is the top DN that finds both client and realm roles - .config("membership.ldap.attribute", "member") - .config("role.name.ldap.attribute", "cn") - .config("role.object.classes", "groupOfNames") - .config("role.attributes", "ou") - .config("mode", "LDAP_ONLY") - .config("use.realm.roles.mapping", "true") - .config(LDAPConstants.CONNECTION_POOLING, "true"); - - cf.spi("client").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("clientScope").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("group").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("realm").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("role").config("map.storage.provider", LdapMapStorageProviderFactory.PROVIDER_ID) - .spi(DeploymentStateSpi.NAME).config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("user").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(UserSessionSpi.NAME).config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(UserLoginFailureSpi.NAME).config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("authorizationPersister").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("authenticationSessions").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).config("map.storage-admin-events.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).config("map.storage-auth-events.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi(SingleUseObjectSpi.NAME).config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID) - .spi("publicKeyStorage").config("map.storage.provider", ConcurrentHashMapStorageProviderFactory.PROVIDER_ID); - - } - - static { - System.setProperty(LDAPEmbeddedServer.PROPERTY_ENABLE_SSL, "false"); - } - - @Override - public Statement classRule(Statement base, Description description) { - return ldapRule.apply(base, description); - } - -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java deleted file mode 100644 index 0f140cd757ac..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/parameters/Map.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2020 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.parameters; - -import org.keycloak.authorization.store.StoreFactorySpi; -import org.keycloak.events.EventStoreSpi; -import org.keycloak.keys.PublicKeyStorageSpi; -import org.keycloak.models.DeploymentStateSpi; -import org.keycloak.models.SingleUseObjectProviderFactory; -import org.keycloak.models.SingleUseObjectSpi; -import org.keycloak.models.UserLoginFailureSpi; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.locking.GlobalLockProviderSpi; -import org.keycloak.models.locking.NoneGlobalLockProviderFactory; -import org.keycloak.models.map.authSession.MapRootAuthenticationSessionProviderFactory; -import org.keycloak.models.map.authorization.MapAuthorizationStoreFactory; -import org.keycloak.models.map.events.MapEventStoreProviderFactory; -import org.keycloak.models.map.keys.MapPublicKeyStorageProviderFactory; -import org.keycloak.models.map.loginFailure.MapUserLoginFailureProviderFactory; -import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.sessions.AuthenticationSessionSpi; -import org.keycloak.testsuite.model.KeycloakModelParameters; -import org.keycloak.models.map.client.MapClientProviderFactory; -import org.keycloak.models.map.clientscope.MapClientScopeProviderFactory; -import org.keycloak.models.map.group.MapGroupProviderFactory; -import org.keycloak.models.map.realm.MapRealmProviderFactory; -import org.keycloak.models.map.role.MapRoleProviderFactory; -import org.keycloak.models.map.deploymentState.MapDeploymentStateProviderFactory; -import org.keycloak.models.map.storage.MapStorageSpi; -import org.keycloak.models.map.user.MapUserProviderFactory; -import org.keycloak.provider.ProviderFactory; -import org.keycloak.provider.Spi; -import org.keycloak.testsuite.model.Config; -import com.google.common.collect.ImmutableSet; -import java.util.Set; - -/** - * - * @author hmlnarik - */ -public class Map extends KeycloakModelParameters { - - static final Set> ALLOWED_SPIS = ImmutableSet.>builder() - .add(AuthenticationSessionSpi.class) - .add(SingleUseObjectSpi.class) - .add(PublicKeyStorageSpi.class) - .add(MapStorageSpi.class) - - .build(); - - static final Set> ALLOWED_FACTORIES = ImmutableSet.>builder() - .add(MapAuthorizationStoreFactory.class) - .add(MapClientProviderFactory.class) - .add(MapClientScopeProviderFactory.class) - .add(MapGroupProviderFactory.class) - .add(MapRealmProviderFactory.class) - .add(MapRoleProviderFactory.class) - .add(MapRootAuthenticationSessionProviderFactory.class) - .add(MapDeploymentStateProviderFactory.class) - .add(MapUserProviderFactory.class) - .add(MapUserSessionProviderFactory.class) - .add(MapUserLoginFailureProviderFactory.class) - .add(NoneGlobalLockProviderFactory.class) - .add(MapEventStoreProviderFactory.class) - .add(SingleUseObjectProviderFactory.class) - .add(MapPublicKeyStorageProviderFactory.class) - .build(); - - public Map() { - super(ALLOWED_SPIS, ALLOWED_FACTORIES); - } - - @Override - public void updateConfig(Config cf) { - cf.spi(AuthenticationSessionSpi.PROVIDER_ID).defaultProvider(MapRootAuthenticationSessionProviderFactory.PROVIDER_ID) - .spi(SingleUseObjectSpi.NAME).defaultProvider(MapSingleUseObjectProviderFactory.PROVIDER_ID) - .spi("client").defaultProvider(MapClientProviderFactory.PROVIDER_ID) - .spi("clientScope").defaultProvider(MapClientScopeProviderFactory.PROVIDER_ID) - .spi("group").defaultProvider(MapGroupProviderFactory.PROVIDER_ID) - .spi("realm").defaultProvider(MapRealmProviderFactory.PROVIDER_ID) - .spi("role").defaultProvider(MapRoleProviderFactory.PROVIDER_ID) - .spi(DeploymentStateSpi.NAME).defaultProvider(MapDeploymentStateProviderFactory.PROVIDER_ID) - .spi(StoreFactorySpi.NAME).defaultProvider(MapAuthorizationStoreFactory.PROVIDER_ID) - .spi("user").defaultProvider(MapUserProviderFactory.PROVIDER_ID) - .spi(UserSessionSpi.NAME).defaultProvider(MapUserSessionProviderFactory.PROVIDER_ID) - .spi(UserLoginFailureSpi.NAME).defaultProvider(MapUserLoginFailureProviderFactory.PROVIDER_ID) - .spi(GlobalLockProviderSpi.GLOBAL_LOCK).defaultProvider(NoneGlobalLockProviderFactory.PROVIDER_ID) - .spi(EventStoreSpi.NAME).defaultProvider(MapEventStoreProviderFactory.PROVIDER_ID) - .spi("publicKeyStorage").defaultProvider(MapPublicKeyStorageProviderFactory.PROVIDER_ID) - ; - cf.spi(MapStorageSpi.NAME).provider(ConcurrentHashMapStorageProviderFactory.PROVIDER_ID).config("keyType.single-use-objects", "string"); - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/HotRodUserSessionClientSessionRelationshipTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/HotRodUserSessionClientSessionRelationshipTest.java deleted file mode 100644 index bc5427f7ce25..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/HotRodUserSessionClientSessionRelationshipTest.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright 2022 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.model.session; - -import org.infinispan.client.hotrod.RemoteCache; -import org.junit.Test; -import org.keycloak.models.AuthenticatedClientSessionModel; -import org.keycloak.models.ClientModel; -import org.keycloak.models.Constants; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserSessionModel; -import org.keycloak.models.UserSessionProvider; -import org.keycloak.models.map.storage.ModelEntityUtil; -import org.keycloak.models.map.storage.hotRod.connections.DefaultHotRodConnectionProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.HotRodConnectionProvider; -import org.keycloak.models.map.storage.hotRod.userSession.HotRodUserSessionEntity; -import org.keycloak.testsuite.model.KeycloakModelTest; -import org.keycloak.testsuite.model.RequireProvider; - -import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Consumer; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.aMapWithSize; -import static org.hamcrest.Matchers.anEmptyMap; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.notNullValue; -import static org.keycloak.protocol.oidc.OIDCConfigAttributes.CLIENT_SESSION_IDLE_TIMEOUT; -import static org.keycloak.protocol.oidc.OIDCConfigAttributes.CLIENT_SESSION_MAX_LIFESPAN; - -@RequireProvider(UserSessionProvider.class) -@RequireProvider(value = HotRodConnectionProvider.class, only = DefaultHotRodConnectionProviderFactory.PROVIDER_ID) -public class HotRodUserSessionClientSessionRelationshipTest extends KeycloakModelTest { - - private String realmId; - private String CLIENT0_CLIENT_ID = "client0"; - - @Override - public void createEnvironment(KeycloakSession s) { - RealmModel realm = createRealm(s, "test"); - realm.setDefaultRole(s.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName())); - realm.setSsoSessionIdleTimeout(1800); - realm.setSsoSessionMaxLifespan(36000); - this.realmId = realm.getId(); - s.clients().addClient(realm, CLIENT0_CLIENT_ID); - - s.users().addUser(realm, "user1").setEmail("user1@localhost"); - } - - @Override - public void cleanEnvironment(KeycloakSession s) { - if (realmId != null) { - s.realms().removeRealm(realmId); - } - } - - @Test - public void testClientSessionAreRemovedOnUserSessionRemoval() { - AtomicReference uSessionId = new AtomicReference<>(); - AtomicReference cSessionId = new AtomicReference<>(); - prepareSessions(uSessionId, cSessionId); - - withRealm(realmId, (session, realm) -> { - UserSessionModel uSession = session.sessions().getUserSession(realm, uSessionId.get()); - session.sessions().removeUserSession(realm, uSession); - return null; - }); - - assertCacheContains(remoteCache -> assertThat(remoteCache, anEmptyMap())); - } - - @Test - public void testSessionsAreRemovedOnUserRemoval() { - AtomicReference uSessionId = new AtomicReference<>(); - AtomicReference cSessionId = new AtomicReference<>(); - prepareSessions(uSessionId, cSessionId); - - withRealm(realmId, (session, realm) -> { - session.users().removeUser(realm, session.users().getUserByUsername(realm, "user1")); - return null; - }); - - assertCacheContains(remoteCache -> { - assertThat(remoteCache, anEmptyMap()); - }); - } - - @Test - public void testSessionsAreRemovedOnRealmRemoval() { - AtomicReference uSessionId = new AtomicReference<>(); - AtomicReference cSessionId = new AtomicReference<>(); - prepareSessions(uSessionId, cSessionId); - - withRealm(realmId, (session, realm) -> { - session.realms().removeRealm(realm.getId()); - return null; - }); - - assertCacheContains(remoteCache -> { - assertThat(remoteCache, anEmptyMap()); - }); - } - - @Test - public void testExpiredClientSessionReferenceIsNotPresentInUserSession() { - // Set lower client session timeouts - withRealm(realmId, (session, realm) -> { - ClientModel client = realm.getClientByClientId(CLIENT0_CLIENT_ID); - client.setAttribute(CLIENT_SESSION_IDLE_TIMEOUT, "60"); - client.setAttribute(CLIENT_SESSION_MAX_LIFESPAN, "65"); - return null; - }); - - AtomicReference uSessionId = new AtomicReference<>(); - AtomicReference cSessionId = new AtomicReference<>(); - prepareSessions(uSessionId, cSessionId); - - // Move in time when client session should be expired but user session not - setTimeOffset(70); - - // Try to create a new client session for the same user session - withRealm(realmId, (session, realm) -> { - ClientModel client = realm.getClientByClientId(CLIENT0_CLIENT_ID); - UserSessionModel uSession = session.sessions().getUserSession(realm, uSessionId.get()); - assertThat(uSession.getAuthenticatedClientSessions(), anEmptyMap()); - assertThat(session.sessions().createClientSession(realm, client, uSession), notNullValue()); - return null; - }); - - // Check session does not contain a reference to expired client session - assertCacheContains(remoteCache -> { - HotRodUserSessionEntity hotRodUserSessionEntity = remoteCache.get(uSessionId.get()); - assertThat(hotRodUserSessionEntity.authenticatedClientSessions, hasSize(1)); - }); - } - - private void assertCacheContains(Consumer> checker) { - withRealm(realmId, (session, realm) -> { - HotRodConnectionProvider provider = session.getProvider(HotRodConnectionProvider.class); - RemoteCache remoteCache = provider.getRemoteCache(ModelEntityUtil.getModelName(UserSessionModel.class)); - checker.accept(remoteCache); - return null; - }); - } - - private void prepareSessions(AtomicReference uSessionId, AtomicReference cSessionId) { - withRealm(realmId, (session, realm) -> { - UserSessionModel uSession = session.sessions().createUserSession(null, realm, session.users().getUserByUsername(realm, "user1"), "user1", "127.0.0.1", "form", true, null, null, UserSessionModel.SessionPersistenceState.PERSISTENT); - ClientModel client = realm.getClientByClientId(CLIENT0_CLIENT_ID); - - AuthenticatedClientSessionModel cSession = session.sessions().createClientSession(realm, client, uSession); - - uSessionId.set(uSession.getId()); - cSessionId.set(cSession.getId()); - return null; - }); - - assertCacheContains(remoteCache -> { - assertThat(remoteCache, aMapWithSize(2)); - assertThat(remoteCache.keySet(), containsInAnyOrder(uSessionId.get(), cSessionId.get())); - }); - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java index 802202c93bf9..569a9ba6424a 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/OfflineSessionPersistenceTest.java @@ -16,7 +16,6 @@ */ package org.keycloak.testsuite.model.session; -import org.infinispan.client.hotrod.RemoteCache; import org.infinispan.commons.CacheException; import org.keycloak.models.AuthenticatedClientSessionModel; import org.keycloak.models.ClientModel; @@ -28,13 +27,8 @@ import org.keycloak.models.UserProvider; import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionProvider; -import org.keycloak.models.map.storage.ModelEntityUtil; -import org.keycloak.models.map.storage.hotRod.connections.DefaultHotRodConnectionProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.HotRodConnectionProvider; -import org.keycloak.models.map.storage.hotRod.userSession.HotRodUserSessionEntity; import org.keycloak.models.session.UserSessionPersisterProvider; import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProvider; -import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory; import org.keycloak.services.managers.RealmManager; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; @@ -131,39 +125,6 @@ public void testPersistenceSingleNodeDeleteRealm() { } } - @Test - @RequireProvider(value = HotRodConnectionProvider.class, only = DefaultHotRodConnectionProviderFactory.PROVIDER_ID) - public void testOfflineSessionsRemovedAfterDeleteRealm() { - String realmId2 = inComittedTransaction(session -> { return prepareRealm(session, "realm2").getId(); }); - List userIds2 = withRealm(realmId2, (session, realm) -> IntStream.range(0, USER_COUNT) - .mapToObj(i -> session.users().addUser(realm, "user2-" + i)) - .map(UserModel::getId) - .collect(Collectors.toList()) - ); - - try { - List offlineSessionIds2 = createOfflineSessions(realmId2, userIds2); - assertOfflineSessionsExist(realmId2, offlineSessionIds2); - - // Simulate server restart - reinitializeKeycloakSessionFactory(); - - assertOfflineSessionsExist(realmId2, offlineSessionIds2); - - inComittedTransaction(session -> { - session.realms().removeRealm(realmId2); - }); - - inComittedTransaction(session -> { - HotRodConnectionProvider provider = session.getProvider(HotRodConnectionProvider.class); - RemoteCache remoteCache = provider.getRemoteCache(ModelEntityUtil.getModelName(UserSessionModel.class)); - assertThat(remoteCache, Matchers.anEmptyMap()); - }); - } finally { - withRealm(realmId2, (session, realm) -> realm == null ? false : new RealmManager(session).removeRealm(realm)); - } - } - @Test public void testPersistenceSingleNode() { List offlineSessionIds = createOfflineSessions(realmId, userIds); @@ -176,7 +137,6 @@ public void testPersistenceSingleNode() { @Test(timeout = 90 * 1000) @RequireProvider(UserSessionPersisterProvider.class) - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testPersistenceMultipleNodesClientSessionAtSameNode() throws InterruptedException { int numClients = 2; List clientIds = withRealm(realmId, (session, realm) -> IntStream.range(0, numClients) @@ -233,7 +193,6 @@ public void testPersistenceMultipleNodesClientSessionAtSameNode() throws Interru @Test(timeout = 90 * 1000) @RequireProvider(UserSessionPersisterProvider.class) - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testPersistenceMultipleNodesClientSessionsAtRandomNode() throws InterruptedException { List clientIds = withRealm(realmId, (session, realm) -> IntStream.range(0, 5) .mapToObj(cid -> session.clients().addClient(realm, "client-" + cid)) @@ -286,7 +245,6 @@ public void testPersistenceMultipleNodesClientSessionsAtRandomNode() throws Inte @Test @RequireProvider(UserSessionPersisterProvider.class) - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testOfflineSessionLoadingAfterCacheRemoval() { List offlineSessionIds = createOfflineSessions(realmId, userIds); assertOfflineSessionsExist(realmId, offlineSessionIds); @@ -311,7 +269,6 @@ public void testOfflineSessionLoadingAfterCacheRemoval() { @Test @RequireProvider(UserSessionPersisterProvider.class) - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testLazyClientSessionStatsFetching() { List clientIds = withRealm(realmId, (session, realm) -> IntStream.range(0, 5) .mapToObj(cid -> session.clients().addClient(realm, "client-" + cid)) @@ -346,7 +303,6 @@ public void testLazyClientSessionStatsFetching() { @Test @RequireProvider(UserSessionPersisterProvider.class) - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testLazyOfflineUserSessionFetching() { Map> offlineSessionIdsDetailed = createOfflineSessionsDetailed(realmId, userIds); Collection offlineSessionIds = offlineSessionIdsDetailed.values().stream().flatMap(Set::stream).collect(Collectors.toCollection(TreeSet::new)); @@ -380,7 +336,6 @@ private String createOfflineClientSession(String offlineUserSessionId, String cl @Test(timeout = 90 * 1000) @RequireProvider(UserSessionPersisterProvider.class) - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testPersistenceClientSessionsMultipleNodes() throws InterruptedException { // Create offline sessions List offlineSessionIds = createOfflineSessions(realmId, userIds); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java index 97f50b9fbf62..0b09cdba27f1 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionConcurrencyTest.java @@ -25,17 +25,10 @@ import org.keycloak.models.RealmModel; import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionProvider; -import org.keycloak.models.UserSessionSpi; -import org.keycloak.models.map.storage.ModelEntityUtil; -import org.keycloak.models.map.storage.file.FileMapStorageProviderFactory; -import org.keycloak.models.map.storage.hotRod.HotRodMapStorageProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.HotRodConnectionProvider; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; -import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; @@ -43,9 +36,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.aMapWithSize; -import static org.hamcrest.Matchers.anEmptyMap; import static org.hamcrest.Matchers.startsWith; -import static org.junit.Assume.assumeFalse; import static org.keycloak.utils.LockObjectsForModification.lockUserSessionsForModification; @@ -56,7 +47,6 @@ public class UserSessionConcurrencyTest extends KeycloakModelTest { private static final int CLIENTS_COUNT = 10; private static final ThreadLocal wasWriting = ThreadLocal.withInitial(() -> false); - private final boolean isHotRodStore = HotRodMapStorageProviderFactory.PROVIDER_ID.equals(CONFIG.getConfig().get("userSessions.map.storage.provider")); @Override public void createEnvironment(KeycloakSession s) { @@ -87,13 +77,6 @@ protected boolean isUseSameKeycloakSessionFactoryForAllThreads() { @Test public void testConcurrentNotesChange() throws InterruptedException { - // Defer this one until file locking is available - // Skip the test if EventProvider == File - String evProvider = CONFIG.getConfig().get(UserSessionSpi.NAME + ".provider"); - String evMapStorageProvider = CONFIG.getConfig().get(UserSessionSpi.NAME + ".map.storage.provider"); - assumeFalse(MapUserSessionProviderFactory.PROVIDER_ID.equals(evProvider) && - (evMapStorageProvider == null || FileMapStorageProviderFactory.PROVIDER_ID.equals(evMapStorageProvider))); - // Create user session String uId = withRealm(this.realmId, (session, realm) -> session.sessions().createUserSession(null, realm, session.users().getUserByUsername(realm, "user1"), "user1", "127.0.0.1", "form", true, null, null, UserSessionModel.SessionPersistenceState.PERSISTENT)).getId(); @@ -134,13 +117,5 @@ public void testConcurrentNotesChange() throws InterruptedException { }); inComittedTransaction((Consumer) session -> session.realms().removeRealm(realmId)); - if (isHotRodStore) { - inComittedTransaction(session -> { - HotRodConnectionProvider provider = session.getProvider(HotRodConnectionProvider.class); - Map remoteCache = provider.getRemoteCache(ModelEntityUtil.getModelName(UserSessionModel.class)); - - assertThat(remoteCache, anEmptyMap()); - }); - } } } diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionExpirationTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionExpirationTest.java deleted file mode 100644 index 288e9430bc2f..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionExpirationTest.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2022 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.model.session; - -import org.junit.Test; -import org.keycloak.models.Constants; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.RealmProvider; -import org.keycloak.models.UserSessionModel; -import org.keycloak.models.UserSessionProvider; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.testsuite.model.KeycloakModelTest; -import org.keycloak.testsuite.model.RequireProvider; - -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -@RequireProvider(value = UserSessionProvider.class, only = MapUserSessionProviderFactory.PROVIDER_ID) -@RequireProvider(RealmProvider.class) -public class UserSessionExpirationTest extends KeycloakModelTest { - - private String realmId; - - @Override - public void createEnvironment(KeycloakSession s) { - RealmModel realm = createRealm(s, "test"); - realm.setDefaultRole(s.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName())); - - s.users().addUser(realm, "user1").setEmail("user1@localhost"); - this.realmId = realm.getId(); - } - - @Override - public void cleanEnvironment(KeycloakSession s) { - s.realms().removeRealm(realmId); - } - - @Test - public void testSsoSessionIdleTimeout() { - - // Set low ssoSessionIdleTimeout - withRealm(realmId, (session, realm) -> { - realm.setSsoSessionIdleTimeout(5); - realm.setSsoSessionMaxLifespan(36000); - realm.setClientSessionIdleTimeout(5); - return null; - }); - - String uSId= withRealm(realmId, (session, realm) -> session.sessions().createUserSession(null, realm, session.users().getUserByUsername(realm, "user1"), "user1", "127.0.0.1", "form", true, null, null, UserSessionModel.SessionPersistenceState.PERSISTENT).getId()); - - assertThat(withRealm(realmId, (session, realm) -> session.sessions().getUserSession(realm, uSId)), notNullValue()); - - setTimeOffset(5); - - assertThat(withRealm(realmId, (session, realm) -> session.sessions().getUserSession(realm, uSId)), nullValue()); - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java index a96c044132ad..2a9292c628fc 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionInitializerTest.java @@ -33,7 +33,6 @@ import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionProvider; import org.keycloak.models.session.UserSessionPersisterProvider; -import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory; import java.util.LinkedList; import java.util.List; @@ -155,7 +154,6 @@ public void testUserSessionInitializerWithDeletingClient() { } @Test - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testUserSessionPropagationBetweenSites() throws InterruptedException { AtomicInteger index = new AtomicInteger(); AtomicReference userSessionId = new AtomicReference<>(); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java index b5a96cf8cc76..2f51d3d62efa 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionPersisterProviderTest.java @@ -53,7 +53,6 @@ import static org.junit.Assert.assertTrue; import static org.hamcrest.MatcherAssert.assertThat; import org.keycloak.models.Constants; -import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory; import org.hamcrest.Matchers; import org.keycloak.storage.client.ClientStorageProvider; import org.keycloak.storage.client.ClientStorageProviderModel; @@ -67,7 +66,7 @@ * @author Martin Kanis */ @RequireProvider(UserSessionPersisterProvider.class) -@RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) +@RequireProvider(UserSessionProvider.class) @RequireProvider(UserProvider.class) @RequireProvider(RealmProvider.class) public class UserSessionPersisterProviderTest extends KeycloakModelTest { diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java index b19e6b6d79c2..e04d5cd3ad6c 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderModelTest.java @@ -17,7 +17,6 @@ package org.keycloak.testsuite.model.session; import org.hamcrest.Matchers; -import org.infinispan.client.hotrod.RemoteCache; import org.junit.Assert; import org.junit.Test; import org.keycloak.models.AuthenticatedClientSessionModel; @@ -26,19 +25,10 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; -import org.keycloak.models.UserManager; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; import org.keycloak.models.UserSessionModel; import org.keycloak.models.UserSessionProvider; -import org.keycloak.models.map.storage.ModelEntityUtil; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.DefaultHotRodConnectionProviderFactory; -import org.keycloak.models.map.storage.hotRod.connections.HotRodConnectionProvider; -import org.keycloak.models.map.storage.hotRod.userSession.HotRodUserSessionEntity; -import org.keycloak.models.map.userSession.MapUserSessionProvider; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; -import org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory; import org.keycloak.models.sessions.infinispan.changes.sessions.PersisterLastSessionRefreshStoreFactory; import org.keycloak.models.utils.KeycloakModelUtils; import org.keycloak.models.utils.ResetTimeOffsetEvent; @@ -50,7 +40,6 @@ import java.util.Collections; import java.util.List; import java.util.Set; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; @@ -59,7 +48,6 @@ import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.CoreMatchers.nullValue; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assume.assumeFalse; import static org.keycloak.testsuite.model.session.UserSessionPersisterProviderTest.createClients; import static org.keycloak.testsuite.model.session.UserSessionPersisterProviderTest.createSessions; @@ -164,22 +152,8 @@ public void testExpiredClientSessions() { Assert.assertEquals(origSessions[1], userSession); }); - - // not possible to expire client session without expiring user sessions with time offset in map storage because - // expiration in map storage takes min of (clientSessionIdleExpiration, ssoSessionIdleTimeout) inComittedTransaction(session -> { - if (session.getProvider(UserSessionProvider.class) instanceof MapUserSessionProvider) { - RealmModel realm = session.realms().getRealm(realmId); - - UserSessionModel userSession = session.sessions().getUserSession(realm, origSessions[0].getId()); - - userSession.getAuthenticatedClientSessions().values().stream().forEach(clientSession -> { - // expire client sessions - clientSession.setTimestamp(1); - }); - } else { - setTimeOffset(1000); - } + setTimeOffset(1000); }); inComittedTransaction(session -> { @@ -230,7 +204,6 @@ public void testTransientUserSessionIsNotPersisted() { } @Test - @RequireProvider(value = UserSessionProvider.class, only = InfinispanUserSessionProviderFactory.PROVIDER_ID) public void testClientSessionIsNotPersistedForTransientUserSession() { Object[] transientUserSessionWithClientSessionId = inComittedTransaction(session -> { RealmModel realm = session.realms().getRealm(realmId); @@ -255,33 +228,8 @@ public void testClientSessionIsNotPersistedForTransientUserSession() { }); } - @Test - @RequireProvider(value = HotRodConnectionProvider.class, only = DefaultHotRodConnectionProviderFactory.PROVIDER_ID) - public void testRemoteCachesParallel() throws InterruptedException { - inIndependentFactories(4, 30, () -> inComittedTransaction(session -> { - HotRodConnectionProvider provider = session.getProvider(HotRodConnectionProvider.class); - RemoteCache remoteCache = provider.getRemoteCache(ModelEntityUtil.getModelName(UserSessionModel.class)); - HotRodUserSessionEntity userSessionEntity = new HotRodUserSessionEntity(); - userSessionEntity.id = UUID.randomUUID().toString(); - userSessionEntity.realmId = realmId; - remoteCache.put(userSessionEntity.id, userSessionEntity); - })); - - inComittedTransaction(session -> { - HotRodConnectionProvider provider = session.getProvider(HotRodConnectionProvider.class); - RemoteCache remoteCache = provider.getRemoteCache(ModelEntityUtil.getModelName(UserSessionModel.class)); - assertThat(remoteCache.size(), Matchers.is(4)); - }); - } - @Test public void testCreateUserSessionsParallel() throws InterruptedException { - // Skip the test if MapUserSessionProvider == CHM - String usProvider = CONFIG.getConfig().get("userSessions.provider"); - String usMapStorageProvider = CONFIG.getConfig().get("userSessions.map.storage.provider"); - assumeFalse(MapUserSessionProviderFactory.PROVIDER_ID.equals(usProvider) && - (usMapStorageProvider == null || ConcurrentHashMapStorageProviderFactory.PROVIDER_ID.equals(usMapStorageProvider))); - Set userSessionIds = Collections.newSetFromMap(new ConcurrentHashMap<>()); CountDownLatch latch = new CountDownLatch(4); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java index 4d4d18ebd217..bbb6c3774f3d 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/session/UserSessionProviderOfflineModelTest.java @@ -68,7 +68,7 @@ * @author Martin Kanis */ @RequireProvider(UserSessionPersisterProvider.class) -@RequireProvider(value=UserSessionProvider.class, only={"infinispan"}) +@RequireProvider(UserSessionProvider.class) @RequireProvider(UserProvider.class) @RequireProvider(RealmProvider.class) public class UserSessionProviderOfflineModelTest extends KeycloakModelTest { diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/singleUseObject/SingleUseObjectModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/singleUseObject/SingleUseObjectModelTest.java index 74017c1dfad1..41992ba000ae 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/singleUseObject/SingleUseObjectModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/singleUseObject/SingleUseObjectModelTest.java @@ -26,12 +26,7 @@ import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.SingleUseObjectProvider; -import org.keycloak.models.SingleUseObjectProviderFactory; -import org.keycloak.models.SingleUseObjectSpi; import org.keycloak.models.UserModel; -import org.keycloak.models.map.singleUseObject.MapSingleUseObjectProviderFactory; -import org.keycloak.models.map.storage.chm.ConcurrentHashMapStorageProviderFactory; -import org.keycloak.models.map.userSession.MapUserSessionProviderFactory; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; @@ -43,7 +38,6 @@ import java.util.concurrent.atomic.AtomicReference; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.Assume.assumeFalse; @RequireProvider(SingleUseObjectProvider.class) public class SingleUseObjectModelTest extends KeycloakModelTest { @@ -171,12 +165,6 @@ public void testSingleUseStore() { @Test public void testCluster() throws InterruptedException { - // Skip the test if SingleUseObjectProvider == CHM - String suProvider = CONFIG.getConfig().get(SingleUseObjectSpi.NAME + ".provider"); - String suMapStorageProvider = CONFIG.getConfig().get(SingleUseObjectSpi.NAME + ".map.storage.provider"); - assumeFalse(MapSingleUseObjectProviderFactory.PROVIDER_ID.equals(suProvider) && - (suMapStorageProvider == null || ConcurrentHashMapStorageProviderFactory.PROVIDER_ID.equals(suMapStorageProvider))); - AtomicInteger index = new AtomicInteger(); CountDownLatch afterFirstNodeLatch = new CountDownLatch(1); CountDownLatch afterDeleteLatch = new CountDownLatch(1); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/Dict.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/Dict.java deleted file mode 100644 index 1beaaf80cb97..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/Dict.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2021 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.storage.tree.sample; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; - -import org.keycloak.models.map.client.MapClientEntity; -import org.keycloak.models.map.client.MapClientEntityFields; -import org.keycloak.models.map.common.DeepCloner; -import org.keycloak.models.map.common.EntityField; -import org.keycloak.models.map.common.UpdatableEntity; -import org.keycloak.models.map.common.delegate.EntityFieldDelegate; -import org.keycloak.models.map.common.delegate.HasEntityFieldDelegate; - -/** - * - * @author hmlnarik - */ -public class Dict extends UpdatableEntity.Impl implements EntityFieldDelegate { - - public static final String CLIENT_FIELD_LOGO = "LOGO"; - public static final String CLIENT_FIELD_ENABLED = "ENABLED"; - public static final String CLIENT_FIELD_NAME = "NAME"; - - private static final Set CLIENT_ALLOWED_KEYS = new HashSet<>(Arrays.asList(CLIENT_FIELD_NAME, CLIENT_FIELD_ENABLED, CLIENT_FIELD_LOGO)); - - public static MapClientEntity clientDelegate() { - // To be replaced by dynamic mapper config - Map fieldName2key = new HashMap<>(); - fieldName2key.put(MapClientEntityFields.ID.getName(), CLIENT_FIELD_NAME); - fieldName2key.put(MapClientEntityFields.CLIENT_ID.getName(), CLIENT_FIELD_NAME); - fieldName2key.put(MapClientEntityFields.ENABLED.getName(), CLIENT_FIELD_ENABLED); - - Map attributeName2key = new HashMap<>(); - attributeName2key.put("logo", CLIENT_FIELD_LOGO); - - Dict dict = new Dict<>(CLIENT_ALLOWED_KEYS, fieldName2key, attributeName2key); - return DeepCloner.DUMB_CLONER.entityFieldDelegate(MapClientEntity.class, dict); - } - - @SuppressWarnings("unchecked") - public static Dict asDict(E entity) { - return (entity instanceof HasEntityFieldDelegate && ((HasEntityFieldDelegate) entity).getEntityFieldDelegate() instanceof Dict) - ? (Dict) ((HasEntityFieldDelegate) entity).getEntityFieldDelegate() - : null; - } - - private final Set allowedKeys; - private final Map contents = new HashMap<>(); - private final Map fieldName2key; - private final Map attributeName2key; - - public Dict(Set allowedKeys, Map fieldName2key, Map attributeName2key) { - this.allowedKeys = allowedKeys; - this.fieldName2key = fieldName2key; - this.attributeName2key = attributeName2key; - } - - @Override - public > & EntityField> Object get(EF field) { - if ("Attributes".equals(field.getName())) { - return attributeName2key.entrySet().stream() - .filter(me -> get(me.getValue()) != null) - .collect(Collectors.toMap(me -> me.getKey(), me -> Collections.singletonList(get(me.getValue())))); - } - String key = fieldName2key.get(field.getName()); - if (key != null) { - return get(key); - } - return null; - } - - @Override - public > & EntityField> void set(EF field, T value) { - String key = fieldName2key.get(field.getName()); - if (key != null) { - put(key, value); - } - } - - @Override - public > & EntityField> Object mapGet(EF field, K key) { - if ("Attributes".equals(field.getName()) && attributeName2key.containsKey(key)) { - Object v = get(attributeName2key.get(key)); - return v == null ? null : Collections.singletonList(get(attributeName2key.get(key))); - } - return null; - } - - @Override - public > & EntityField> void mapPut(EF field, K key, T value) { - if ("Attributes".equals(field.getName()) && attributeName2key.containsKey(key) && (value instanceof List)) { - List l = (List) value; - if (l.isEmpty()) { - remove(attributeName2key.get(key)); - } else { - put(attributeName2key.get(key), l.get(0)); - } - } - } - - @Override - public > & EntityField> Object mapRemove(EF field, K key) { - if ("Attributes".equals(field.getName()) && attributeName2key.containsKey(key)) { - Object o = remove(attributeName2key.get(key)); - return o == null ? null : Collections.singletonList(o); - } - return null; - } - - - @Override - public > & org.keycloak.models.map.common.EntityField> void collectionAdd(EF field, T value) { - throw new UnsupportedOperationException("Not supported yet."); - } - - @Override - public > & org.keycloak.models.map.common.EntityField> Object collectionRemove(EF field, T value) { - throw new UnsupportedOperationException("Not supported yet."); - } - - protected boolean isKeyAllowed(String key) { - return allowedKeys.contains(key); - } - - public Object get(String key) { - return isKeyAllowed(key) ? contents.get(key) : null; - } - - public void put(String key, Object value) { - if (isKeyAllowed(key)) { - updated |= ! Objects.equals(contents.put(key, value), value); - } - } - - public Object remove(String key) { - key = key == null ? null : key.toUpperCase(); - if (isKeyAllowed(key)) { - Object res = contents.remove(key); - updated |= res != null; - return res; - } - return null; - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/DictStorage.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/DictStorage.java deleted file mode 100644 index 994bb749ccf4..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/DictStorage.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2021 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.keycloak.testsuite.model.storage.tree.sample; - -import org.keycloak.models.map.common.AbstractEntity; -import org.keycloak.models.map.common.DeepCloner; -import org.keycloak.models.map.storage.MapStorage; -import org.keycloak.models.map.storage.QueryParameters; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; - -/** - * - * @author hmlnarik - */ -public class DictStorage implements MapStorage { - - private final DeepCloner cloner; - - private final List store; - - public DictStorage(DeepCloner cloner, List store) { - this.cloner = cloner; - this.store = store; - } - - List getStore() { - return store; - } - - @Override - public V create(V value) { - V res = cloner.from(value); - store.add(res); - return res; - } - - @Override - public V read(String key) { - return store.stream() - .filter(e -> Objects.equals(e.getId(), key)) - .findFirst() - .orElse(null); - } - - @Override - public Stream read(QueryParameters queryParameters) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public long getCount(QueryParameters queryParameters) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public boolean delete(String key) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } - - @Override - public long delete(QueryParameters queryParameters) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/DictTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/DictTest.java deleted file mode 100644 index a24fa3749f64..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/storage/tree/sample/DictTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.keycloak.testsuite.model.storage.tree.sample; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.empty; -import static org.hamcrest.Matchers.hasItems; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.nullValue; - -import java.util.Arrays; - -import org.junit.Test; -import org.keycloak.models.map.client.MapClientEntity; - -public class DictTest { - @Test - public void testDictClientFromMap() { - MapClientEntity mce = Dict.clientDelegate(); - assertThat(mce.getClientId(), nullValue()); - assertThat(mce.isEnabled(), nullValue()); - assertThat(mce.getAttribute("logo"), nullValue()); - assertThat(mce.getAttributes().keySet(), is(empty())); - - Dict.asDict(mce).put(Dict.CLIENT_FIELD_NAME, "name"); - Dict.asDict(mce).put(Dict.CLIENT_FIELD_ENABLED, false); - Dict.asDict(mce).put(Dict.CLIENT_FIELD_LOGO, "thisShouldBeBase64Logo"); - Dict.asDict(mce).put("nonexistent", "nonexistent"); - - assertThat(mce.getId(), is("name")); - assertThat(mce.getClientId(), is("name")); - assertThat(mce.isEnabled(), is(false)); - assertThat(mce.getAttribute("logo"), hasItems("thisShouldBeBase64Logo")); - assertThat(mce.getAttributes().keySet(), hasItems("logo")); - } - - @Test - public void testDictClientFromEntity() { - MapClientEntity mce = Dict.clientDelegate(); - - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_NAME), nullValue()); - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_ENABLED), nullValue()); - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_LOGO), nullValue()); - - mce.setClientId("name"); - mce.setEnabled(false); - mce.setAttribute("logo", Arrays.asList("thisShouldBeBase64Logo")); - mce.setAttribute("blah", Arrays.asList("thisShouldBeBase64Logofdas")); - - assertThat(mce.getAttributes().keySet(), hasItems("logo")); - - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_NAME), is("name")); - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_ENABLED), is(false)); - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_LOGO), is("thisShouldBeBase64Logo")); - - mce.setAttribute("logo", Arrays.asList("thisShouldBeAnotherBase64Logo")); - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_LOGO), is("thisShouldBeAnotherBase64Logo")); - - mce.removeAttribute("logo"); - assertThat(Dict.asDict(mce).get(Dict.CLIENT_FIELD_LOGO), nullValue()); - } -} diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/transaction/StorageTransactionTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/transaction/StorageTransactionTest.java index 2acac7a52c5d..d9dd6877ffc3 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/transaction/StorageTransactionTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/transaction/StorageTransactionTest.java @@ -20,43 +20,18 @@ import org.junit.Test; import org.keycloak.models.Constants; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ModelException; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; -import org.keycloak.models.UserModel; -import org.keycloak.models.UserSessionModel; -import org.keycloak.models.locking.LockAcquiringTimeoutException; -import org.keycloak.models.map.storage.MapStorageProvider; -import org.keycloak.models.map.storage.hotRod.HotRodMapStorageProviderFactory; -import org.keycloak.models.map.storage.jpa.JpaMapStorageProviderFactory; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; import org.keycloak.testsuite.model.util.TransactionController; -import org.keycloak.utils.LockObjectsForModification; -import jakarta.persistence.OptimisticLockException; -import jakarta.persistence.PessimisticLockException; -import jakarta.transaction.RollbackException; - -import java.util.UUID; -import java.util.function.Function; - -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.internal.matchers.ThrowableCauseMatcher.hasCause; -import static org.keycloak.testsuite.model.util.KeycloakAssertions.assertException; @RequireProvider(RealmProvider.class) public class StorageTransactionTest extends KeycloakModelTest { - // System variable is used to simplify configuration for more storages that support pessimistic locking. - // Instead of searching which storage is used and then configure its factory, we can just configure - // lockTimeout like this: .config("lockTimeout", "${keycloak.model.tests.lockTimeout:}") and - // system property will be picked when factory is reinitialized. - public static final String LOCK_TIMEOUT_SYSTEM_PROPERTY = "keycloak.model.tests.lockTimeout"; private String realmId; @Override @@ -135,235 +110,4 @@ public void testRepeatableRead() throws Exception { tx3.commit(); } } - - @Test - // LockObjectForModification currently works only in map-jpa and map-hotrod - @RequireProvider(value = MapStorageProvider.class, only = {JpaMapStorageProviderFactory.PROVIDER_ID, HotRodMapStorageProviderFactory.PROVIDER_ID}) - public void testLockObjectForModificationById() throws Exception { - testLockObjectForModification(session -> LockObjectsForModification.lockRealmsForModification(session, () -> session.realms().getRealm(realmId))); - } - - @Test - // LockObjectForModification currently works only in map-jpa and map-hotrod - @RequireProvider(value = MapStorageProvider.class, only = {JpaMapStorageProviderFactory.PROVIDER_ID, HotRodMapStorageProviderFactory.PROVIDER_ID}) - public void testLockUserSessionForModificationByQuery() throws Exception { - // Create user session - final String sessionId = withRealm(realmId, (session, realm) -> { - UserModel myUser = session.users().addUser(realm, "myUser"); - return session.sessions().createUserSession(realm, myUser, "myUser", "127.0.0.1", "form", true, null, null).getId(); - }); - - testLockObjectForModification(session -> LockObjectsForModification.lockUserSessionsForModification(session, readUserSessionByIdUsingQueryParameters(session, sessionId))); - } - - private void testLockObjectForModification(Function lockedExecution) throws Exception { - String originalTimeoutValue = System.getProperty(LOCK_TIMEOUT_SYSTEM_PROPERTY); - try { - System.setProperty(LOCK_TIMEOUT_SYSTEM_PROPERTY, "300"); - reinitializeKeycloakSessionFactory(); - try (TransactionController tx1 = new TransactionController(getFactory()); - TransactionController tx2 = new TransactionController(getFactory()); - TransactionController tx3 = new TransactionController(getFactory())) { - - tx1.begin(); - tx2.begin(); - - // tx1 acquires lock - tx1.runStep(lockedExecution); - - // tx2 should fail as tx1 locked the realm - assertException(() -> tx2.runStep(lockedExecution), - anyOf(allOf(instanceOf(ModelException.class), hasCause(anyOf(instanceOf(PessimisticLockException.class), instanceOf(org.hibernate.PessimisticLockException.class)))), - instanceOf(LockAcquiringTimeoutException.class))); - - // end both transactions - tx2.rollback(); - tx1.commit(); - - // start new transaction and read again, it should be successful - tx3.begin(); - tx3.runStep(lockedExecution); - tx3.commit(); - } - } finally { - if (originalTimeoutValue == null) { - System.clearProperty(LOCK_TIMEOUT_SYSTEM_PROPERTY); - } else { - System.setProperty(LOCK_TIMEOUT_SYSTEM_PROPERTY, originalTimeoutValue); - } - reinitializeKeycloakSessionFactory(); - } - } - - private LockObjectsForModification.CallableWithoutThrowingAnException readUserSessionByIdUsingQueryParameters(KeycloakSession session, String sessionId) { - RealmModel realm = session.realms().getRealm(realmId); - return () -> session.sessions().getUserSession(realm, sessionId); - } - - @Test - // Optimistic locking works only with map-jpa and map-hotrod - @RequireProvider(value = MapStorageProvider.class, only = {JpaMapStorageProviderFactory.PROVIDER_ID, - HotRodMapStorageProviderFactory.PROVIDER_ID}) - public void testOptimisticLockingExceptionReadById() throws Exception { - withRealm(realmId, (session, realm) -> { - realm.setDisplayName("displayName1"); - return null; - }); - - try (TransactionController tx1 = new TransactionController(getFactory()); - TransactionController tx2 = new TransactionController(getFactory())) { - - // tx1 acquires lock - tx1.begin(); - tx2.begin(); - - // both transactions touch the same entity - tx1.runStep(session -> { - session.realms().getRealm(realmId).setDisplayName("displayName2"); - return null; - }); - tx2.runStep(session -> { - session.realms().getRealm(realmId).setDisplayName("displayName3"); - return null; - }); - - // tx1 transaction should be successful - tx1.commit(); - - // tx2 should fail as tx1 already changed the value - assertException(tx2::commit, - anyOf( - allOf(instanceOf(RuntimeException.class), hasCause(instanceOf(RollbackException.class))), - allOf(instanceOf(ModelException.class), hasCause(instanceOf(OptimisticLockException.class))), - allOf(instanceOf(OptimisticLockException.class)) - )); - } - } - - @Test - // Optimistic locking works only with map-jpa and map-hotrod - @RequireProvider(value = MapStorageProvider.class, only = {JpaMapStorageProviderFactory.PROVIDER_ID, - HotRodMapStorageProviderFactory.PROVIDER_ID}) - public void testOptimisticLockingExceptionReadByQuery() throws Exception { - withRealm(realmId, (session, realm) -> { - realm.setDisplayName("displayName1"); - return null; - }); - - try (TransactionController tx1 = new TransactionController(getFactory()); - TransactionController tx2 = new TransactionController(getFactory())) { - - // tx1 acquires lock - tx1.begin(); - tx2.begin(); - - // both transactions touch the same entity - tx1.runStep(session -> { - session.realms().getRealmByName("1").setDisplayName("displayName2"); - return null; - }); - tx2.runStep(session -> { - session.realms().getRealmByName("1").setDisplayName("displayName3"); - return null; - }); - - // tx1 transaction should be successful - tx1.commit(); - - // tx2 should fail as tx1 already changed the value - assertException(tx2::commit, - anyOf( - allOf(instanceOf(RuntimeException.class), hasCause(instanceOf(RollbackException.class))), - allOf(instanceOf(ModelException.class), hasCause(instanceOf(OptimisticLockException.class))), - allOf(instanceOf(OptimisticLockException.class)) - )); - } - } - - @Test - // Optimistic locking works only with map-jpa and map-hotrod - @RequireProvider(value = MapStorageProvider.class, only = {JpaMapStorageProviderFactory.PROVIDER_ID, - HotRodMapStorageProviderFactory.PROVIDER_ID}) - public void testOptimisticLockingDeleteWhenReadingByQuery() throws Exception { - withRealm(realmId, (session, realm) -> { - session.users().addUser(realm, "user", "user", false, false); - return null; - }); - - try (TransactionController tx1 = new TransactionController(getFactory()); - TransactionController tx2 = new TransactionController(getFactory())) { - - tx1.begin(); - tx2.begin(); - - // both transactions touch the same entity - tx1.runStep(session -> { - // read by criteria - session.users().getUserByUsername(session.realms().getRealm(realmId), "user").setFirstName("firstName"); - return null; - }); - tx2.runStep(session -> { - RealmModel realm = session.realms().getRealm(realmId); - - // remove by id - session.users().removeUser(realm, session.users().getUserByUsername(realm, "user")); - return null; - }); - - // tx1 transaction should be successful - tx1.commit(); - - // tx2 should fail as tx1 already changed the value - assertException(tx2::commit, - anyOf( - allOf(instanceOf(RuntimeException.class), hasCause(instanceOf(RollbackException.class))), - allOf(instanceOf(ModelException.class), hasCause(instanceOf(OptimisticLockException.class))), - allOf(instanceOf(OptimisticLockException.class)) - )); - } - } - - @Test - // Optimistic locking works only with map-jpa and map-hotrod - @RequireProvider(value = MapStorageProvider.class, only = {JpaMapStorageProviderFactory.PROVIDER_ID, - HotRodMapStorageProviderFactory.PROVIDER_ID}) - public void testOptimisticLockingDeleteWhenReadingById() throws Exception { - String userId = UUID.randomUUID().toString(); - withRealm(realmId, (session, realm) -> { - session.users().addUser(realm, userId, "user", false, false); - return null; - }); - - try (TransactionController tx1 = new TransactionController(getFactory()); - TransactionController tx2 = new TransactionController(getFactory())) { - - tx1.begin(); - tx2.begin(); - - // both transactions touch the same entity - tx1.runStep(session -> { - // read by id - session.users().getUserById(session.realms().getRealm(realmId), userId).setFirstName("firstName"); - return null; - }); - tx2.runStep(session -> { - RealmModel realm = session.realms().getRealm(realmId); - - // remove by id after read by id - session.users().removeUser(realm, session.users().getUserById(realm, userId)); - return null; - }); - - // tx1 transaction should be successful - tx1.commit(); - - // tx2 should fail as tx1 already changed the value - assertException(tx2::commit, - anyOf( - allOf(instanceOf(RuntimeException.class), hasCause(instanceOf(RollbackException.class))), - allOf(instanceOf(ModelException.class), hasCause(instanceOf(OptimisticLockException.class))), - allOf(instanceOf(OptimisticLockException.class)) - )); - } - } } diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/user/UserModelTest.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/user/UserModelTest.java index 6f92548b7378..5928aca66109 100644 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/user/UserModelTest.java +++ b/testsuite/model/src/test/java/org/keycloak/testsuite/model/user/UserModelTest.java @@ -16,17 +16,16 @@ */ package org.keycloak.testsuite.model.user; +import org.hamcrest.Matchers; +import org.junit.Test; import org.keycloak.component.ComponentModel; import org.keycloak.models.Constants; import org.keycloak.models.GroupModel; import org.keycloak.models.KeycloakSession; -import org.keycloak.models.ModelDuplicateException; import org.keycloak.models.RealmModel; import org.keycloak.models.RealmProvider; import org.keycloak.models.UserModel; import org.keycloak.models.UserProvider; -import org.keycloak.models.map.realm.MapRealmProviderFactory; -import org.keycloak.models.map.user.MapUserProviderFactory; import org.keycloak.storage.UserStorageProvider; import org.keycloak.storage.UserStorageProviderFactory; import org.keycloak.storage.UserStorageProviderModel; @@ -34,29 +33,23 @@ import org.keycloak.storage.user.UserRegistrationProvider; import org.keycloak.testsuite.model.KeycloakModelTest; import org.keycloak.testsuite.model.RequireProvider; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.hamcrest.Matchers; -import org.junit.Test; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.hasItem; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; import static org.junit.Assume.assumeThat; /** @@ -73,8 +66,6 @@ public class UserModelTest extends KeycloakModelTest { private static final int DELETED_USER_COUNT = LAST_DELETED_USER_INDEX - FIRST_DELETED_USER_INDEX; private String realmId; - private String realm1Id; - private String realm2Id; private final List groupIds = new ArrayList<>(NUM_GROUPS); private String userFederationId; @@ -92,8 +83,6 @@ public void createEnvironment(KeycloakSession s) { @Override public void cleanEnvironment(KeycloakSession s) { s.realms().removeRealm(realmId); - if (realm1Id != null) s.realms().removeRealm(realm1Id); - if (realm2Id != null) s.realms().removeRealm(realm2Id); } @Override @@ -126,67 +115,6 @@ private Void addRemoveUser(KeycloakSession session, int i) { return null; } - @Test - @RequireProvider(value = UserProvider.class, only = {MapUserProviderFactory.PROVIDER_ID}) - @RequireProvider(value = RealmProvider.class, only = {MapRealmProviderFactory.PROVIDER_ID}) - public void testCaseSensitivityGetUserByUsername() { - - realm1Id = inComittedTransaction((Function) session -> { - RealmModel realm = session.realms().createRealm("realm1"); - realm.setDefaultRole(session.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName())); - realm.setAttribute(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, true); - return realm.getId(); - }); - - withRealm(realm1Id, (session, realm) -> { - UserModel user1 = session.users().addUser(realm, "user"); - UserModel user2 = session.users().addUser(realm, "USER"); - - assertThat(user1, not(nullValue())); - assertThat(user2, not(nullValue())); - - assertThat(user1.getUsername(), equalTo("user")); - assertThat(user2.getUsername(), equalTo("USER")); - - return null; - }); - - // try to query storage in a separate transaction to make sure that storage can handle case-sensitive usernames - withRealm(realm1Id, (session, realm) -> { - UserModel user1 = session.users().getUserByUsername(realm, "user"); - UserModel user2 = session.users().getUserByUsername(realm, "USER"); - - assertThat(user1, not(nullValue())); - assertThat(user2, not(nullValue())); - - assertThat(user1.getUsername(), equalTo("user")); - assertThat(user2.getUsername(), equalTo("USER")); - - return null; - }); - - realm2Id = inComittedTransaction((Function) session -> { - RealmModel realm = session.realms().createRealm("realm2"); - realm.setDefaultRole(session.roles().addRealmRole(realm, Constants.DEFAULT_ROLES_ROLE_PREFIX + "-" + realm.getName())); - realm.setAttribute(Constants.REALM_ATTR_USERNAME_CASE_SENSITIVE, false); - return realm.getId(); - }); - - withRealm(realm2Id, (session, realm) -> { - UserModel user1 = session.users().addUser(realm, "user"); - assertThat(user1, not(nullValue())); - - try { - session.users().addUser(realm, "USER"); - } catch (ModelDuplicateException e) { - return null; // expected - } - - fail("ModelDuplicateException expected"); - return null; - }); - } - @Test public void testAddRemoveUser() { inRolledBackTransaction(1, this::addRemoveUser); diff --git a/testsuite/model/src/test/java/org/keycloak/testsuite/model/util/KeycloakAssertions.java b/testsuite/model/src/test/java/org/keycloak/testsuite/model/util/KeycloakAssertions.java deleted file mode 100644 index 70bd85a7c351..000000000000 --- a/testsuite/model/src/test/java/org/keycloak/testsuite/model/util/KeycloakAssertions.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2023 Red Hat, Inc. and/or its affiliates - * and other contributors as indicated by the @author tags. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.keycloak.testsuite.model.util; - -import org.hamcrest.Matcher; - -import static org.hamcrest.CoreMatchers.allOf; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.MatcherAssert.assertThat; - -public class KeycloakAssertions { - - /** - * Runs {@code task} and checks whether the execution resulted in - * an exception that matches {@code matcher}. The method fails also - * when no exception is thrown. - * - * @param task task - * @param matcher matcher that the exception should match - */ - public static void assertException(Runnable task, Matcher matcher) { - Throwable ex = catchException(task); - assertThat(ex, allOf(notNullValue(), matcher)); - } - - /** - * Runs the {@code task} and returns any throwable that is thrown. - * If not exception is thrown, the method returns {@code null} - * - * @param task task - */ - public static Throwable catchException(Runnable task) { - try { - task.run(); - return null; - } catch (Throwable ex) { - return ex; - } - } -} diff --git a/testsuite/model/src/test/resources/log4j.properties b/testsuite/model/src/test/resources/log4j.properties index 9f922038ce7e..dbbf4539b433 100644 --- a/testsuite/model/src/test/resources/log4j.properties +++ b/testsuite/model/src/test/resources/log4j.properties @@ -42,9 +42,6 @@ log4j.logger.org.keycloak.connections.jpa.updater.liquibase=${keycloak.liquibase log4j.logger.org.keycloak.connections.jpa.DefaultJpaConnectionProviderFactory=debug # Enable to log short stack traces for log entries enabled with StackUtil.getShortStackTrace() calls -#log4j.logger.org.keycloak.models.map=trace -#log4j.logger.org.keycloak.models.map.transaction=debug -# #log4j.logger.org.keycloak.STACK_TRACE=trace #log4j.logger.org.keycloak.models.sessions.infinispan=trace diff --git a/themes/src/main/resources-community/theme/base/account/messages/messages_th.properties b/themes/src/main/resources-community/theme/base/account/messages/messages_th.properties index d5c5ce3a4ddb..7e11fc77ce9c 100644 --- a/themes/src/main/resources-community/theme/base/account/messages/messages_th.properties +++ b/themes/src/main/resources-community/theme/base/account/messages/messages_th.properties @@ -1,4 +1,3 @@ -# encoding: utf-8 doSave=บันทึก doCancel=ยกเลิก doLogOutAllSessions=ออกจากระบบทุกเซสชัน diff --git a/themes/src/main/resources-community/theme/base/email/messages/messages_th.properties b/themes/src/main/resources-community/theme/base/email/messages/messages_th.properties index c276362fed6e..dc3d181f3dbb 100644 --- a/themes/src/main/resources-community/theme/base/email/messages/messages_th.properties +++ b/themes/src/main/resources-community/theme/base/email/messages/messages_th.properties @@ -1,4 +1,3 @@ -# encoding: UTF-8 emailVerificationSubject=ตรวจสอบอีเมล emailVerificationBody=มีคนสร้างบัญชี {2} ด้วยที่อยู่อีเมลนี้ หากคุณเป็นผู้สร้างบัญชี คลิกที่ลิงก์ด้านล่างเพื่อยืนยันที่อยู่อีเมลของคุณ\n\n{0}\n\nลิงก์นี้จะหมดอายุภายใน {3}.\n\nถ้าคุณไม่ได้สร้างบัญชี ไม่ต้องสนใจข้อความนี้ emailVerificationBodyHtml=

มีคนสร้างบัญชี {2} ด้วยที่อยู่อีเมลนี้ หากคุณเป็นผู้สร้างบัญชี คลิกที่ลิงก์ด้านล่างเพื่อยืนยันที่อยู่อีเมลของคุณ

ลิงก์สำหรับการตรวจสอบที่อยู่อีเมล

ลิงก์นี้จะหมดอายุภายใน {3}.

ถ้าคุณไม่ได้สร้างบัญชี ไม่ต้องสนใจข้อความนี้

diff --git a/themes/src/main/resources-community/theme/base/login/messages/messages_th.properties b/themes/src/main/resources-community/theme/base/login/messages/messages_th.properties index 6b5d160558b3..77d23dd2d4c9 100644 --- a/themes/src/main/resources-community/theme/base/login/messages/messages_th.properties +++ b/themes/src/main/resources-community/theme/base/login/messages/messages_th.properties @@ -1,4 +1,3 @@ -# encoding: UTF-8 doLogIn=เข้าสู่ระบบ doRegister=ลงทะเบียน doCancel=ยกเลิก diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_ca.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_ca.properties index 6b207ef999f1..5b57fc1fccc0 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_ca.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_ca.properties @@ -1,5 +1,3 @@ -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=No s''ha trobat la pàgina forbidden=Prohibit needAccessRights=No teniu permisos d''accés a aquesta petició. Contacteu amb l''administrador. diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_de.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_de.properties index 3bc37b6c6a5a..ac97ab110235 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_de.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_de.properties @@ -1,5 +1,3 @@ -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=Seite nicht gefunden forbidden=Verboten needAccessRights=Sie haben keine Zugriffsrechte auf diese Anfrage. Wenden Sie sich an Ihren Administrator. diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_el.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_el.properties index bb1b2804e289..11eb3af23aa0 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_el.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_el.properties @@ -167,6 +167,4 @@ actionRequiresIDP=Αυτή η ενέργεια απαιτεί ανακατεύθ invalidRoute=Το {0} δεν είναι μια έγκυρη διαδρομή. needAccessRights=Δεν έχετε άδειες πρόσβασης για αυτή την αίτηση. Επικοινωνήστε με το διαχειριστή σας. forbidden=Απαγορεύεται -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=Η σελίδα δε βρέθηκε diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_fa.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_fa.properties index 5b181d854754..8438a7706cf4 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_fa.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_fa.properties @@ -1,6 +1,3 @@ -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme - pageNotFound=صفحه یافت نشد forbidden=غیرمجاز needAccessRights=شما مجوز دسترسی به این درخواست را ندارید. لطفا با مدیریت خود صحبت کنید. diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_hu.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_hu.properties index 8b67ce7a6775..c117761b5a90 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_hu.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_hu.properties @@ -1,5 +1,3 @@ -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=Az oldal nem található forbidden=Hozzáférés megtagadva needAccessRights=Nincs jogosultsága a művelet elvégzéséhez. Kérem, vegye fel a kapcsolatot az alkalmazás adminisztrátorával. diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_pt_BR.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_pt_BR.properties index 096681d0684c..dd34bac34753 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_pt_BR.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_pt_BR.properties @@ -1,5 +1,3 @@ -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=Página Não Encontrada forbidden=Proibido needAccessRights=Você não tem as permissões de acesso para esta solicitação. Entre em contato com um administrador. diff --git a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_th.properties b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_th.properties index c4cfac3d25e6..7b437b5042d8 100644 --- a/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_th.properties +++ b/themes/src/main/resources-community/theme/keycloak.v2/account/messages/messages_th.properties @@ -1,6 +1,3 @@ -# encoding: UTF-8 -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=ไม่พบหน้า forbidden=ไม่มีสิทธิ์ needAccessRights=คุณไม่มีสิทธิ์เข้าถึงคำขอนี้ ติดต่อผู้ดูแลระบบของคุณ diff --git a/themes/src/main/resources/theme/base/login/login-update-password.ftl b/themes/src/main/resources/theme/base/login/login-update-password.ftl index 4eb2d6a5b94d..f1ac3b99cbd7 100755 --- a/themes/src/main/resources/theme/base/login/login-update-password.ftl +++ b/themes/src/main/resources/theme/base/login/login-update-password.ftl @@ -5,17 +5,6 @@ ${msg("updatePasswordTitle")} <#elseif section = "form">
- -
- - -
-
diff --git a/themes/src/main/resources/theme/keycloak.v2/account/messages/messages_en.properties b/themes/src/main/resources/theme/keycloak.v2/account/messages/messages_en.properties index 45f8bdad68e7..fcc289d8ff74 100644 --- a/themes/src/main/resources/theme/keycloak.v2/account/messages/messages_en.properties +++ b/themes/src/main/resources/theme/keycloak.v2/account/messages/messages_en.properties @@ -1,5 +1,3 @@ -# Put new messages for Account Console Here -# Feel free to use any existing messages from the base theme pageNotFound=Page not found forbidden=Forbidden needAccessRights=You do not have access rights to this request. Contact your administrator.