mirror of
https://github.com/ansible/awx.git
synced 2026-03-26 21:35:01 -02:30
Use credential_types from credential.summary_fields to display "Type" column
This commit is contained in:
@@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { withI18n } from '@lingui/react';
|
import { withI18n } from '@lingui/react';
|
||||||
import { t } from '@lingui/macro';
|
import { t } from '@lingui/macro';
|
||||||
import { CredentialsAPI, CredentialTypesAPI } from '@api';
|
import { CredentialsAPI } from '@api';
|
||||||
import { Card, PageSection } from '@patternfly/react-core';
|
import { Card, PageSection } from '@patternfly/react-core';
|
||||||
import AlertModal from '@components/AlertModal';
|
import AlertModal from '@components/AlertModal';
|
||||||
import ErrorDetail from '@components/ErrorDetail';
|
import ErrorDetail from '@components/ErrorDetail';
|
||||||
@@ -14,31 +14,17 @@ import PaginatedDataList, {
|
|||||||
import { getQSConfig, parseQueryString } from '@util/qs';
|
import { getQSConfig, parseQueryString } from '@util/qs';
|
||||||
import { CredentialListItem } from '.';
|
import { CredentialListItem } from '.';
|
||||||
|
|
||||||
const QS_CONFIG = getQSConfig('project', {
|
const QS_CONFIG = getQSConfig('credential', {
|
||||||
page: 1,
|
page: 1,
|
||||||
page_size: 20,
|
page_size: 20,
|
||||||
order_by: 'name',
|
order_by: 'name',
|
||||||
});
|
});
|
||||||
|
|
||||||
const assignCredentialKinds = (credentials, credentialTypes) => {
|
|
||||||
const typesById = credentialTypes.reduce((accumulator, type) => {
|
|
||||||
accumulator[type.id] = type.name;
|
|
||||||
return accumulator;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
credentials.forEach(credential => {
|
|
||||||
credential.kind = typesById[credential.credential_type];
|
|
||||||
});
|
|
||||||
|
|
||||||
return credentials;
|
|
||||||
};
|
|
||||||
|
|
||||||
function CredentialList({ i18n }) {
|
function CredentialList({ i18n }) {
|
||||||
const [actions, setActions] = useState(null);
|
const [actions, setActions] = useState(null);
|
||||||
const [contentError, setContentError] = useState(null);
|
const [contentError, setContentError] = useState(null);
|
||||||
const [credentialCount, setCredentialCount] = useState(0);
|
const [credentialCount, setCredentialCount] = useState(0);
|
||||||
const [credentials, setCredentials] = useState([]);
|
const [credentials, setCredentials] = useState([]);
|
||||||
const [credentialTypes, setCredentialTypes] = useState(null);
|
|
||||||
const [deletionError, setDeletionError] = useState(null);
|
const [deletionError, setDeletionError] = useState(null);
|
||||||
const [hasContentLoading, setHasContentLoading] = useState(true);
|
const [hasContentLoading, setHasContentLoading] = useState(true);
|
||||||
const [selected, setSelected] = useState([]);
|
const [selected, setSelected] = useState([]);
|
||||||
@@ -57,19 +43,14 @@ function CredentialList({ i18n }) {
|
|||||||
{
|
{
|
||||||
data: { actions: optionActions },
|
data: { actions: optionActions },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
data: { results: credentialTypeResults },
|
|
||||||
},
|
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
CredentialsAPI.read(params),
|
CredentialsAPI.read(params),
|
||||||
loadCredentialActions(),
|
loadCredentialActions(),
|
||||||
loadCredentialTypes(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
setActions(optionActions);
|
setCredentials(results);
|
||||||
setCredentialCount(count);
|
setCredentialCount(count);
|
||||||
setCredentials(assignCredentialKinds(results, credentialTypeResults));
|
setActions(optionActions);
|
||||||
setCredentialTypes(credentialTypeResults);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setContentError(error);
|
setContentError(error);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -81,13 +62,6 @@ function CredentialList({ i18n }) {
|
|||||||
loadCredentials(location);
|
loadCredentials(location);
|
||||||
}, [location]); // eslint-disable-line react-hooks/exhaustive-deps
|
}, [location]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||||
|
|
||||||
const loadCredentialTypes = () => {
|
|
||||||
if (credentialTypes) {
|
|
||||||
return Promise.resolve({ data: { results: credentialTypes } });
|
|
||||||
}
|
|
||||||
return CredentialTypesAPI.read({ page_size: 200 });
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadCredentialActions = () => {
|
const loadCredentialActions = () => {
|
||||||
if (actions) {
|
if (actions) {
|
||||||
return Promise.resolve({ data: { actions } });
|
return Promise.resolve({ data: { actions } });
|
||||||
@@ -124,7 +98,7 @@ function CredentialList({ i18n }) {
|
|||||||
data: { count, results },
|
data: { count, results },
|
||||||
} = await CredentialsAPI.read(params);
|
} = await CredentialsAPI.read(params);
|
||||||
|
|
||||||
setCredentials(assignCredentialKinds(results, credentialTypes));
|
setCredentials(results);
|
||||||
setCredentialCount(count);
|
setCredentialCount(count);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setContentError(error);
|
setContentError(error);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { act } from 'react-dom/test-utils';
|
import { act } from 'react-dom/test-utils';
|
||||||
import { CredentialsAPI, CredentialTypesAPI } from '@api';
|
import { CredentialsAPI } from '@api';
|
||||||
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts, waitForElement } from '@testUtils/enzymeHelpers';
|
||||||
import { CredentialList } from '.';
|
import { CredentialList } from '.';
|
||||||
import { mockCredentials, mockCredentialTypes } from '../shared';
|
import mockCredentials from '../shared';
|
||||||
|
|
||||||
jest.mock('@api');
|
jest.mock('@api');
|
||||||
|
|
||||||
@@ -12,9 +12,6 @@ describe('<CredentialList />', () => {
|
|||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
CredentialsAPI.read.mockResolvedValueOnce({ data: mockCredentials });
|
CredentialsAPI.read.mockResolvedValueOnce({ data: mockCredentials });
|
||||||
CredentialTypesAPI.read.mockResolvedValueOnce({
|
|
||||||
data: mockCredentialTypes,
|
|
||||||
});
|
|
||||||
CredentialsAPI.readOptions.mockResolvedValue({
|
CredentialsAPI.readOptions.mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
actions: {
|
actions: {
|
||||||
@@ -101,9 +98,6 @@ describe('<CredentialList />', () => {
|
|||||||
|
|
||||||
test('should call api delete credentials for each selected credential', async () => {
|
test('should call api delete credentials for each selected credential', async () => {
|
||||||
CredentialsAPI.read.mockResolvedValueOnce({ data: mockCredentials });
|
CredentialsAPI.read.mockResolvedValueOnce({ data: mockCredentials });
|
||||||
CredentialTypesAPI.read.mockResolvedValueOnce({
|
|
||||||
data: mockCredentialTypes,
|
|
||||||
});
|
|
||||||
CredentialsAPI.destroy = jest.fn();
|
CredentialsAPI.destroy = jest.fn();
|
||||||
|
|
||||||
await act(async () => {
|
await act(async () => {
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ function CredentialListItem({
|
|||||||
<b>{credential.name}</b>
|
<b>{credential.name}</b>
|
||||||
</Link>
|
</Link>
|
||||||
</DataListCell>,
|
</DataListCell>,
|
||||||
<DataListCell key="type">{credential.kind}</DataListCell>,
|
<DataListCell key="type">
|
||||||
|
{credential.summary_fields.credential_type.name}
|
||||||
|
</DataListCell>,
|
||||||
<ActionButtonCell lastcolumn="true" key="action">
|
<ActionButtonCell lastcolumn="true" key="action">
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
<Tooltip content={i18n._(t`Edit Credential`)} position="top">
|
<Tooltip content={i18n._(t`Edit Credential`)} position="top">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
import { mountWithContexts } from '@testUtils/enzymeHelpers';
|
||||||
import { CredentialListItem } from '.';
|
import { CredentialListItem } from '.';
|
||||||
import { mockCredentials } from '../shared';
|
import mockCredentials from '../shared';
|
||||||
|
|
||||||
describe('<CredentialListItem />', () => {
|
describe('<CredentialListItem />', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
{
|
|
||||||
"count": 3,
|
|
||||||
"next": null,
|
|
||||||
"previous": null,
|
|
||||||
"results": [
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"type": "credential_type",
|
|
||||||
"url": "/api/v2/credential_types/1/",
|
|
||||||
"related": {
|
|
||||||
"credentials": "/api/v2/credential_types/1/credentials/",
|
|
||||||
"activity_stream": "/api/v2/credential_types/1/activity_stream/"
|
|
||||||
},
|
|
||||||
"summary_fields": {
|
|
||||||
"user_capabilities": {
|
|
||||||
"edit": false,
|
|
||||||
"delete": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"created": "2019-12-16T21:01:03.430100Z",
|
|
||||||
"modified": "2019-12-16T21:01:24.834078Z",
|
|
||||||
"name": "Machine",
|
|
||||||
"description": "",
|
|
||||||
"kind": "ssh",
|
|
||||||
"namespace": "ssh",
|
|
||||||
"managed_by_tower": true,
|
|
||||||
"inputs": {
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"id": "username",
|
|
||||||
"label": "Username",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "password",
|
|
||||||
"label": "Password",
|
|
||||||
"type": "string",
|
|
||||||
"secret": true,
|
|
||||||
"ask_at_runtime": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ssh_key_data",
|
|
||||||
"label": "SSH Private Key",
|
|
||||||
"type": "string",
|
|
||||||
"format": "ssh_private_key",
|
|
||||||
"secret": true,
|
|
||||||
"multiline": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ssh_public_key_data",
|
|
||||||
"label": "Signed SSH Certificate",
|
|
||||||
"type": "string",
|
|
||||||
"multiline": true,
|
|
||||||
"secret": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ssh_key_unlock",
|
|
||||||
"label": "Private Key Passphrase",
|
|
||||||
"type": "string",
|
|
||||||
"secret": true,
|
|
||||||
"ask_at_runtime": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "become_method",
|
|
||||||
"label": "Privilege Escalation Method",
|
|
||||||
"type": "string",
|
|
||||||
"help_text": "Specify a method for \"become\" operations. This is equivalent to specifying the --become-method Ansible parameter."
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "become_username",
|
|
||||||
"label": "Privilege Escalation Username",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "become_password",
|
|
||||||
"label": "Privilege Escalation Password",
|
|
||||||
"type": "string",
|
|
||||||
"secret": true,
|
|
||||||
"ask_at_runtime": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"injectors": {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"type": "credential_type",
|
|
||||||
"url": "/api/v2/credential_types/2/",
|
|
||||||
"related": {
|
|
||||||
"credentials": "/api/v2/credential_types/2/credentials/",
|
|
||||||
"activity_stream": "/api/v2/credential_types/2/activity_stream/"
|
|
||||||
},
|
|
||||||
"summary_fields": {
|
|
||||||
"user_capabilities": {
|
|
||||||
"edit": false,
|
|
||||||
"delete": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"created": "2019-12-16T21:01:03.443889Z",
|
|
||||||
"modified": "2019-12-16T21:01:24.844433Z",
|
|
||||||
"name": "Source Control",
|
|
||||||
"description": "",
|
|
||||||
"kind": "scm",
|
|
||||||
"namespace": "scm",
|
|
||||||
"managed_by_tower": true,
|
|
||||||
"inputs": {
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"id": "username",
|
|
||||||
"label": "Username",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "password",
|
|
||||||
"label": "Password",
|
|
||||||
"type": "string",
|
|
||||||
"secret": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ssh_key_data",
|
|
||||||
"label": "SCM Private Key",
|
|
||||||
"type": "string",
|
|
||||||
"format": "ssh_private_key",
|
|
||||||
"secret": true,
|
|
||||||
"multiline": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "ssh_key_unlock",
|
|
||||||
"label": "Private Key Passphrase",
|
|
||||||
"type": "string",
|
|
||||||
"secret": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"injectors": {}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"type": "credential_type",
|
|
||||||
"url": "/api/v2/credential_types/3/",
|
|
||||||
"related": {
|
|
||||||
"created_by": "/api/v2/users/1/",
|
|
||||||
"modified_by": "/api/v2/users/1/",
|
|
||||||
"credentials": "/api/v2/credential_types/3/credentials/",
|
|
||||||
"activity_stream": "/api/v2/credential_types/3/activity_stream/"
|
|
||||||
},
|
|
||||||
"summary_fields": {
|
|
||||||
"created_by": {
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"first_name": "",
|
|
||||||
"last_name": ""
|
|
||||||
},
|
|
||||||
"modified_by": {
|
|
||||||
"id": 1,
|
|
||||||
"username": "admin",
|
|
||||||
"first_name": "",
|
|
||||||
"last_name": ""
|
|
||||||
},
|
|
||||||
"user_capabilities": {
|
|
||||||
"edit": true,
|
|
||||||
"delete": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"created": "2019-12-17T16:11:57.723478Z",
|
|
||||||
"modified": "2019-12-17T16:12:01.582942Z",
|
|
||||||
"name": "Bar",
|
|
||||||
"description": "",
|
|
||||||
"kind": "cloud",
|
|
||||||
"namespace": null,
|
|
||||||
"managed_by_tower": false,
|
|
||||||
"inputs": {},
|
|
||||||
"injectors": {}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -21,6 +21,11 @@
|
|||||||
"user": "/api/v2/users/7/"
|
"user": "/api/v2/users/7/"
|
||||||
},
|
},
|
||||||
"summary_fields": {
|
"summary_fields": {
|
||||||
|
"credential_type": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Machine",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
"created_by": {
|
"created_by": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
@@ -84,6 +89,11 @@
|
|||||||
"user": "/api/v2/users/7/"
|
"user": "/api/v2/users/7/"
|
||||||
},
|
},
|
||||||
"summary_fields": {
|
"summary_fields": {
|
||||||
|
"credential_type": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Machine",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
"created_by": {
|
"created_by": {
|
||||||
"id": 8,
|
"id": 8,
|
||||||
"username": "user-2",
|
"username": "user-2",
|
||||||
@@ -158,6 +168,11 @@
|
|||||||
"user": "/api/v2/users/8/"
|
"user": "/api/v2/users/8/"
|
||||||
},
|
},
|
||||||
"summary_fields": {
|
"summary_fields": {
|
||||||
|
"credential_type": {
|
||||||
|
"id": 1,
|
||||||
|
"name": "Machine",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
"created_by": {
|
"created_by": {
|
||||||
"id": 9,
|
"id": 9,
|
||||||
"username": "user-3",
|
"username": "user-3",
|
||||||
@@ -232,6 +247,11 @@
|
|||||||
"user": "/api/v2/users/1/"
|
"user": "/api/v2/users/1/"
|
||||||
},
|
},
|
||||||
"summary_fields": {
|
"summary_fields": {
|
||||||
|
"credential_type": {
|
||||||
|
"id": 2,
|
||||||
|
"name": "Vault",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
"created_by": {
|
"created_by": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
@@ -306,6 +326,11 @@
|
|||||||
"user": "/api/v2/users/1/"
|
"user": "/api/v2/users/1/"
|
||||||
},
|
},
|
||||||
"summary_fields": {
|
"summary_fields": {
|
||||||
|
"credential_type": {
|
||||||
|
"id": 3,
|
||||||
|
"name": "Source Control",
|
||||||
|
"description": ""
|
||||||
|
},
|
||||||
"created_by": {
|
"created_by": {
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"username": "admin",
|
"username": "admin",
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
export { default as mockCredentials } from './data.credentials.json';
|
export { default } from './data.credentials.json';
|
||||||
export { default as mockCredentialTypes } from './data.credential_types.json';
|
|
||||||
|
|||||||
Reference in New Issue
Block a user