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:
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');
|
||||
}
|
||||
}
|
||||
@@ -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');
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
@@ -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,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}}
|
||||
|
||||
+1
-6
@@ -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}}
|
||||
|
||||
+1
-1
@@ -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}}
|
||||
|
||||
+2
-4
@@ -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
|
||||
|
||||
+24
-25
@@ -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
|
||||
|
||||
+26
-25
@@ -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
|
||||
|
||||
Reference in new issue
Block a user