diff --git a/packages/core/forms/src/forms/OIDCForm.vue b/packages/core/forms/src/forms/OIDCForm.vue index d20de44b8a..72b7bee7df 100644 --- a/packages/core/forms/src/forms/OIDCForm.vue +++ b/packages/core/forms/src/forms/OIDCForm.vue @@ -354,4 +354,19 @@ export default { .link-wrapper { margin-bottom: 8px; } + +:deep(.k-tabs ul[role="tablist"]) { + margin-bottom: 32px; +} + +:deep(.jwk-array-input-wrapper) { + display: flex; + justify-content: space-between; + margin-bottom: 12px; + width: 400px; + + input.form-control { + width: 300px; + } +} diff --git a/packages/core/forms/src/forms/schemas/OIDCAdvanced.js b/packages/core/forms/src/forms/schemas/OIDCAdvanced.js index 6a6bf1eda0..d9f17d2219 100644 --- a/packages/core/forms/src/forms/schemas/OIDCAdvanced.js +++ b/packages/core/forms/src/forms/schemas/OIDCAdvanced.js @@ -1,12 +1,183 @@ export default { fields: [ { - help: 'The input must be in JSON format.', - type: 'input', - valueArrayType: 'record', - inputType: 'text', - default: undefined, - valueType: 'array', + type: 'array', + showRemoveButton: false, + newElementButtonLabelClasses: 'kong-form-new-element-button-label', + itemContainerComponent: 'FieldArrayCardContainer', + fieldClasses: 'array-card-container-wrapper', + + newElementButtonLabel: '+ Add Client JWK', + items: { + type: 'object', + schema: { + fields: [ + { + model: 'kid', + label: 'kid', + type: 'input', + inputType: 'string', + }, + { + model: 'issuer', + label: 'issuer', + type: 'input', + inputType: 'string', + }, + { + model: 'kty', + label: 'kty', + type: 'input', + inputType: 'string', + }, + { + model: 'use', + label: 'use', + type: 'input', + inputType: 'string', + }, + { + model: 'key_ops', + label: 'key_ops', + type: 'array', + fieldItemsClasses: 'jwk-array-input-wrapper', + showRemoveButton: true, + removeElementButtonLabel: 'Remove', + items: { + type: 'input', + inputType: 'string', + }, + }, + { + model: 'alg', + label: 'alg', + type: 'input', + inputType: 'string', + }, + { + model: 'x5u', + label: 'x5u', + type: 'input', + inputType: 'string', + }, + { + model: 'x5c', + label: 'x5c', + type: 'array', + fieldItemsClasses: 'jwk-array-input-wrapper', + showRemoveButton: true, + removeElementButtonLabel: 'Remove', + items: { + type: 'input', + inputType: 'string', + }, + }, + { + model: 'x5t', + label: 'x5t', + type: 'input', + inputType: 'string', + }, + { + model: 'x5t#S256', + label: 'x5t#S256', + type: 'input', + inputType: 'string', + }, + { + model: 'k', + label: 'k', + type: 'input', + inputType: 'string', + }, + { + model: 'x', + label: 'x', + type: 'input', + inputType: 'string', + }, + { + model: 'y', + label: 'y', + type: 'input', + inputType: 'string', + }, + { + model: 'crv', + label: 'crv', + type: 'input', + inputType: 'string', + }, + { + model: 'n', + label: 'n', + type: 'input', + inputType: 'string', + }, + { + model: 'e', + label: 'e', + type: 'input', + inputType: 'string', + }, + { + model: 'd', + label: 'd', + type: 'input', + inputType: 'string', + }, + { + model: 'p', + label: 'p', + type: 'input', + inputType: 'string', + }, + { + model: 'q', + label: 'q', + type: 'input', + inputType: 'string', + }, + { + model: 'dp', + label: 'dp', + type: 'input', + inputType: 'string', + }, + { + model: 'dq', + label: 'dq', + type: 'input', + inputType: 'string', + }, + { + model: 'qi', + label: 'qi', + type: 'input', + inputType: 'string', + }, + { + model: 'oth', + label: 'oth', + type: 'input', + inputType: 'string', + }, + { + model: 'r', + label: 'r', + type: 'input', + inputType: 'string', + }, + { + model: 't', + label: 't', + type: 'input', + inputType: 'string', + }, + ], + }, + }, + model: 'config-client_jwk', label: 'Config.Client Jwk', order: 0, @@ -14,12 +185,30 @@ export default { link: 'https://docs.konghq.com/hub/kong-inc/openid-connect/#jwk-record', }, { - help: 'The input must be in JSON format.', - type: 'input', - valueArrayType: 'record', - inputType: 'text', - default: undefined, - valueType: 'array', + type: 'array', + showRemoveButton: false, + newElementButtonLabelClasses: 'kong-form-new-element-button-label', + itemContainerComponent: 'FieldArrayCardContainer', + fieldClasses: 'array-card-container-wrapper', + + newElementButtonLabel: '+ Add Cluster Node', + items: { + type: 'object', + schema: { + fields: [{ + label: 'IP', + model: 'ip', + type: 'input', + inputType: 'text', + }, { + label: 'Port', + model: 'port', + type: 'input', + inputType: 'number', + }], + }, + }, + model: 'config-session_redis_cluster_nodes', label: 'Config.Session Redis Cluster Nodes', order: 0, diff --git a/packages/core/forms/src/generator/fields/advanced/FieldArray.vue b/packages/core/forms/src/generator/fields/advanced/FieldArray.vue index 6c1d940238..ccacfb3b8e 100644 --- a/packages/core/forms/src/generator/fields/advanced/FieldArray.vue +++ b/packages/core/forms/src/generator/fields/advanced/FieldArray.vue @@ -100,12 +100,25 @@ import FieldObjectAdvanced from './FieldObjectAdvanced.vue' import FieldAutoSuggest from './FieldAutoSuggest.vue' import FieldArrayCardContainer from './FieldArrayCardContainer.vue' import FieldRadio from './FieldRadio.vue' +import FieldInput from '../core/fieldInput.vue' import FieldSelect from '../core/fieldSelect.vue' import FieldTextArea from '../core/fieldTextArea.vue' export default { name: 'FieldArray', - components: { FieldArrayItem, FieldArrayMultiItem, FieldSelect, FieldMetric, FieldObject, FieldObjectAdvanced, FieldAutoSuggest, FieldRadio, FieldArrayCardContainer, FieldTextArea }, + components: { + FieldArrayItem, + FieldArrayMultiItem, + FieldSelect, + FieldMetric, + FieldObject, + FieldObjectAdvanced, + FieldAutoSuggest, + FieldRadio, + FieldArrayCardContainer, + FieldTextArea, + FieldInput, + }, mixins: [abstractField], props: { newElementButtonLabel: { @@ -125,7 +138,7 @@ export default { if (schema) { copy = JSON.parse(JSON.stringify(schema)) - copy.schema.fields.map(field => { + copy.schema?.fields?.map?.(field => { field.id = `${field.id || field.model}-${index}` return field }) @@ -170,3 +183,14 @@ export default { }, } + + diff --git a/packages/entities/entities-plugins/src/composables/plugin-schemas/SAML.ts b/packages/entities/entities-plugins/src/composables/plugin-schemas/SAML.ts new file mode 100644 index 0000000000..eb8b65a68b --- /dev/null +++ b/packages/entities/entities-plugins/src/composables/plugin-schemas/SAML.ts @@ -0,0 +1,25 @@ +import type { SAMLSchema } from '../../types/plugins/saml' +import { arrayCardContainerFieldSchema } from './ArrayCardContainerFields' + +export const samlSchema: SAMLSchema = { + 'config-session_redis_cluster_nodes': { + ...arrayCardContainerFieldSchema, + newElementButtonLabel: '+ Add Cluster Node', + items: { + type: 'object', + schema: { + fields: [{ + label: 'IP', + model: 'ip', + type: 'input', + inputType: 'text', + }, { + label: 'Port', + model: 'port', + type: 'input', + inputType: 'number', + }], + }, + }, + }, +} diff --git a/packages/entities/entities-plugins/src/composables/useSchemas.ts b/packages/entities/entities-plugins/src/composables/useSchemas.ts index 2b4430de3c..45c8f4d437 100644 --- a/packages/entities/entities-plugins/src/composables/useSchemas.ts +++ b/packages/entities/entities-plugins/src/composables/useSchemas.ts @@ -13,6 +13,7 @@ import { requestTransformerAdvancedSchema } from './plugin-schemas/RequestTransf import { routeByHeaderSchema } from './plugin-schemas/RouteByHeader' import { graphqlRateLimitingAdvancedSchema } from './plugin-schemas/GraphQLRateLimitingAdvanced' import { statsDSchema } from './plugin-schemas/StatsD' +import { samlSchema } from './plugin-schemas/SAML' import { ArrayStringFieldSchema } from './plugin-schemas/ArrayStringFieldSchema' import RequestValidatorSchema from './plugin-schemas/RequestValidator' import ZipkinSchema from './plugin-schemas/Zipkin' @@ -110,6 +111,10 @@ export const useSchemas = (entityId?: string) => { zipkin: { ...ZipkinSchema, }, + + saml: { + ...samlSchema, + }, } /** diff --git a/packages/entities/entities-plugins/src/types/plugin-form.ts b/packages/entities/entities-plugins/src/types/plugin-form.ts index 82dad865dc..b4524ad296 100644 --- a/packages/entities/entities-plugins/src/types/plugin-form.ts +++ b/packages/entities/entities-plugins/src/types/plugin-form.ts @@ -12,6 +12,7 @@ import type { UpstreamTlsSchema } from './plugins/upstream-tls' import type { RateLimitingSchema } from './plugins/rate-limiting' import type { RouteByHeaderSchema } from './plugins/route-by-header' import type { GraphQLRateLimitingAdvancedSchema } from './plugins/graphql-rate-limiting-advanced' +import type { SAMLSchema } from './plugins/saml' export interface BasePluginSelectConfig { /** A function that returns the route for creating a plugin */ @@ -197,4 +198,5 @@ export interface CustomSchemas { 'request-transformer-advanced': CommonSchemaFields & Record 'request-validator': CommonSchemaFields & Record zipkin: CommonSchemaFields & Record + saml: SAMLSchema } diff --git a/packages/entities/entities-plugins/src/types/plugins/saml.ts b/packages/entities/entities-plugins/src/types/plugins/saml.ts new file mode 100644 index 0000000000..0c8b2569ba --- /dev/null +++ b/packages/entities/entities-plugins/src/types/plugins/saml.ts @@ -0,0 +1,14 @@ +import type { ItemsSchema, CommonSchemaFields } from '../../types/plugins/shared' + +export interface SAMLSchema extends CommonSchemaFields { + 'config-session_redis_cluster_nodes': { + type: string + showRemoveButton: boolean + newElementButtonLabelClasses: string + itemContainerComponent: string + fieldClasses: string + + newElementButtonLabel: string + items: ItemsSchema + } +}