Icu 6153 unknown credential support (#1344)

* feat: 🎸 Add support for unknown credential types

✅ Closes: ICU-6153

* fix: 🐛 add unknown cred type

* refactor: 💡 move credential type logic to a component

* chore: 🤖 fix component name

* fix: 🐛 update component name, remove unused translated string

* fix: 🐛 file name

Co-authored-by: Cameron Perera <cameron.perera@hashicorp.com>
This commit is contained in:
Dharini JeevaandCameron Perera authored and GitHub committed 2022-09-20 19:31:16 -05:00
1 parent 6aec408003
commit 5224512da0
18 files changed
+174 -80

No files matched your search

@@ -0,0 +1,15 @@
import ModelAbility from './model';
/**
* Provides abilities for credential.
*/
export default class CredentialLibaryAbility extends ModelAbility {
// =permissions
/**
* Only "known" credential libary types may be read.
* @type {boolean}
*/
get canRead() {
return !this.model.isUnknown && this.hasAuthorizedAction('read');
}
}
+15
View File
@@ -0,0 +1,15 @@
import ModelAbility from "./model";
/**
* Provides abilities for credential.
*/
export default class CredentialAbility extends ModelAbility {
// =permissions
/**
* Only "known" credential types may be read.
* @type {boolean}
*/
get canRead() {
return !this.model.isUnknown && this.hasAuthorizedAction('read');
}
}
+24 -1
View File
@@ -7,4 +7,27 @@ export const options = {
http_method: ['GET', 'POST'],
};
export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel {}
/**
* Supported Credential Library types.
*/
export const types = ['vault'];
export default class CredentialLibraryModel extends GeneratedCredentialLibraryModel {
// =attributes
/**
* True if credential is an unknown type.
* @type {boolean}
*/
get isUnknown() {
return !types.includes(this.type);
}
/**
* True if credential is a vault type.
* @type {boolean}
*/
get isVault() {
return this.type === 'vault';
}
}
+13
View File
@@ -1,10 +1,23 @@
import GeneratedCredentialModel from '../generated/models/credential';
import { equal } from '@ember/object/computed';
/**
* Supported Credential types.
*/
export const types = ['username_password', 'ssh_private_key'];
export default class CredentialModel extends GeneratedCredentialModel {
// =attributes
/**
* @type {boolean}
*/
@equal('type', 'username_password') isUsernamePassword;
/**
* True if credential is an unknown type.
* @type {boolean}
*/
get isUnknown() {
return !types.includes(this.type);
}
}
@@ -0,0 +1 @@
export { default } from 'api/abilities/credential-library';
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/abilities/credential';
@@ -59,7 +59,7 @@ export default factory.extend({
break;
case 'static':
default:
server.createList('credential', 2, {
server.createList('credential', 3, {
scope,
credentialStore,
});
+3 -1
View File
@@ -3,7 +3,7 @@ import { faker } from '@faker-js/faker';
import permissions from '../helpers/permissions';
import generatedId from '../helpers/id';
const types = ['username_password', 'ssh_private_key'];
const types = ['username_password', 'ssh_private_key', 'json'];
export default factory.extend({
type: (i) => types[i % types.length],
@@ -13,6 +13,8 @@ export default factory.extend({
return generatedId('credspk_');
case 'username_password':
return generatedId('credup_');
case 'json':
return generatedId('credjson_');
}
},
authorized_actions: () =>
@@ -4,10 +4,19 @@ import { setupTest } from 'ember-qunit';
module('Unit | Model | credential library', function (hooks) {
setupTest(hooks);
// Replace this with your real tests.
test('it exists', function (assert) {
let store = this.owner.lookup('service:store');
let model = store.createRecord('credential-library', {});
assert.ok(model);
});
test('it has isUnknown property and returns the expected values', async function (assert) {
assert.expect(2);
const store = this.owner.lookup('service:store');
const modelA = store.createRecord('credential-library', { type: 'vault' });
const modelB = store.createRecord('credential-library', { type: 'unknown' });
assert.false(modelA.isUnknown);
assert.true(modelB.isUnknown);
});
});
@@ -9,4 +9,26 @@ module('Unit | Model | credential', function (hooks) {
const model = store.createRecord('credential', {});
assert.ok(model);
});
test('it has isUsernamePassword property and returns the expected values', async function (assert) {
assert.expect(2);
const store = this.owner.lookup('service:store');
const modelA = store.createRecord('credential', { type: 'username_password' });
const modelB = store.createRecord('credential', { type: 'ssh_private_key' });
assert.true(modelA.isUsernamePassword);
assert.false(modelB.isUsernamePassword);
});
test('it has isUnknown property and returns the expected values', async function (assert) {
assert.expect(3);
const store = this.owner.lookup('service:store');
const modelA = store.createRecord('credential', { type: 'username_password' });
const modelB = store.createRecord('credential', { type: 'ssh_private_key' });
const modelC = store.createRecord('credential', { type: 'unknown' });
assert.false(modelA.isUnknown);
assert.false(modelB.isUnknown);
assert.true(modelC.isUnknown);
});
});
@@ -304,10 +304,6 @@ target:
brokered-credential-source:
title: Brokered Credential
title_plural: Brokered Credentials
types:
vault: Vault
username_password: Username & Password
ssh_private_key: Username & Key Pair
messages:
welcome:
title: Welcome to brokered credentials
@@ -321,10 +317,6 @@ target:
injected-application-credential-source:
title: Injected Application Credential
title_plural: Injected Application Credentials
types:
vault: Vault
username_password: Username & Password
ssh_private_key: Username & Key Pair
messages:
welcome:
title: Welcome to Injected Application credentials
@@ -403,7 +395,6 @@ credential-library:
types:
vault: Vault
static: Static
username_password: Username & Password
credential:
title: Credential
title_plural: Credentials
@@ -418,6 +409,7 @@ credential:
types:
username_password: Username & Password
ssh_private_key: Username & Key Pair
unknown: Unknown
help:
username_password: This host requires a username and password to connect.
ssh_private_key: This host requires a username, public key, and private key to connect.
@@ -0,0 +1,13 @@
{{#if @model.isUnknown}}
<Rose::Badge>
{{t 'resources.credential.types.unknown'}}
</Rose::Badge>
{{else if @model.isVault}}
<Rose::Badge>
{{t (concat 'resources.credential-library.types.' @model.type)}}
</Rose::Badge>
{{else}}
<Rose::Badge>
{{t (concat 'resources.credential.types.' @model.type)}}
</Rose::Badge>
{{/if}}
@@ -31,12 +31,7 @@
</row.headerCell>
<row.cell>{{credentialSource.name}}</row.cell>
<row.cell>
<Rose::Badge>{{t
(concat
'resources.target.brokered-credential-source.types.'
credentialSource.type
)
}}</Rose::Badge>
<CredSourceTypeBadge @model={{credentialSource}} />
</row.cell>
</body.row>
{{/each}}
@@ -32,12 +32,7 @@
</row.headerCell>
<row.cell>{{credentialSource.name}}</row.cell>
<row.cell>
<Rose::Badge>{{t
(concat
'resources.target.injected-application-credential-source.types.'
credentialSource.type
)
}}</Rose::Badge>
<CredSourceTypeBadge @model={{credentialSource}} />
</row.cell>
</body.row>
{{/each}}
@@ -35,7 +35,7 @@
{{#each @model as |credentialLibrary|}}
<body.row as |row|>
<row.headerCell>
{{#if (can 'read model' credentialLibrary)}}
{{#if (can 'read credential-library' credentialLibrary)}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credential-libraries.credential-library'
@model={{credentialLibrary.id}}
@@ -35,7 +35,7 @@
{{#each @model as |credential|}}
<body.row as |row|>
<row.headerCell>
{{#if (can 'read model' credential)}}
{{#if (can 'read credential' credential)}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credentials.credential'
@model={{credential.id}}
@@ -48,9 +48,7 @@
<p>{{credential.description}}</p>
</row.headerCell>
<row.cell>
<Rose::Badge>{{t
(concat 'resources.credential.types.' credential.type)
}}</Rose::Badge>
<CredSourceTypeBadge @model={{credential}} />
</row.cell>
<row.cell>
<Copyable
@@ -37,37 +37,36 @@
}}
<body.row as |row|>
<row.headerCell>
{{#if brokeredCredentialSource.isUsernamePassword}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credentials.credential'
@models={{array
brokeredCredentialSource.credential_store_id
brokeredCredentialSource.id
}}
>
{{brokeredCredentialSource.displayName}}
</LinkTo>
{{#if brokeredCredentialSource.isUnknown}}
{{brokeredCredentialSource.displayName}}
{{else}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credential-libraries.credential-library'
@models={{array
brokeredCredentialSource.credential_store_id
brokeredCredentialSource.id
}}
>
{{brokeredCredentialSource.displayName}}
</LinkTo>
{{#if brokeredCredentialSource.isUsernamePassword}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credentials.credential'
@models={{array
brokeredCredentialSource.credential_store_id
brokeredCredentialSource.id
}}
>
{{brokeredCredentialSource.displayName}}
</LinkTo>
{{else}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credential-libraries.credential-library'
@models={{array
brokeredCredentialSource.credential_store_id
brokeredCredentialSource.id
}}
>
{{brokeredCredentialSource.displayName}}
</LinkTo>
{{/if}}
{{/if}}
<p>{{brokeredCredentialSource.description}}</p>
</row.headerCell>
<row.cell>
<Rose::Badge>{{t
(concat
'resources.target.brokered-credential-source.types.'
brokeredCredentialSource.type
)
}}</Rose::Badge>
<CredSourceTypeBadge @model={{brokeredCredentialSource}} />
</row.cell>
<row.cell>
<Copyable
@@ -39,37 +39,38 @@
}}
<body.row as |row|>
<row.headerCell>
{{#if injectedApplicationCredentialSource.isUsernamePassword}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credentials.credential'
@models={{array
injectedApplicationCredentialSource.credential_store_id
injectedApplicationCredentialSource.id
}}
>
{{injectedApplicationCredentialSource.displayName}}
</LinkTo>
{{#if injectedApplicationCredentialSource.isUnknown}}
{{injectedApplicationCredentialSource.displayName}}
{{else}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credential-libraries.credential-library'
@models={{array
injectedApplicationCredentialSource.credential_store_id
injectedApplicationCredentialSource.id
}}
>
{{injectedApplicationCredentialSource.displayName}}
</LinkTo>
{{#if injectedApplicationCredentialSource.isUsernamePassword}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credentials.credential'
@models={{array
injectedApplicationCredentialSource.credential_store_id
injectedApplicationCredentialSource.id
}}
>
{{injectedApplicationCredentialSource.displayName}}
</LinkTo>
{{else}}
<LinkTo
@route='scopes.scope.credential-stores.credential-store.credential-libraries.credential-library'
@models={{array
injectedApplicationCredentialSource.credential_store_id
injectedApplicationCredentialSource.id
}}
>
{{injectedApplicationCredentialSource.displayName}}
</LinkTo>
{{/if}}
{{/if}}
<p>{{injectedApplicationCredentialSource.description}}</p>
</row.headerCell>
<row.cell>
<Rose::Badge>{{t
(concat
'resources.target.injected-application-credential-source.types.'
injectedApplicationCredentialSource.type
)
}}</Rose::Badge>
<CredSourceTypeBadge
@model={{injectedApplicationCredentialSource}}
/>
</row.cell>
<row.cell>
<Copyable