feat: 🎸 create form for json credentials (#1498)

* feat: 🎸 create form for json credentials

✅ Closes: ICU-6682

* refactor: 💡 add new info field

* refactor: 💡 add feature flag

* refactor: 💡 add hds radio cards to json cred

* Update ui/admin/tests/acceptance/credential-store/credentials/create-test.js

* test: 💍 add test for json cred

* chore: 🤖 Remove ember-data-model-fragments package

* fix: 🐛 Update how json is added as a known credential type

* refactor: 💡 update credentialTypes if statement to ternary

* chore: 🤖 add ember-data back to addon/api project

* chore: 🤖 remove ember-feature-flag from addon/api

* refactor: 💡 remove if statement in cred form

* refactor: 💡 update selectors for json cred. tests

* refactor: 💡 Update Credential Form to use form.disabled

* test: 💍 Fix test selectors for radio card credential tests

* refactor: 💡 update credential types declaration to const

* style: 💄 Fix style issue with SecretEditor in edit mode

* refactor: 💡 remove disabled and readonly attributes in form

* refactor: 💡 Create credential ability canRead override

* test: 💍 add credential ability override tests

* test: 💍 Fix brokered credential test with json support added

* refactor: 💡 add attributes comment back to credential model

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
This commit is contained in:
lisbet-alvarezandCameron Perera authored and GitHub committed 2022-12-12 18:37:01 -06:00
1 parent e18b30a54e
commit e418017bc2
17 files changed
+420 -86

No files matched your search

+13
View File
@@ -0,0 +1,13 @@
import CredentialAbility from 'api/abilities/credential';
import { inject as service } from '@ember/service';
export default class OverrideCredentialAbility extends CredentialAbility {
// =service
@service features;
get canRead() {
return (this.features.isEnabled('json-credentials') || this.model.type !== 'json')
? super.canRead
: false;
}
}
@@ -2,6 +2,7 @@
{{component
(concat 'form/credential/' @model.type)
model=@model
types=this.credentialTypes
submit=@submit
cancel=@cancel
changeType=@changeType
@@ -0,0 +1,19 @@
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { types } from 'api/models/credential';
export default class FormCredentialComponent extends Component {
// =services
@service features;
// =attributes
/**
* Returns an array of available credential types the user can create
* @type {object}
*/
get credentialTypes() {
return this.features.isEnabled('json-credentials')
? types
: types.filter((type) => type !== 'json');
}
}
@@ -0,0 +1,112 @@
<Rose::Form
@onSubmit={{@submit}}
@cancel={{@cancel}}
@disabled={{@model.isSaving}}
@showEditToggle={{if @model.isNew false true}}
as |form|
>
<form.input
@name='name'
@value={{@model.name}}
@label={{t 'form.name.label'}}
@error={{@model.errors.name}}
@helperText={{t 'form.name.help'}}
as |field|
>
{{#if @model.errors.name}}
<field.errors as |errors|>
{{#each @model.errors.name as |error|}}
<errors.message>{{error.message}}</errors.message>
{{/each}}
</field.errors>
{{/if}}
</form.input>
<form.textarea
@name='description'
@value={{@model.description}}
@label={{t 'form.description.label'}}
@error={{@model.errors.description}}
@helperText={{t 'form.description.help'}}
as |field|
>
{{#if @model.errors.description}}
<field.errors as |errors|>
{{#each @model.errors.description as |error|}}
<errors.message>{{error.message}}</errors.message>
{{/each}}
</field.errors>
{{/if}}
</form.textarea>
{{#if @model.isNew}}
<form.fieldset>
<:body>
<Hds::Form::RadioCard::Group as |G|>
<G.Legend>{{t 'form.type.label'}}</G.Legend>
{{#each @types as |credentialType|}}
<G.RadioCard
@name={{credentialType}}
@value={{credentialType}}
@checked={{eq credentialType @model.type}}
@maxWidth='20rem'
{{on 'input' (fn @changeType credentialType)}}
as |R|
>
<R.Label>{{t
(concat 'resources.credential.types.' credentialType)
}}</R.Label>
<R.Description>{{t
(concat 'resources.credential.help.' credentialType)
}}</R.Description>
</G.RadioCard>
{{/each}}
</Hds::Form::RadioCard::Group>
</:body>
</form.fieldset>
<form.fieldset>
<:title>{{t 'resources.credential.form.json.label'}}</:title>
<:description>{{t 'resources.credential.form.json.help'}}</:description>
<:body>
<Form::Field::JsonSecret
@value={{@model.json_object}}
@onInput={{fn (mut @model.json_object)}}
@showEditButton={{false}}
/>
</:body>
</form.fieldset>
{{else}}
<InfoField
@value={{t (concat 'resources.credential.help.' @model.type)}}
as |F|
>
<F.Label>{{t 'form.type.label'}}</F.Label>
<F.HelperText>{{t (concat 'resources.credential.types.' @model.type)}}
</F.HelperText>
</InfoField>
<form.fieldset>
<:title>{{t 'resources.credential.form.json.label'}}</:title>
<:description>{{t 'resources.credential.form.json.help'}}</:description>
<:body>
<Form::Field::JsonSecret
@disabled={{form.disabled}}
@value={{@model.json_object}}
@onInput={{fn (mut @model.json_object)}}
@showEditButton={{true}}
/>
</:body>
</form.fieldset>
{{/if}}
{{#if (can 'save model' @model)}}
<form.actions
@enableEditText={{t 'actions.edit-form'}}
@submitText={{t 'actions.save'}}
@cancelText={{t 'actions.cancel'}}
/>
{{/if}}
</Rose::Form>
@@ -12,8 +12,6 @@
@label={{t 'form.name.label'}}
@error={{@model.errors.name}}
@helperText={{t 'form.name.help'}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.name}}
@@ -31,8 +29,6 @@
@label={{t 'form.description.label'}}
@error={{@model.errors.description}}
@helperText={{t 'form.description.help'}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.description}}
@@ -46,7 +42,7 @@
{{#if @model.isNew}}
<Hds::Form::RadioCard::Group @name='types' as |G|>
<G.Legend>{{t 'form.type.label'}}</G.Legend>
{{#each this.credentialTypes as |credentialType|}}
{{#each @types as |credentialType|}}
<G.RadioCard
@name={{credentialType}}
@value={{credentialType}}
@@ -82,8 +78,6 @@
@label={{t 'resources.credential.form.username.label'}}
@helperText={{t 'resources.credential.form.username.help'}}
@error={{@model.errors.username}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.username}}
@@ -102,8 +96,6 @@
@label={{t 'resources.credential.form.private_key.label'}}
@helperText={{t 'resources.credential.form.private_key.help'}}
@error={{@model.errors.private_key}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.private_key}}
@@ -121,8 +113,6 @@
@label={{t 'resources.credential.form.private_key_passphrase.label'}}
@helperText={{t 'resources.credential.form.private_key_passphrase.help'}}
@error={{@model.errors.private_key_passphrase}}
disabled={{@model.isSaving}}
readonly={{false}}
autocomplete='new-password'
as |field|
>
@@ -1,10 +0,0 @@
import Component from '@glimmer/component';
import { types } from 'api/models/credential';
export default class FormSSHPrivateKeyCredentialComponent extends Component {
// =attributes
/**
* @type {Array}
*/
credentialTypes = types;
}
@@ -12,8 +12,6 @@
@label={{t 'form.name.label'}}
@error={{@model.errors.name}}
@helperText={{t 'form.name.help'}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.name}}
@@ -31,8 +29,6 @@
@label={{t 'form.description.label'}}
@error={{@model.errors.description}}
@helperText={{t 'form.description.help'}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.description}}
@@ -46,7 +42,7 @@
{{#if @model.isNew}}
<Hds::Form::RadioCard::Group @name='types' as |G|>
<G.Legend>{{t 'form.type.label'}}</G.Legend>
{{#each this.credentialTypes as |credentialType|}}
{{#each @types as |credentialType|}}
<G.RadioCard
@name={{credentialType}}
@value={{credentialType}}
@@ -82,8 +78,6 @@
@label={{t 'resources.credential.form.username.label'}}
@helperText={{t 'resources.credential.form.username.help'}}
@error={{@model.errors.username}}
disabled={{@model.isSaving}}
readonly={{false}}
as |field|
>
{{#if @model.errors.username}}
@@ -103,8 +97,6 @@
@label={{t 'resources.credential.form.password.label'}}
@helperText={{t 'resources.credential.form.password.help'}}
@error={{@model.errors.password}}
disabled={{@model.isSaving}}
readonly={{false}}
autocomplete='new-password'
as |field|
>
@@ -1,10 +0,0 @@
import Component from '@glimmer/component';
import { types } from 'api/models/credential';
export default class FormUserNamePasswordCredentialComponent extends Component {
// =attributes
/**
* @type {Array}
*/
credentialTypes = types;
}
@@ -29,15 +29,23 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialsNewRou
'scopes.scope.credential-stores.credential-store'
);
let name, description;
/**
* this sets the credential attribute json_object to a string that
* replicates an empty json blob as CodeMirror expects a string
*/
const json_object = '{}';
if (this.currentModel?.isNew) {
({ name, description } = this.currentModel);
this.currentModel.rollbackAttributes();
}
return this.store.createRecord('credential', {
type,
credential_store_id,
name,
description,
json_object,
});
}
+2 -5
View File
@@ -508,21 +508,18 @@
border-radius: sizing.rems(xxs);
height: var(--secret-editor-height);
margin-bottom: sizing.rems(l);
width: 100%;
.secret-editor-json {
.CodeMirror {
border-radius: sizing.rems(xxs);
height: var(--secret-editor-height);
display: block;
}
.CodeMirror-gutters {
background: var(--secret-editor-gutter);
}
// override CodeMirror padding to add padding to left of line numbers
.CodeMirror-linenumber {
padding: 0;
}
}
.secret-editor-skeleton-wrapper {
@@ -37,7 +37,7 @@
}}
<body.row as |row|>
<row.headerCell>
{{#if brokeredCredentialSource.isUnknown}}
{{#if (cannot 'read credential' brokeredCredentialSource)}}
{{brokeredCredentialSource.displayName}}
{{else}}
{{#if brokeredCredentialSource.isStatic}}