Skip to content

Commit

Permalink
feat(entities-certificates): support sni field in form [KM-199] (#1458)
Browse files Browse the repository at this point in the history
* feat(entities-certificates): support sni field in form [KM-199]

* test(*): add tests
  • Loading branch information
Leopoldthecoder committed Aug 1, 2024
1 parent d8ff823 commit 90d4ba0
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 22 deletions.
14 changes: 14 additions & 0 deletions packages/entities/entities-certificates/docs/certificate-form.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@ A form component for Certificates.
- default: `undefined`
- Route to return to when canceling creation of an Certificate.

- `sniListRoute`:
- type: `RouteLocationRaw`
- required: `false`
- default: `undefined`
- Route of listing SNIs.

- `workspace`:
- type: `string`
- required: `true`
Expand All @@ -77,6 +83,14 @@ The base konnect or kongManger config.

If showing the `Edit` type form, the ID of the Certificate.

#### `showSnisField`

- type: `boolean`
- required: `false`
- default: `false`

Whether to show the SNIs field in the form.

### Events

#### error
Expand Down
5 changes: 5 additions & 0 deletions packages/entities/entities-certificates/sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ const init = async () => {
props: true,
component: () => import('./pages/FallbackPage.vue'),
},
{
path: '/snis',
name: 'sni-list',
component: () => import('./pages/FallbackPage.vue'),
},
{
path: '/certificate-list',
name: 'certificate-list',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
<CertificateForm
:certificate-id="id"
:config="kongManagerConfig"
show-snis-field
@error="onError"
@update="onUpdate"
/>
Expand Down Expand Up @@ -48,6 +49,7 @@ const kongManagerConfig = ref<KongManagerCertificateFormConfig>({
workspace: 'default',
apiBaseUrl: '/kong-manager', // For local dev server proxy
cancelRoute: { name: 'certificate-list' },
sniListRoute: { name: 'sni-list' },
})
const onError = (error: AxiosError) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ import type { KongManagerCertificateFormConfig, KonnectCertificateFormConfig } f
import CertificateForm from './CertificateForm.vue'

const cancelRoute = { name: 'certificates-list' }
const sniListRoute = { name: 'snis-list' }

const baseConfigKonnect:KonnectCertificateFormConfig = {
const baseConfigKonnect: KonnectCertificateFormConfig = {
app: 'konnect',
controlPlaneId: '1234-abcd-ilove-cats',
apiBaseUrl: '/us/kong-api',
cancelRoute,
sniListRoute,
}

const baseConfigKM:KongManagerCertificateFormConfig = {
const baseConfigKM: KongManagerCertificateFormConfig = {
app: 'kongManager',
workspace: 'default',
apiBaseUrl: '/kong-manager',
cancelRoute,
sniListRoute,
}

/**
Expand Down Expand Up @@ -120,6 +123,7 @@ describe('<CertificateForm />', () => {
cy.mount(CertificateForm, {
props: {
config: baseConfigKM,
showSnisField: true,
},
})
cy.get('.kong-ui-entities-certificates-form').should('be.visible')
Expand All @@ -134,6 +138,7 @@ describe('<CertificateForm />', () => {
cy.getTestId('certificate-form-key').should('be.visible')
cy.getTestId('certificate-form-cert-alt').should('be.visible')
cy.getTestId('certificate-form-key-alt').should('be.visible')
cy.getTestId('sni-field-input-1').should('be.visible')
cy.getTestId('certificate-form-tags').should('be.visible')
})

Expand All @@ -151,8 +156,8 @@ describe('<CertificateForm />', () => {
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
// enables save when required fields have values
cy.getTestId('certificate-form-cert').type(certificate1.cert)
cy.getTestId('certificate-form-key').type(certificate1.key)
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })
cy.getTestId('form-submit').should('be.enabled')
// disables save when required field is cleared
cy.getTestId('certificate-form-cert').clear()
Expand Down Expand Up @@ -279,12 +284,12 @@ describe('<CertificateForm />', () => {
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
// enables save when required fields have values
cy.getTestId('certificate-form-cert').type(certificate1.cert)
cy.getTestId('certificate-form-key').type(certificate1.key)
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })

// replaces all the newlines with spaces; this should fail the validation
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert.replaceAll('\n', ' '))
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key.replaceAll('\n', ' '))
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert.replaceAll('\n', ' '), { delay: 0 })
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key.replaceAll('\n', ' '), { delay: 0 })

cy.getTestId('form-submit').should('be.enabled')

Expand Down Expand Up @@ -312,12 +317,43 @@ describe('<CertificateForm />', () => {
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
// enables save when required fields have values
cy.getTestId('certificate-form-cert').type(certificate1.cert)
cy.getTestId('certificate-form-key').type(certificate1.key)
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })

// replaces all the newlines with spaces; this should fail the validation
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert)
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key)
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert, { delay: 0 })
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key, { delay: 0 })

cy.getTestId('form-submit').should('be.enabled')

cy.get('@vueWrapper').then((wrapper: any) => wrapper.findComponent(EntityBaseForm)
.vm.$emit('submit'))

cy.wait('@validateCertificate').its('response.statusCode').should('eq', 200)
cy.wait('@createCertificate').its('response.statusCode').should('eq', 200)
})

it('should not fail when SNI is provided', () => {
interceptKM()
interceptUpdate()

cy.mount(CertificateForm, {
props: {
config: baseConfigKM,
showSnisField: true,
},
}).then(({ wrapper }) => wrapper)
.as('vueWrapper')

cy.get('.kong-ui-entities-certificates-form').should('be.visible')
// default button state
cy.getTestId('form-cancel').should('be.visible')
cy.getTestId('form-submit').should('be.visible')
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })
cy.getTestId('sni-field-input-1').type('foo')

cy.getTestId('form-submit').should('be.enabled')

Expand Down Expand Up @@ -391,6 +427,7 @@ describe('<CertificateForm />', () => {
cy.mount(CertificateForm, {
props: {
config: baseConfigKonnect,
showSnisField: true,
},
})

Expand All @@ -406,6 +443,7 @@ describe('<CertificateForm />', () => {
cy.getTestId('certificate-form-key').should('be.visible')
cy.getTestId('certificate-form-cert-alt').should('be.visible')
cy.getTestId('certificate-form-key-alt').should('be.visible')
cy.getTestId('sni-field-input-1').should('be.visible')
cy.getTestId('certificate-form-tags').should('be.visible')
})

Expand All @@ -422,8 +460,8 @@ describe('<CertificateForm />', () => {
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
// enables save when required fields have values
cy.getTestId('certificate-form-cert').type(certificate1.cert)
cy.getTestId('certificate-form-key').type(certificate1.key)
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })
cy.getTestId('form-submit').should('be.enabled')
// disables save when required field is cleared
cy.getTestId('certificate-form-cert').clear()
Expand Down Expand Up @@ -550,12 +588,12 @@ describe('<CertificateForm />', () => {
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
// enables save when required fields have values
cy.getTestId('certificate-form-cert').type(certificate1.cert)
cy.getTestId('certificate-form-key').type(certificate1.key)
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })

// replaces all the newlines with spaces; this should fail the validation
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert.replaceAll('\n', ' '))
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key.replaceAll('\n', ' '))
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert.replaceAll('\n', ' '), { delay: 0 })
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key.replaceAll('\n', ' '), { delay: 0 })

cy.getTestId('form-submit').should('be.enabled')

Expand Down Expand Up @@ -583,12 +621,43 @@ describe('<CertificateForm />', () => {
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
// enables save when required fields have values
cy.getTestId('certificate-form-cert').type(certificate1.cert)
cy.getTestId('certificate-form-key').type(certificate1.key)
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })

// replaces all the newlines with spaces; this should fail the validation
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert)
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key)
cy.getTestId('certificate-form-cert-alt').type(secp384r1CertKeyPair.cert, { delay: 0 })
cy.getTestId('certificate-form-key-alt').type(secp384r1CertKeyPair.key, { delay: 0 })

cy.getTestId('form-submit').should('be.enabled')

cy.get('@vueWrapper').then((wrapper: any) => wrapper.findComponent(EntityBaseForm)
.vm.$emit('submit'))

cy.wait('@validateCertificate').its('response.statusCode').should('eq', 200)
cy.wait('@createCertificate').its('response.statusCode').should('eq', 200)
})

it('should not fail when SNI is provided', () => {
interceptKonnect()
interceptUpdate()

cy.mount(CertificateForm, {
props: {
config: baseConfigKonnect,
showSnisField: true,
},
}).then(({ wrapper }) => wrapper)
.as('vueWrapper')

cy.get('.kong-ui-entities-certificates-form').should('be.visible')
// default button state
cy.getTestId('form-cancel').should('be.visible')
cy.getTestId('form-submit').should('be.visible')
cy.getTestId('form-cancel').should('be.enabled')
cy.getTestId('form-submit').should('be.disabled')
cy.getTestId('certificate-form-cert').type(certificate1.cert, { delay: 0 })
cy.getTestId('certificate-form-key').type(certificate1.key, { delay: 0 })
cy.getTestId('sni-field-input-1').type('foo')

cy.getTestId('form-submit').should('be.enabled')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@
</i18nT>
</template>
</KTextArea>

<CertificateFormSniField
v-if="showSnisField && config.sniListRoute"
v-model="form.fields.snis"
:is-editing="formType === EntityBaseFormType.Edit"
:sni-list-route="config.sniListRoute"
@add="handleAddSni"
@remove="(index: number) => handleRemoveSni(index)"
/>
</EntityFormSection>

<EntityFormSection
Expand Down Expand Up @@ -134,6 +143,7 @@ import type {
} from '../types'
import endpoints from '../certificates-endpoints'
import composables from '../composables'
import CertificateFormSniField from './CertificateFormSniField.vue'
import { useAxios, useErrors, EntityFormSection, EntityBaseForm, EntityBaseFormType } from '@kong-ui-public/entities-shared'
import '@kong-ui-public/entities-shared/dist/style.css'
Expand Down Expand Up @@ -163,6 +173,12 @@ const props = defineProps({
required: false,
default: '',
},
/** If true, the SNI field will be shown */
showSnisField: {
type: Boolean,
required: false,
default: false,
},
})
const router = useRouter()
Expand All @@ -180,6 +196,7 @@ const form = reactive<CertificateFormState>({
key: '',
certAlt: '',
keyAlt: '',
snis: [''],
tags: '',
},
isReadonly: false,
Expand All @@ -191,6 +208,7 @@ const formFieldsOriginal = reactive<CertificateFormFields>({
key: '',
certAlt: '',
keyAlt: '',
snis: [''],
tags: '',
})
Expand All @@ -205,6 +223,7 @@ const initForm = (data: Record<string, any>): void => {
form.fields.key = data?.key || ''
form.fields.certAlt = data?.cert_alt || ''
form.fields.keyAlt = data?.key_alt || ''
form.fields.snis = data?.snis?.length ? data.snis : ['']
form.fields.tags = data?.tags?.join(', ') || ''
// Set initial state of `formFieldsOriginal` to these values in order to detect changes
Expand All @@ -215,6 +234,14 @@ const handleClickCancel = (): void => {
router.push(props.config.cancelRoute)
}
const handleAddSni = (): void => {
form.fields.snis.push('')
}
const handleRemoveSni = (index: number): void => {
form.fields.snis.splice(index, 1)
}
/* ---------------
* Saving
* ---------------
Expand Down Expand Up @@ -259,6 +286,7 @@ const requestBody = computed((): Record<string, any> => {
key: form.fields.key,
cert_alt: form.fields.certAlt || null,
key_alt: form.fields.keyAlt || null,
snis: form.fields.snis.filter(Boolean),
tags: form.fields.tags.split(',')?.map((tag: string) => String(tag || '').trim())?.filter((tag: string) => tag !== ''),
}
})
Expand All @@ -285,6 +313,7 @@ const saveFormData = async (): Promise<void> => {
form.fields.key = response?.data?.key || ''
form.fields.certAlt = response?.data?.cert_alt || ''
form.fields.keyAlt = response?.data?.key_alt || ''
form.fields.snis = response?.data?.snis?.length ? response.data.snis : ['']
form.fields.tags = response?.data?.tags?.join(', ') || ''
// Set initial state of `formFieldsOriginal` to these values in order to detect changes
Expand Down
Loading

0 comments on commit 90d4ba0

Please sign in to comment.