From 6cd467d773a9eb6750a8e049e5dae15be3c25f95 Mon Sep 17 00:00:00 2001 From: Mario Andrija Balug <37574078+mbalug7@users.noreply.github.com> Date: Mon, 8 Jul 2024 08:03:30 +0200 Subject: [PATCH 01/34] docs: note audience scope for service user (#8252) # Which Problems Are Solved - It is not possible to introspect service user token if `urn:zitadel:iam:org:project:id:{projectid}:aud` scope is not added in token request. - Adding this note to the document could reduce confusion and debugging time - https://discord.com/channels/927474939156643850/1168857403945660436/1168930850029707386 --------- Co-authored-by: Livio Spring --- docs/docs/guides/integrate/service-users/client-credentials.md | 3 +++ docs/docs/guides/integrate/service-users/private-key-jwt.md | 3 +++ 2 files changed, 6 insertions(+) diff --git a/docs/docs/guides/integrate/service-users/client-credentials.md b/docs/docs/guides/integrate/service-users/client-credentials.md index 438fec1ef1..a6ef909d24 100644 --- a/docs/docs/guides/integrate/service-users/client-credentials.md +++ b/docs/docs/guides/integrate/service-users/client-credentials.md @@ -49,6 +49,9 @@ curl --request POST \ If you want to access ZITADEL APIs, make sure to include the required scopes `urn:zitadel:iam:org:project:id:zitadel:aud`. Read our guide [how to access ZITADEL APIs](../zitadel-apis/access-zitadel-apis) to learn more. +**Important Note:** If the service user token needs to be validated using token introspection, ensure you include the `urn:zitadel:iam:org:project:id:{projectid}:aud` scope in your token request. +Without this, token introspection will fail. + You should receive a successful response with `access_token`, `token_type` and time to expiry in seconds as `expires_in`. ```bash diff --git a/docs/docs/guides/integrate/service-users/private-key-jwt.md b/docs/docs/guides/integrate/service-users/private-key-jwt.md index da1c6de432..3993831aff 100644 --- a/docs/docs/guides/integrate/service-users/private-key-jwt.md +++ b/docs/docs/guides/integrate/service-users/private-key-jwt.md @@ -163,6 +163,9 @@ curl --request POST \ If you want to access ZITADEL APIs, make sure to include the required scopes `urn:zitadel:iam:org:project:id:zitadel:aud`. Read our guide [how to access ZITADEL APIs](../zitadel-apis/access-zitadel-apis) to learn more. +**Important Note:** If the service user token needs to be validated using token introspection, ensure you include the `urn:zitadel:iam:org:project:id:{projectid}:aud` scope in your token request. +Without this, token introspection will fail. + You should receive a successful response with `access_token`, `token_type` and time to expiry in seconds as `expires_in`. ```bash From ab7c484157f545cc042e575259a54db6c678b50f Mon Sep 17 00:00:00 2001 From: Dakshitha Ratnayake Date: Mon, 8 Jul 2024 16:41:09 +0530 Subject: [PATCH 02/34] docs: Add the SAML intro docs (#8112) Please refer to this issue for more information: https://github.com/zitadel/zitadel/issues/7436 --- docs/docs/guides/integrate/login/saml.md | 285 +++++++++++++++++++++++ docs/sidebars.js | 23 +- 2 files changed, 288 insertions(+), 20 deletions(-) create mode 100644 docs/docs/guides/integrate/login/saml.md diff --git a/docs/docs/guides/integrate/login/saml.md b/docs/docs/guides/integrate/login/saml.md new file mode 100644 index 0000000000..5639352658 --- /dev/null +++ b/docs/docs/guides/integrate/login/saml.md @@ -0,0 +1,285 @@ +--- +title: Authenticate users with SAML +sidebar_label: SAML +--- + +SAML stands for Security Assertion Markup Language. It is a standard commonly used for identity federation and single sign-on (SSO). It is one of the original and most popular standards for SSO. Although it is prone to certain security flaws and exploits if not implemented correctly, it remains relevant and widely used. + + +## Why use SAML? + +Here are some reasons why organizations might choose SAML: + +**Legacy systems compatibility** + +SAML has been in use since 2002 and is deeply integrated into many legacy systems and enterprise environments. Organizations with existing SAML infrastructure may prefer to continue using it to avoid costly and complex migrations. + +**Enterprise use cases** + +SAML is often favored in enterprise settings where detailed user attributes and complex authorization requirements are necessary. Its support for rich metadata and customizable assertions makes it suitable for intricate access control scenarios. + +**Mature ecosystem** + +The SAML ecosystem is mature, with extensive support from a wide range of enterprise applications and identity providers. This broad compatibility ensures that SAML can be used seamlessly across various platforms and services. + +## Common SAML terms +- **Service Provider (SP)**: The application the user is trying to sign into. +- **Identity Provider (IdP)**: The centralized point of authentication. +- **SAML Request**: A communication from the SP to the IdP. +- **SAML Response**: A communication from the IdP to the SP, containing assertions about the user. +- **Assertions**: Statements within the SAML response about the user, signed using XML signatures. +- **Assertion Consumer Service (ACS)**: The endpoint at the SP responsible for processing the SAML response. +- **Attributes**: User information within the SAML response. +- **Relay State**: A way for the IdP to remember where a user was before authentication. +- **SAML Trust**: The configuration between the identity provider and the service provider +- **Metadata**: Trust information exchanged between the identity provider and service provider + + +## SAML explained + +The **Service Provider (SP)** is the application that the user is trying to sign into. When the service provider sends a communication to the identity provider, it is called a **SAML request**. When the **Identity Provider (IdP)** responds or sends a communication to the service provider, it is called a SAML response. + +Within the SAML response, there are multiple statements about the user, known as **assertions**. These assertions are all signed using XML signatures (also known as DSig) and are sent to be processed at the service provider's specific endpoint called an **Assertion Consumer Service (ACS)**. The ACS is responsible for receiving the SAML response from the identity provider, checking the assertions' signatures, and validating the entire document. This is a crucial part of implementing SAML from the service provider's perspective. + +Additionally, the SAML response contains other pieces of information about the user, such as their first name, last name, and other profile information, referred to as **attributes**. + +Another important concept in SAML is the **relay state**. The relay state allows the identity provider to remember where a user was before authentication. If a user is browsing anonymously through the service provider and triggers authentication, they will be redirected to the identity provider. After validating the user's identity, the identity provider will redirect them back to the service provider's ACS. The relay state makes sure that the user returns to their original location instead of being dropped on a generic home page. + +**SAML trust** is the configuration between the identity provider and the service provider, involving shared information such as a signing certificate and an entity ID (also known as an issuer) from the identity provider. This shared information establishes a trust that allows both parties to validate communications, requests, and responses. + +**Metadata** is another crucial term in SAML. Metadata allows for self-configuration between the identity provider and the service provider. Instead of manually exchanging certificates, endpoint URLs, and issuer information, metadata enables the sharing of an XML configuration file or URLs to these files. This allows the service provider and identity provider to self-configure based on the information within these configuration files, making the process less manual and more convenient. + + +## SAML workflow + +One important aspect of SAML is that the user can initiate the authentication process in two primary workflows: + +**1. IdP-Initiated: The user starts at the IdP, which sends a SAML response to the SP.** + +Commonly, with workforce identity providers, there is a centralized user portal where a user can see a list of applications. Clicking on one of these applications initiates the authentication process without the user first going to the service provider. This method is called IdP-initiated (Identity Provider-initiated) authentication. In this flow, the user goes to the identity provider, which automatically kicks off the SAML response, directing them to the desired application. + +**2. SP-Initiated: The user starts at the SP, which sends a SAML request to the IdP, followed by a SAML response from the IdP.** + +The other method is SP-initiated (Service Provider-initiated) authentication. Here, the user starts at the service provider, which then sends a SAML request to the identity provider. The identity provider processes this request and sends back a SAML response. +In IdP-initiated flows, there is no SAML request, while in SP-initiated flows, the SAML request and response are both involved. The identity provider must understand how to receive a SAML request and create a SAML response. The service provider, particularly its Assertion Consumer Service (ACS), needs to validate the SAML response and potentially generate a SAML request if SP-initiated flow is supported. + +It's important to note that not all service providers support both methods. Some only support IdP-initiated, while others only support SP-initiated. The choice between supporting IdP-initiated or SP-initiated authentication depends on the specific requirements of the product and the preferences of the developer implementing SAML. ZITADEL, for instance, supports only the SP-initiated flow. + +## SAML requests and responses + +SAML uses XML for both requests and responses. A typical SAML request from an SP to an IdP includes an ID, timestamp, destination URL, and issuer information. The IdP processes this request and returns a SAML response containing user assertions, which the SP validates. + +Let's delve into what a SAML request and response look like with the following shortened examples. + +**Sample SAML request** + +```xml + + + + https://zitadel-test.sp/metadata + + + + + + + + + + + + WSz/EQ72RZ0DTh3DBSRCElpITqM= + + + HHjsNh0OLj7... + + + MIIDtzCCAp+gAwIBAgIUfITRQGue... + + + + +``` + +In this SAML request: + +- The **ID** (id-8LjuzBEUQFYFWjL55) is generated by the service provider, and the identity provider will respond to this ID in the SAML response. +- **IssueInstant** (2024-05-11T04:13:52Z) is the timestamp for this request, used by the identity provider for verification to ensure the request is within an acceptable time frame. +- **Destination** (https://my-instance-xtzfbc.zitadel.cloud/saml/v2/SSO) points to the identity provider's URL, ensuring the request is sent to the correct recipient. +- **AssertionConsumerServiceURL** (http://127.0.0.1:5000/acs) indicates where the response should be sent after user authentication. +- **Issuer** (https://zitadel-test.sp/metadata) is a predefined string formatted as a URL, matching what the identity provider expects. +- **Signature** ensures the integrity and authenticity of the SAML request. It includes: + - **SignedInfo** contains details about the canonicalization and signature methods. + - **Reference** points to the signed data and includes a transform and digest method. + - **SignatureValue** provides the actual digital signature. + - **KeyInfo** containing the X.509 certificate, which holds the public key used to verify the signature. + +These XMLs are stringified, encoded, and transmitted according to the SAML binding used. For instance, in HTTP Redirect Binding, the request is sent as URL parameters, while in HTTP POST Binding, it is included in the request body. The signature's transmission method also depends on the binding used, ensuring the integrity and authenticity of the SAML message across different communication channels. + + +**Sample SAML response** + +```xml + + + https://my-instance-xtzfbc.zitadel.cloud/saml/v2/metadata + + + + + + https://my-instance-xtzfbc.zitadel.cloud/saml/v2/metadata + + + + + + + + + + + /b1R9LJJSeNX... + + + n5GbV4xhkXV... + + + MIIFITCCAwmgAwIBAgIBUTANBgkqh... + + + + + dakshitha.devrel@gmail.com + + + + + + + https://zitadel-test.sp/metadata + + + + + urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport + + + + + tony.stark@gmail.com + + + Stark + + + Tony + + + Tony Stark + + + tony.stark@gmail.com + + + 260242264868201995 + + + + +``` + +In this SAML response: + +- The **ID** (_164ba12b-6711-40e0-8ddb-55aa810f1c92) matches the ID from the SAML request (id-8LjuzBEUQFYFWjL55), allowing the service provider to verify it. +- **InResponseTo** references the ID of the SAML request. +- **IssueInstant** (2024-06-11T04:17:41Z) is the timestamp of the response. +- **Destination** (http://127.0.0.1:5000/acs) confirms that the response is intended for the service provider's Assertion Consumer Service URL. +- **Issuer** (https://my-instance-xtzfbc.zitadel.cloud/saml/v2/metadata) is the identity provider's unique string, used to verify the response's origin. +- **StatusCode** indicates the status of the authentication process, with a value of "Success." If the status is not "Success," it means there was a problem with the login, such as incorrect credentials or other authentication issues. +- **Signature** ensures the integrity and authenticity of the SAML response. It includes: + - **SignedInfo** contains details about the canonicalization and signature methods. + - **Reference** points to the signed data and including transforms and a digest method. + - **SignatureValue** provides the actual digital signature. + - **KeyInfo** contains the X.509 certificate, which holds the public key used to verify the signature. +- **Assertion** includes user information, such as email, surname, first name, full name, username, user ID etc. +- **Subject** contains the user's unique identifier. +- **Conditions** specify the response's validity window. +- **AuthnStatement** includes authentication details. +- **AttributeStatement** contains additional user attributes. + +## SAML identity brokering + +### How SAML identity brokering works + +- **Initial Authentication Request**: A user attempts to access a service (SP1) that is protected by an IdP (IdP1). +- **Redirection to IdP1**: The user is redirected to IdP1 for authentication. If IdP1 trusts another IdP (IdP2) for authentication, it will redirect the user to IdP2. +- **Authentication at IdP2**: The user authenticates with IdP2, which generates a SAML assertion containing the user's identity and attributes. +- **Assertion Processing**: ZITADEL (IdP1) processes the SAML assertion from IdP2. ZITADEL then creates an independent SAML assertion based on the information received and its own policies. +- **Response to SP1**: ZITADEL (IdP1) sends this newly created SAML assertion to SP1, completing the authentication process. +- **Access Granted to SP1**:IdP1 then sends a final SAML assertion to SP1, which grants the user access to the requested service. + +See [Let Users Login with Preferred Identity Provider](https://zitadel.com/docs/guides/integrate/identity-providers/introduction) for more information. + + +## Best practices for SAML implementation + +Implementing SAML securely involves several best practices: + +- Limit XML Parser Features: Disable unnecessary features to prevent XML external entity (XXE) attacks. +- Use Canonicalized XML: Normalize XML to prevent manipulation. +- Validate XML Schema: Ensure only expected XML formats are accepted. +- Validate Signatures: Check all signatures in the SAML response. +- Use SSL Encryption: Protect against interception. +- Validate Parties: Ensure the destination, audience, recipient, and issuer information is correct. +- Enforce Validation Window: Accept responses only within a valid time frame. +- Use Historical Cache: Track and reject duplicate IDs to prevent replay attacks. +- Minimize Buffer Size: Protect against DDoS attacks. + +## Alternatives to SAML + +SAML has its flaws; it can be complex and cumbersome to implement. The primary alternatives to consider is OpenID Connect (OIDC). Some illustrate this with the following analogy: “SAML is to OpenID Connect as SOAP is to REST." Just as REST was created to address some inherent flaws in SOAP, OpenID Connect was created to address some of the limitations in specifications like SAML. OpenID Connect is flexible, easy to use, widely adopted, and reliably secure. + +For example, SAML is not well-suited for desktop and mobile applications due to its reliance on HTTP redirects, cookie-based session management, and complex certificate handling. OIDC, on the other hand, offers a modern, flexible, and simpler solution for authentication and authorization needs across desktop and mobile applications. It uses authorization codes and tokens that are easier to manage and supports custom URL schemes and deep linking, which simplifies the handling of redirects and improves the overall user experience​. Furthermore, OIDC offers more flexibility in managing sessions without relying solely on cookies. + +If a project requires SAML due to specific requirements or existing infrastructure, it should be used. However, for new projects, it is advisable to consider OpenID Connect because it is a more modern standard and is the more popular choice in the industry. + + +## Testing SAML scenarios using ZITADEL + +To test SAML scenarios with ZITADEL, follow these steps: + +1. Integrate a SAML SP with ZITADEL as the IdP: + - Sign up for a ZITADEL account if you don't already have one. If you are self-hosting ZITADEL, you can skip this step. + - Create an Organization and a Project in ZITADEL. + - Within your project, create a SAML application. + - Follow this example on how to create a SAML SP and integrate ZITADEL as the SAML IdP: [ZITADEL Python SAML SP Integration](https://github.com/zitadel/python-saml-sp). + +2. Integrate ZITADEL with another SAML IdP for identity brokering: + + - Configure an identity provider that supports SAML. + - Set up the necessary metadata and endpoints. Here are some guides to help with this setup: + - [Configure Entra ID as a SAML IdP](https://zitadel.com/docs/guides/integrate/identity-providers/azure-ad-saml) + - [Configure Okta as a SAML IdP](https://zitadel.com/docs/guides/integrate/identity-providers/okta-saml) + - [Configure MockSAML as a SAML IdP](https://zitadel.com/docs/guides/integrate/identity-providers/mocksaml) + +3. Create test users and simulate authentication requests: + - Create test users in ZITADEL. + - Simulate authentication requests to verify that the SAML assertions are correctly generated and transmitted. + - Ensure that the SAML assertions contain the expected attributes and that these attributes are correctly processed by the service provider. + +4. Simulate various scenarios: + - Successful Login: Verify that a valid user can successfully authenticate and access the service. + - Failed Login: Test scenarios where authentication fails, such as incorrect credentials or disabled accounts. + - Attribute Mapping: Check that user attributes (e.g., roles, permissions) are correctly mapped and utilized by the service provider. + - Logout Requests: Test single logout (SLO) to ensure that logging out from one service logs the user out of all connected services. + +For more information, refer to [SAML Endpoints in ZITADEL](https://zitadel.com/docs/apis/saml/endpoints). diff --git a/docs/sidebars.js b/docs/sidebars.js index 70669d4d6e..8dbf546bc6 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -121,7 +121,7 @@ module.exports = { title: "Overview", slug: "guides/manage/cloud/overview", description: - "Our customer portal is used to manage all your ZITADEL instances. You can also manage your subscriptions, billing, newsletters and support requests.", + "Our customer portal is used to manage all your ZITADEL instances. You can also manage your subscriptions, billing, newsletters and support requests.", }, items: [ "guides/manage/cloud/start", @@ -216,7 +216,7 @@ module.exports = { "guides/integrate/login/login-users", { type: "category", - label: "Openid Connect", + label: "OpenID Connect", collapsed: true, link: { type: "generated-index", @@ -232,24 +232,7 @@ module.exports = { "guides/integrate/login/oidc/logout", ], }, - /* - { - type: "category", - label: "SAML", - collapsed: true, - link: { - type: "generated-index", - title: "Authenticate users with openid connect (OIDC)", - slug: "guides/integrate/login/saml", - description: ".", - }, - items: [ - { - type: "autogenerated", - dirName: "guides/integrate/login/saml", - }, - ], - },*/ + "guides/integrate/login/saml", ], }, { From 23bebc7e30ebd6a20dd0a87480863a5557d5b3fc Mon Sep 17 00:00:00 2001 From: Silvan Date: Mon, 8 Jul 2024 17:54:19 +0200 Subject: [PATCH 03/34] fix(fields): add index to improve search by aggregate (#8267) # Which Problems Are Solved During performance testing of the `eventstore.fields` table we found some long running queries which searched for the aggregate id. # How the Problems Are Solved A new index was added to the `eventstore.fields`-table called `f_aggregate_object_type_idx`. # Additional Changes None # Additional Context - Table was added in https://github.com/zitadel/zitadel/pull/8191 - Part of https://github.com/zitadel/zitadel/issues/7639 --- cmd/setup/31.go | 27 +++++++++++++++++++++++++++ cmd/setup/31.sql | 1 + cmd/setup/config.go | 1 + cmd/setup/setup.go | 2 ++ 4 files changed, 31 insertions(+) create mode 100644 cmd/setup/31.go create mode 100644 cmd/setup/31.sql diff --git a/cmd/setup/31.go b/cmd/setup/31.go new file mode 100644 index 0000000000..640c11b1c0 --- /dev/null +++ b/cmd/setup/31.go @@ -0,0 +1,27 @@ +package setup + +import ( + "context" + _ "embed" + + "github.com/zitadel/zitadel/internal/database" + "github.com/zitadel/zitadel/internal/eventstore" +) + +var ( + //go:embed 31.sql + addAggregateIndexToFields string +) + +type AddAggregateIndexToFields struct { + dbClient *database.DB +} + +func (mig *AddAggregateIndexToFields) Execute(ctx context.Context, _ eventstore.Event) error { + _, err := mig.dbClient.ExecContext(ctx, addAggregateIndexToFields) + return err +} + +func (mig *AddAggregateIndexToFields) String() string { + return "31_add_aggregate_index_to_fields" +} diff --git a/cmd/setup/31.sql b/cmd/setup/31.sql new file mode 100644 index 0000000000..4198f2326e --- /dev/null +++ b/cmd/setup/31.sql @@ -0,0 +1 @@ +CREATE INDEX CONCURRENTLY IF NOT EXISTS f_aggregate_object_type_idx ON eventstore.fields (aggregate_type, aggregate_id, object_type); \ No newline at end of file diff --git a/cmd/setup/config.go b/cmd/setup/config.go index 2f4f47c768..2bee4642aa 100644 --- a/cmd/setup/config.go +++ b/cmd/setup/config.go @@ -114,6 +114,7 @@ type Steps struct { s28AddFieldTable *AddFieldTable s29FillFieldsForProjectGrant *FillFieldsForProjectGrant s30FillFieldsForOrgDomainVerified *FillFieldsForOrgDomainVerified + s31AddAggregateIndexToFields *AddAggregateIndexToFields } func MustNewSteps(v *viper.Viper) *Steps { diff --git a/cmd/setup/setup.go b/cmd/setup/setup.go index a36ccfbe0c..f9a40697a2 100644 --- a/cmd/setup/setup.go +++ b/cmd/setup/setup.go @@ -159,6 +159,7 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string) steps.s28AddFieldTable = &AddFieldTable{dbClient: esPusherDBClient} steps.s29FillFieldsForProjectGrant = &FillFieldsForProjectGrant{eventstore: eventstoreClient} steps.s30FillFieldsForOrgDomainVerified = &FillFieldsForOrgDomainVerified{eventstore: eventstoreClient} + steps.s31AddAggregateIndexToFields = &AddAggregateIndexToFields{dbClient: esPusherDBClient} err = projection.Create(ctx, projectionDBClient, eventstoreClient, config.Projections, nil, nil, nil) logging.OnError(err).Fatal("unable to start projections") @@ -182,6 +183,7 @@ func Setup(ctx context.Context, config *Config, steps *Steps, masterKey string) steps.s1ProjectionTable, steps.s2AssetsTable, steps.s28AddFieldTable, + steps.s31AddAggregateIndexToFields, steps.FirstInstance, steps.s5LastFailed, steps.s6OwnerRemoveColumns, From 82d950019f6c5f35fd1dbdd5d15bf7e92af3f149 Mon Sep 17 00:00:00 2001 From: Silvan Date: Tue, 9 Jul 2024 17:16:50 +0200 Subject: [PATCH 04/34] test: add load test for session creation (#8088) # Which Problems Are Solved Extends load tests by testing session creation. # How the Problems Are Solved The test creates a session including a check for user id. # Additional Context - part of https://github.com/zitadel/zitadel/issues/7639 --- load-test/Makefile | 8 +++ load-test/README.md | 8 ++- load-test/src/oidc.ts | 32 ++++++++++++ load-test/src/session.ts | 42 ++++++++++++++++ .../machine_client_credentials_login.ts | 49 +++++++++++++++++++ load-test/src/use_cases/session.ts | 41 ++++++++++++++++ load-test/src/user.ts | 26 ++++++++++ 7 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 load-test/src/session.ts create mode 100644 load-test/src/use_cases/machine_client_credentials_login.ts create mode 100644 load-test/src/use_cases/session.ts diff --git a/load-test/Makefile b/load-test/Makefile index 4d2e9aa18e..106b272811 100644 --- a/load-test/Makefile +++ b/load-test/Makefile @@ -12,6 +12,10 @@ human_password_login: bundle machine_pat_login: bundle k6 run dist/machine_pat_login.js --vus ${VUS} --duration ${DURATION} +.PHONY: machine_client_credentials_login +machine_client_credentials_login: bundle + k6 run dist/machine_client_credentials_login.js --vus ${VUS} --duration ${DURATION} + .PHONY: user_info user_info: bundle k6 run dist/user_info.js --vus ${VUS} --duration ${DURATION} @@ -26,6 +30,10 @@ introspect: ensure_modules bundle cd ../../xk6-modules && xk6 build --with xk6-zitadel=. ./../../xk6-modules/k6 run dist/introspection.js --vus ${VUS} --duration ${DURATION} +.PHONY: add_session +add_session: bundle + k6 run dist/session.js --vus ${VUS} --duration ${DURATION} + .PHONY: lint lint: npm i diff --git a/load-test/README.md b/load-test/README.md index 6e1542da40..18705a897d 100644 --- a/load-test/README.md +++ b/load-test/README.md @@ -36,6 +36,9 @@ Before you run the tests you need an initialized user. The tests don't implement * `make machine_pat_login` setup: creates machines and a pat for each machine test: calls user info endpoint with the given pats +* `make machine_client_credentials_login` + setup: creates machines and a client credential secret for each machine + test: calls token endpoint with the `client_credentials` grant type. * `make user_info` setup: creates human users and signs them in test: calls user info endpoint using the given humans @@ -43,4 +46,7 @@ Before you run the tests you need an initialized user. The tests don't implement test: creates a human, updates its profile, locks the user and then deletes it * `make introspect` setup: creates projects, one api per project, one key per api and generates the jwt from the given keys - test: calls introspection endpoint using the given JWTs \ No newline at end of file + test: calls introspection endpoint using the given JWTs +* `make add_session` + setup: creates human users + test: creates new sessions with user id check \ No newline at end of file diff --git a/load-test/src/oidc.ts b/load-test/src/oidc.ts index 0f09fba965..a9173bfceb 100644 --- a/load-test/src/oidc.ts +++ b/load-test/src/oidc.ts @@ -72,3 +72,35 @@ export function introspect(jwt: string, token: string) { introspectTrend.add(res.timings.duration); } + +const clientCredentialsTrend = new Trend('oidc_client_credentials_duration', true); +export function clientCredentials(clientId: string, clientSecret: string): Promise { + return new Promise((resolve, reject) => { + const response = http.asyncRequest('POST', configuration().token_endpoint, + { + grant_type: "client_credentials", + scope: 'openid profile urn:zitadel:iam:org:project:id:zitadel:aud', + client_id: clientId, + client_secret: clientSecret, + }, + { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }, + ); + response.then((res) => { + check(res, { + 'client credentials status ok': (r) => r.status === 200, + }) || reject(`client credentials request failed (client id: ${clientId}) status: ${res.status} body: ${res.body}`); + + clientCredentialsTrend.add(res.timings.duration); + const tokens = new Tokens(res.json() as JSONObject) + check(tokens, { + 'client credentials token ok': (t) => t.accessToken !== undefined, + }) || reject(`client credentials access token missing (client id: ${clientId}`); + + resolve(tokens) + }); + }); +} \ No newline at end of file diff --git a/load-test/src/session.ts b/load-test/src/session.ts new file mode 100644 index 0000000000..28a994c975 --- /dev/null +++ b/load-test/src/session.ts @@ -0,0 +1,42 @@ +import { Trend } from 'k6/metrics'; +import { Org } from './org'; +import http from 'k6/http'; +import url from './url'; +import { check } from 'k6'; +import { User } from './user'; + +export type Session = { + id: string; +}; + +const addSessionTrend = new Trend('session_add_session_duration', true); +export function createSession(user: User, org: Org, accessToken: string): Promise { + return new Promise((resolve, reject) => { + let response = http.asyncRequest( + 'POST', + url('/v2beta/sessions'), + JSON.stringify({ + checks: { + user: { + userId: user.userId, + } + } + }), + { + headers: { + authorization: `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + 'x-zitadel-orgid': org.organizationId, + }, + }, + ); + response.then((res) => { + check(res, { + 'add Session status ok': (r) => r.status === 201, + }) || reject(`unable to add Session status: ${res.status} body: ${res.body}`); + + addSessionTrend.add(res.timings.duration); + resolve(res.json() as Session); + }); + }); +} diff --git a/load-test/src/use_cases/machine_client_credentials_login.ts b/load-test/src/use_cases/machine_client_credentials_login.ts new file mode 100644 index 0000000000..a2cbcca8da --- /dev/null +++ b/load-test/src/use_cases/machine_client_credentials_login.ts @@ -0,0 +1,49 @@ +import { loginByUsernamePassword } from '../login_ui'; +import { createOrg, removeOrg } from '../org'; +import {createMachine, User, addMachineSecret} from '../user'; +import {clientCredentials, userinfo} from '../oidc'; +import { Config, MaxVUs } from '../config'; + +export async function setup() { + const tokens = loginByUsernamePassword(Config.admin as User); + console.info('setup: admin signed in'); + + const org = await createOrg(tokens.accessToken!); + console.info(`setup: org (${org.organizationId}) created`); + + let machines = ( + await Promise.all( + Array.from({ length: MaxVUs() }, (_, i) => { + return createMachine(`zitachine-${i}`, org, tokens.accessToken!); + }), + ) + ).map((machine) => { + return { userId: machine.userId, loginName: machine.loginNames[0] }; + }); + console.info(`setup: ${machines.length} machines created`); + + let credentials = ( + await Promise.all( + machines.map((machine) => { + return addMachineSecret(machine.userId, org, tokens.accessToken!); + }), + ) + ).map((credentials, i) => { + return { userId: machines[i].userId, loginName: machines[i].loginName, password: credentials.clientSecret }; + }); + console.info(`setup: secrets added`); + + return { tokens, machines: credentials, org }; +} + +export default function (data: any) { + clientCredentials(data.machines[__VU - 1].loginName, data.machines[__VU - 1].password) + .then((token) => { + userinfo(token.accessToken!) + }) +} + +export function teardown(data: any) { + removeOrg(data.org, data.tokens.accessToken); + console.info('teardown: org removed'); +} diff --git a/load-test/src/use_cases/session.ts b/load-test/src/use_cases/session.ts new file mode 100644 index 0000000000..d9cdfbd3b7 --- /dev/null +++ b/load-test/src/use_cases/session.ts @@ -0,0 +1,41 @@ +import { loginByUsernamePassword } from '../login_ui'; +import { createOrg, removeOrg } from '../org'; +import { User, createHuman } from '../user'; +import { Trend } from 'k6/metrics'; +import { Config, MaxVUs } from '../config'; +import { createSession } from '../session'; +import { check } from 'k6'; + +export async function setup() { + const tokens = loginByUsernamePassword(Config.admin as User); + console.log('setup: admin signed in'); + + const org = await createOrg(tokens.accessToken!); + console.log(`setup: org (${org.organizationId}) created`); + + const humanPromises = Array.from({ length: MaxVUs() }, (_, i) => { + return createHuman(`zitizen-${i}`, org, tokens.accessToken!); + }); + + const humans = (await Promise.all(humanPromises)).map((user) => { + return { userId: user.userId, loginName: user.loginNames[0], password: 'Password1!' }; + }); + console.log(`setup: ${humans.length} users created`); + return { tokens, users: humans, org }; +} + +const addSessionTrend = new Trend('add_session_duration', true); +export default async function (data: any) { + const start = new Date(); + const session = await createSession(data.users[__VU - 1], data.org, data.tokens.accessToken); + + check(session, { + 'add session is status ok': (s) => s.id !== "", + }); + + addSessionTrend.add(new Date().getTime() - start.getTime()); +} + +export function teardown(data: any) { + removeOrg(data.org, data.tokens.accessToken); +} diff --git a/load-test/src/user.ts b/load-test/src/user.ts index a4abd09325..21214b16ab 100644 --- a/load-test/src/user.ts +++ b/load-test/src/user.ts @@ -171,6 +171,32 @@ export function addMachinePat(userId: string, org: Org, accessToken: string): Pr }); } +export type MachineSecret = { + clientId: string; + clientSecret: string; +}; + +const addMachineSecretTrend = new Trend('user_add_machine_secret_duration', true); +export function addMachineSecret(userId: string, org: Org, accessToken: string): Promise { + return new Promise((resolve, reject) => { + let response = http.asyncRequest('PUT', url(`/management/v1/users/${userId}/secret`), null, { + headers: { + authorization: `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + 'x-zitadel-orgid': org.organizationId, + }, + }); + response.then((res) => { + check(res, { + 'generate machine secret status ok': (r) => r.status === 200, + }) || reject(`unable to generate machine secret (user id: ${userId}) status: ${res.status} body: ${res.body}`); + + addMachineSecretTrend.add(res.timings.duration); + resolve(res.json()! as MachineSecret); + }); + }); +} + const lockUserTrend = new Trend('lock_user_duration', true); export function lockUser(userId: string, org: Org, accessToken: string): Promise> { return new Promise((resolve, reject) => { From 19a8ab02adc97d452333fa49f60460daef2d6e71 Mon Sep 17 00:00:00 2001 From: Stefan Benz <46600784+stebenz@users.noreply.github.com> Date: Wed, 10 Jul 2024 14:31:28 +0200 Subject: [PATCH 05/34] fix: add missing totp remove endpoint in user v2 API (#8256) # Which Problems Are Solved TOTP remove endpoint available in management API, not in user v2 API. # How the Problems Are Solved Add endpoint RemoveTOTP to user v2 API. # Additional Changes None # Additional Context close #6605 --------- Co-authored-by: Livio Spring --- internal/api/grpc/user/v2/totp.go | 9 ++- .../api/grpc/user/v2/totp_integration_test.go | 77 +++++++++++++++++++ internal/command/user_human_otp.go | 5 ++ internal/command/user_human_otp_test.go | 33 +++++++- proto/zitadel/user/v2beta/user_service.proto | 42 +++++++++- 5 files changed, 160 insertions(+), 6 deletions(-) diff --git a/internal/api/grpc/user/v2/totp.go b/internal/api/grpc/user/v2/totp.go index 691f31a833..e426f5788d 100644 --- a/internal/api/grpc/user/v2/totp.go +++ b/internal/api/grpc/user/v2/totp.go @@ -12,7 +12,6 @@ func (s *Server) RegisterTOTP(ctx context.Context, req *user.RegisterTOTPRequest return totpDetailsToPb( s.command.AddUserTOTP(ctx, req.GetUserId(), ""), ) - } func totpDetailsToPb(totp *domain.TOTP, err error) (*user.RegisterTOTPResponse, error) { @@ -35,3 +34,11 @@ func (s *Server) VerifyTOTPRegistration(ctx context.Context, req *user.VerifyTOT Details: object.DomainToDetailsPb(objectDetails), }, nil } + +func (s *Server) RemoveTOTP(ctx context.Context, req *user.RemoveTOTPRequest) (*user.RemoveTOTPResponse, error) { + objectDetails, err := s.command.HumanRemoveTOTP(ctx, req.GetUserId(), "") + if err != nil { + return nil, err + } + return &user.RemoveTOTPResponse{Details: object.DomainToDetailsPb(objectDetails)}, nil +} diff --git a/internal/api/grpc/user/v2/totp_integration_test.go b/internal/api/grpc/user/v2/totp_integration_test.go index cf7e6ffa3a..489c189b03 100644 --- a/internal/api/grpc/user/v2/totp_integration_test.go +++ b/internal/api/grpc/user/v2/totp_integration_test.go @@ -205,3 +205,80 @@ func TestServer_VerifyTOTPRegistration(t *testing.T) { }) } } + +func TestServer_RemoveTOTP(t *testing.T) { + userID := Tester.CreateHumanUser(CTX).GetUserId() + Tester.RegisterUserPasskey(CTX, userID) + _, sessionToken, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userID) + + userVerified := Tester.CreateHumanUser(CTX) + Tester.RegisterUserPasskey(CTX, userVerified.GetUserId()) + _, sessionTokenVerified, _, _ := Tester.CreateVerifiedWebAuthNSession(t, CTX, userVerified.GetUserId()) + userVerifiedCtx := Tester.WithAuthorizationToken(context.Background(), sessionTokenVerified) + _, err := Tester.Client.UserV2.VerifyPhone(userVerifiedCtx, &user.VerifyPhoneRequest{ + UserId: userVerified.GetUserId(), + VerificationCode: userVerified.GetPhoneCode(), + }) + require.NoError(t, err) + + regOtherUser, err := Client.RegisterTOTP(CTX, &user.RegisterTOTPRequest{ + UserId: userVerified.GetUserId(), + }) + require.NoError(t, err) + codeOtherUser, err := totp.GenerateCode(regOtherUser.Secret, time.Now()) + require.NoError(t, err) + _, err = Client.VerifyTOTPRegistration(userVerifiedCtx, &user.VerifyTOTPRegistrationRequest{ + UserId: userVerified.GetUserId(), + Code: codeOtherUser, + }, + ) + require.NoError(t, err) + + type args struct { + ctx context.Context + req *user.RemoveTOTPRequest + } + tests := []struct { + name string + args args + want *user.RemoveTOTPResponse + wantErr bool + }{ + { + name: "not added", + args: args{ + ctx: Tester.WithAuthorizationToken(context.Background(), sessionToken), + req: &user.RemoveTOTPRequest{ + UserId: userID, + }, + }, + wantErr: true, + }, + { + name: "success", + args: args{ + ctx: userVerifiedCtx, + req: &user.RemoveTOTPRequest{ + UserId: userVerified.GetUserId(), + }, + }, + want: &user.RemoveTOTPResponse{ + Details: &object.Details{ + ResourceOwner: Tester.Organisation.ResourceOwner, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Client.RemoveTOTP(tt.args.ctx, tt.args.req) + if tt.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + require.NotNil(t, got) + integration.AssertDetails(t, tt.want, got) + }) + } +} diff --git a/internal/command/user_human_otp.go b/internal/command/user_human_otp.go index bc65ba7245..8ecd517519 100644 --- a/internal/command/user_human_otp.go +++ b/internal/command/user_human_otp.go @@ -239,6 +239,11 @@ func (c *Commands) HumanRemoveTOTP(ctx context.Context, userID, resourceOwner st if existingOTP.State == domain.MFAStateUnspecified || existingOTP.State == domain.MFAStateRemoved { return nil, zerrors.ThrowNotFound(nil, "COMMAND-Hd9sd", "Errors.User.MFA.OTP.NotExisting") } + if userID != authz.GetCtxData(ctx).UserID { + if err := c.checkPermission(ctx, domain.PermissionUserWrite, existingOTP.ResourceOwner, userID); err != nil { + return nil, err + } + } userAgg := UserAggregateFromWriteModel(&existingOTP.WriteModel) pushedEvents, err := c.eventstore.Push(ctx, user.NewHumanOTPRemovedEvent(ctx, userAgg)) if err != nil { diff --git a/internal/command/user_human_otp_test.go b/internal/command/user_human_otp_test.go index 81615a4f6e..806d24dd47 100644 --- a/internal/command/user_human_otp_test.go +++ b/internal/command/user_human_otp_test.go @@ -841,7 +841,8 @@ func TestCommands_HumanCheckMFATOTPSetup(t *testing.T) { func TestCommandSide_RemoveHumanTOTP(t *testing.T) { type fields struct { - eventstore func(t *testing.T) *eventstore.Eventstore + eventstore func(t *testing.T) *eventstore.Eventstore + checkPermission domain.PermissionCheck } type ( args struct { @@ -891,7 +892,31 @@ func TestCommandSide_RemoveHumanTOTP(t *testing.T) { }, }, { - name: "otp not existing, not found error", + name: "otp, no permission error", + fields: fields{ + eventstore: expectEventstore( + expectFilter( + eventFromEventPusher( + user.NewHumanOTPAddedEvent(context.Background(), + &user.NewAggregate("user1", "org1").Aggregate, + nil, + ), + ), + ), + ), + checkPermission: newMockPermissionCheckNotAllowed(), + }, + args: args{ + ctx: context.Background(), + orgID: "org1", + userID: "user1", + }, + res: res{ + err: zerrors.IsPermissionDenied, + }, + }, + { + name: "otp remove, ok", fields: fields{ eventstore: expectEventstore( expectFilter( @@ -908,6 +933,7 @@ func TestCommandSide_RemoveHumanTOTP(t *testing.T) { ), ), ), + checkPermission: newMockPermissionCheckAllowed(), }, args: args{ ctx: context.Background(), @@ -924,7 +950,8 @@ func TestCommandSide_RemoveHumanTOTP(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { r := &Commands{ - eventstore: tt.fields.eventstore(t), + eventstore: tt.fields.eventstore(t), + checkPermission: tt.fields.checkPermission, } got, err := r.HumanRemoveTOTP(tt.args.ctx, tt.args.userID, tt.args.orgID) if tt.res.err == nil { diff --git a/proto/zitadel/user/v2beta/user_service.proto b/proto/zitadel/user/v2beta/user_service.proto index f3d8de747c..3a0fb2dfa5 100644 --- a/proto/zitadel/user/v2beta/user_service.proto +++ b/proto/zitadel/user/v2beta/user_service.proto @@ -655,6 +655,28 @@ service UserService { }; } + rpc RemoveTOTP (RemoveTOTPRequest) returns (RemoveTOTPResponse) { + option (google.api.http) = { + delete: "/v2beta/users/{user_id}/totp" + }; + + option (zitadel.protoc_gen_zitadel.v2.options) = { + auth_option: { + permission: "authenticated" + } + }; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Remove TOTP generator from a user"; + description: "Remove the configured TOTP generator of a user. As only one TOTP generator per user is allowed, the user will not have TOTP as a second-factor afterward." + responses: { + key: "200" + value: { + description: "OK"; + } + }; + }; + } + rpc AddOTPSMS (AddOTPSMSRequest) returns (AddOTPSMSResponse) { option (google.api.http) = { post: "/v2beta/users/{user_id}/otp_sms" @@ -690,7 +712,7 @@ service UserService { }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { summary: "Remove One-Time-Password (OTP) SMS from a user"; - description: "Remove the configured One-Time-Password (OTP) SMS factor of the authenticated user. As only one OTP SMS per user is allowed, the user will not have OTP SMS as a second-factor afterward." + description: "Remove the configured One-Time-Password (OTP) SMS factor of a user. As only one OTP SMS per user is allowed, the user will not have OTP SMS as a second-factor afterward." responses: { key: "200" value: { @@ -735,7 +757,7 @@ service UserService { }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { summary: "Remove One-Time-Password (OTP) Email from a user"; - description: "Remove the configured One-Time-Password (OTP) Email factor of the authenticated user. As only one OTP Email per user is allowed, the user will not have OTP Email as a second-factor afterward." + description: "Remove the configured One-Time-Password (OTP) Email factor of a user. As only one OTP Email per user is allowed, the user will not have OTP Email as a second-factor afterward." responses: { key: "200" value: { @@ -1471,6 +1493,22 @@ message VerifyTOTPRegistrationResponse { zitadel.object.v2beta.Details details = 1; } +message RemoveTOTPRequest { + string user_id = 1 [ + (validate.rules).string = {min_len: 1, max_len: 200}, + (google.api.field_behavior) = REQUIRED, + (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { + min_length: 1; + max_length: 200; + example: "\"163840776835432705\""; + } + ]; +} + +message RemoveTOTPResponse { + zitadel.object.v2beta.Details details = 1; +} + message AddOTPSMSRequest { string user_id = 1 [ (validate.rules).string = {min_len: 1, max_len: 200}, From fb2d4545b914ed8bb223bacded42f280c5e86861 Mon Sep 17 00:00:00 2001 From: Stefan Benz <46600784+stebenz@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:49:35 +0200 Subject: [PATCH 06/34] fix: add details to ListUsers for user results (#8255) # Which Problems Are Solved In User v2 API, the ListUsers endpoint doesn't provide the information to which organization the user belongs to. # How the Problems Are Solved Add the details to the user results from the ListUsers endpoint, so that the OrgID is also included as ResourceOwner. # Additional Changes None # Additional Context Closes #8172 --- internal/api/grpc/user/v2/query.go | 7 ++- .../grpc/user/v2/query_integration_test.go | 52 +++++++++++-------- internal/integration/client.go | 5 +- proto/zitadel/user/v2beta/user.proto | 1 + proto/zitadel/user/v2beta/user_service.proto | 1 + 5 files changed, 39 insertions(+), 27 deletions(-) diff --git a/internal/api/grpc/user/v2/query.go b/internal/api/grpc/user/v2/query.go index 5ccaea84b0..2aaf0ad8ef 100644 --- a/internal/api/grpc/user/v2/query.go +++ b/internal/api/grpc/user/v2/query.go @@ -60,7 +60,12 @@ func UsersToPb(users []*query.User, assetPrefix string) []*user.User { func userToPb(userQ *query.User, assetPrefix string) *user.User { return &user.User{ - UserId: userQ.ID, + UserId: userQ.ID, + Details: object.DomainToDetailsPb(&domain.ObjectDetails{ + Sequence: userQ.Sequence, + EventDate: userQ.ChangeDate, + ResourceOwner: userQ.ResourceOwner, + }), State: userStateToPb(userQ.State), Username: userQ.Username, LoginNames: userQ.LoginNames, diff --git a/internal/api/grpc/user/v2/query_integration_test.go b/internal/api/grpc/user/v2/query_integration_test.go index 9b5c74e42c..b4b770481b 100644 --- a/internal/api/grpc/user/v2/query_integration_test.go +++ b/internal/api/grpc/user/v2/query_integration_test.go @@ -23,7 +23,7 @@ func TestServer_GetUserByID(t *testing.T) { type args struct { ctx context.Context req *user.GetUserByIDRequest - dep func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*timestamppb.Timestamp, error) + dep func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) } tests := []struct { name string @@ -38,7 +38,7 @@ func TestServer_GetUserByID(t *testing.T) { &user.GetUserByIDRequest{ UserId: "", }, - func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*timestamppb.Timestamp, error) { + func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { return nil, nil }, }, @@ -51,7 +51,7 @@ func TestServer_GetUserByID(t *testing.T) { &user.GetUserByIDRequest{ UserId: "unknown", }, - func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*timestamppb.Timestamp, error) { + func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { return nil, nil }, }, @@ -62,10 +62,10 @@ func TestServer_GetUserByID(t *testing.T) { args: args{ IamCTX, &user.GetUserByIDRequest{}, - func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*timestamppb.Timestamp, error) { + func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) request.UserId = resp.GetUserId() - return nil, nil + return &userAttr{resp.GetUserId(), username, nil, resp.GetDetails()}, nil }, }, want: &user.GetUserByIDResponse{ @@ -106,11 +106,11 @@ func TestServer_GetUserByID(t *testing.T) { args: args{ IamCTX, &user.GetUserByIDRequest{}, - func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*timestamppb.Timestamp, error) { + func(ctx context.Context, username string, request *user.GetUserByIDRequest) (*userAttr, error) { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) request.UserId = resp.GetUserId() - changed := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) - return changed, nil + details := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) + return &userAttr{resp.GetUserId(), username, details.GetChangeDate(), resp.GetDetails()}, nil }, }, want: &user.GetUserByIDResponse{ @@ -152,7 +152,7 @@ func TestServer_GetUserByID(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { username := fmt.Sprintf("%d@mouse.com", time.Now().UnixNano()) - changed, err := tt.args.dep(tt.args.ctx, username, tt.args.req) + userAttr, err := tt.args.dep(tt.args.ctx, username, tt.args.req) require.NoError(t, err) retryDuration := time.Minute if ctxDeadline, ok := CTX.Deadline(); ok { @@ -168,14 +168,15 @@ func TestServer_GetUserByID(t *testing.T) { if getErr != nil { return } - tt.want.User.UserId = tt.args.req.GetUserId() - tt.want.User.Username = username - tt.want.User.PreferredLoginName = username - tt.want.User.LoginNames = []string{username} + tt.want.User.Details = userAttr.Details + tt.want.User.UserId = userAttr.UserID + tt.want.User.Username = userAttr.Username + tt.want.User.PreferredLoginName = userAttr.Username + tt.want.User.LoginNames = []string{userAttr.Username} if human := tt.want.User.GetHuman(); human != nil { - human.Email.Email = username + human.Email.Email = userAttr.Username if tt.want.User.GetHuman().GetPasswordChanged() != nil { - human.PasswordChanged = changed + human.PasswordChanged = userAttr.Changed } } assert.Equal(ttt, tt.want.User, got.User) @@ -311,6 +312,9 @@ func TestServer_GetUserByID_Permission(t *testing.T) { if human := tt.want.User.GetHuman(); human != nil { human.Email.Email = newOrgOwnerEmail } + // details tested in GetUserByID + tt.want.User.Details = got.User.GetDetails() + assert.Equal(t, tt.want.User, got.User) } }) @@ -321,6 +325,7 @@ type userAttr struct { UserID string Username string Changed *timestamppb.Timestamp + Details *object.Details } func TestServer_ListUsers(t *testing.T) { @@ -374,7 +379,7 @@ func TestServer_ListUsers(t *testing.T) { for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() - infos[i] = userAttr{resp.GetUserId(), username, nil} + infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserIDsQuery(userIDs)) return infos, nil @@ -428,8 +433,8 @@ func TestServer_ListUsers(t *testing.T) { for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() - changed := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) - infos[i] = userAttr{resp.GetUserId(), username, changed} + details := Tester.SetUserPassword(ctx, resp.GetUserId(), integration.UserPassword, true) + infos[i] = userAttr{resp.GetUserId(), username, details.GetChangeDate(), resp.GetDetails()} } request.Queries = append(request.Queries, InUserIDsQuery(userIDs)) return infos, nil @@ -485,7 +490,7 @@ func TestServer_ListUsers(t *testing.T) { for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() - infos[i] = userAttr{resp.GetUserId(), username, nil} + infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserIDsQuery(userIDs)) return infos, nil @@ -581,7 +586,7 @@ func TestServer_ListUsers(t *testing.T) { for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) userIDs[i] = resp.GetUserId() - infos[i] = userAttr{resp.GetUserId(), username, nil} + infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} request.Queries = append(request.Queries, UsernameQuery(username)) } return infos, nil @@ -633,7 +638,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) - infos[i] = userAttr{resp.GetUserId(), username, nil} + infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) return infos, nil @@ -685,7 +690,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) - infos[i] = userAttr{resp.GetUserId(), username, nil} + infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) return infos, nil @@ -800,7 +805,7 @@ func TestServer_ListUsers(t *testing.T) { infos := make([]userAttr, len(usernames)) for i, username := range usernames { resp := Tester.CreateHumanUserVerified(ctx, orgResp.OrganizationId, username) - infos[i] = userAttr{resp.GetUserId(), username, nil} + infos[i] = userAttr{resp.GetUserId(), username, nil, resp.GetDetails()} } request.Queries = append(request.Queries, OrganizationIdQuery(orgResp.OrganizationId)) request.Queries = append(request.Queries, InUserEmailsQuery(usernames)) @@ -920,6 +925,7 @@ func TestServer_ListUsers(t *testing.T) { human.PasswordChanged = infos[i].Changed } } + tt.want.Result[i].Details = infos[i].Details } for i := range tt.want.Result { assert.Contains(ttt, got.Result, tt.want.Result[i]) diff --git a/internal/integration/client.go b/internal/integration/client.go index 90f7518fea..783eca4c9b 100644 --- a/internal/integration/client.go +++ b/internal/integration/client.go @@ -17,7 +17,6 @@ import ( "google.golang.org/grpc" "google.golang.org/protobuf/types/known/durationpb" "google.golang.org/protobuf/types/known/structpb" - "google.golang.org/protobuf/types/known/timestamppb" "github.com/zitadel/zitadel/internal/api/authz" "github.com/zitadel/zitadel/internal/command" @@ -312,7 +311,7 @@ func (s *Tester) RegisterUserU2F(ctx context.Context, userID string) { logging.OnError(err).Fatal("create user u2f") } -func (s *Tester) SetUserPassword(ctx context.Context, userID, password string, changeRequired bool) *timestamppb.Timestamp { +func (s *Tester) SetUserPassword(ctx context.Context, userID, password string, changeRequired bool) *object.Details { resp, err := s.Client.UserV2.SetPassword(ctx, &user.SetPasswordRequest{ UserId: userID, NewPassword: &user.Password{ @@ -321,7 +320,7 @@ func (s *Tester) SetUserPassword(ctx context.Context, userID, password string, c }, }) logging.OnError(err).Fatal("set user password") - return resp.GetDetails().GetChangeDate() + return resp.GetDetails() } func (s *Tester) AddGenericOAuthProvider(t *testing.T, ctx context.Context) string { diff --git a/proto/zitadel/user/v2beta/user.proto b/proto/zitadel/user/v2beta/user.proto index 69d9f8dce3..9f1fd8a8c7 100644 --- a/proto/zitadel/user/v2beta/user.proto +++ b/proto/zitadel/user/v2beta/user.proto @@ -183,6 +183,7 @@ message User { example: "\"d654e6ba-70a3-48ef-a95d-37c8d8a7901a\""; } ]; + zitadel.object.v2beta.Details details = 8; UserState state = 2 [ (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { description: "current state of the user"; diff --git a/proto/zitadel/user/v2beta/user_service.proto b/proto/zitadel/user/v2beta/user_service.proto index 3a0fb2dfa5..cb3a1610e6 100644 --- a/proto/zitadel/user/v2beta/user_service.proto +++ b/proto/zitadel/user/v2beta/user_service.proto @@ -989,6 +989,7 @@ message GetUserByIDRequest { } message GetUserByIDResponse { + //deprecated: details is moved into user zitadel.object.v2beta.Details details = 1; zitadel.user.v2beta.User user = 2; } From 86c124955d673b4fb73dd9865c71d48f29527de6 Mon Sep 17 00:00:00 2001 From: Fabi Date: Thu, 11 Jul 2024 07:54:04 +0200 Subject: [PATCH 07/34] fix: multiple docs issues (#8244) # Which Problems Are Solved - `
` tag is rendered in some cases in the docs, instead of rendering a detail section which can be expanded - New API V2 and V3 services where not rendered correctly - The plugin which made it possible to integrate external code files and show them on the docs didn't work anymore # How the Problems Are Solved - remove / from details tag, so it is properly rendered - changing link source from tag to auto - Someone already forked the repository and made it available for docusaurus v3, we integrated the forked version --------- Co-authored-by: Stefan Benz <46600784+stebenz@users.noreply.github.com> --- docs/docs/apis/v3.mdx | 98 +++-- docs/docs/self-hosting/deploy/compose.mdx | 10 +- .../loadbalancing-example.mdx | 25 +- .../manage/configure/_compose.mdx | 23 +- .../self-hosting/manage/configure/_helm.mdx | 11 +- .../manage/configure/_linuxunix.mdx | 17 +- docs/docusaurus.config.js | 24 +- docs/package.json | 6 +- docs/yarn.lock | 391 +++++++++--------- .../settings/v2beta/settings_service.proto | 2 - 10 files changed, 318 insertions(+), 289 deletions(-) diff --git a/docs/docs/apis/v3.mdx b/docs/docs/apis/v3.mdx index 101551feee..202e907bd8 100644 --- a/docs/docs/apis/v3.mdx +++ b/docs/docs/apis/v3.mdx @@ -136,21 +136,25 @@ Additional to the standard CRUD methods: - ListAvailableExecutionMethods - ListAvailableExecutionFunctions -\
action_service.proto -{ActionServiceProto} -\
+
+ action_service.proto + {ActionServiceProto} +
-\
action_target.proto -{ActionTargetProto} -\
+
+ action_target.proto + {ActionTargetProto} +
-\
action_execution.proto -{ActionExecutionProto} -\
+
+ action_execution.proto + {ActionExecutionProto} +
-\
action_query.proto -{ActionSearchProto} -\
+
+ action_query.proto + {ActionSearchProto} +
### ZITADELUsers @@ -165,29 +169,35 @@ Standard CRUD methods - Standard CRUD and methods for all IDPs - Resources have additional properties for reusability capabilities. -\
idp_service.proto -{IDPServiceProto} -\
+
+ idp_service.proto + {IDPServiceProto} +
-\
idp.proto -{IDPProto} -\
+
+ idp.proto + {IDPProto} +
-\
idp_search.proto -{IDPSearchProto} -\
+
+ idp_search.proto + {IDPSearchProto} +
-\
idp_gitlab.proto -{IDPGitLabProto} -\
+
+ idp_gitlab.proto + {IDPGitLabProto} +
-\
object.proto -{ObjectProto} -\
+
+ object.proto + {ObjectProto} +
-\
resource_object.proto -{ResourceObjectProto} -\
+
+ resource_object.proto + {ResourceObjectProto} +
### ZITADELInstances @@ -267,21 +277,25 @@ For a full proto example, have a look at the [ZITADELLanguageSettings service](# Default language, restricted languages, supported languages -\
language_service.proto -{LanguageServiceProto} -\
+
+ language_service.proto + {LanguageServiceProto} +
-\
language.proto -{LanguageProto} -\
+
+ language.proto + {LanguageProto} +
-\
object.proto -{ObjectProto} -\
+
+ object.proto + {ObjectProto} +
-\
settings_object.proto -{SettingsObjectProto} -\
+
+ settings_object.proto + {SettingsObjectProto} +
### ZITADELTextSettings diff --git a/docs/docs/self-hosting/deploy/compose.mdx b/docs/docs/self-hosting/deploy/compose.mdx index 808f5fbd54..9d8efae1ad 100644 --- a/docs/docs/self-hosting/deploy/compose.mdx +++ b/docs/docs/self-hosting/deploy/compose.mdx @@ -18,9 +18,10 @@ The setup is tested against Docker version 20.10.17 and Docker Compose version v By executing the commands below, you will download the following file: -\
docker-compose.yaml +
+ docker-compose.yaml {DockerComposeSource} -\
+
```bash # Download the docker compose example configuration. @@ -41,9 +42,10 @@ docker compose up --detach By executing the commands below, you will download the following file: -\
docker-compose-sa.yaml +
+ docker-compose-sa.yaml {DockerComposeSaSource} -\
+
```bash # Download the docker compose example configuration. diff --git a/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx b/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx index 160a542b4c..7f25a9b210 100644 --- a/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx +++ b/docs/docs/self-hosting/deploy/loadbalancing-example/loadbalancing-example.mdx @@ -21,21 +21,26 @@ The setup is tested against Docker version 20.10.17 and Docker Compose version v By executing the commands below, you will download the following files: -\
docker-compose.yaml +
+ docker-compose.yaml {DockerComposeSource} -\
-\
example-traefik.yaml +
+
+ example-traefik.yaml {ExampleTraefikSource} -\
-\
example-zitadel-config.yaml +
+
+ example-zitadel-config.yaml {ExampleZITADELConfigSource} -\
-\
example-zitadel-secrets.yaml +
+
+ example-zitadel-secrets.yaml {ExampleZITADELSecretsSource} -\
-\
example-zitadel-init-steps.yaml +
+
+ example-zitadel-init-steps.yaml {ExampleZITADELInitStepsSource} -\
+
```bash # Download the docker compose example configuration. diff --git a/docs/docs/self-hosting/manage/configure/_compose.mdx b/docs/docs/self-hosting/manage/configure/_compose.mdx index 88c0478b0c..5e8b1c3937 100644 --- a/docs/docs/self-hosting/manage/configure/_compose.mdx +++ b/docs/docs/self-hosting/manage/configure/_compose.mdx @@ -8,18 +8,25 @@ The docker compose example mounts the example zitadel configuration files to the By executing the commands below, you will download the following files: -\
docker-compose.yaml +
+ docker-compose.yaml {DockerComposeSource} -\
-\
example-zitadel-config.yaml +
+ +
+ example-zitadel-config.yaml {ExampleZITADELConfigSource} -\
-\
example-zitadel-secrets.yaml +
+ +
+ example-zitadel-secrets.yaml {ExampleZITADELSecretsSource} -\
-\
example-zitadel-init-steps.yaml +
+ +
+ example-zitadel-init-steps.yaml {ExampleZITADELInitStepsSource} -\
+
```bash # Download the docker compose example configuration. diff --git a/docs/docs/self-hosting/manage/configure/_helm.mdx b/docs/docs/self-hosting/manage/configure/_helm.mdx index a1a8d73b92..9f03e4237a 100644 --- a/docs/docs/self-hosting/manage/configure/_helm.mdx +++ b/docs/docs/self-hosting/manage/configure/_helm.mdx @@ -9,12 +9,15 @@ For a secure installation with Docker Compose, [go to the loadbalancing example] By executing the commands below, you will download the following files: -\
example-zitadel-values.yaml +
+ example-zitadel-values.yaml {ExampleZITADELValuesSource} -\
-\
example-zitadel-values-secrets.yaml +
+ +
+ example-zitadel-values-secrets.yaml {ExampleZITADELValuesSecretsSource} -\
+
```bash # Download and adjust the example configuration file containing standard configuration diff --git a/docs/docs/self-hosting/manage/configure/_linuxunix.mdx b/docs/docs/self-hosting/manage/configure/_linuxunix.mdx index 9b57a1e5d0..6be833caea 100644 --- a/docs/docs/self-hosting/manage/configure/_linuxunix.mdx +++ b/docs/docs/self-hosting/manage/configure/_linuxunix.mdx @@ -7,15 +7,20 @@ import ExampleZITADELInitStepsSource from '!!raw-loader!./example-zitadel-init-s By executing the commands below, you will download the following files: -\
example-zitadel-config.yaml +
+ example-zitadel-config.yaml {ExampleZITADELConfigSource} -\
-\
example-zitadel-secrets.yaml +
+ +
+ example-zitadel-secrets.yaml {ExampleZITADELSecretsSource} -\
-\
example-zitadel-init-steps.yaml +
+ +
+ example-zitadel-init-steps.yaml {ExampleZITADELInitStepsSource} -\
+
```bash # Download and adjust the example configuration file containing standard configuration diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 2fe9d57d6d..183ac67b64 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -194,6 +194,12 @@ module.exports = { disableSwitch: false, respectPrefersColorScheme: true, }, + codeblock: { + showGithubLink: true, + githubLinkLabel: 'View on GitHub', + showRunmeLink: false, + runmeLinkLabel: 'Checkout via Runme' + }, }, webpack: { jsLoader: (isServer) => ({ @@ -283,7 +289,7 @@ module.exports = { outputDir: "docs/apis/resources/user_service", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, session: { @@ -291,7 +297,7 @@ module.exports = { outputDir: "docs/apis/resources/session_service", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, oidc: { @@ -299,7 +305,7 @@ module.exports = { outputDir: "docs/apis/resources/oidc_service", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, settings: { @@ -307,7 +313,7 @@ module.exports = { outputDir: "docs/apis/resources/settings_service", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, user_schema: { @@ -315,7 +321,7 @@ module.exports = { outputDir: "docs/apis/resources/user_schema_service_v3", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, user_v3: { @@ -323,7 +329,7 @@ module.exports = { outputDir: "docs/apis/resources/user_service_v3", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, action_v3: { @@ -331,7 +337,7 @@ module.exports = { outputDir: "docs/apis/resources/action_service_v3", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, feature_v2: { @@ -339,7 +345,7 @@ module.exports = { outputDir: "docs/apis/resources/feature_service_v2", sidebarOptions: { groupPathsBy: "tag", - categoryLinkSource: "tag", + categoryLinkSource: "auto", }, }, }, @@ -358,5 +364,5 @@ module.exports = { }; }, ], - themes: ["@saucelabs/theme-github-codeblock", "docusaurus-theme-openapi-docs"], + themes: [ "docusaurus-theme-github-codeblock", "docusaurus-theme-openapi-docs"], }; diff --git a/docs/package.json b/docs/package.json index 8ff0b27e9d..edaf6e72ca 100644 --- a/docs/package.json +++ b/docs/package.json @@ -29,13 +29,13 @@ "@headlessui/react": "^1.7.4", "@heroicons/react": "^2.0.13", "@mdx-js/react": "^3.0.0", - "@saucelabs/theme-github-codeblock": "^0.2.3", "@swc/core": "^1.3.74", "autoprefixer": "^10.4.13", "clsx": "^1.2.1", "docusaurus-plugin-image-zoom": "^1.0.1", - "docusaurus-plugin-openapi-docs": "3.0.0-beta.10", - "docusaurus-theme-openapi-docs": "3.0.0-beta.10", + "docusaurus-plugin-openapi-docs": "3.0.1", + "docusaurus-theme-github-codeblock": "^2.0.2", + "docusaurus-theme-openapi-docs": "3.0.1", "mdx-mermaid": "^2.0.0", "mermaid": "^10.9.1", "postcss": "^8.4.31", diff --git a/docs/yarn.lock b/docs/yarn.lock index d85d1bacee..668f590f28 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -1670,7 +1670,7 @@ fs-extra "^11.1.1" tslib "^2.6.0" -"@docusaurus/types@3.4.0": +"@docusaurus/types@3.4.0", "@docusaurus/types@^3.0.0": version "3.4.0" resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.4.0.tgz#237c3f737e9db3f7c1a5935a3ef48d6eadde8292" integrity sha512-4jcDO8kXi5Cf9TcyikB/yKmz14f2RZ2qTRerbHAsS+5InE9ZgSLBNLsewtFTcTOXSVcbU3FoGOzcNWAmU1TR0A== @@ -1737,6 +1737,11 @@ resolved "https://registry.yarnpkg.com/@exodus/schemasafe/-/schemasafe-1.3.0.tgz#731656abe21e8e769a7f70a4d833e6312fe59b7f" integrity sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw== +"@faker-js/faker@5.5.3": + version "5.5.3" + resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-5.5.3.tgz#18e3af6b8eae7984072bbeb0c0858474d7c4cefe" + integrity sha512-R11tGE6yIFwqpaIqcfkcg7AICXzFg14+5h5v0TfF/9+RMDL6jhzCy/pxHVOfbALGdtVYdt6JdR21tuxEgl34dw== + "@hapi/hoek@^9.0.0", "@hapi/hoek@^9.3.0": version "9.3.0" resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" @@ -1905,49 +1910,6 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" -"@paloaltonetworks/openapi-to-postmanv2@3.1.0-hotfix.1": - version "3.1.0-hotfix.1" - resolved "https://registry.yarnpkg.com/@paloaltonetworks/openapi-to-postmanv2/-/openapi-to-postmanv2-3.1.0-hotfix.1.tgz#4baf401d2e94ba86d888e6011a4c45d824e88114" - integrity sha512-0bdaPCEyQbnUo4xpOu7EzxXXkDx4BAXqc8QSbVBlzlVB5KoTLJiKKB4c3fa4BXbK+3u/OqfLbeNCebc2EC8ngA== - dependencies: - "@paloaltonetworks/postman-collection" "^4.1.0" - ajv "8.1.0" - ajv-formats "2.1.1" - async "3.2.1" - commander "2.20.3" - js-yaml "3.14.1" - json-schema-merge-allof "0.8.1" - lodash "4.17.21" - oas-resolver-browser "2.5.2" - path-browserify "1.0.1" - yaml "1.10.2" - -"@paloaltonetworks/postman-code-generators@1.1.15-patch.2": - version "1.1.15-patch.2" - resolved "https://registry.yarnpkg.com/@paloaltonetworks/postman-code-generators/-/postman-code-generators-1.1.15-patch.2.tgz#012051485269a2da6bd9a6b60031ddbc53e5e363" - integrity sha512-tRnAKtV4M8wLxcVnAx6ZCjCqbrR1xiqJNQkf1A71K8UxEP3N/+EspT82N5c0555w02oYFk21ViHuzuhm4gaGLw== - dependencies: - "@paloaltonetworks/postman-collection" "^4.1.0" - async "^3.2.4" - path "^0.12.7" - shelljs "^0.8.5" - -"@paloaltonetworks/postman-collection@^4.1.0": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@paloaltonetworks/postman-collection/-/postman-collection-4.1.1.tgz#b2130bc8d7396ea8e6a6b2e4642a6b224b41e1e1" - integrity sha512-9JHHkkD8Xb4rvdKob7TDPRfqfmdG3KU0aO5gJyyjvMFbOVysam5I0d8/9HPOuJXWkUHGo3Sn+ov2Fcm2bnJ52Q== - dependencies: - file-type "3.9.0" - http-reasons "0.1.0" - iconv-lite "0.6.3" - liquid-json "0.3.1" - lodash "4.17.21" - mime-format "2.0.1" - mime-types "2.1.34" - postman-url-encoder "3.0.5" - semver "7.3.5" - uuid "8.3.2" - "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -2020,11 +1982,6 @@ redux-thunk "^2.4.2" reselect "^4.1.8" -"@saucelabs/theme-github-codeblock@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@saucelabs/theme-github-codeblock/-/theme-github-codeblock-0.2.3.tgz#706a43292f600532271979941b0155db667c2c21" - integrity sha512-GSl3Lr/jOWm4OP3BPX2vXxc8FMSOXj1mJnls6cUqMwlGOfKQ1Ia9pq1O9/ES+5TrZHIzAws/n5FFSn1OkGJw/Q== - "@sideway/address@^4.1.5": version "4.1.5" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5" @@ -2858,6 +2815,11 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-draft-04@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz#3b64761b268ba0b9e668f0b41ba53fce0ad77fc8" + integrity sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw== + ajv-formats@2.1.1, ajv-formats@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" @@ -2877,10 +2839,10 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.1.0.tgz#45d5d3d36c7cdd808930cc3e603cf6200dbeb736" - integrity sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ== +ajv@8.11.0: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.0.tgz#977e91dd96ca669f54a11e23e378e33b884a565f" + integrity sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg== dependencies: fast-deep-equal "^3.1.1" json-schema-traverse "^1.0.0" @@ -3041,15 +3003,15 @@ astring@^1.8.0: resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.6.tgz#2c9c157cf1739d67561c56ba896e6948f6b93731" integrity sha512-ISvCdHdlTDlH5IpxQJIex7BWBywFWgjJSVdwst+/iQCoEYnyOaQ95+X1JGshuBjGp6nxKUy1jMgE3zPqN7fQdg== -async@3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.1.tgz#d3274ec66d107a47476a4c49136aacdb00665fc8" - integrity sha512-XdD5lRO/87udXCMC9meWdYiR+Nq6ZjUfXidViUZGu2F1MO4T3XwZ1et0hb2++BgLfhyJwy44BGB/yx80ABx8hg== +async@3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.2.tgz#2eb7671034bb2194d45d30e31e24ec7e7f9670cd" + integrity sha512-H0E+qZaDEfx/FY4t7iLRv1W2fFI6+pyCeTw1uN20AQPiwqwM6ojPxHxdLv4z8hi2DtnW9BOckSspLucW7pIE5g== -async@^3.2.4: - version "3.2.5" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" - integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== +async@3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== at-least-node@^1.0.0: version "1.0.0" @@ -3426,11 +3388,6 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" @@ -3607,15 +3564,6 @@ client-only@^0.0.1: resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== -cliui@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" - integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== - dependencies: - string-width "^4.2.0" - strip-ansi "^6.0.0" - wrap-ansi "^6.2.0" - cliui@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" @@ -4473,11 +4421,6 @@ debug@4.3.4: dependencies: ms "2.1.2" -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== - decode-named-character-reference@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" @@ -4665,17 +4608,15 @@ docusaurus-plugin-image-zoom@^1.0.1: medium-zoom "^1.0.6" validate-peer-dependencies "^2.2.0" -docusaurus-plugin-openapi-docs@3.0.0-beta.10, docusaurus-plugin-openapi-docs@^3.0.0-beta.10: - version "3.0.0-beta.10" - resolved "https://registry.yarnpkg.com/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-3.0.0-beta.10.tgz#f0c303ee852487c852c163d019678a92b53abf81" - integrity sha512-BtMBH4TzCiMM0WbO2ZAMXSuL7Ge9yyASZhAycb5vX+KSUnUgp47/Ex2f6/evBfaadnr6vXYEr1UBT1fSiJYh5w== +docusaurus-plugin-openapi-docs@3.0.1, docusaurus-plugin-openapi-docs@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/docusaurus-plugin-openapi-docs/-/docusaurus-plugin-openapi-docs-3.0.1.tgz#954fdc4103d7e47133aede210a98353b3e0f0f99" + integrity sha512-6SRqwey/TXMNu2G02mbWgxrifhpjGOjDr30N+58AR0Ytgc+HXMqlPAUIvTe+e7sOBfAtBbiNlmOWv5KSYIjf3w== dependencies: "@apidevtools/json-schema-ref-parser" "^11.5.4" "@docusaurus/plugin-content-docs" "^3.0.1" "@docusaurus/utils" "^3.0.1" "@docusaurus/utils-validation" "^3.0.1" - "@paloaltonetworks/openapi-to-postmanv2" "3.1.0-hotfix.1" - "@paloaltonetworks/postman-collection" "^4.1.0" "@redocly/openapi-core" "^1.10.5" chalk "^4.1.2" clsx "^1.1.1" @@ -4685,6 +4626,8 @@ docusaurus-plugin-openapi-docs@3.0.0-beta.10, docusaurus-plugin-openapi-docs@^3. json5 "^2.2.3" lodash "^4.17.20" mustache "^4.2.0" + openapi-to-postmanv2 "^4.21.0" + postman-collection "^4.4.0" slugify "^1.6.5" swagger2openapi "^7.0.8" xml-formatter "^2.6.1" @@ -4696,24 +4639,31 @@ docusaurus-plugin-sass@^0.2.3: dependencies: sass-loader "^10.1.1" -docusaurus-theme-openapi-docs@3.0.0-beta.10: - version "3.0.0-beta.10" - resolved "https://registry.yarnpkg.com/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-3.0.0-beta.10.tgz#f9a790b1ef88ff01f266224064f4b2f80d0892ff" - integrity sha512-8oUMMZSrRJ9EssrjWwbM9aYuHOt1AAm6wQDzWr8k6VvefGvVAibg4Y9PK7GeZ243lJikq9s45KqUA0SMwsm+Fg== +docusaurus-theme-github-codeblock@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/docusaurus-theme-github-codeblock/-/docusaurus-theme-github-codeblock-2.0.2.tgz#88b7044b81f9091330e8e4a07a1bdc9114a9fb93" + integrity sha512-H2WoQPWOLjGZO6KS58Gsd+eUVjTFJemkReiSSu9chqokyLc/3Ih3+zPRYfuEZ/HsDvSMIarf7CNcp+Vt+/G+ig== + dependencies: + "@docusaurus/types" "^3.0.0" + +docusaurus-theme-openapi-docs@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/docusaurus-theme-openapi-docs/-/docusaurus-theme-openapi-docs-3.0.1.tgz#49789c63377f294e624a9632eddb8265a421020f" + integrity sha512-tqypV91tC3wuWj9O+4n0M/e5AgHOeMT2nvPj1tjlPkC7/dLinZvpwQStT4YDUPYSoHRseqxd7lhivFQHcmlryg== dependencies: "@docusaurus/theme-common" "^3.0.1" "@hookform/error-message" "^2.0.1" - "@paloaltonetworks/postman-code-generators" "1.1.15-patch.2" - "@paloaltonetworks/postman-collection" "^4.1.0" "@reduxjs/toolkit" "^1.7.1" clsx "^1.1.1" copy-text-to-clipboard "^3.1.0" crypto-js "^4.1.1" - docusaurus-plugin-openapi-docs "^3.0.0-beta.10" + docusaurus-plugin-openapi-docs "^3.0.1" docusaurus-plugin-sass "^0.2.3" file-saver "^2.0.5" lodash "^4.17.20" node-polyfill-webpack-plugin "^2.0.1" + postman-code-generators "^1.10.1" + postman-collection "^4.4.0" prism-react-renderer "^2.3.0" react-hook-form "^7.43.8" react-live "^4.0.0" @@ -5205,6 +5155,11 @@ extract-zip@2.0.1: optionalDependencies: "@types/yauzl" "^2.9.1" +faker@5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/faker/-/faker-5.5.3.tgz#c57974ee484431b25205c2c8dc09fda861e51e0e" + integrity sha512-wLTv2a28wjUyWkbnX7u/ABZBkUkIF2fCd73V6P2oFqEGEktDfzWx4UxrSqtPRw0xPRAcjeAOIiJWqZm3pP4u3g== + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -5336,14 +5291,6 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" - integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== - dependencies: - locate-path "^5.0.0" - path-exists "^4.0.0" - find-up@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" @@ -5483,7 +5430,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.1, get-caller-file@^2.0.5: +get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -5648,6 +5595,13 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +graphlib@2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da" + integrity sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A== + dependencies: + lodash "^4.17.15" + gray-matter@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" @@ -6609,7 +6563,14 @@ js-levenshtein@^1.1.6: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.14.1, js-yaml@^3.13.1: +js-yaml@4.1.0, js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== @@ -6617,13 +6578,6 @@ js-yaml@3.14.1, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" - integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== - dependencies: - argparse "^2.0.1" - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -6807,13 +6761,6 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -locate-path@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" - integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== - dependencies: - p-locate "^4.1.0" - locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -6853,7 +6800,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== -lodash@4.17.21, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: +lodash@4.17.21, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -8044,10 +7991,10 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.51.0: - version "1.51.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.51.0.tgz#d9ff62451859b18342d960850dc3cfb77e63fb0c" - integrity sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g== +mime-db@1.48.0: + version "1.48.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" + integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": version "1.52.0" @@ -8073,14 +8020,14 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@2.1.34: - version "2.1.34" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.34.tgz#5a712f9ec1503511a945803640fafe09d3793c24" - integrity sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A== +mime-types@2.1.31: + version "2.1.31" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" + integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== dependencies: - mime-db "1.51.0" + mime-db "1.48.0" -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@2.1.35, mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -8365,17 +8312,17 @@ oas-linter@^3.2.2: should "^13.2.1" yaml "^1.10.0" -oas-resolver-browser@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/oas-resolver-browser/-/oas-resolver-browser-2.5.2.tgz#d972525a840d7a74ab1aa43e215e9531a99412ba" - integrity sha512-L3ugWyBHOpKLT+lb+pFXCOpk3byh6usis5T9u9mfu92jH5bR6YK8MA2bebUTIjY7I4415PzDeZcmcc+i7X05MA== +oas-resolver-browser@2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/oas-resolver-browser/-/oas-resolver-browser-2.5.6.tgz#1974db66d594fa8c67d3aa866b46b9e2156a8b55" + integrity sha512-Jw5elT/kwUJrnGaVuRWe1D7hmnYWB8rfDDjBnpQ+RYY/dzAewGXeTexXzt4fGEo6PUE4eqKqPWF79MZxxvMppA== dependencies: node-fetch-h2 "^2.3.0" oas-kit-common "^1.0.8" path-browserify "^1.0.1" - reftools "^1.1.6" + reftools "^1.1.9" yaml "^1.10.0" - yargs "^15.3.1" + yargs "^17.0.1" oas-resolver@^2.5.6: version "2.5.6" @@ -8412,7 +8359,7 @@ object-assign@^4.0.1, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-hash@^3.0.0: +object-hash@3.0.0, object-hash@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9" integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw== @@ -8485,6 +8432,28 @@ open@^8.0.9, open@^8.4.0: is-docker "^2.1.1" is-wsl "^2.2.0" +openapi-to-postmanv2@^4.21.0: + version "4.21.0" + resolved "https://registry.yarnpkg.com/openapi-to-postmanv2/-/openapi-to-postmanv2-4.21.0.tgz#4bc5b19ccbd1514c2b3466268a7f5dd64b61f535" + integrity sha512-UyHf2xOjDfl4bIaYrUP6w4UiR894gsiOt1HR93cWOxv33Ucw4rGG0B6ewQczSGBpvFMgri+KSSykNEVjsmB55w== + dependencies: + ajv "8.11.0" + ajv-draft-04 "1.0.0" + ajv-formats "2.1.1" + async "3.2.4" + commander "2.20.3" + graphlib "2.1.8" + js-yaml "4.1.0" + json-schema-merge-allof "0.8.1" + lodash "4.17.21" + oas-resolver-browser "2.5.6" + object-hash "3.0.0" + path-browserify "1.0.1" + postman-collection "4.2.1" + swagger2openapi "7.0.8" + traverse "0.6.6" + yaml "1.10.2" + opener@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" @@ -8500,7 +8469,7 @@ p-cancelable@^3.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== -p-limit@^2.0.0, p-limit@^2.2.0: +p-limit@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -8528,13 +8497,6 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" -p-locate@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" - integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== - dependencies: - p-limit "^2.2.0" - p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -8755,7 +8717,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -path@^0.12.7: +path@0.12.7: version "0.12.7" resolved "https://registry.yarnpkg.com/path/-/path-0.12.7.tgz#d4dc2a506c4ce2197eb481ebfcd5b36c0140b10f" integrity sha512-aXXC6s+1w7otVF9UletFkFcDsJeO7lSZBPUQhtb5O0xJe8LtYhj/GxldoL09bBj9+ZmE2hNoHqQSFMN5fikh4Q== @@ -9152,6 +9114,75 @@ postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.24, postcss@^8.4.26, postcss@^8.4 picocolors "^1.0.0" source-map-js "^1.2.0" +postman-code-generators@^1.10.1: + version "1.10.1" + resolved "https://registry.yarnpkg.com/postman-code-generators/-/postman-code-generators-1.10.1.tgz#5d8d8500616b2bb0cac7417e923c36b2e73cbffe" + integrity sha512-VGjqIFezG6tZRP3GvSbYjLDq3bQtXUeNDnBrN5CUIbgc9siu5Ubkva9hZnFpk+/qfi+PXs3CUR5mvV+WzpMhsg== + dependencies: + async "3.2.2" + lodash "4.17.21" + path "0.12.7" + postman-collection "4.0.0" + shelljs "0.8.5" + +postman-collection@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postman-collection/-/postman-collection-4.0.0.tgz#4a72c60f0d9725656d0e02d44e294e1c22ef3ffa" + integrity sha512-vDrXG/dclSu6RMqPqBz4ZqoQBwcj/a80sJYsQZmzWJ6dWgXiudPhwu6Vm3C1Hy7zX5W8A6am1Z6vb/TB4eyURA== + dependencies: + faker "5.5.3" + file-type "3.9.0" + http-reasons "0.1.0" + iconv-lite "0.6.3" + liquid-json "0.3.1" + lodash "4.17.21" + mime-format "2.0.1" + mime-types "2.1.31" + postman-url-encoder "3.0.1" + semver "7.3.5" + uuid "8.3.2" + +postman-collection@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/postman-collection/-/postman-collection-4.2.1.tgz#86e3c8ee11530a1f00a30864503d487846ee516f" + integrity sha512-DFLt3/yu8+ldtOTIzmBUctoupKJBOVK4NZO0t68K2lIir9smQg7OdQTBjOXYy+PDh7u0pSDvD66tm93eBHEPHA== + dependencies: + "@faker-js/faker" "5.5.3" + file-type "3.9.0" + http-reasons "0.1.0" + iconv-lite "0.6.3" + liquid-json "0.3.1" + lodash "4.17.21" + mime-format "2.0.1" + mime-types "2.1.35" + postman-url-encoder "3.0.5" + semver "7.5.4" + uuid "8.3.2" + +postman-collection@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/postman-collection/-/postman-collection-4.4.0.tgz#6acb6e3796fcd9f6ac5a94e6894185e42387d7da" + integrity sha512-2BGDFcUwlK08CqZFUlIC8kwRJueVzPjZnnokWPtJCd9f2J06HBQpGL7t2P1Ud1NEsK9NHq9wdipUhWLOPj5s/Q== + dependencies: + "@faker-js/faker" "5.5.3" + file-type "3.9.0" + http-reasons "0.1.0" + iconv-lite "0.6.3" + liquid-json "0.3.1" + lodash "4.17.21" + mime-format "2.0.1" + mime-types "2.1.35" + postman-url-encoder "3.0.5" + semver "7.5.4" + uuid "8.3.2" + +postman-url-encoder@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/postman-url-encoder/-/postman-url-encoder-3.0.1.tgz#a7434a169567c45f022dc435d46a86d71de6a8aa" + integrity sha512-dMPqXnkDlstM2Eya+Gw4MIGWEan8TzldDcUKZIhZUsJ/G5JjubfQPhFhVWKzuATDMvwvrWbSjF+8VmAvbu6giw== + dependencies: + punycode "^2.1.1" + postman-url-encoder@3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/postman-url-encoder/-/postman-url-encoder-3.0.5.tgz#af2efee3bb7644e2b059d8a78bc8070fae0467a5" @@ -9700,7 +9731,7 @@ redux@^4.0.0, redux@^4.2.1: dependencies: "@babel/runtime" "^7.9.2" -reftools@^1.1.6, reftools@^1.1.9: +reftools@^1.1.9: version "1.1.9" resolved "https://registry.yarnpkg.com/reftools/-/reftools-1.1.9.tgz#e16e19f662ccd4648605312c06d34e5da3a2b77e" integrity sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w== @@ -9911,11 +9942,6 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" integrity sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A== -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -10152,6 +10178,13 @@ semver@7.3.5: dependencies: lru-cache "^6.0.0" +semver@7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -10225,11 +10258,6 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== - set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -10294,7 +10322,7 @@ shell-quote@^1.7.3, shell-quote@^1.8.1: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.1.tgz#6dbf4db75515ad5bac63b4f1894c3a154c766680" integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA== -shelljs@^0.8.5: +shelljs@0.8.5, shelljs@^0.8.5: version "0.8.5" resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== @@ -10722,7 +10750,7 @@ svgo@^3.0.2, svgo@^3.2.0: csso "^5.0.5" picocolors "^1.0.0" -swagger2openapi@^7.0.8: +swagger2openapi@7.0.8, swagger2openapi@^7.0.8: version "7.0.8" resolved "https://registry.yarnpkg.com/swagger2openapi/-/swagger2openapi-7.0.8.tgz#12c88d5de776cb1cbba758994930f40ad0afac59" integrity sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g== @@ -10904,6 +10932,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +traverse@0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + integrity sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw== + trim-lines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" @@ -11562,11 +11595,6 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which-module@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" - integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== - which-typed-array@^1.1.14, which-typed-array@^1.1.2: version "1.1.15" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" @@ -11613,15 +11641,6 @@ wildcard@^2.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" - integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -11699,11 +11718,6 @@ xtend@^4.0.2: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" - integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -11734,36 +11748,11 @@ yaml@^2.3.4: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.5.tgz#60630b206dd6d84df97003d33fc1ddf6296cca5e" integrity sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg== -yargs-parser@^18.1.2: - version "18.1.3" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" - integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - yargs-parser@^21.1.1: version "21.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== -yargs@^15.3.1: - version "15.4.1" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" - integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== - dependencies: - cliui "^6.0.0" - decamelize "^1.2.0" - find-up "^4.1.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^4.2.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^18.1.2" - yargs@^17.0.1: version "17.7.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" diff --git a/proto/zitadel/settings/v2beta/settings_service.proto b/proto/zitadel/settings/v2beta/settings_service.proto index 988a284004..88331ddc54 100644 --- a/proto/zitadel/settings/v2beta/settings_service.proto +++ b/proto/zitadel/settings/v2beta/settings_service.proto @@ -337,7 +337,6 @@ service SettingsService { }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { - tags: "Settings"; summary: "Get Security Settings"; description: "Returns the security settings of the ZITADEL instance." }; @@ -357,7 +356,6 @@ service SettingsService { }; option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { - tags: "Settings"; summary: "Set Security Settings"; description: "Set the security settings of the ZITADEL instance." }; From aa273ad00042c34ec87c25ed63ec3a03cb68984e Mon Sep 17 00:00:00 2001 From: Silvan Date: Thu, 11 Jul 2024 15:22:01 +0200 Subject: [PATCH 08/34] fix(api): grpc content type matcher all grpc types (#8285) # Which Problems Are Solved ZITADEL returned a 404 Unimplemented error if the client sent 'application/grpc+proto' or 'application/grpc+json' which are both valid content types. # How the Problems Are Solved changed the header matcher to regexp # Additional Context Problem occured in https://github.com/zitadel/typescript/tree/grpc-transport --- internal/api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/api/api.go b/internal/api/api.go index 2b94e1e284..6695403e46 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -180,7 +180,7 @@ func (a *API) RouteGRPC() { Name("grpc") http2Route. Methods(http.MethodPost). - Headers("Content-Type", "application/grpc"). + HeadersRegexp(http_util.ContentType, `application\/grpc(\+proto|\+json)?`). Handler(a.grpcServer) a.routeGRPCWeb() From d7c0ec282ae34773d682e60f79bc9723e8f4c9ec Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Fri, 12 Jul 2024 11:54:02 +0200 Subject: [PATCH 09/34] fix: correctly differ between grpc and grpc-web (#8292) # Which Problems Are Solved While #8285 also checked for `+proto` and `+json` grpc content types, it accidentally matched all grpc-web requests to grpc. # How the Problems Are Solved - fixed the regex by checking for an exact match (added start `^` and end `$` anchors) # Additional Changes None # Additional Context - relates to #8285 --- internal/api/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/api/api.go b/internal/api/api.go index 6695403e46..f3ed27c2b0 100644 --- a/internal/api/api.go +++ b/internal/api/api.go @@ -180,7 +180,7 @@ func (a *API) RouteGRPC() { Name("grpc") http2Route. Methods(http.MethodPost). - HeadersRegexp(http_util.ContentType, `application\/grpc(\+proto|\+json)?`). + HeadersRegexp(http_util.ContentType, `^application\/grpc(\+proto|\+json)?$`). Handler(a.grpcServer) a.routeGRPCWeb() From 8afdcd99c692fd3f0a2906746be1d76291d4c475 Mon Sep 17 00:00:00 2001 From: Zhang Zhe <16097046+zzzz0317@users.noreply.github.com> Date: Mon, 15 Jul 2024 16:13:55 +0800 Subject: [PATCH 10/34] fix: Correct misspelling in zh.yaml file (#8299) # Which Problems Are Solved - Corrected a typo in the file `internal/api/ui/login/static/i18n/zh.yaml` where "Migrosoft" was changed to "Microsoft". # How the Problems Are Solved - Updated the misspelled word "Migrosoft" to "Microsoft" for consistency and accuracy. # Additional Changes - None # Additional Context - None --- internal/api/ui/login/static/i18n/zh.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/api/ui/login/static/i18n/zh.yaml b/internal/api/ui/login/static/i18n/zh.yaml index c49d4ed735..072b45e575 100644 --- a/internal/api/ui/login/static/i18n/zh.yaml +++ b/internal/api/ui/login/static/i18n/zh.yaml @@ -89,7 +89,7 @@ InitUserDone: InitMFAPrompt: Title: 两步验证设置 Description: 两步验证为您的账户提供了额外的安全保障。这确保只有你能访问你的账户。 - Provider0: 软件应用(如 Google/Migrosoft Authenticator、Authy) + Provider0: 软件应用(如 Google/Microsoft Authenticator、Authy) Provider1: 硬件设备(如 Face ID、Windows Hello、指纹) Provider3: 一次性密码短信 Provider4: 一次性密码电子邮件 From ffe73645e84becc546c22c7f31ee5c8fd1047ac4 Mon Sep 17 00:00:00 2001 From: Miguel Cabrerizo <30386061+doncicuto@users.noreply.github.com> Date: Mon, 15 Jul 2024 11:31:46 +0200 Subject: [PATCH 11/34] fix(console): missing styles for ProfilePictureComponent dialog (#8293) # Which Problems Are Solved - The UI layout is broken in Upload your Profile Picture # How the Problems Are Solved - MatDialog module was missing # Additional Context Here's a screenshot showing the fix ![Captura desde 2024-07-12 12-18-43](https://github.com/user-attachments/assets/7a01fa0e-3e89-4679-9606-085610f5adfe) - Closes #8284 Co-authored-by: Fabi --- .../pages/users/user-detail/detail-form/detail-form.module.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/console/src/app/pages/users/user-detail/detail-form/detail-form.module.ts b/console/src/app/pages/users/user-detail/detail-form/detail-form.module.ts index a126377f1a..d7817946f3 100644 --- a/console/src/app/pages/users/user-detail/detail-form/detail-form.module.ts +++ b/console/src/app/pages/users/user-detail/detail-form/detail-form.module.ts @@ -12,6 +12,7 @@ import { InputModule } from 'src/app/modules/input/input.module'; import { DetailFormComponent } from './detail-form.component'; import { ProfilePictureComponent } from './profile-picture/profile-picture.component'; +import { MatDialogModule } from '@angular/material/dialog'; @NgModule({ declarations: [DetailFormComponent, ProfilePictureComponent], @@ -26,6 +27,7 @@ import { ProfilePictureComponent } from './profile-picture/profile-picture.compo MatButtonModule, MatTooltipModule, MatIconModule, + MatDialogModule, TranslateModule, InputModule, ], From 8dd21a729238e3839871c8679784fa2726f115c2 Mon Sep 17 00:00:00 2001 From: Silvan Date: Mon, 15 Jul 2024 13:03:51 +0200 Subject: [PATCH 12/34] chore(stable): update to v2.51.4 (#8304) # Which Problems Are Solved Update stable to next minor version. --- release-channels.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-channels.yaml b/release-channels.yaml index cfbb41aef5..102bfc9e81 100644 --- a/release-channels.yaml +++ b/release-channels.yaml @@ -1 +1 @@ -stable: "v2.50.6" +stable: "v2.51.4" From 9d29098aa63557902436f347b37dce1f2e3a2885 Mon Sep 17 00:00:00 2001 From: Max Peintner Date: Mon, 15 Jul 2024 13:25:59 +0200 Subject: [PATCH 13/34] fix(console): identity provider title layout (#8302) # Which Problems Are Solved Fixes the alignment of the identity provider layouts Screenshot 2024-07-15 at 08 42 21 # Context - noted internally while implementing https://github.com/zitadel/zitadel/pull/8295 --------- Co-authored-by: Livio Spring --- .../providers/provider-apple/provider-apple.component.html | 2 +- .../provider-azure-ad/provider-azure-ad.component.html | 2 +- .../provider-github-es/provider-github-es.component.html | 2 +- .../providers/provider-github/provider-github.component.html | 2 +- .../provider-gitlab-self-hosted.component.html | 2 +- .../providers/provider-gitlab/provider-gitlab.component.html | 2 +- .../providers/provider-google/provider-google.component.html | 2 +- .../modules/providers/provider-jwt/provider-jwt.component.html | 2 +- .../providers/provider-ldap/provider-ldap.component.html | 2 +- .../providers/provider-next/provider-next.component.html | 2 +- .../providers/provider-oauth/provider-oauth.component.html | 2 +- .../providers/provider-oidc/provider-oidc.component.html | 2 +- .../providers/provider-saml-sp/provider-saml-sp.component.html | 2 +- console/src/app/modules/providers/providers.scss | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/console/src/app/modules/providers/provider-apple/provider-apple.component.html b/console/src/app/modules/providers/provider-apple/provider-apple.component.html index c4ff96e47e..4fd1c1694a 100644 --- a/console/src/app/modules/providers/provider-apple/provider-apple.component.html +++ b/console/src/app/modules/providers/provider-apple/provider-apple.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.APPLE.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.html b/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.html index 17b00492c4..a6a9ef6ecb 100644 --- a/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.html +++ b/console/src/app/modules/providers/provider-azure-ad/provider-azure-ad.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.AZUREAD.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html index 820deb14d9..d48d8df589 100644 --- a/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html +++ b/console/src/app/modules/providers/provider-github-es/provider-github-es.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.GITHUBES.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-github/provider-github.component.html b/console/src/app/modules/providers/provider-github/provider-github.component.html index 7c2a6f26df..9f7a169c4d 100644 --- a/console/src/app/modules/providers/provider-github/provider-github.component.html +++ b/console/src/app/modules/providers/provider-github/provider-github.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.GITHUB.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html index 9a0085b0d0..6a94e1a901 100644 --- a/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html +++ b/console/src/app/modules/providers/provider-gitlab-self-hosted/provider-gitlab-self-hosted.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.GITLABSELFHOSTED.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html index e864551884..d9efddd1cf 100644 --- a/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html +++ b/console/src/app/modules/providers/provider-gitlab/provider-gitlab.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.GITLAB.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-google/provider-google.component.html b/console/src/app/modules/providers/provider-google/provider-google.component.html index 4c3053f4d4..af409c7c56 100644 --- a/console/src/app/modules/providers/provider-google/provider-google.component.html +++ b/console/src/app/modules/providers/provider-google/provider-google.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+

{{ 'IDP.CREATE.GOOGLE.TITLE' | translate }}

diff --git a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html index 8e8a456585..f86c5cec4a 100644 --- a/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html +++ b/console/src/app/modules/providers/provider-jwt/provider-jwt.component.html @@ -3,7 +3,7 @@ (closed)="close()" >
-
+