diff --git a/packages/core/forms/src/forms/ACMEForm.vue b/packages/core/forms/src/forms/ACMEForm.vue index ac1a52961e..154699d009 100644 --- a/packages/core/forms/src/forms/ACMEForm.vue +++ b/packages/core/forms/src/forms/ACMEForm.vue @@ -390,4 +390,8 @@ const onChangeStorage = (payload: string, schema: string): void => { .description { margin-bottom: 12px; } + +:deep(.k-tabs ul[role="tablist"]) { + margin-bottom: 32px; +} diff --git a/packages/core/forms/src/forms/ExitTransformer.vue b/packages/core/forms/src/forms/ExitTransformer.vue index 792215d09f..54fe338d79 100644 --- a/packages/core/forms/src/forms/ExitTransformer.vue +++ b/packages/core/forms/src/forms/ExitTransformer.vue @@ -60,8 +60,8 @@ const finalSchema = computed((): Object => { f.type = 'array' f.valueArrayType = 'array' f.itemContainerComponent = 'FieldArrayItem' - f.fieldClasses = 'w-100' - f.fieldItemsClasses = 'w-100 mt-2 mb-2' + f.fieldClasses = 'exit-transformer-array-item-container' + f.fieldItemsClasses = 'exit-transformer-array-item' f.inputAttributes = { ...f.inputAttributes, type: 'textarea' } } return f @@ -69,3 +69,13 @@ const finalSchema = computed((): Object => { return final }) + + diff --git a/packages/core/forms/src/forms/OIDCForm.vue b/packages/core/forms/src/forms/OIDCForm.vue index 5ef5b7fe20..a2477cb4a7 100644 --- a/packages/core/forms/src/forms/OIDCForm.vue +++ b/packages/core/forms/src/forms/OIDCForm.vue @@ -322,6 +322,10 @@ export default { margin-top: 24px; } + .k-input-switch .k-label { + margin-top: 0; + } + .auth-method-container { display: flex; flex-wrap: wrap; @@ -383,4 +387,17 @@ export default { width: 300px; } } + +:deep(.auth-array-item-container) { + width: 100%; +} + +:deep(.auth-array-item) { + display: flex; + margin-top: 8px; +} + +:deep(.k-button.auth-array-item-new) { + margin-top: 24px; +} diff --git a/packages/core/forms/src/forms/PostFunction.vue b/packages/core/forms/src/forms/PostFunction.vue index 916a57f90c..4ab62628f2 100644 --- a/packages/core/forms/src/forms/PostFunction.vue +++ b/packages/core/forms/src/forms/PostFunction.vue @@ -60,8 +60,8 @@ const finalSchema = computed((): Object => { f.type = 'array' f.valueArrayType = 'array' f.itemContainerComponent = 'FieldArrayItem' - f.fieldClasses = 'w-100' - f.fieldItemsClasses = 'w-100 mt-2 mb-2' + f.fieldClasses = 'post-function-array-item-container' + f.fieldItemsClasses = 'post-function-array-item' f.inputAttributes = { ...f.inputAttributes, type: 'textarea' } } return f @@ -69,3 +69,13 @@ const finalSchema = computed((): Object => { return final }) + + diff --git a/packages/core/forms/src/forms/schemas/OIDCAuth.js b/packages/core/forms/src/forms/schemas/OIDCAuth.js index 9bdeeb9198..921c283b24 100644 --- a/packages/core/forms/src/forms/schemas/OIDCAuth.js +++ b/packages/core/forms/src/forms/schemas/OIDCAuth.js @@ -37,11 +37,11 @@ export default { valueType: 'string', valueArrayType: 'array', itemContainerComponent: 'FieldArrayItem', - fieldClasses: 'w-100', - fieldItemsClasses: 'd-flex mt-2 w-90', + fieldClasses: 'auth-array-item-container', + fieldItemsClasses: 'auth-array-item', inputAttributes: { class: 'form-control', style: { minWidth: '200px' } }, validator: 'array', - styleClasses: 'w-100', + newElementButtonLabelClasses: 'auth-array-item-new', newElementButtonLabel: '+ Add', }, { inputType: 'text', @@ -51,11 +51,11 @@ export default { valueType: 'string', valueArrayType: 'array', itemContainerComponent: 'FieldArrayItem', - fieldClasses: 'w-100', - fieldItemsClasses: 'd-flex mt-2 w-90', + fieldClasses: 'auth-array-item-container', + fieldItemsClasses: 'auth-array-item', inputAttributes: { class: 'form-control', style: { minWidth: '200px' } }, validator: 'array', - styleClasses: 'w-100', + newElementButtonLabelClasses: 'auth-array-item-new', newElementButtonLabel: '+ Add', }, { inputType: 'text', @@ -65,11 +65,11 @@ export default { valueType: 'string', valueArrayType: 'array', itemContainerComponent: 'FieldArrayItem', - fieldClasses: 'w-100', - fieldItemsClasses: 'd-flex mt-2 w-90', + fieldClasses: 'auth-array-item-container', + fieldItemsClasses: 'auth-array-item', inputAttributes: { class: 'form-control', style: { minWidth: '200px' } }, validator: 'array', - styleClasses: 'w-100', + newElementButtonLabelClasses: 'auth-array-item-new', newElementButtonLabel: '+ Add', }], } diff --git a/packages/core/forms/src/generator/FormGenerator.vue b/packages/core/forms/src/generator/FormGenerator.vue index 14f7e969db..e55b5b0647 100644 --- a/packages/core/forms/src/generator/FormGenerator.vue +++ b/packages/core/forms/src/generator/FormGenerator.vue @@ -374,7 +374,6 @@ export default { } } .label { - background-color: $kui-color-background-neutral-weakest; box-shadow: none; &:before, &:after { diff --git a/packages/core/forms/src/generator/fields/advanced/FieldMetric.vue b/packages/core/forms/src/generator/fields/advanced/FieldMetric.vue index 8e36d79a23..34760e5b3d 100644 --- a/packages/core/forms/src/generator/fields/advanced/FieldMetric.vue +++ b/packages/core/forms/src/generator/fields/advanced/FieldMetric.vue @@ -73,7 +73,7 @@ export default { cursor: pointer; display: flex; height: 45px; - padding: 0 16px 0 5px; + padding: 0 16px; position: relative; transition: transform .2s cubic-bezier(0.41,0.35,1,0.28) 0s, background-color .2s ease-in; width: 100%; diff --git a/packages/core/forms/src/generator/fields/optional/fieldSwitch.vue b/packages/core/forms/src/generator/fields/optional/fieldSwitch.vue index 381db418b7..eb790e00a6 100644 --- a/packages/core/forms/src/generator/fields/optional/fieldSwitch.vue +++ b/packages/core/forms/src/generator/fields/optional/fieldSwitch.vue @@ -61,6 +61,7 @@ $field-switch-height: 30px; height: inherit; position: relative; text-transform: uppercase; + width: 100%; } .label:before, .label:after { @@ -87,7 +88,6 @@ $field-switch-height: 30px; text-shadow: 0 1px rgba(0, 0, 0, 0.2); } input:checked ~ .label { - background: #e1b42b; box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.15), inset 0 0 3px rgba(0, 0, 0, 0.2); } input:checked ~ .label:before { diff --git a/packages/entities/entities-plugins/docs/plugin-form.md b/packages/entities/entities-plugins/docs/plugin-form.md index ecde1cc92b..547504b98a 100644 --- a/packages/entities/entities-plugins/docs/plugin-form.md +++ b/packages/entities/entities-plugins/docs/plugin-form.md @@ -119,6 +119,14 @@ Manually toggle visibility of plugin scope selection control. A boolean indicating whether the form is being used to create a plugin or an auth credential. +#### `developer` + +- type: `Boolean` +- required: `false` +- default: `false` + +*Specific to Kong Manager*. A boolean indicating whether the form is being used to create or update a plugin for a portal developer. + #### `isWizardStep` - type: `Boolean` diff --git a/packages/entities/entities-plugins/src/components/PluginEntityForm.vue b/packages/entities/entities-plugins/src/components/PluginEntityForm.vue index c25b2b4e32..b347a22a24 100644 --- a/packages/entities/entities-plugins/src/components/PluginEntityForm.vue +++ b/packages/entities/entities-plugins/src/components/PluginEntityForm.vue @@ -76,7 +76,6 @@ const props = defineProps({ if (!config || !['konnect', 'kongManager'].includes(config?.app)) return false if (config.app === 'konnect' && !config.controlPlaneId) return false if (config.app === 'kongManager' && typeof config.workspace !== 'string') return false - if (!config.cancelRoute || !config.backRoute) return false return true }, }, @@ -416,6 +415,9 @@ const getModel = (): Record => { // fired whenever the form data is modified const onModelUpdated = (model: Record, schema: string) => { const newData = { [schema]: model } + if (typeof props.schema[schema]?.modelTransformer === 'function') { + newData[schema] = props.schema[schema].modelTransformer(model) + } const newModel = Object.assign({}, formModel, newData) Object.assign(formModel, newModel) @@ -433,8 +435,11 @@ const updateModel = (data: Record, parent?: string) => { let modelKey = parent ? `${parent}-${key}` : key let scheme = props.schema[modelKey] - // If `scheme` is undefined, it is either because the key is not the deepest nested key of the schema object - // or the field name has dashes in it and its schema key was converted to underscores during initiation. + // If `scheme` is undefined, it is because + // 1. the key is not the deepest nested key of the schema object + // 2. or the field name has dashes in it and its schema key was converted to underscores during initiation + // 3. or `parent` is already a schema key and `key` is a nested key of its value object + // For reasons 2 and 3, we need special logic to find the correct schema key if (!scheme) { const underscoredModelKey = parent ? `${parent}-${key.replace(/-/g, '_')}` : key.replace(/-/g, '_') @@ -443,6 +448,12 @@ const updateModel = (data: Record, parent?: string) => { modelKey = underscoredModelKey scheme = props.schema[modelKey] } + + // Here we check if `parent` is a schema key and `key` is a nested key of its value object + if (parent && props.schema[parent]?.keyFromObject === key) { + modelKey = parent + scheme = props.schema[modelKey] + } } const value = data[key] @@ -629,10 +640,14 @@ onBeforeMount(() => { display: none; } - .form-group hr.divider, + .form-group hr.divider { + border-color: $kui-color-border; + opacity: .3; + } + .form-group hr.wide-divider { border-color: $kui-color-border; - opacity: .2; + opacity: .6; } .form-group label { diff --git a/packages/entities/entities-plugins/src/components/PluginForm.cy.ts b/packages/entities/entities-plugins/src/components/PluginForm.cy.ts index 383341eedf..6c78d74bd1 100644 --- a/packages/entities/entities-plugins/src/components/PluginForm.cy.ts +++ b/packages/entities/entities-plugins/src/components/PluginForm.cy.ts @@ -121,11 +121,17 @@ describe('', () => { alias?: string status?: number credential?: boolean + entityType?: string entityId?: string }) => { - const url = params?.credential - ? `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/consumers/${params.entityId}/acls/${params.id}` - : `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/plugins/${params.id}` + let url: string + if (params?.credential) { + url = `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/consumers/${params.entityId}/acls/${params.id}` + } else if (params?.entityType && params?.entityId) { + url = `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/${params.entityType}/${params.entityId}/plugins/${params.id}` + } else { + url = `${baseConfigKM.apiBaseUrl}/${baseConfigKM.workspace}/plugins/${params.id}` + } cy.intercept( { @@ -354,7 +360,13 @@ describe('', () => { it('should show edit form', () => { const config = { ...baseConfigKM, entityId: scopedService.id, entityType: 'services' } interceptKMSchema() - interceptKMOperatePlugin({ method: 'GET', alias: 'getPlugin', id: plugin1.id }) + interceptKMOperatePlugin({ + method: 'GET', + alias: 'getPlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) interceptKMScopedEntity({ entityType: config.entityType }) cy.mount(PluginForm, { @@ -397,9 +409,21 @@ describe('', () => { const config = { ...baseConfigKM, entityId: scopedService.id, entityType: 'services' } interceptKMSchema() interceptKMScopedEntity({ entityType: config.entityType }) - interceptKMOperatePlugin({ method: 'GET', alias: 'getPlugin', id: plugin1.id }) + interceptKMOperatePlugin({ + method: 'GET', + alias: 'getPlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) interceptKMValidatePlugin() - interceptKMOperatePlugin({ method: 'PATCH', alias: 'updatePlugin', id: plugin1.id }) + interceptKMOperatePlugin({ + method: 'PATCH', + alias: 'updatePlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) cy.mount(PluginForm, { global: { components: { VueFormGenerator } }, @@ -454,7 +478,13 @@ describe('', () => { const config = { ...baseConfigKM, entityId: scopedService.id, entityType: 'services' } interceptKMSchema() interceptKMScopedEntity({ entityType: config.entityType }) - interceptKMOperatePlugin({ method: 'GET', alias: 'getPlugin', id: plugin1.id }) + interceptKMOperatePlugin({ + method: 'GET', + alias: 'getPlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) cy.mount(PluginForm, { global: { components: { VueFormGenerator } }, @@ -721,11 +751,17 @@ describe('', () => { alias?: string status?: number credential?: boolean + entityType?: string entityId?: string }) => { - const url = params?.credential - ? `${baseConfigKonnect.apiBaseUrl}/v2/control-planes/${baseConfigKonnect.controlPlaneId}/core-entities/consumers/${params.entityId}/acls/${params.id}` - : `${baseConfigKonnect.apiBaseUrl}/v2/control-planes/${baseConfigKonnect.controlPlaneId}/core-entities/plugins/${params.id}` + let url: string + if (params?.credential) { + url = `${baseConfigKonnect.apiBaseUrl}/v2/control-planes/${baseConfigKonnect.controlPlaneId}/core-entities/consumers/${params.entityId}/acls/${params.id}` + } else if (params?.entityType && params?.entityId) { + url = `${baseConfigKonnect.apiBaseUrl}/v2/control-planes/${baseConfigKonnect.controlPlaneId}/core-entities/${params.entityType}/${params.entityId}/plugins/${params.id}` + } else { + url = `${baseConfigKonnect.apiBaseUrl}/v2/control-planes/${baseConfigKonnect.controlPlaneId}/core-entities/plugins/${params.id}` + } cy.intercept( { @@ -974,7 +1010,13 @@ describe('', () => { it('should show edit form', () => { const config = { ...baseConfigKonnect, entityId: scopedService.id, entityType: 'services' } interceptKonnectSchema() - interceptKonnectOperatePlugin({ method: 'GET', alias: 'getPlugin', id: plugin1.id }) + interceptKonnectOperatePlugin({ + method: 'GET', + alias: 'getPlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) interceptKonnectScopedEntity({ entityType: config.entityType }) cy.mount(PluginForm, { @@ -1018,9 +1060,21 @@ describe('', () => { const config = { ...baseConfigKonnect, entityId: scopedService.id, entityType: 'services' } interceptKonnectSchema() interceptKonnectScopedEntity({ entityType: config.entityType }) - interceptKonnectOperatePlugin({ method: 'GET', alias: 'getPlugin', id: plugin1.id }) + interceptKonnectOperatePlugin({ + method: 'GET', + alias: 'getPlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) interceptKonnectValidatePlugin() - interceptKonnectOperatePlugin({ method: 'PUT', alias: 'updatePlugin', id: plugin1.id }) + interceptKonnectOperatePlugin({ + method: 'PUT', + alias: 'updatePlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) cy.mount(PluginForm, { global: { components: { VueFormGenerator } }, @@ -1074,7 +1128,13 @@ describe('', () => { const config = { ...baseConfigKonnect, entityId: scopedService.id, entityType: 'services' } interceptKonnectSchema() interceptKonnectScopedEntity({ entityType: config.entityType }) - interceptKonnectOperatePlugin({ method: 'GET', alias: 'getPlugin', id: plugin1.id }) + interceptKonnectOperatePlugin({ + method: 'GET', + alias: 'getPlugin', + id: plugin1.id, + entityId: scopedService.id, + entityType: 'services', + }) cy.mount(PluginForm, { global: { components: { VueFormGenerator } }, diff --git a/packages/entities/entities-plugins/src/components/PluginForm.vue b/packages/entities/entities-plugins/src/components/PluginForm.vue index 33cf99cebb..136a3f2adf 100644 --- a/packages/entities/entities-plugins/src/components/PluginForm.vue +++ b/packages/entities/entities-plugins/src/components/PluginForm.vue @@ -106,7 +106,6 @@ import { type PluginFormFields, type DefaultPluginsSchemaRecord, type DefaultPluginsFormSchema, - type EntityType, type PluginEntityInfo, } from '../types' import endpoints from '../plugins-endpoints' @@ -167,6 +166,12 @@ const props = defineProps({ default: false, }, + /** For Kong Manager portal developers */ + developer: { + type: Boolean, + default: false, + }, + /** Don't render buttons and allow the host app to handle submitting the payload */ isWizardStep: { type: Boolean, @@ -228,7 +233,13 @@ const fetchUrl = computed((): string => { } // plugin - return endpoints.form[props.config.app].edit + if (props.config.entityType && props.config.entityId) { + return endpoints.form[props.config.app].edit.forEntity + .replace(/{entityType}/gi, props.config.entityType) + .replace(/{entityId}/gi, props.config.entityId) + } else { + return endpoints.form[props.config.app].edit.all + } }) const entityMap = computed((): Record => { @@ -365,14 +376,14 @@ const defaultFormSchema: DefaultPluginsSchemaRecord = reactive({ }, }) -// This is specifically used for credential plugins +// This is specifically used for credential plugins and portal developer plugins // To create an 'ACL' credential we will end up submitting to a URL like: ///acl const resourceEndpoint = computed((): string => { - const entityPath: EntityType = 'consumers' + const entityPath: string = props.developer ? 'developers' : 'consumers' const type = credentialMetaData[props.pluginType]?.endpoint || '/plugins' - return `${entityPath}/${props.config.entityId}${type}` + return `${entityPath}/${props.config.entityId}${props.developer ? '/credentials' : ''}${type}` }) const getArrayType = (list: unknown[]): string => { @@ -389,6 +400,7 @@ const formatPluginFieldLabel = (label: string) => { const buildFormSchema = (parentKey: string, response: Record, initialFormSchema: Record) => { let schema = (response && response.fields) || [] const pluginSchema = customSchemas[props.pluginType as keyof typeof customSchemas] + const credentialSchema = credentialMetaData[props.pluginType]?.schema?.fields // schema can either be an object or an array of objects. If it's an array, convert it to an object if (Array.isArray(schema)) { @@ -570,6 +582,18 @@ const buildFormSchema = (parentKey: string, response: Record, initi } + if (treatAsCredential.value && props.config.app === 'kongManager' && credentialSchema) { + for (let i = 0; i < credentialSchema.length; i++) { + if (credentialSchema[i][field]) { + initialFormSchema[field] = { + ...initialFormSchema[field], + ...credentialSchema[i][field], + } + break + } + } + } + // required fields, if it's boolean (a checkbox) it will be marked as required even though it isn't if (scheme.required && scheme.type !== 'boolean') { initialFormSchema[field].required = true @@ -615,6 +639,8 @@ const buildFormSchema = (parentKey: string, response: Record, initi if (scheme.len_min > 0) { initialFormSchema[field].submitWhenNull = true } + } else if (scheme.type === 'foreign') { + valueType = 'object' } else if (scheme.default && Array.isArray(scheme.default)) { valueType = 'array' initialFormSchema[field].valueArrayType = getArrayType(scheme.default) @@ -842,8 +868,11 @@ const validateSubmitUrl = computed((): string => { * Build the submit URL */ const submitUrl = computed((): string => { + const isScoped = props.config.entityType && props.config.entityId && !props.developer // plugin endpoint vs credential endpoint - const submitEndpoint = !treatAsCredential.value ? endpoints.form[props.config.app][formType.value] : endpoints.form[props.config.app].credential[formType.value] + const submitEndpoint = !treatAsCredential.value + ? endpoints.form[props.config.app][formType.value][isScoped ? 'forEntity' : 'all'] + : endpoints.form[props.config.app].credential[formType.value] let url = `${props.config.apiBaseUrl}${submitEndpoint}` @@ -857,6 +886,9 @@ const submitUrl = computed((): string => { url = url.replace(/{resourceEndpoint}/gi, resourceEndpoint.value) // Always replace the id when editing url = url.replace(/{id}/gi, props.pluginId) + // replace entityType and entityId if scoped + url = url.replace(/{entityType}/gi, props.config.entityType || '') + url = url.replace(/{entityId}/gi, props.config.entityId || '') return url }) diff --git a/packages/entities/entities-plugins/src/composables/plugin-schemas/VaultAuth.ts b/packages/entities/entities-plugins/src/composables/plugin-schemas/VaultAuth.ts new file mode 100644 index 0000000000..0a60ec984c --- /dev/null +++ b/packages/entities/entities-plugins/src/composables/plugin-schemas/VaultAuth.ts @@ -0,0 +1,14 @@ +import type { VaultAuthSchema } from '../../types/plugins/vault-auth' + +export const vaultAuthSchema: VaultAuthSchema = { + 'config-vault': { + type: 'AutoSuggest', + entity: 'vaults', + placeholder: 'Select a Vault', + inputValues: { + fields: ['prefix', 'name', 'id'], + }, + modelTransformer: (val: string) => ({ id: val }), + keyFromObject: 'id', + }, +} diff --git a/packages/entities/entities-plugins/src/composables/usePluginMeta.ts b/packages/entities/entities-plugins/src/composables/usePluginMeta.ts index b3267895bd..8e2d9c3135 100644 --- a/packages/entities/entities-plugins/src/composables/usePluginMeta.ts +++ b/packages/entities/entities-plugins/src/composables/usePluginMeta.ts @@ -286,7 +286,6 @@ export const usePluginMetaData = () => { name: t('plugins.meta.pre-function.name'), scope: [PluginScope.GLOBAL, PluginScope.SERVICE, PluginScope.ROUTE], imageName: 'kong-function', - docsUrlName: 'serverless-functions', }, 'post-function': { description: t('plugins.meta.post-function.description'), @@ -295,7 +294,6 @@ export const usePluginMetaData = () => { name: t('plugins.meta.post-function.name'), scope: [PluginScope.GLOBAL, PluginScope.SERVICE, PluginScope.ROUTE], imageName: 'kong-function', - docsUrlName: 'serverless-functions', }, datadog: { description: t('plugins.meta.datadog.description'), diff --git a/packages/entities/entities-plugins/src/composables/useSchemas.ts b/packages/entities/entities-plugins/src/composables/useSchemas.ts index 91fd6843cc..5f52fe37e1 100644 --- a/packages/entities/entities-plugins/src/composables/useSchemas.ts +++ b/packages/entities/entities-plugins/src/composables/useSchemas.ts @@ -15,6 +15,7 @@ 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 { vaultAuthSchema } from './plugin-schemas/VaultAuth' import { ArrayStringFieldSchema } from './plugin-schemas/ArrayStringFieldSchema' import RequestValidatorSchema from './plugin-schemas/RequestValidator' import ZipkinSchema from './plugin-schemas/Zipkin' @@ -74,6 +75,10 @@ export const useSchemas = (entityId?: string) => { ...routeByHeaderSchema, }, + 'vault-auth': { + ...vaultAuthSchema, + }, + mocking: { ...mockingSchema, }, diff --git a/packages/entities/entities-plugins/src/plugins-endpoints.ts b/packages/entities/entities-plugins/src/plugins-endpoints.ts index d160eefaff..e902d1c170 100644 --- a/packages/entities/entities-plugins/src/plugins-endpoints.ts +++ b/packages/entities/entities-plugins/src/plugins-endpoints.ts @@ -20,8 +20,14 @@ export default { }, form: { konnect: { - create: '/v2/control-planes/{controlPlaneId}/core-entities/plugins', - edit: '/v2/control-planes/{controlPlaneId}/core-entities/plugins/{id}', + create: { + all: '/v2/control-planes/{controlPlaneId}/core-entities/plugins', + forEntity: '/v2/control-planes/{controlPlaneId}/core-entities/{entityType}/{entityId}/plugins', + }, + edit: { + all: '/v2/control-planes/{controlPlaneId}/core-entities/plugins/{id}', + forEntity: '/v2/control-planes/{controlPlaneId}/core-entities/{entityType}/{entityId}/plugins/{id}', + }, pluginSchema: '/v2/control-planes/{controlPlaneId}/schemas/core-entities/plugins/{plugin}', credential: { create: '/v2/control-planes/{controlPlaneId}/core-entities/{resourceEndpoint}', @@ -34,8 +40,14 @@ export default { entityGetAll: '/v2/control-planes/{controlPlaneId}/core-entities/{entity}?size=1000', }, kongManager: { - create: '/{workspace}/plugins', - edit: '/{workspace}/plugins/{id}', + create: { + all: '/{workspace}/plugins', + forEntity: '/{workspace}/{entityType}/{entityId}/plugins', + }, + edit: { + all: '/{workspace}/plugins/{id}', + forEntity: '/{workspace}/{entityType}/{entityId}/plugins/{id}', + }, pluginSchema: '/{workspace}/schemas/plugins/{plugin}', credential: { create: '/{workspace}/{resourceEndpoint}', diff --git a/packages/entities/entities-plugins/src/types/plugin-form.ts b/packages/entities/entities-plugins/src/types/plugin-form.ts index a999f9adb3..e3caf54f5e 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 { KafkaSchema } from './plugins/kafka-schema' import type { UpstreamTlsSchema } from './plugins/upstream-tls' import type { RateLimitingSchema } from './plugins/rate-limiting' import type { RouteByHeaderSchema } from './plugins/route-by-header' +import type { VaultAuthSchema } from './plugins/vault-auth' import type { GraphQLRateLimitingAdvancedSchema } from './plugins/graphql-rate-limiting-advanced' import type { SAMLSchema } from './plugins/saml' @@ -193,6 +194,7 @@ export interface CustomSchemas { 'rate-limiting': RateLimitingSchema 'rate-limiting-advanced': RateLimitingSchema 'route-by-header': RouteByHeaderSchema + 'vault-auth': VaultAuthSchema 'graphql-rate-limiting-advanced': GraphQLRateLimitingAdvancedSchema 'response-ratelimiting': RateLimitingSchema 'pre-function': CommonSchemaFields & Record diff --git a/packages/entities/entities-plugins/src/types/plugin.ts b/packages/entities/entities-plugins/src/types/plugin.ts index d938311ee7..2f90a31bca 100644 --- a/packages/entities/entities-plugins/src/types/plugin.ts +++ b/packages/entities/entities-plugins/src/types/plugin.ts @@ -62,7 +62,6 @@ export interface PluginEntityInfo { export type PluginMetaData = { description: string // A string to describe a Plugin. - docsUrlName?: string // An optional field for plugin's documentation URL. group: PluginGroup // Plugin categories meta. imageName?: string // An optional tag to define plugin's icon image. isEnterprise: boolean // The value will be True if the Plugin is enterprise only. diff --git a/packages/entities/entities-plugins/src/types/plugins/vault-auth.d.ts b/packages/entities/entities-plugins/src/types/plugins/vault-auth.d.ts new file mode 100644 index 0000000000..dfbf43d97a --- /dev/null +++ b/packages/entities/entities-plugins/src/types/plugins/vault-auth.d.ts @@ -0,0 +1,14 @@ +import type { CommonSchemaFields } from './shared' + +export interface VaultAuthSchema extends CommonSchemaFields { + 'config-vault': { + type: string + entity: string + placeholder: string + inputValues: { + fields: string[] + } + modelTransformer: (val: string) => { id: string } + keyFromObject: string + } +}