From a42a0f772af3625c457032d6dcc34289a62acc61 Mon Sep 17 00:00:00 2001 From: Mathias Polligkeit <13847569+woylie@users.noreply.github.com> Date: Sun, 17 Apr 2022 08:10:20 +0900 Subject: [PATCH] fix(sdk): improved OpenAPI specifications for UI nodes (#2375) Closes #2357 Co-authored-by: zepatrik --- .schema/openapi/patches/schema.yaml | 4 +- Makefile | 8 ++ README.md | 9 ++ internal/httpclient/api/openapi.yaml | 126 +++++++++++++----- .../docs/SelfServiceRecoveryFlow.md | 9 +- .../docs/SelfServiceRegistrationFlow.md | 9 +- .../docs/SelfServiceSettingsFlow.md | 9 +- internal/httpclient/docs/UiNode.md | 4 +- .../httpclient/docs/UiNodeAnchorAttributes.md | 2 +- internal/httpclient/docs/UiNodeAttributes.md | 2 +- .../httpclient/docs/UiNodeImageAttributes.md | 2 +- .../httpclient/docs/UiNodeInputAttributes.md | 2 +- .../httpclient/docs/UiNodeScriptAttributes.md | 2 +- .../httpclient/docs/UiNodeTextAttributes.md | 2 +- .../model_self_service_recovery_flow.go | 33 ++--- .../model_self_service_registration_flow.go | 33 ++--- .../model_self_service_settings_flow.go | 33 ++--- internal/httpclient/model_ui_node.go | 10 +- .../model_ui_node_anchor_attributes.go | 3 +- .../model_ui_node_image_attributes.go | 3 +- .../model_ui_node_input_attributes.go | 3 +- .../model_ui_node_script_attributes.go | 3 +- .../model_ui_node_text_attributes.go | 3 +- selfservice/flow/login/error.go | 2 +- selfservice/flow/login/error_test.go | 2 +- selfservice/flow/login/sort.go | 2 +- selfservice/flow/login/strategy.go | 2 +- selfservice/flow/recovery/error.go | 2 +- selfservice/flow/recovery/error_test.go | 8 +- selfservice/flow/recovery/flow.go | 2 + selfservice/flow/recovery/handler.go | 2 +- selfservice/flow/recovery/strategy.go | 2 +- selfservice/flow/registration/error.go | 2 +- selfservice/flow/registration/error_test.go | 2 +- selfservice/flow/registration/flow.go | 2 + selfservice/flow/registration/sort.go | 2 +- selfservice/flow/registration/strategy.go | 2 +- selfservice/flow/settings/error.go | 2 +- selfservice/flow/settings/error_test.go | 2 +- selfservice/flow/settings/flow.go | 2 + selfservice/flow/settings/sort.go | 2 +- selfservice/flow/settings/strategy.go | 2 +- selfservice/flow/verification/error.go | 2 +- selfservice/flow/verification/error_test.go | 8 +- selfservice/flow/verification/flow.go | 1 + selfservice/flow/verification/handler.go | 2 +- selfservice/flow/verification/strategy.go | 2 +- selfservice/strategy/link/strategy.go | 8 +- .../strategy/link/strategy_recovery.go | 10 +- .../strategy/link/strategy_recovery_test.go | 8 +- .../strategy/link/strategy_verification.go | 10 +- .../link/strategy_verification_test.go | 8 +- selfservice/strategy/lookup/strategy.go | 2 +- selfservice/strategy/oidc/strategy.go | 2 +- selfservice/strategy/password/strategy.go | 2 +- selfservice/strategy/profile/strategy.go | 2 +- selfservice/strategy/totp/strategy.go | 2 +- selfservice/strategy/webauthn/strategy.go | 2 +- spec/api.json | 86 +++++++++--- spec/swagger.json | 82 ++++++++++-- ui/container/container.go | 14 +- ui/container/types.go | 2 +- ui/node/attributes.go | 22 +-- ui/node/attributes_input.go | 14 +- ui/node/attributes_test.go | 2 +- ui/node/node.go | 63 ++++----- ui/node/node_test.go | 12 +- 67 files changed, 449 insertions(+), 277 deletions(-) diff --git a/.schema/openapi/patches/schema.yaml b/.schema/openapi/patches/schema.yaml index db683b55f429..a06a4e495b87 100644 --- a/.schema/openapi/patches/schema.yaml +++ b/.schema/openapi/patches/schema.yaml @@ -8,8 +8,8 @@ mapping: input: "#/components/schemas/uiNodeInputAttributes" text: "#/components/schemas/uiNodeTextAttributes" - image: "#/components/schemas/uiNodeImageAttributes" - anchor: "#/components/schemas/uiNodeAnchorAttributes" + img: "#/components/schemas/uiNodeImageAttributes" + a: "#/components/schemas/uiNodeAnchorAttributes" script: "#/components/schemas/uiNodeScriptAttributes" - op: add path: /components/schemas/uiNodeAttributes/oneOf diff --git a/Makefile b/Makefile index 0359a659c7c3..a1ab49a47908 100644 --- a/Makefile +++ b/Makefile @@ -39,6 +39,14 @@ $(call make-lint-dependency) docs/cli: go run ./cmd/clidoc/. . +.PHONY: docs/api +docs/api: + npx @redocly/openapi-cli preview-docs spec/api.json + +.PHONY: docs/swagger +docs/swagger: + npx @redocly/openapi-cli preview-docs spec/swagger.json + .bin/ory: Makefile bash <(curl https://raw.githubusercontent.com/ory/meta/master/install.sh) -d -b .bin ory v0.1.14 touch -a -m .bin/ory diff --git a/README.md b/README.md index f9dd72b5cba6..999c5b71679f 100644 --- a/README.md +++ b/README.md @@ -578,3 +578,12 @@ To prepare documentation tests, run `npm i` to install - test all documentation: make test-docs - test an individual file: text-run + +#### Preview API documentation + +- update the SDK including the OpenAPI specification: + make sdk +- run preview server for API documentation: make + docs/api +- run preview server for swagger documentation: make + docs/swagger diff --git a/internal/httpclient/api/openapi.yaml b/internal/httpclient/api/openapi.yaml index bd5633433c51..4a3feb650f3b 100644 --- a/internal/httpclient/api/openapi.yaml +++ b/internal/httpclient/api/openapi.yaml @@ -3461,8 +3461,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default - meta: label: context: '{}' @@ -3478,8 +3478,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default method: method action: action messages: @@ -3593,8 +3593,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default - meta: label: context: '{}' @@ -3610,8 +3610,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default method: method action: action messages: @@ -3670,6 +3670,7 @@ components: - issued_at - request_url - state + - type - ui title: A Recovery Flow type: object @@ -3727,8 +3728,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default - meta: label: context: '{}' @@ -3744,8 +3745,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default method: method action: action messages: @@ -3797,6 +3798,7 @@ components: - id - issued_at - request_url + - type - ui type: object selfServiceSettingsFlow: @@ -3824,8 +3826,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default - meta: label: context: '{}' @@ -3841,8 +3843,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default method: method action: action messages: @@ -3949,6 +3951,7 @@ components: - issued_at - request_url - state + - type - ui title: Flow represents a Settings Flow type: object @@ -3988,8 +3991,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default - meta: label: context: '{}' @@ -4005,8 +4008,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default method: method action: action messages: @@ -4964,8 +4967,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default - meta: label: context: '{}' @@ -4981,8 +4984,8 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default method: method action: action messages: @@ -5035,12 +5038,23 @@ components: id: 0 text: text type: type - type: type - group: group + type: text + group: default properties: attributes: $ref: '#/components/schemas/uiNodeAttributes' group: + description: Group specifies which group (e.g. password authenticator) this + node belongs to. + enum: + - default + - password + - oidc + - profile + - link + - totp + - lookup_secret + - webauthn type: string messages: items: @@ -5049,6 +5063,13 @@ components: meta: $ref: '#/components/schemas/uiNodeMeta' type: + description: The node's type + enum: + - text + - input + - img + - a + - script type: string required: - attributes @@ -5070,6 +5091,15 @@ components: description: A unique identifier type: string node_type: + description: |- + NodeType represents this node's types. It is a mirror of `node.type` and + is primarily used to allow compatibility with OpenAPI 3.0. + enum: + - text + - input + - img + - a + - script type: string title: $ref: '#/components/schemas/uiText' @@ -5083,8 +5113,8 @@ components: uiNodeAttributes: discriminator: mapping: - anchor: '#/components/schemas/uiNodeAnchorAttributes' - image: '#/components/schemas/uiNodeImageAttributes' + a: '#/components/schemas/uiNodeAnchorAttributes' + img: '#/components/schemas/uiNodeImageAttributes' input: '#/components/schemas/uiNodeInputAttributes' script: '#/components/schemas/uiNodeScriptAttributes' text: '#/components/schemas/uiNodeTextAttributes' @@ -5096,8 +5126,6 @@ components: - $ref: '#/components/schemas/uiNodeAnchorAttributes' - $ref: '#/components/schemas/uiNodeScriptAttributes' title: Attributes represents a list of attributes (e.g. `href="foo"` for links). - uiNodeGroup: - type: string uiNodeImageAttributes: properties: height: @@ -5108,6 +5136,15 @@ components: description: A unique identifier type: string node_type: + description: |- + NodeType represents this node's types. It is a mirror of `node.type` and + is primarily used to allow compatibility with OpenAPI 3.0. + enum: + - text + - input + - img + - a + - script type: string src: description: |- @@ -5141,6 +5178,15 @@ components: description: The input's element name. type: string node_type: + description: |- + NodeType represents this node's types. It is a mirror of `node.type` and + is primarily used to allow compatibility with OpenAPI 3.0. + enum: + - text + - input + - img + - a + - script type: string onclick: description: |- @@ -5194,6 +5240,15 @@ components: description: The script's integrity hash type: string node_type: + description: |- + NodeType represents this node's types. It is a mirror of `node.type` and + is primarily used to allow compatibility with OpenAPI 3.0. + enum: + - text + - input + - img + - a + - script type: string nonce: description: |- @@ -5230,6 +5285,15 @@ components: description: A unique identifier type: string node_type: + description: |- + NodeType represents this node's types. It is a mirror of `node.type` and + is primarily used to allow compatibility with OpenAPI 3.0. + enum: + - text + - input + - img + - a + - script type: string text: $ref: '#/components/schemas/uiText' @@ -5239,8 +5303,6 @@ components: - text title: TextAttributes represents the attributes of a text node. type: object - uiNodeType: - type: string uiNodes: items: $ref: '#/components/schemas/uiNode' diff --git a/internal/httpclient/docs/SelfServiceRecoveryFlow.md b/internal/httpclient/docs/SelfServiceRecoveryFlow.md index d42afbf4c194..68d613914725 100644 --- a/internal/httpclient/docs/SelfServiceRecoveryFlow.md +++ b/internal/httpclient/docs/SelfServiceRecoveryFlow.md @@ -11,14 +11,14 @@ Name | Type | Description | Notes **RequestUrl** | **string** | RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. | **ReturnTo** | Pointer to **string** | ReturnTo contains the requested return_to URL. | [optional] **State** | [**SelfServiceRecoveryFlowState**](SelfServiceRecoveryFlowState.md) | | -**Type** | Pointer to **string** | The flow type can either be `api` or `browser`. | [optional] +**Type** | **string** | The flow type can either be `api` or `browser`. | **Ui** | [**UiContainer**](UiContainer.md) | | ## Methods ### NewSelfServiceRecoveryFlow -`func NewSelfServiceRecoveryFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, state SelfServiceRecoveryFlowState, ui UiContainer, ) *SelfServiceRecoveryFlow` +`func NewSelfServiceRecoveryFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, state SelfServiceRecoveryFlowState, type_ string, ui UiContainer, ) *SelfServiceRecoveryFlow` NewSelfServiceRecoveryFlow instantiates a new SelfServiceRecoveryFlow object This constructor will assign default values to properties that have it defined, @@ -202,11 +202,6 @@ and a boolean to check if the value has been set. SetType sets Type field to given value. -### HasType - -`func (o *SelfServiceRecoveryFlow) HasType() bool` - -HasType returns a boolean if a field has been set. ### GetUi diff --git a/internal/httpclient/docs/SelfServiceRegistrationFlow.md b/internal/httpclient/docs/SelfServiceRegistrationFlow.md index e80ea40845c2..bc7901df27fb 100644 --- a/internal/httpclient/docs/SelfServiceRegistrationFlow.md +++ b/internal/httpclient/docs/SelfServiceRegistrationFlow.md @@ -10,14 +10,14 @@ Name | Type | Description | Notes **IssuedAt** | **time.Time** | IssuedAt is the time (UTC) when the flow occurred. | **RequestUrl** | **string** | RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. | **ReturnTo** | Pointer to **string** | ReturnTo contains the requested return_to URL. | [optional] -**Type** | Pointer to **string** | The flow type can either be `api` or `browser`. | [optional] +**Type** | **string** | The flow type can either be `api` or `browser`. | **Ui** | [**UiContainer**](UiContainer.md) | | ## Methods ### NewSelfServiceRegistrationFlow -`func NewSelfServiceRegistrationFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, ui UiContainer, ) *SelfServiceRegistrationFlow` +`func NewSelfServiceRegistrationFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, type_ string, ui UiContainer, ) *SelfServiceRegistrationFlow` NewSelfServiceRegistrationFlow instantiates a new SelfServiceRegistrationFlow object This constructor will assign default values to properties that have it defined, @@ -181,11 +181,6 @@ and a boolean to check if the value has been set. SetType sets Type field to given value. -### HasType - -`func (o *SelfServiceRegistrationFlow) HasType() bool` - -HasType returns a boolean if a field has been set. ### GetUi diff --git a/internal/httpclient/docs/SelfServiceSettingsFlow.md b/internal/httpclient/docs/SelfServiceSettingsFlow.md index 78d1348796d3..2628c8ea60c3 100644 --- a/internal/httpclient/docs/SelfServiceSettingsFlow.md +++ b/internal/httpclient/docs/SelfServiceSettingsFlow.md @@ -12,14 +12,14 @@ Name | Type | Description | Notes **RequestUrl** | **string** | RequestURL is the initial URL that was requested from Ory Kratos. It can be used to forward information contained in the URL's path or query for example. | **ReturnTo** | Pointer to **string** | ReturnTo contains the requested return_to URL. | [optional] **State** | [**SelfServiceSettingsFlowState**](SelfServiceSettingsFlowState.md) | | -**Type** | Pointer to **string** | The flow type can either be `api` or `browser`. | [optional] +**Type** | **string** | The flow type can either be `api` or `browser`. | **Ui** | [**UiContainer**](UiContainer.md) | | ## Methods ### NewSelfServiceSettingsFlow -`func NewSelfServiceSettingsFlow(expiresAt time.Time, id string, identity Identity, issuedAt time.Time, requestUrl string, state SelfServiceSettingsFlowState, ui UiContainer, ) *SelfServiceSettingsFlow` +`func NewSelfServiceSettingsFlow(expiresAt time.Time, id string, identity Identity, issuedAt time.Time, requestUrl string, state SelfServiceSettingsFlowState, type_ string, ui UiContainer, ) *SelfServiceSettingsFlow` NewSelfServiceSettingsFlow instantiates a new SelfServiceSettingsFlow object This constructor will assign default values to properties that have it defined, @@ -223,11 +223,6 @@ and a boolean to check if the value has been set. SetType sets Type field to given value. -### HasType - -`func (o *SelfServiceSettingsFlow) HasType() bool` - -HasType returns a boolean if a field has been set. ### GetUi diff --git a/internal/httpclient/docs/UiNode.md b/internal/httpclient/docs/UiNode.md index 59a6f949d28a..956290963e39 100644 --- a/internal/httpclient/docs/UiNode.md +++ b/internal/httpclient/docs/UiNode.md @@ -5,10 +5,10 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Attributes** | [**UiNodeAttributes**](UiNodeAttributes.md) | | -**Group** | **string** | | +**Group** | **string** | Group specifies which group (e.g. password authenticator) this node belongs to. | **Messages** | [**[]UiText**](UiText.md) | | **Meta** | [**UiNodeMeta**](UiNodeMeta.md) | | -**Type** | **string** | | +**Type** | **string** | The node's type | ## Methods diff --git a/internal/httpclient/docs/UiNodeAnchorAttributes.md b/internal/httpclient/docs/UiNodeAnchorAttributes.md index b3f178380c71..44099ac60ccc 100644 --- a/internal/httpclient/docs/UiNodeAnchorAttributes.md +++ b/internal/httpclient/docs/UiNodeAnchorAttributes.md @@ -6,7 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Href** | **string** | The link's href (destination) URL. format: uri | **Id** | **string** | A unique identifier | -**NodeType** | **string** | | +**NodeType** | **string** | NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. | **Title** | [**UiText**](UiText.md) | | ## Methods diff --git a/internal/httpclient/docs/UiNodeAttributes.md b/internal/httpclient/docs/UiNodeAttributes.md index b2c451fd841b..03760d3ecc68 100644 --- a/internal/httpclient/docs/UiNodeAttributes.md +++ b/internal/httpclient/docs/UiNodeAttributes.md @@ -7,7 +7,7 @@ Name | Type | Description | Notes **Disabled** | **bool** | Sets the input's disabled field to true or false. | **Label** | Pointer to [**UiText**](UiText.md) | | [optional] **Name** | **string** | The input's element name. | -**NodeType** | **string** | | +**NodeType** | **string** | NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. | **Onclick** | Pointer to **string** | OnClick may contain javascript which should be executed on click. This is primarily used for WebAuthn. | [optional] **Pattern** | Pointer to **string** | The input's pattern. | [optional] **Required** | Pointer to **bool** | Mark this input field as required. | [optional] diff --git a/internal/httpclient/docs/UiNodeImageAttributes.md b/internal/httpclient/docs/UiNodeImageAttributes.md index e8138b78cca4..f79dc91c4e8c 100644 --- a/internal/httpclient/docs/UiNodeImageAttributes.md +++ b/internal/httpclient/docs/UiNodeImageAttributes.md @@ -6,7 +6,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Height** | **int64** | Height of the image | **Id** | **string** | A unique identifier | -**NodeType** | **string** | | +**NodeType** | **string** | NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. | **Src** | **string** | The image's source URL. format: uri | **Width** | **int64** | Width of the image | diff --git a/internal/httpclient/docs/UiNodeInputAttributes.md b/internal/httpclient/docs/UiNodeInputAttributes.md index 45b6439d1b5a..d684252a73c2 100644 --- a/internal/httpclient/docs/UiNodeInputAttributes.md +++ b/internal/httpclient/docs/UiNodeInputAttributes.md @@ -7,7 +7,7 @@ Name | Type | Description | Notes **Disabled** | **bool** | Sets the input's disabled field to true or false. | **Label** | Pointer to [**UiText**](UiText.md) | | [optional] **Name** | **string** | The input's element name. | -**NodeType** | **string** | | +**NodeType** | **string** | NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. | **Onclick** | Pointer to **string** | OnClick may contain javascript which should be executed on click. This is primarily used for WebAuthn. | [optional] **Pattern** | Pointer to **string** | The input's pattern. | [optional] **Required** | Pointer to **bool** | Mark this input field as required. | [optional] diff --git a/internal/httpclient/docs/UiNodeScriptAttributes.md b/internal/httpclient/docs/UiNodeScriptAttributes.md index d6dfa8576e78..54dd12571580 100644 --- a/internal/httpclient/docs/UiNodeScriptAttributes.md +++ b/internal/httpclient/docs/UiNodeScriptAttributes.md @@ -8,7 +8,7 @@ Name | Type | Description | Notes **Crossorigin** | **string** | The script cross origin policy | **Id** | **string** | A unique identifier | **Integrity** | **string** | The script's integrity hash | -**NodeType** | **string** | | +**NodeType** | **string** | NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. | **Nonce** | **string** | Nonce for CSP A nonce you may want to use to improve your Content Security Policy. You do not have to use this value but if you want to improve your CSP policies you may use it. You can also choose to use your own nonce value! | **Referrerpolicy** | **string** | The script referrer policy | **Src** | **string** | The script source | diff --git a/internal/httpclient/docs/UiNodeTextAttributes.md b/internal/httpclient/docs/UiNodeTextAttributes.md index 2eb29b2fcb7f..6139132c1116 100644 --- a/internal/httpclient/docs/UiNodeTextAttributes.md +++ b/internal/httpclient/docs/UiNodeTextAttributes.md @@ -5,7 +5,7 @@ Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- **Id** | **string** | A unique identifier | -**NodeType** | **string** | | +**NodeType** | **string** | NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. | **Text** | [**UiText**](UiText.md) | | ## Methods diff --git a/internal/httpclient/model_self_service_recovery_flow.go b/internal/httpclient/model_self_service_recovery_flow.go index 311c4d213506..996e5f0a1894 100644 --- a/internal/httpclient/model_self_service_recovery_flow.go +++ b/internal/httpclient/model_self_service_recovery_flow.go @@ -31,7 +31,7 @@ type SelfServiceRecoveryFlow struct { ReturnTo *string `json:"return_to,omitempty"` State SelfServiceRecoveryFlowState `json:"state"` // The flow type can either be `api` or `browser`. - Type *string `json:"type,omitempty"` + Type string `json:"type"` Ui UiContainer `json:"ui"` } @@ -39,13 +39,14 @@ type SelfServiceRecoveryFlow struct { // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewSelfServiceRecoveryFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, state SelfServiceRecoveryFlowState, ui UiContainer) *SelfServiceRecoveryFlow { +func NewSelfServiceRecoveryFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, state SelfServiceRecoveryFlowState, type_ string, ui UiContainer) *SelfServiceRecoveryFlow { this := SelfServiceRecoveryFlow{} this.ExpiresAt = expiresAt this.Id = id this.IssuedAt = issuedAt this.RequestUrl = requestUrl this.State = state + this.Type = type_ this.Ui = ui return &this } @@ -242,36 +243,28 @@ func (o *SelfServiceRecoveryFlow) SetState(v SelfServiceRecoveryFlowState) { o.State = v } -// GetType returns the Type field value if set, zero value otherwise. +// GetType returns the Type field value func (o *SelfServiceRecoveryFlow) GetType() string { - if o == nil || o.Type == nil { + if o == nil { var ret string return ret } - return *o.Type + + return o.Type } -// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// GetTypeOk returns a tuple with the Type field value // and a boolean to check if the value has been set. func (o *SelfServiceRecoveryFlow) GetTypeOk() (*string, bool) { - if o == nil || o.Type == nil { + if o == nil { return nil, false } - return o.Type, true -} - -// HasType returns a boolean if a field has been set. -func (o *SelfServiceRecoveryFlow) HasType() bool { - if o != nil && o.Type != nil { - return true - } - - return false + return &o.Type, true } -// SetType gets a reference to the given string and assigns it to the Type field. +// SetType sets field value func (o *SelfServiceRecoveryFlow) SetType(v string) { - o.Type = &v + o.Type = v } // GetUi returns the Ui field value @@ -321,7 +314,7 @@ func (o SelfServiceRecoveryFlow) MarshalJSON() ([]byte, error) { if true { toSerialize["state"] = o.State } - if o.Type != nil { + if true { toSerialize["type"] = o.Type } if true { diff --git a/internal/httpclient/model_self_service_registration_flow.go b/internal/httpclient/model_self_service_registration_flow.go index 31c6c78c459f..4e42e7b99001 100644 --- a/internal/httpclient/model_self_service_registration_flow.go +++ b/internal/httpclient/model_self_service_registration_flow.go @@ -29,7 +29,7 @@ type SelfServiceRegistrationFlow struct { // ReturnTo contains the requested return_to URL. ReturnTo *string `json:"return_to,omitempty"` // The flow type can either be `api` or `browser`. - Type *string `json:"type,omitempty"` + Type string `json:"type"` Ui UiContainer `json:"ui"` } @@ -37,12 +37,13 @@ type SelfServiceRegistrationFlow struct { // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewSelfServiceRegistrationFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, ui UiContainer) *SelfServiceRegistrationFlow { +func NewSelfServiceRegistrationFlow(expiresAt time.Time, id string, issuedAt time.Time, requestUrl string, type_ string, ui UiContainer) *SelfServiceRegistrationFlow { this := SelfServiceRegistrationFlow{} this.ExpiresAt = expiresAt this.Id = id this.IssuedAt = issuedAt this.RequestUrl = requestUrl + this.Type = type_ this.Ui = ui return &this } @@ -215,36 +216,28 @@ func (o *SelfServiceRegistrationFlow) SetReturnTo(v string) { o.ReturnTo = &v } -// GetType returns the Type field value if set, zero value otherwise. +// GetType returns the Type field value func (o *SelfServiceRegistrationFlow) GetType() string { - if o == nil || o.Type == nil { + if o == nil { var ret string return ret } - return *o.Type + + return o.Type } -// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// GetTypeOk returns a tuple with the Type field value // and a boolean to check if the value has been set. func (o *SelfServiceRegistrationFlow) GetTypeOk() (*string, bool) { - if o == nil || o.Type == nil { + if o == nil { return nil, false } - return o.Type, true -} - -// HasType returns a boolean if a field has been set. -func (o *SelfServiceRegistrationFlow) HasType() bool { - if o != nil && o.Type != nil { - return true - } - - return false + return &o.Type, true } -// SetType gets a reference to the given string and assigns it to the Type field. +// SetType sets field value func (o *SelfServiceRegistrationFlow) SetType(v string) { - o.Type = &v + o.Type = v } // GetUi returns the Ui field value @@ -291,7 +284,7 @@ func (o SelfServiceRegistrationFlow) MarshalJSON() ([]byte, error) { if o.ReturnTo != nil { toSerialize["return_to"] = o.ReturnTo } - if o.Type != nil { + if true { toSerialize["type"] = o.Type } if true { diff --git a/internal/httpclient/model_self_service_settings_flow.go b/internal/httpclient/model_self_service_settings_flow.go index 550fffeaedc6..275a7d9b8cbb 100644 --- a/internal/httpclient/model_self_service_settings_flow.go +++ b/internal/httpclient/model_self_service_settings_flow.go @@ -32,7 +32,7 @@ type SelfServiceSettingsFlow struct { ReturnTo *string `json:"return_to,omitempty"` State SelfServiceSettingsFlowState `json:"state"` // The flow type can either be `api` or `browser`. - Type *string `json:"type,omitempty"` + Type string `json:"type"` Ui UiContainer `json:"ui"` } @@ -40,7 +40,7 @@ type SelfServiceSettingsFlow struct { // This constructor will assign default values to properties that have it defined, // and makes sure properties required by API are set, but the set of arguments // will change when the set of required properties is changed -func NewSelfServiceSettingsFlow(expiresAt time.Time, id string, identity Identity, issuedAt time.Time, requestUrl string, state SelfServiceSettingsFlowState, ui UiContainer) *SelfServiceSettingsFlow { +func NewSelfServiceSettingsFlow(expiresAt time.Time, id string, identity Identity, issuedAt time.Time, requestUrl string, state SelfServiceSettingsFlowState, type_ string, ui UiContainer) *SelfServiceSettingsFlow { this := SelfServiceSettingsFlow{} this.ExpiresAt = expiresAt this.Id = id @@ -48,6 +48,7 @@ func NewSelfServiceSettingsFlow(expiresAt time.Time, id string, identity Identit this.IssuedAt = issuedAt this.RequestUrl = requestUrl this.State = state + this.Type = type_ this.Ui = ui return &this } @@ -268,36 +269,28 @@ func (o *SelfServiceSettingsFlow) SetState(v SelfServiceSettingsFlowState) { o.State = v } -// GetType returns the Type field value if set, zero value otherwise. +// GetType returns the Type field value func (o *SelfServiceSettingsFlow) GetType() string { - if o == nil || o.Type == nil { + if o == nil { var ret string return ret } - return *o.Type + + return o.Type } -// GetTypeOk returns a tuple with the Type field value if set, nil otherwise +// GetTypeOk returns a tuple with the Type field value // and a boolean to check if the value has been set. func (o *SelfServiceSettingsFlow) GetTypeOk() (*string, bool) { - if o == nil || o.Type == nil { + if o == nil { return nil, false } - return o.Type, true -} - -// HasType returns a boolean if a field has been set. -func (o *SelfServiceSettingsFlow) HasType() bool { - if o != nil && o.Type != nil { - return true - } - - return false + return &o.Type, true } -// SetType gets a reference to the given string and assigns it to the Type field. +// SetType sets field value func (o *SelfServiceSettingsFlow) SetType(v string) { - o.Type = &v + o.Type = v } // GetUi returns the Ui field value @@ -350,7 +343,7 @@ func (o SelfServiceSettingsFlow) MarshalJSON() ([]byte, error) { if true { toSerialize["state"] = o.State } - if o.Type != nil { + if true { toSerialize["type"] = o.Type } if true { diff --git a/internal/httpclient/model_ui_node.go b/internal/httpclient/model_ui_node.go index 6c94ae0b6613..e94114166a0b 100644 --- a/internal/httpclient/model_ui_node.go +++ b/internal/httpclient/model_ui_node.go @@ -18,10 +18,12 @@ import ( // UiNode Nodes are represented as HTML elements or their native UI equivalents. For example, a node can be an `` tag, or an `` but also `some plain text`. type UiNode struct { Attributes UiNodeAttributes `json:"attributes"` - Group string `json:"group"` - Messages []UiText `json:"messages"` - Meta UiNodeMeta `json:"meta"` - Type string `json:"type"` + // Group specifies which group (e.g. password authenticator) this node belongs to. + Group string `json:"group"` + Messages []UiText `json:"messages"` + Meta UiNodeMeta `json:"meta"` + // The node's type + Type string `json:"type"` } // NewUiNode instantiates a new UiNode object diff --git a/internal/httpclient/model_ui_node_anchor_attributes.go b/internal/httpclient/model_ui_node_anchor_attributes.go index 0e544f31948d..e995d86cbdba 100644 --- a/internal/httpclient/model_ui_node_anchor_attributes.go +++ b/internal/httpclient/model_ui_node_anchor_attributes.go @@ -20,7 +20,8 @@ type UiNodeAnchorAttributes struct { // The link's href (destination) URL. format: uri Href string `json:"href"` // A unique identifier - Id string `json:"id"` + Id string `json:"id"` + // NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. NodeType string `json:"node_type"` Title UiText `json:"title"` } diff --git a/internal/httpclient/model_ui_node_image_attributes.go b/internal/httpclient/model_ui_node_image_attributes.go index 418eb0a72820..be775ff2146c 100644 --- a/internal/httpclient/model_ui_node_image_attributes.go +++ b/internal/httpclient/model_ui_node_image_attributes.go @@ -20,7 +20,8 @@ type UiNodeImageAttributes struct { // Height of the image Height int64 `json:"height"` // A unique identifier - Id string `json:"id"` + Id string `json:"id"` + // NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. NodeType string `json:"node_type"` // The image's source URL. format: uri Src string `json:"src"` diff --git a/internal/httpclient/model_ui_node_input_attributes.go b/internal/httpclient/model_ui_node_input_attributes.go index bee7c2245d9d..ff7360de828a 100644 --- a/internal/httpclient/model_ui_node_input_attributes.go +++ b/internal/httpclient/model_ui_node_input_attributes.go @@ -21,7 +21,8 @@ type UiNodeInputAttributes struct { Disabled bool `json:"disabled"` Label *UiText `json:"label,omitempty"` // The input's element name. - Name string `json:"name"` + Name string `json:"name"` + // NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. NodeType string `json:"node_type"` // OnClick may contain javascript which should be executed on click. This is primarily used for WebAuthn. Onclick *string `json:"onclick,omitempty"` diff --git a/internal/httpclient/model_ui_node_script_attributes.go b/internal/httpclient/model_ui_node_script_attributes.go index a077823a78b7..d2d668bb165c 100644 --- a/internal/httpclient/model_ui_node_script_attributes.go +++ b/internal/httpclient/model_ui_node_script_attributes.go @@ -25,7 +25,8 @@ type UiNodeScriptAttributes struct { Id string `json:"id"` // The script's integrity hash Integrity string `json:"integrity"` - NodeType string `json:"node_type"` + // NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. + NodeType string `json:"node_type"` // Nonce for CSP A nonce you may want to use to improve your Content Security Policy. You do not have to use this value but if you want to improve your CSP policies you may use it. You can also choose to use your own nonce value! Nonce string `json:"nonce"` // The script referrer policy diff --git a/internal/httpclient/model_ui_node_text_attributes.go b/internal/httpclient/model_ui_node_text_attributes.go index 4fea508c1d87..b2d0066aeba2 100644 --- a/internal/httpclient/model_ui_node_text_attributes.go +++ b/internal/httpclient/model_ui_node_text_attributes.go @@ -18,7 +18,8 @@ import ( // UiNodeTextAttributes struct for UiNodeTextAttributes type UiNodeTextAttributes struct { // A unique identifier - Id string `json:"id"` + Id string `json:"id"` + // NodeType represents this node's types. It is a mirror of `node.type` and is primarily used to allow compatibility with OpenAPI 3.0. NodeType string `json:"node_type"` Text UiText `json:"text"` } diff --git a/selfservice/flow/login/error.go b/selfservice/flow/login/error.go index 67f873bf49ce..eb7562986e58 100644 --- a/selfservice/flow/login/error.go +++ b/selfservice/flow/login/error.go @@ -70,7 +70,7 @@ func (s *ErrorHandler) PrepareReplacementForExpiredFlow(w http.ResponseWriter, r return e.WithFlow(a), nil } -func (s *ErrorHandler) WriteFlowError(w http.ResponseWriter, r *http.Request, f *Flow, group node.Group, err error) { +func (s *ErrorHandler) WriteFlowError(w http.ResponseWriter, r *http.Request, f *Flow, group node.UiNodeGroup, err error) { s.d.Audit(). WithError(err). WithRequest(r). diff --git a/selfservice/flow/login/error_test.go b/selfservice/flow/login/error_test.go index 08b294663255..a7de240feb7c 100644 --- a/selfservice/flow/login/error_test.go +++ b/selfservice/flow/login/error_test.go @@ -51,7 +51,7 @@ func TestHandleError(t *testing.T) { var loginFlow *login.Flow var flowError error - var ct node.Group + var ct node.UiNodeGroup router.GET("/error", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { h.WriteFlowError(w, r, loginFlow, ct, flowError) }) diff --git a/selfservice/flow/login/sort.go b/selfservice/flow/login/sort.go index c98a5834ec76..816f6a53a3c0 100644 --- a/selfservice/flow/login/sort.go +++ b/selfservice/flow/login/sort.go @@ -8,7 +8,7 @@ import ( func sortNodes(ctx context.Context, n node.Nodes) error { return n.SortBySchema(ctx, - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.OpenIDConnectGroup, node.DefaultGroup, node.WebAuthnGroup, diff --git a/selfservice/flow/login/strategy.go b/selfservice/flow/login/strategy.go index 6956cebc3357..ff7fd8c242de 100644 --- a/selfservice/flow/login/strategy.go +++ b/selfservice/flow/login/strategy.go @@ -15,7 +15,7 @@ import ( type Strategy interface { ID() identity.CredentialsType - NodeGroup() node.Group + NodeGroup() node.UiNodeGroup RegisterLoginRoutes(*x.RouterPublic) PopulateLoginMethod(r *http.Request, requestedAAL identity.AuthenticatorAssuranceLevel, sr *Flow) error Login(w http.ResponseWriter, r *http.Request, f *Flow, ss *session.Session) (i *identity.Identity, err error) diff --git a/selfservice/flow/recovery/error.go b/selfservice/flow/recovery/error.go index 4785945dca3f..826528e9b726 100644 --- a/selfservice/flow/recovery/error.go +++ b/selfservice/flow/recovery/error.go @@ -54,7 +54,7 @@ func (s *ErrorHandler) WriteFlowError( w http.ResponseWriter, r *http.Request, f *Flow, - group node.Group, + group node.UiNodeGroup, err error, ) { s.d.Audit(). diff --git a/selfservice/flow/recovery/error_test.go b/selfservice/flow/recovery/error_test.go index a932342e4810..e467a40bb96c 100644 --- a/selfservice/flow/recovery/error_test.go +++ b/selfservice/flow/recovery/error_test.go @@ -52,7 +52,7 @@ func TestHandleError(t *testing.T) { var recoveryFlow *recovery.Flow var flowError error - var methodName node.Group + var methodName node.UiNodeGroup router.GET("/error", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { h.WriteFlowError(w, r, recoveryFlow, methodName, flowError) }) @@ -195,7 +195,7 @@ func TestHandleError(t *testing.T) { recoveryFlow = &recovery.Flow{Type: flow.TypeBrowser} flowError = flow.NewFlowExpiredError(anHourAgo) - methodName = node.RecoveryLinkGroup + methodName = node.LinkGroup lf, _ := expectRecoveryUI(t) require.Len(t, lf.UI.Messages, 1, "%s", jsonx.TestMarshalJSONString(t, lf)) @@ -207,7 +207,7 @@ func TestHandleError(t *testing.T) { recoveryFlow = newFlow(t, time.Minute, flow.TypeBrowser) flowError = schema.NewInvalidCredentialsError() - methodName = node.RecoveryLinkGroup + methodName = node.LinkGroup lf, _ := expectRecoveryUI(t) require.NotEmpty(t, lf.UI, x.MustEncodeJSON(t, lf)) @@ -220,7 +220,7 @@ func TestHandleError(t *testing.T) { recoveryFlow = newFlow(t, time.Minute, flow.TypeBrowser) flowError = herodot.ErrInternalServerError.WithReason("system error") - methodName = node.RecoveryLinkGroup + methodName = node.LinkGroup sse, _ := expectErrorUI(t) assertx.EqualAsJSON(t, flowError, sse) diff --git a/selfservice/flow/recovery/flow.go b/selfservice/flow/recovery/flow.go index cc13b7064b8e..48d8f0de1e1b 100644 --- a/selfservice/flow/recovery/flow.go +++ b/selfservice/flow/recovery/flow.go @@ -38,6 +38,8 @@ type Flow struct { ID uuid.UUID `json:"id" db:"id" faker:"-"` // Type represents the flow's type which can be either "api" or "browser", depending on the flow interaction. + // + // required: true Type flow.Type `json:"type" db:"type" faker:"flow_type"` // ExpiresAt is the time (UTC) when the request expires. If the user still wishes to update the setting, diff --git a/selfservice/flow/recovery/handler.go b/selfservice/flow/recovery/handler.go index d3da91a411c8..d998de2f5229 100644 --- a/selfservice/flow/recovery/handler.go +++ b/selfservice/flow/recovery/handler.go @@ -370,7 +370,7 @@ func (h *Handler) submitFlow(w http.ResponseWriter, r *http.Request, ps httprout return } - var g node.Group + var g node.UiNodeGroup var found bool for _, ss := range h.d.AllRecoveryStrategies() { err := ss.Recover(w, r, f) diff --git a/selfservice/flow/recovery/strategy.go b/selfservice/flow/recovery/strategy.go index 4c38c17196df..c8e3ecbf5d3f 100644 --- a/selfservice/flow/recovery/strategy.go +++ b/selfservice/flow/recovery/strategy.go @@ -18,7 +18,7 @@ const ( type ( Strategy interface { RecoveryStrategyID() string - RecoveryNodeGroup() node.Group + RecoveryNodeGroup() node.UiNodeGroup PopulateRecoveryMethod(*http.Request, *Flow) error Recover(w http.ResponseWriter, r *http.Request, f *Flow) (err error) } diff --git a/selfservice/flow/registration/error.go b/selfservice/flow/registration/error.go index cd0a07ec60f8..0a132ef5fe77 100644 --- a/selfservice/flow/registration/error.go +++ b/selfservice/flow/registration/error.go @@ -66,7 +66,7 @@ func (s *ErrorHandler) WriteFlowError( w http.ResponseWriter, r *http.Request, f *Flow, - group node.Group, + group node.UiNodeGroup, err error, ) { s.d.Audit(). diff --git a/selfservice/flow/registration/error_test.go b/selfservice/flow/registration/error_test.go index 7ba809409cb9..3e1b1fd5748b 100644 --- a/selfservice/flow/registration/error_test.go +++ b/selfservice/flow/registration/error_test.go @@ -54,7 +54,7 @@ func TestHandleError(t *testing.T) { var registrationFlow *registration.Flow var flowError error - var group node.Group + var group node.UiNodeGroup router.GET("/error", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { h.WriteFlowError(w, r, registrationFlow, group, flowError) }) diff --git a/selfservice/flow/registration/flow.go b/selfservice/flow/registration/flow.go index c442c0208a6a..b2d21cad4603 100644 --- a/selfservice/flow/registration/flow.go +++ b/selfservice/flow/registration/flow.go @@ -37,6 +37,8 @@ type Flow struct { ID uuid.UUID `json:"id" faker:"-" db:"id"` // Type represents the flow's type which can be either "api" or "browser", depending on the flow interaction. + // + // required: true Type flow.Type `json:"type" db:"type" faker:"flow_type"` // ExpiresAt is the time (UTC) when the flow expires. If the user still wishes to log in, diff --git a/selfservice/flow/registration/sort.go b/selfservice/flow/registration/sort.go index de247112cc4e..f22f085c0be0 100644 --- a/selfservice/flow/registration/sort.go +++ b/selfservice/flow/registration/sort.go @@ -9,7 +9,7 @@ import ( func SortNodes(ctx context.Context, n node.Nodes, schemaRef string) error { return n.SortBySchema(ctx, node.SortBySchema(schemaRef), - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.DefaultGroup, node.OpenIDConnectGroup, node.WebAuthnGroup, diff --git a/selfservice/flow/registration/strategy.go b/selfservice/flow/registration/strategy.go index 79fdf0594499..1085ee544b3d 100644 --- a/selfservice/flow/registration/strategy.go +++ b/selfservice/flow/registration/strategy.go @@ -14,7 +14,7 @@ import ( type Strategy interface { ID() identity.CredentialsType - NodeGroup() node.Group + NodeGroup() node.UiNodeGroup RegisterRegistrationRoutes(*x.RouterPublic) PopulateRegistrationMethod(r *http.Request, sr *Flow) error Register(w http.ResponseWriter, r *http.Request, f *Flow, i *identity.Identity) (err error) diff --git a/selfservice/flow/settings/error.go b/selfservice/flow/settings/error.go index 086f7611f05e..1432ba720146 100644 --- a/selfservice/flow/settings/error.go +++ b/selfservice/flow/settings/error.go @@ -115,7 +115,7 @@ func (s *ErrorHandler) PrepareReplacementForExpiredFlow(w http.ResponseWriter, r func (s *ErrorHandler) WriteFlowError( w http.ResponseWriter, r *http.Request, - group node.Group, + group node.UiNodeGroup, f *Flow, id *identity.Identity, err error, diff --git a/selfservice/flow/settings/error_test.go b/selfservice/flow/settings/error_test.go index 9a7f8cefefc4..e446b5e83c3b 100644 --- a/selfservice/flow/settings/error_test.go +++ b/selfservice/flow/settings/error_test.go @@ -57,7 +57,7 @@ func TestHandleError(t *testing.T) { var settingsFlow *settings.Flow var flowError error - var flowMethod node.Group + var flowMethod node.UiNodeGroup var id identity.Identity require.NoError(t, faker.FakeData(&id)) id.SchemaID = "default" diff --git a/selfservice/flow/settings/flow.go b/selfservice/flow/settings/flow.go index 496df80782b6..7a3b783f6911 100644 --- a/selfservice/flow/settings/flow.go +++ b/selfservice/flow/settings/flow.go @@ -50,6 +50,8 @@ type Flow struct { ID uuid.UUID `json:"id" db:"id" faker:"-"` // Type represents the flow's type which can be either "api" or "browser", depending on the flow interaction. + // + // required: true Type flow.Type `json:"type" db:"type" faker:"flow_type"` // ExpiresAt is the time (UTC) when the flow expires. If the user still wishes to update the setting, diff --git a/selfservice/flow/settings/sort.go b/selfservice/flow/settings/sort.go index fb8777c0afdd..2cc7798989da 100644 --- a/selfservice/flow/settings/sort.go +++ b/selfservice/flow/settings/sort.go @@ -9,7 +9,7 @@ import ( func sortNodes(ctx context.Context, n node.Nodes, schemaRef string) error { return n.SortBySchema(ctx, node.SortBySchema(schemaRef), - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.DefaultGroup, node.ProfileGroup, node.PasswordGroup, diff --git a/selfservice/flow/settings/strategy.go b/selfservice/flow/settings/strategy.go index 787d75709112..3e199457a7c6 100644 --- a/selfservice/flow/settings/strategy.go +++ b/selfservice/flow/settings/strategy.go @@ -23,7 +23,7 @@ var pkgName = reflect.TypeOf(Strategies{}).PkgPath() type Strategy interface { SettingsStrategyID() string - NodeGroup() node.Group + NodeGroup() node.UiNodeGroup RegisterSettingsRoutes(*x.RouterPublic) PopulateSettingsMethod(*http.Request, *identity.Identity, *Flow) error Settings(w http.ResponseWriter, r *http.Request, f *Flow, s *session.Session) (*UpdateContext, error) diff --git a/selfservice/flow/verification/error.go b/selfservice/flow/verification/error.go index 9fcd5a12c0ff..879d13f9555a 100644 --- a/selfservice/flow/verification/error.go +++ b/selfservice/flow/verification/error.go @@ -51,7 +51,7 @@ func (s *ErrorHandler) WriteFlowError( w http.ResponseWriter, r *http.Request, f *Flow, - group node.Group, + group node.UiNodeGroup, err error, ) { s.d.Audit(). diff --git a/selfservice/flow/verification/error_test.go b/selfservice/flow/verification/error_test.go index 969a32f6875c..21c990626298 100644 --- a/selfservice/flow/verification/error_test.go +++ b/selfservice/flow/verification/error_test.go @@ -52,7 +52,7 @@ func TestHandleError(t *testing.T) { var verificationFlow *verification.Flow var flowError error - var methodName node.Group + var methodName node.UiNodeGroup router.GET("/error", func(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { h.WriteFlowError(w, r, verificationFlow, methodName, flowError) }) @@ -195,7 +195,7 @@ func TestHandleError(t *testing.T) { verificationFlow = &verification.Flow{Type: flow.TypeBrowser} flowError = flow.NewFlowExpiredError(anHourAgo) - methodName = node.VerificationLinkGroup + methodName = node.LinkGroup lf, _ := expectVerificationUI(t) require.Len(t, lf.UI.Messages, 1, "%s", jsonx.TestMarshalJSONString(t, lf)) @@ -207,7 +207,7 @@ func TestHandleError(t *testing.T) { verificationFlow = newFlow(t, time.Minute, flow.TypeBrowser) flowError = schema.NewInvalidCredentialsError() - methodName = node.VerificationLinkGroup + methodName = node.LinkGroup lf, _ := expectVerificationUI(t) require.NotEmpty(t, lf.UI, x.MustEncodeJSON(t, lf)) @@ -220,7 +220,7 @@ func TestHandleError(t *testing.T) { verificationFlow = newFlow(t, time.Minute, flow.TypeBrowser) flowError = herodot.ErrInternalServerError.WithReason("system error") - methodName = node.VerificationLinkGroup + methodName = node.LinkGroup sse, _ := expectErrorUI(t) assertx.EqualAsJSON(t, flowError, sse) diff --git a/selfservice/flow/verification/flow.go b/selfservice/flow/verification/flow.go index a5d190c97f39..aadde59034bd 100644 --- a/selfservice/flow/verification/flow.go +++ b/selfservice/flow/verification/flow.go @@ -39,6 +39,7 @@ type Flow struct { ID uuid.UUID `json:"id" db:"id" faker:"-"` // Type represents the flow's type which can be either "api" or "browser", depending on the flow interaction. + // // required: true Type flow.Type `json:"type" db:"type" faker:"flow_type"` diff --git a/selfservice/flow/verification/handler.go b/selfservice/flow/verification/handler.go index c62ede047c03..41b816bb2851 100644 --- a/selfservice/flow/verification/handler.go +++ b/selfservice/flow/verification/handler.go @@ -352,7 +352,7 @@ func (h *Handler) submitFlow(w http.ResponseWriter, r *http.Request, ps httprout return } - var g node.Group + var g node.UiNodeGroup var found bool for _, ss := range h.d.AllVerificationStrategies() { err := ss.Verify(w, r, f) diff --git a/selfservice/flow/verification/strategy.go b/selfservice/flow/verification/strategy.go index 4e8aed9e1482..96d958940683 100644 --- a/selfservice/flow/verification/strategy.go +++ b/selfservice/flow/verification/strategy.go @@ -18,7 +18,7 @@ const ( type ( Strategy interface { VerificationStrategyID() string - VerificationNodeGroup() node.Group + VerificationNodeGroup() node.UiNodeGroup PopulateVerificationMethod(*http.Request, *Flow) error Verify(w http.ResponseWriter, r *http.Request, f *Flow) (err error) } diff --git a/selfservice/strategy/link/strategy.go b/selfservice/strategy/link/strategy.go index ab20019ce87d..e9b02cd88800 100644 --- a/selfservice/strategy/link/strategy.go +++ b/selfservice/strategy/link/strategy.go @@ -79,10 +79,10 @@ func NewStrategy(d strategyDependencies) *Strategy { return &Strategy{d: d, dx: decoderx.NewHTTP()} } -func (s *Strategy) RecoveryNodeGroup() node.Group { - return node.RecoveryLinkGroup +func (s *Strategy) RecoveryNodeGroup() node.UiNodeGroup { + return node.LinkGroup } -func (s *Strategy) VerificationNodeGroup() node.Group { - return node.VerificationLinkGroup +func (s *Strategy) VerificationNodeGroup() node.UiNodeGroup { + return node.LinkGroup } diff --git a/selfservice/strategy/link/strategy_recovery.go b/selfservice/strategy/link/strategy_recovery.go index 1965ba17d2ef..df95f40c1290 100644 --- a/selfservice/strategy/link/strategy_recovery.go +++ b/selfservice/strategy/link/strategy_recovery.go @@ -49,9 +49,9 @@ func (s *Strategy) PopulateRecoveryMethod(r *http.Request, f *recovery.Flow) err f.UI.SetCSRF(s.d.GenerateCSRFToken(r)) f.UI.GetNodes().Upsert( // v0.5: form.Field{Name: "email", Type: "email", Required: true}, - node.NewInputField("email", nil, node.RecoveryLinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute).WithMetaLabel(text.NewInfoNodeInputEmail()), + node.NewInputField("email", nil, node.LinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute).WithMetaLabel(text.NewInfoNodeInputEmail()), ) - f.UI.GetNodes().Append(node.NewInputField("method", s.RecoveryStrategyID(), node.RecoveryLinkGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoNodeLabelSubmit())) + f.UI.GetNodes().Append(node.NewInputField("method", s.RecoveryStrategyID(), node.LinkGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoNodeLabelSubmit())) return nil } @@ -394,7 +394,7 @@ func (s *Strategy) retryRecoveryFlowWithError(w http.ResponseWriter, r *http.Req if expired := new(flow.ExpiredError); errors.As(recErr, &expired) { return s.retryRecoveryFlowWithMessage(w, r, ft, text.NewErrorValidationRecoveryFlowExpired(expired.Ago)) } else { - if err := req.UI.ParseError(node.RecoveryLinkGroup, recErr); err != nil { + if err := req.UI.ParseError(node.LinkGroup, recErr); err != nil { return err } } @@ -437,7 +437,7 @@ func (s *Strategy) recoveryHandleFormSubmission(w http.ResponseWriter, r *http.R f.UI.SetCSRF(s.d.GenerateCSRFToken(r)) f.UI.GetNodes().Upsert( // v0.5: form.Field{Name: "email", Type: "email", Required: true, Value: body.Body.Email} - node.NewInputField("email", body.Email, node.RecoveryLinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), + node.NewInputField("email", body.Email, node.LinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), ) f.Active = sqlxx.NullString(s.RecoveryNodeGroup()) @@ -483,7 +483,7 @@ func (s *Strategy) HandleRecoveryError(w http.ResponseWriter, r *http.Request, r req.UI.SetCSRF(s.d.GenerateCSRFToken(r)) req.UI.GetNodes().Upsert( // v0.5: form.Field{Name: "email", Type: "email", Required: true, Value: body.Body.Email} - node.NewInputField("email", email, node.RecoveryLinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), + node.NewInputField("email", email, node.LinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), ) } diff --git a/selfservice/strategy/link/strategy_recovery_test.go b/selfservice/strategy/link/strategy_recovery_test.go index 5763bde40ca1..8d47dc9036f6 100644 --- a/selfservice/strategy/link/strategy_recovery_test.go +++ b/selfservice/strategy/link/strategy_recovery_test.go @@ -251,7 +251,7 @@ func TestRecovery(t *testing.T) { t.Run("description=should require an email to be sent", func(t *testing.T) { var check = func(t *testing.T, actual string) { - assert.EqualValues(t, node.RecoveryLinkGroup, gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, node.LinkGroup, gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, "Property email is missing.", gjson.Get(actual, "ui.nodes.#(attributes.name==email).messages.0.text").String(), "%s", actual) @@ -276,7 +276,7 @@ func TestRecovery(t *testing.T) { t.Run("description=should require a valid email to be sent", func(t *testing.T) { var check = func(t *testing.T, actual string, value string) { - assert.EqualValues(t, node.RecoveryLinkGroup, gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, node.LinkGroup, gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, fmt.Sprintf("%q is not valid \"email\"", value), gjson.Get(actual, "ui.nodes.#(attributes.name==email).messages.0.text").String(), "%s", actual) @@ -356,7 +356,7 @@ func TestRecovery(t *testing.T) { t.Run("description=should try to recover an email that does not exist", func(t *testing.T) { var email string var check = func(t *testing.T, actual string) { - assert.EqualValues(t, node.RecoveryLinkGroup, gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, node.LinkGroup, gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, email, gjson.Get(actual, "ui.nodes.#(attributes.name==email).attributes.value").String(), "%s", actual) assertx.EqualAsJSON(t, text.NewRecoveryEmailSent(), json.RawMessage(gjson.Get(actual, "ui.messages.0").Raw)) @@ -443,7 +443,7 @@ func TestRecovery(t *testing.T) { assert.Nil(t, addr.VerifiedAt) assert.Equal(t, identity.VerifiableAddressStatusPending, addr.Status) - assert.EqualValues(t, node.RecoveryLinkGroup, gjson.Get(recoverySubmissionResponse, "active").String(), "%s", recoverySubmissionResponse) + assert.EqualValues(t, node.LinkGroup, gjson.Get(recoverySubmissionResponse, "active").String(), "%s", recoverySubmissionResponse) assert.EqualValues(t, recoveryEmail, gjson.Get(recoverySubmissionResponse, "ui.nodes.#(attributes.name==email).attributes.value").String(), "%s", recoverySubmissionResponse) require.Len(t, gjson.Get(recoverySubmissionResponse, "ui.messages").Array(), 1, "%s", recoverySubmissionResponse) assertx.EqualAsJSON(t, text.NewRecoveryEmailSent(), json.RawMessage(gjson.Get(recoverySubmissionResponse, "ui.messages.0").Raw)) diff --git a/selfservice/strategy/link/strategy_verification.go b/selfservice/strategy/link/strategy_verification.go index dd89e81bd521..552f44e063f4 100644 --- a/selfservice/strategy/link/strategy_verification.go +++ b/selfservice/strategy/link/strategy_verification.go @@ -34,9 +34,9 @@ func (s *Strategy) PopulateVerificationMethod(r *http.Request, f *verification.F f.UI.SetCSRF(s.d.GenerateCSRFToken(r)) f.UI.GetNodes().Upsert( // v0.5: form.Field{Name: "email", Type: "email", Required: true} - node.NewInputField("email", nil, node.VerificationLinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute).WithMetaLabel(text.NewInfoNodeInputEmail()), + node.NewInputField("email", nil, node.LinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute).WithMetaLabel(text.NewInfoNodeInputEmail()), ) - f.UI.GetNodes().Append(node.NewInputField("method", s.VerificationStrategyID(), node.VerificationLinkGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoNodeLabelSubmit())) + f.UI.GetNodes().Append(node.NewInputField("method", s.VerificationStrategyID(), node.LinkGroup, node.InputAttributeTypeSubmit).WithMetaLabel(text.NewInfoNodeLabelSubmit())) return nil } @@ -75,7 +75,7 @@ func (s *Strategy) handleVerificationError(w http.ResponseWriter, r *http.Reques f.UI.SetCSRF(s.d.GenerateCSRFToken(r)) f.UI.GetNodes().Upsert( // v0.5: form.Field{Name: "email", Type: "email", Required: true, Value: body.Body.Email} - node.NewInputField("email", body.Email, node.VerificationLinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), + node.NewInputField("email", body.Email, node.LinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), ) } @@ -166,7 +166,7 @@ func (s *Strategy) verificationHandleFormSubmission(w http.ResponseWriter, r *ht f.UI.SetCSRF(s.d.GenerateCSRFToken(r)) f.UI.GetNodes().Upsert( // v0.5: form.Field{Name: "email", Type: "email", Required: true, Value: body.Body.Email} - node.NewInputField("email", body.Email, node.VerificationLinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), + node.NewInputField("email", body.Email, node.LinkGroup, node.InputAttributeTypeEmail, node.WithRequiredInputAttribute), ) f.Active = sqlxx.NullString(s.VerificationNodeGroup()) @@ -305,7 +305,7 @@ func (s *Strategy) retryVerificationFlowWithError(w http.ResponseWriter, r *http if expired := new(flow.ExpiredError); errors.As(verErr, &expired) { return s.retryVerificationFlowWithMessage(w, r, ft, text.NewErrorValidationVerificationFlowExpired(expired.Ago)) } else { - if err := f.UI.ParseError(node.RecoveryLinkGroup, verErr); err != nil { + if err := f.UI.ParseError(node.LinkGroup, verErr); err != nil { return err } } diff --git a/selfservice/strategy/link/strategy_verification_test.go b/selfservice/strategy/link/strategy_verification_test.go index b0d10a45ee5b..d1d064a90898 100644 --- a/selfservice/strategy/link/strategy_verification_test.go +++ b/selfservice/strategy/link/strategy_verification_test.go @@ -112,7 +112,7 @@ func TestVerification(t *testing.T) { t.Run("description=should require an email to be sent", func(t *testing.T) { var check = func(t *testing.T, actual string) { - assert.EqualValues(t, string(node.VerificationLinkGroup), gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, string(node.LinkGroup), gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, "Property email is missing.", gjson.Get(actual, "ui.nodes.#(attributes.name==email).messages.0.text").String(), "%s", actual) @@ -137,7 +137,7 @@ func TestVerification(t *testing.T) { t.Run("description=should require a valid email to be sent", func(t *testing.T) { var check = func(t *testing.T, actual string, value string) { - assert.EqualValues(t, string(node.VerificationLinkGroup), gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, string(node.LinkGroup), gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, fmt.Sprintf("%q is not valid \"email\"", value), gjson.Get(actual, "ui.nodes.#(attributes.name==email).messages.0.text").String(), "%s", actual) @@ -165,7 +165,7 @@ func TestVerification(t *testing.T) { t.Run("description=should try to verify an email that does not exist", func(t *testing.T) { var email string var check = func(t *testing.T, actual string) { - assert.EqualValues(t, string(node.VerificationLinkGroup), gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, string(node.LinkGroup), gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, email, gjson.Get(actual, "ui.nodes.#(attributes.name==email).attributes.value").String(), "%s", actual) assertx.EqualAsJSON(t, text.NewVerificationEmailSent(), json.RawMessage(gjson.Get(actual, "ui.messages.0").Raw)) @@ -260,7 +260,7 @@ func TestVerification(t *testing.T) { t.Run("description=should verify an email address", func(t *testing.T) { var check = func(t *testing.T, actual string) { - assert.EqualValues(t, string(node.VerificationLinkGroup), gjson.Get(actual, "active").String(), "%s", actual) + assert.EqualValues(t, string(node.LinkGroup), gjson.Get(actual, "active").String(), "%s", actual) assert.EqualValues(t, verificationEmail, gjson.Get(actual, "ui.nodes.#(attributes.name==email).attributes.value").String(), "%s", actual) assertx.EqualAsJSON(t, text.NewVerificationEmailSent(), json.RawMessage(gjson.Get(actual, "ui.messages.0").Raw)) diff --git a/selfservice/strategy/lookup/strategy.go b/selfservice/strategy/lookup/strategy.go index 30ab83bf4a7c..12c78ffd485a 100644 --- a/selfservice/strategy/lookup/strategy.go +++ b/selfservice/strategy/lookup/strategy.go @@ -97,7 +97,7 @@ func (s *Strategy) ID() identity.CredentialsType { return identity.CredentialsTypeLookup } -func (s *Strategy) NodeGroup() node.Group { +func (s *Strategy) NodeGroup() node.UiNodeGroup { return node.LookupGroup } diff --git a/selfservice/strategy/oidc/strategy.go b/selfservice/strategy/oidc/strategy.go index ae7fa66ffff5..176e25944340 100644 --- a/selfservice/strategy/oidc/strategy.go +++ b/selfservice/strategy/oidc/strategy.go @@ -461,7 +461,7 @@ func (s *Strategy) handleError(w http.ResponseWriter, r *http.Request, f flow.Fl return err } -func (s *Strategy) NodeGroup() node.Group { +func (s *Strategy) NodeGroup() node.UiNodeGroup { return node.OpenIDConnectGroup } diff --git a/selfservice/strategy/password/strategy.go b/selfservice/strategy/password/strategy.go index fa8437d8c281..866d72793164 100644 --- a/selfservice/strategy/password/strategy.go +++ b/selfservice/strategy/password/strategy.go @@ -111,6 +111,6 @@ func (s *Strategy) CompletedAuthenticationMethod(ctx context.Context) session.Au } } -func (s *Strategy) NodeGroup() node.Group { +func (s *Strategy) NodeGroup() node.UiNodeGroup { return node.PasswordGroup } diff --git a/selfservice/strategy/profile/strategy.go b/selfservice/strategy/profile/strategy.go index 748e503eefa7..1f53dc3ff368 100644 --- a/selfservice/strategy/profile/strategy.go +++ b/selfservice/strategy/profile/strategy.go @@ -276,6 +276,6 @@ func (s *Strategy) newSettingsProfileDecoder(ctx context.Context, i *identity.Id return o, nil } -func (s *Strategy) NodeGroup() node.Group { +func (s *Strategy) NodeGroup() node.UiNodeGroup { return node.ProfileGroup } diff --git a/selfservice/strategy/totp/strategy.go b/selfservice/strategy/totp/strategy.go index c54b66938975..ebc47ead85a8 100644 --- a/selfservice/strategy/totp/strategy.go +++ b/selfservice/strategy/totp/strategy.go @@ -100,7 +100,7 @@ func (s *Strategy) ID() identity.CredentialsType { return identity.CredentialsTypeTOTP } -func (s *Strategy) NodeGroup() node.Group { +func (s *Strategy) NodeGroup() node.UiNodeGroup { return node.TOTPGroup } diff --git a/selfservice/strategy/webauthn/strategy.go b/selfservice/strategy/webauthn/strategy.go index b001fb22f284..3b8f53d25b08 100644 --- a/selfservice/strategy/webauthn/strategy.go +++ b/selfservice/strategy/webauthn/strategy.go @@ -107,7 +107,7 @@ func (s *Strategy) ID() identity.CredentialsType { return identity.CredentialsTypeWebAuthn } -func (s *Strategy) NodeGroup() node.Group { +func (s *Strategy) NodeGroup() node.UiNodeGroup { return node.WebAuthnGroup } diff --git a/spec/api.json b/spec/api.json index 84cc6e6f938a..f1589876deeb 100755 --- a/spec/api.json +++ b/spec/api.json @@ -897,6 +897,7 @@ }, "required": [ "id", + "type", "expires_at", "issued_at", "request_url", @@ -968,6 +969,7 @@ }, "required": [ "id", + "type", "expires_at", "issued_at", "request_url", @@ -1018,6 +1020,7 @@ }, "required": [ "id", + "type", "expires_at", "issued_at", "request_url", @@ -1823,7 +1826,18 @@ "$ref": "#/components/schemas/uiNodeAttributes" }, "group": { - "$ref": "#/components/schemas/uiNodeGroup" + "description": "Group specifies which group (e.g. password authenticator) this node belongs to.", + "enum": [ + "default", + "password", + "oidc", + "profile", + "link", + "totp", + "lookup_secret", + "webauthn" + ], + "type": "string" }, "messages": { "$ref": "#/components/schemas/uiTexts" @@ -1832,7 +1846,15 @@ "$ref": "#/components/schemas/uiNodeMeta" }, "type": { - "$ref": "#/components/schemas/uiNodeType" + "description": "The node's type", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ], + "type": "string" } }, "required": [ @@ -1856,7 +1878,15 @@ "type": "string" }, "node_type": { - "$ref": "#/components/schemas/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ], + "type": "string" }, "title": { "$ref": "#/components/schemas/uiText" @@ -1874,8 +1904,8 @@ "uiNodeAttributes": { "discriminator": { "mapping": { - "anchor": "#/components/schemas/uiNodeAnchorAttributes", - "image": "#/components/schemas/uiNodeImageAttributes", + "a": "#/components/schemas/uiNodeAnchorAttributes", + "img": "#/components/schemas/uiNodeImageAttributes", "input": "#/components/schemas/uiNodeInputAttributes", "script": "#/components/schemas/uiNodeScriptAttributes", "text": "#/components/schemas/uiNodeTextAttributes" @@ -1901,9 +1931,6 @@ ], "title": "Attributes represents a list of attributes (e.g. `href=\"foo\"` for links)." }, - "uiNodeGroup": { - "type": "string" - }, "uiNodeImageAttributes": { "properties": { "height": { @@ -1916,7 +1943,15 @@ "type": "string" }, "node_type": { - "$ref": "#/components/schemas/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ], + "type": "string" }, "src": { "description": "The image's source URL.\n\nformat: uri", @@ -1956,7 +1991,15 @@ "type": "string" }, "node_type": { - "$ref": "#/components/schemas/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ], + "type": "string" }, "onclick": { "description": "OnClick may contain javascript which should be executed on click. This is primarily\nused for WebAuthn.", @@ -2015,7 +2058,15 @@ "type": "string" }, "node_type": { - "$ref": "#/components/schemas/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ], + "type": "string" }, "nonce": { "description": "Nonce for CSP\n\nA nonce you may want to use to improve your Content Security Policy.\nYou do not have to use this value but if you want to improve your CSP\npolicies you may use it. You can also choose to use your own nonce value!", @@ -2055,7 +2106,15 @@ "type": "string" }, "node_type": { - "$ref": "#/components/schemas/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ], + "type": "string" }, "text": { "$ref": "#/components/schemas/uiText" @@ -2069,9 +2128,6 @@ "title": "TextAttributes represents the attributes of a text node.", "type": "object" }, - "uiNodeType": { - "type": "string" - }, "uiNodes": { "items": { "$ref": "#/components/schemas/uiNode" diff --git a/spec/swagger.json b/spec/swagger.json index 712814b064a3..559aa3492daf 100755 --- a/spec/swagger.json +++ b/spec/swagger.json @@ -3183,6 +3183,7 @@ "title": "A Recovery Flow", "required": [ "id", + "type", "expires_at", "issued_at", "request_url", @@ -3252,6 +3253,7 @@ "type": "object", "required": [ "id", + "type", "expires_at", "issued_at", "request_url", @@ -3296,6 +3298,7 @@ "title": "Flow represents a Settings Flow", "required": [ "id", + "type", "expires_at", "issued_at", "request_url", @@ -4031,7 +4034,18 @@ "$ref": "#/definitions/uiNodeAttributes" }, "group": { - "$ref": "#/definitions/uiNodeGroup" + "description": "Group specifies which group (e.g. password authenticator) this node belongs to.", + "type": "string", + "enum": [ + "default", + "password", + "oidc", + "profile", + "link", + "totp", + "lookup_secret", + "webauthn" + ] }, "messages": { "$ref": "#/definitions/uiTexts" @@ -4040,7 +4054,15 @@ "$ref": "#/definitions/uiNodeMeta" }, "type": { - "$ref": "#/definitions/uiNodeType" + "description": "The node's type", + "type": "string", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ] } } }, @@ -4063,7 +4085,15 @@ "type": "string" }, "node_type": { - "$ref": "#/definitions/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "type": "string", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ] }, "title": { "$ref": "#/definitions/uiText" @@ -4074,9 +4104,6 @@ "type": "object", "title": "Attributes represents a list of attributes (e.g. `href=\"foo\"` for links)." }, - "uiNodeGroup": { - "type": "string" - }, "uiNodeImageAttributes": { "type": "object", "title": "ImageAttributes represents the attributes of an image node.", @@ -4098,7 +4125,15 @@ "type": "string" }, "node_type": { - "$ref": "#/definitions/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "type": "string", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ] }, "src": { "description": "The image's source URL.\n\nformat: uri", @@ -4136,7 +4171,15 @@ "type": "string" }, "node_type": { - "$ref": "#/definitions/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "type": "string", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ] }, "onclick": { "description": "OnClick may contain javascript which should be executed on click. This is primarily\nused for WebAuthn.", @@ -4201,7 +4244,15 @@ "type": "string" }, "node_type": { - "$ref": "#/definitions/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "type": "string", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ] }, "nonce": { "description": "Nonce for CSP\n\nA nonce you may want to use to improve your Content Security Policy.\nYou do not have to use this value but if you want to improve your CSP\npolicies you may use it. You can also choose to use your own nonce value!", @@ -4235,16 +4286,21 @@ "type": "string" }, "node_type": { - "$ref": "#/definitions/uiNodeType" + "description": "NodeType represents this node's types. It is a mirror of `node.type` and\nis primarily used to allow compatibility with OpenAPI 3.0.", + "type": "string", + "enum": [ + "text", + "input", + "img", + "a", + "script" + ] }, "text": { "$ref": "#/definitions/uiText" } } }, - "uiNodeType": { - "type": "string" - }, "uiNodes": { "type": "array", "items": { diff --git a/ui/container/container.go b/ui/container/container.go index 6d9c0a3b3f40..c64682ac15a4 100644 --- a/ui/container/container.go +++ b/ui/container/container.go @@ -68,7 +68,7 @@ func New(action string) *Container { // NewFromHTTPRequest creates a new Container and populates fields by parsing the HTTP Request body. // A jsonSchemaRef needs to be added to allow HTTP Form Post Body parsing. -func NewFromHTTPRequest(r *http.Request, group node.Group, action string, compiler decoderx.HTTPDecoderOption) (*Container, error) { +func NewFromHTTPRequest(r *http.Request, group node.UiNodeGroup, action string, compiler decoderx.HTTPDecoderOption) (*Container, error) { c := New(action) raw := json.RawMessage(`{}`) if err := decoder.Decode(r, &raw, compiler); err != nil { @@ -82,7 +82,7 @@ func NewFromHTTPRequest(r *http.Request, group node.Group, action string, compil } // NewFromJSON creates a UI Container based on the provided JSON struct. -func NewFromJSON(action string, group node.Group, raw json.RawMessage, prefix string) *Container { +func NewFromJSON(action string, group node.UiNodeGroup, raw json.RawMessage, prefix string) *Container { c := New(action) c.UpdateNodeValuesFromJSON(raw, prefix, group) return c @@ -90,7 +90,7 @@ func NewFromJSON(action string, group node.Group, raw json.RawMessage, prefix st // NewFromJSONSchema creates a new Container and populates the fields // using the provided JSON Schema. -func NewFromJSONSchema(ctx context.Context, action string, group node.Group, jsonSchemaRef, prefix string, compiler *jsonschema.Compiler) (*Container, error) { +func NewFromJSONSchema(ctx context.Context, action string, group node.UiNodeGroup, jsonSchemaRef, prefix string, compiler *jsonschema.Compiler) (*Container, error) { c := New(action) nodes, err := NodesFromJSONSchema(ctx, group, jsonSchemaRef, prefix, compiler) if err != nil { @@ -101,7 +101,7 @@ func NewFromJSONSchema(ctx context.Context, action string, group node.Group, jso return c, nil } -func NodesFromJSONSchema(ctx context.Context, group node.Group, jsonSchemaRef, prefix string, compiler *jsonschema.Compiler) (node.Nodes, error) { +func NodesFromJSONSchema(ctx context.Context, group node.UiNodeGroup, jsonSchemaRef, prefix string, compiler *jsonschema.Compiler) (node.Nodes, error) { paths, err := jsonschemax.ListPaths(ctx, jsonSchemaRef, compiler) if err != nil { return nil, err @@ -150,7 +150,7 @@ func (c *Container) Reset(exclude ...string) { // formUI Container, the error is returned. // // This method DOES NOT touch the values of the node values/names, only its errors. -func (c *Container) ParseError(group node.Group, err error) error { +func (c *Container) ParseError(group node.UiNodeGroup, err error) error { if e := richError(nil); errors.As(err, &e) { if e.StatusCode() == http.StatusBadRequest { c.AddMessage(group, text.NewValidationErrorGeneric(e.Reason())) @@ -195,7 +195,7 @@ func (c *Container) ParseError(group node.Group, err error) error { } // UpdateNodeValuesFromJSON sets the container's fields to the provided values. -func (c *Container) UpdateNodeValuesFromJSON(raw json.RawMessage, prefix string, group node.Group) { +func (c *Container) UpdateNodeValuesFromJSON(raw json.RawMessage, prefix string, group node.UiNodeGroup) { for k, v := range jsonx.Flatten(raw) { k = addPrefix(k, prefix, ".") @@ -236,7 +236,7 @@ func (c *Container) SetValue(id string, n *node.Node) { // AddMessage adds the provided error, and if a non-empty names list is set, // adds the error on the corresponding field. -func (c *Container) AddMessage(group node.Group, err *text.Message, setForFields ...string) { +func (c *Container) AddMessage(group node.UiNodeGroup, err *text.Message, setForFields ...string) { if len(stringslice.TrimSpaceEmptyFilter(setForFields)) == 0 { c.Messages = append(c.Messages, *err) return diff --git a/ui/container/types.go b/ui/container/types.go index 170635bda3da..593ba66560d9 100644 --- a/ui/container/types.go +++ b/ui/container/types.go @@ -9,7 +9,7 @@ type ErrorParser interface { // ParseError type asserts the given error and sets the forms's errors or a // field's errors and if the error is not something to be handled by the // formUI Container itself, the error is returned for further propagation (e.g. showing a 502 status code). - ParseError(group node.Group, err error) error + ParseError(group node.UiNodeGroup, err error) error } type NodeSetter interface { diff --git a/ui/node/attributes.go b/ui/node/attributes.go index 0d7d7ba36cab..f59135f50f51 100644 --- a/ui/node/attributes.go +++ b/ui/node/attributes.go @@ -36,7 +36,7 @@ type Attributes interface { GetValue() interface{} // swagger:ignore - GetNodeType() Type + GetNodeType() UiNodeType } // InputAttributes represents the attributes of an input node @@ -78,7 +78,7 @@ type InputAttributes struct { // is primarily used to allow compatibility with OpenAPI 3.0. // // required: true - NodeType Type `json:"node_type"` + NodeType UiNodeType `json:"node_type"` } // ImageAttributes represents the attributes of an image node. @@ -110,7 +110,7 @@ type ImageAttributes struct { // is primarily used to allow compatibility with OpenAPI 3.0. // // required: true - NodeType Type `json:"node_type"` + NodeType UiNodeType `json:"node_type"` } // AnchorAttributes represents the attributes of an anchor node. @@ -137,7 +137,7 @@ type AnchorAttributes struct { // is primarily used to allow compatibility with OpenAPI 3.0. // // required: true - NodeType Type `json:"node_type"` + NodeType UiNodeType `json:"node_type"` } // TextAttributes represents the attributes of a text node. @@ -159,7 +159,7 @@ type TextAttributes struct { // is primarily used to allow compatibility with OpenAPI 3.0. // // required: true - NodeType Type `json:"node_type"` + NodeType UiNodeType `json:"node_type"` } // ScriptAttributes represent script nodes which load javascript. @@ -214,7 +214,7 @@ type ScriptAttributes struct { // is primarily used to allow compatibility with OpenAPI 3.0. // // required: true - NodeType Type `json:"node_type"` + NodeType UiNodeType `json:"node_type"` } var ( @@ -301,22 +301,22 @@ func (a *TextAttributes) Reset() { func (a *ScriptAttributes) Reset() { } -func (a *InputAttributes) GetNodeType() Type { +func (a *InputAttributes) GetNodeType() UiNodeType { return a.NodeType } -func (a *ImageAttributes) GetNodeType() Type { +func (a *ImageAttributes) GetNodeType() UiNodeType { return a.NodeType } -func (a *AnchorAttributes) GetNodeType() Type { +func (a *AnchorAttributes) GetNodeType() UiNodeType { return a.NodeType } -func (a *TextAttributes) GetNodeType() Type { +func (a *TextAttributes) GetNodeType() UiNodeType { return a.NodeType } -func (a *ScriptAttributes) GetNodeType() Type { +func (a *ScriptAttributes) GetNodeType() UiNodeType { return a.NodeType } diff --git a/ui/node/attributes_input.go b/ui/node/attributes_input.go index b57c2c6c1175..bfe3e78ecb7d 100644 --- a/ui/node/attributes_input.go +++ b/ui/node/attributes_input.go @@ -80,7 +80,7 @@ func applyScriptAttributes(opts ScriptAttributesModifiers, attributes *ScriptAtt return attributes } -func NewInputFieldFromJSON(name string, value interface{}, group Group, opts ...InputAttributesModifier) *Node { +func NewInputFieldFromJSON(name string, value interface{}, group UiNodeGroup, opts ...InputAttributesModifier) *Node { return &Node{ Type: Input, Group: group, @@ -89,7 +89,7 @@ func NewInputFieldFromJSON(name string, value interface{}, group Group, opts ... } } -func NewInputField(name string, value interface{}, group Group, inputType InputAttributeType, opts ...InputAttributesModifier) *Node { +func NewInputField(name string, value interface{}, group UiNodeGroup, inputType InputAttributeType, opts ...InputAttributesModifier) *Node { return &Node{ Type: Input, Group: group, @@ -98,7 +98,7 @@ func NewInputField(name string, value interface{}, group Group, inputType InputA } } -func NewImageField(id string, src string, group Group, opts ...ImageAttributesModifier) *Node { +func NewImageField(id string, src string, group UiNodeGroup, opts ...ImageAttributesModifier) *Node { return &Node{ Type: Image, Group: group, @@ -107,7 +107,7 @@ func NewImageField(id string, src string, group Group, opts ...ImageAttributesMo } } -func NewTextField(id string, text *text.Message, group Group) *Node { +func NewTextField(id string, text *text.Message, group UiNodeGroup) *Node { return &Node{ Type: Text, Group: group, @@ -116,7 +116,7 @@ func NewTextField(id string, text *text.Message, group Group) *Node { } } -func NewAnchorField(id string, href string, group Group, title *text.Message) *Node { +func NewAnchorField(id string, href string, group UiNodeGroup, title *text.Message) *Node { return &Node{ Type: Anchor, Group: group, @@ -125,7 +125,7 @@ func NewAnchorField(id string, href string, group Group, title *text.Message) *N } } -func NewScriptField(name string, src string, group Group, integrity string, opts ...ScriptAttributesModifier) *Node { +func NewScriptField(name string, src string, group UiNodeGroup, integrity string, opts ...ScriptAttributesModifier) *Node { return &Node{ Type: Script, Group: group, @@ -143,7 +143,7 @@ func NewScriptField(name string, src string, group Group, integrity string, opts } } -func NewInputFieldFromSchema(name string, group Group, p jsonschemax.Path, opts ...InputAttributesModifier) *Node { +func NewInputFieldFromSchema(name string, group UiNodeGroup, p jsonschemax.Path, opts ...InputAttributesModifier) *Node { attr := &InputAttributes{ Name: name, Type: toFormType(p.Name, p.Type), diff --git a/ui/node/attributes_test.go b/ui/node/attributes_test.go index f4c3624c362a..a158cdccabc7 100644 --- a/ui/node/attributes_test.go +++ b/ui/node/attributes_test.go @@ -41,7 +41,7 @@ func TestNodeEncode(t *testing.T) { } func TestNodeDecode(t *testing.T) { - for _, kind := range []Type{ + for _, kind := range []UiNodeType{ Text, Input, Image, diff --git a/ui/node/node.go b/ui/node/node.go index b0cf0fdcae40..edc38c6c2488 100644 --- a/ui/node/node.go +++ b/ui/node/node.go @@ -17,34 +17,39 @@ import ( "github.com/ory/x/stringslice" ) -// swagger:model uiNodeType -type Type string +// swagger:enum UiNodeType +type UiNodeType string -// swagger:model uiNodeGroup -type Group string +const ( + Text UiNodeType = "text" + Input UiNodeType = "input" + Image UiNodeType = "img" + Anchor UiNodeType = "a" + Script UiNodeType = "script" +) -func (g Group) String() string { - return string(g) +func (t UiNodeType) String() string { + return string(t) } +// swagger:enum UiNodeGroup +type UiNodeGroup string + const ( - DefaultGroup Group = "default" - PasswordGroup Group = "password" - OpenIDConnectGroup Group = "oidc" - ProfileGroup Group = "profile" - RecoveryLinkGroup Group = "link" - VerificationLinkGroup Group = "link" - TOTPGroup Group = "totp" - LookupGroup Group = "lookup_secret" - WebAuthnGroup Group = "webauthn" - - Text Type = "text" - Input Type = "input" - Image Type = "img" - Anchor Type = "a" - Script Type = "script" + DefaultGroup UiNodeGroup = "default" + PasswordGroup UiNodeGroup = "password" + OpenIDConnectGroup UiNodeGroup = "oidc" + ProfileGroup UiNodeGroup = "profile" + LinkGroup UiNodeGroup = "link" + TOTPGroup UiNodeGroup = "totp" + LookupGroup UiNodeGroup = "lookup_secret" + WebAuthnGroup UiNodeGroup = "webauthn" ) +func (g UiNodeGroup) String() string { + return string(g) +} + // swagger:model uiNodes type Nodes []*Node @@ -57,15 +62,13 @@ type Nodes []*Node type Node struct { // The node's type // - // Can be one of: text, input, img, a - // // required: true - Type Type `json:"type" faker:"-"` + Type UiNodeType `json:"type" faker:"-"` // Group specifies which group (e.g. password authenticator) this node belongs to. // // required: true - Group Group `json:"group"` + Group UiNodeGroup `json:"group"` // The node's attributes. // @@ -106,8 +109,8 @@ type Meta struct { // Used for en/decoding the Attributes field. type jsonRawNode struct { - Type Type `json:"type"` - Group Group `json:"group"` + Type UiNodeType `json:"type"` + Group UiNodeGroup `json:"group"` Attributes Attributes `json:"attributes"` Messages text.Messages `json:"messages"` Meta *Meta `json:"meta"` @@ -190,7 +193,7 @@ type sortOptions struct { type SortOption func(*sortOptions) -func SortByGroups(orderByGroups []Group) func(*sortOptions) { +func SortByGroups(orderByGroups []UiNodeGroup) func(*sortOptions) { return func(options *sortOptions) { options.orderByGroups = make([]string, len(orderByGroups)) for k := range orderByGroups { @@ -347,7 +350,7 @@ func (n *Nodes) Append(node *Node) { func (n *Node) UnmarshalJSON(data []byte) error { var attr Attributes - switch t := gjson.GetBytes(data, "type").String(); Type(t) { + switch t := gjson.GetBytes(data, "type").String(); UiNodeType(t) { case Text: attr = &TextAttributes{ NodeType: Text, @@ -388,7 +391,7 @@ func (n *Node) UnmarshalJSON(data []byte) error { } func (n *Node) MarshalJSON() ([]byte, error) { - var t Type + var t UiNodeType if n.Attributes != nil { switch attr := n.Attributes.(type) { case *TextAttributes: diff --git a/ui/node/node_test.go b/ui/node/node_test.go index 493825943df1..2a26eced911b 100644 --- a/ui/node/node_test.go +++ b/ui/node/node_test.go @@ -49,19 +49,19 @@ func TestNodesSort(t *testing.T) { "1.json": { node.SortUseOrder([]string{"password_identifier"}), node.SortUpdateOrder(node.PasswordLoginOrder), - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.DefaultGroup, node.ProfileGroup, node.OpenIDConnectGroup, node.PasswordGroup, - node.RecoveryLinkGroup, - node.VerificationLinkGroup, + node.LinkGroup, + node.LinkGroup, }), }, "2.json": { node.SortBySchema(filepath.Join("fixtures/sort/schema", "2.json")), node.SortUpdateOrder(node.PasswordLoginOrder), - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.DefaultGroup, node.OpenIDConnectGroup, node.PasswordGroup, @@ -69,7 +69,7 @@ func TestNodesSort(t *testing.T) { }, "3.json": { node.SortBySchema(filepath.Join("fixtures/sort/schema", "3.json")), - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.DefaultGroup, node.OpenIDConnectGroup, node.PasswordGroup, @@ -77,7 +77,7 @@ func TestNodesSort(t *testing.T) { }, "4.json": { node.SortBySchema(filepath.Join("fixtures/sort/schema", "4.json")), - node.SortByGroups([]node.Group{ + node.SortByGroups([]node.UiNodeGroup{ node.DefaultGroup, node.ProfileGroup, node.PasswordGroup,