diff --git a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/AccessRules.tsx b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/AccessRules.tsx
index 78b680e21e8b3..dc42ed12bd12a 100644
--- a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/AccessRules.tsx
+++ b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/AccessRules.tsx
@@ -38,7 +38,7 @@ import {
RuleModel,
verbOptions,
} from './standardmodel';
-import { Section, SectionProps } from './sections';
+import { SectionBox, SectionProps } from './sections';
export function AccessRules({
value,
@@ -86,7 +86,7 @@ function AccessRule({
}) {
const { resources, verbs } = value;
return (
-
-
+
);
}
diff --git a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/MetadataSection.tsx b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/MetadataSection.tsx
index 8b3c072abcf2a..40a199bad0cb9 100644
--- a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/MetadataSection.tsx
+++ b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/MetadataSection.tsx
@@ -24,7 +24,7 @@ import Text from 'design/Text';
import { LabelsInput } from 'teleport/components/LabelsInput';
-import { Section, SectionProps } from './sections';
+import { SectionBox, SectionProps } from './sections';
import { MetadataModel } from './standardmodel';
import { MetadataValidationResult } from './validation';
@@ -34,7 +34,7 @@ export const MetadataSection = ({
validation,
onChange,
}: SectionProps) => (
- onChange?.({ ...value, labels })}
rule={precomputed(validation.fields.labels)}
/>
-
+
);
diff --git a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.test.tsx b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.test.tsx
index da52de8befdce..a866d881b040b 100644
--- a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.test.tsx
+++ b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.test.tsx
@@ -22,36 +22,39 @@ import { Validator } from 'shared/components/Validation';
import selectEvent from 'react-select-event';
import {
- AppAccessSpec,
- DatabaseAccessSpec,
- KubernetesAccessSpec,
- newAccessSpec,
- ServerAccessSpec,
- WindowsDesktopAccessSpec,
+ ServerAccess,
+ newResourceAccess,
+ KubernetesAccess,
+ AppAccess,
+ DatabaseAccess,
+ WindowsDesktopAccess,
} from './standardmodel';
-import { AccessSpecValidationResult, validateAccessSpec } from './validation';
import {
- ServerAccessSpecSection,
- KubernetesAccessSpecSection,
- AppAccessSpecSection,
- DatabaseAccessSpecSection,
- WindowsDesktopAccessSpecSection,
+ ResourceAccessValidationResult,
+ validateResourceAccess,
+} from './validation';
+import {
+ ServerAccessSection,
+ KubernetesAccessSection,
+ AppAccessSection,
+ DatabaseAccessSection,
+ WindowsDesktopAccessSection,
} from './Resources';
import { StatefulSection } from './StatefulSection';
-describe('ServerAccessSpecSection', () => {
+describe('ServerAccessSection', () => {
const setup = () => {
const onChange = jest.fn();
let validator: Validator;
render(
-
- component={ServerAccessSpecSection}
- defaultValue={newAccessSpec('node')}
+
+ component={ServerAccessSection}
+ defaultValue={newResourceAccess('node')}
onChange={onChange}
validatorRef={v => {
validator = v;
}}
- validate={validateAccessSpec}
+ validate={validateResourceAccess}
/>
);
return { user: userEvent.setup(), onChange, validator };
@@ -80,7 +83,7 @@ describe('ServerAccessSpecSection', () => {
expect.objectContaining({ label: 'root', value: 'root' }),
expect.objectContaining({ label: 'some-user', value: 'some-user' }),
],
- } as ServerAccessSpec);
+ } as ServerAccess);
});
test('validation', async () => {
@@ -99,25 +102,25 @@ describe('ServerAccessSpecSection', () => {
});
});
-describe('KubernetesAccessSpecSection', () => {
+describe('KubernetesAccessSection', () => {
const setup = () => {
const onChange = jest.fn();
let validator: Validator;
render(
-
- component={KubernetesAccessSpecSection}
- defaultValue={newAccessSpec('kube_cluster')}
+
+ component={KubernetesAccessSection}
+ defaultValue={newResourceAccess('kube_cluster')}
onChange={onChange}
validatorRef={v => {
validator = v;
}}
- validate={validateAccessSpec}
+ validate={validateResourceAccess}
/>
);
return { user: userEvent.setup(), onChange, validator };
};
- test('editing the spec', async () => {
+ test('editing', async () => {
const { user, onChange } = setup();
await selectEvent.create(screen.getByLabelText('Groups'), 'group1', {
@@ -167,7 +170,7 @@ describe('KubernetesAccessSpecSection', () => {
],
},
],
- } as KubernetesAccessSpec);
+ } as KubernetesAccess);
});
test('adding and removing resources', async () => {
@@ -242,19 +245,19 @@ describe('KubernetesAccessSpecSection', () => {
});
});
-describe('AppAccessSpecSection', () => {
+describe('AppAccessSection', () => {
const setup = () => {
const onChange = jest.fn();
let validator: Validator;
render(
-
- component={AppAccessSpecSection}
- defaultValue={newAccessSpec('app')}
+
+ component={AppAccessSection}
+ defaultValue={newResourceAccess('app')}
onChange={onChange}
validatorRef={v => {
validator = v;
}}
- validate={validateAccessSpec}
+ validate={validateResourceAccess}
/>
);
return { user: userEvent.setup(), onChange, validator };
@@ -314,7 +317,7 @@ describe('AppAccessSpecSection', () => {
'{{internal.gcp_service_accounts}}',
'admin@some-project.iam.gserviceaccount.com',
],
- } as AppAccessSpec);
+ } as AppAccess);
});
test('validation', async () => {
@@ -348,19 +351,19 @@ describe('AppAccessSpecSection', () => {
});
});
-describe('DatabaseAccessSpecSection', () => {
+describe('DatabaseAccessSection', () => {
const setup = () => {
const onChange = jest.fn();
let validator: Validator;
render(
-
- component={DatabaseAccessSpecSection}
- defaultValue={newAccessSpec('db')}
+
+ component={DatabaseAccessSection}
+ defaultValue={newResourceAccess('db')}
onChange={onChange}
validatorRef={v => {
validator = v;
}}
- validate={validateAccessSpec}
+ validate={validateResourceAccess}
/>
);
return { user: userEvent.setup(), onChange, validator };
@@ -395,7 +398,7 @@ describe('DatabaseAccessSpecSection', () => {
expect.objectContaining({ value: '{{internal.db_users}}' }),
expect.objectContaining({ label: 'mary', value: 'mary' }),
],
- } as DatabaseAccessSpec);
+ } as DatabaseAccess);
});
test('validation', async () => {
@@ -414,19 +417,19 @@ describe('DatabaseAccessSpecSection', () => {
});
});
-describe('WindowsDesktopAccessSpecSection', () => {
+describe('WindowsDesktopAccessSection', () => {
const setup = () => {
const onChange = jest.fn();
let validator: Validator;
render(
-
- component={WindowsDesktopAccessSpecSection}
- defaultValue={newAccessSpec('windows_desktop')}
+
+ component={WindowsDesktopAccessSection}
+ defaultValue={newResourceAccess('windows_desktop')}
onChange={onChange}
validatorRef={v => {
validator = v;
}}
- validate={validateAccessSpec}
+ validate={validateResourceAccess}
/>
);
return { user: userEvent.setup(), onChange, validator };
@@ -447,7 +450,7 @@ describe('WindowsDesktopAccessSpecSection', () => {
expect.objectContaining({ value: '{{internal.windows_logins}}' }),
expect.objectContaining({ label: 'julio', value: 'julio' }),
],
- } as WindowsDesktopAccessSpec);
+ } as WindowsDesktopAccess);
});
test('validation', async () => {
diff --git a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.tsx b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.tsx
index 57315a48b122b..65f1281e64baa 100644
--- a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.tsx
+++ b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/Resources.tsx
@@ -33,33 +33,33 @@ import styled, { useTheme } from 'styled-components';
import { LabelsInput } from 'teleport/components/LabelsInput';
-import { SectionProps, Section } from './sections';
+import { SectionProps, SectionBox } from './sections';
import {
- AccessSpecKind,
- AccessSpec,
- ServerAccessSpec,
- KubernetesAccessSpec,
+ ResourceAccessKind,
+ ResourceAccess,
+ ServerAccess,
+ KubernetesAccess,
newKubernetesResourceModel,
KubernetesResourceModel,
kubernetesResourceKindOptions,
kubernetesVerbOptions,
- AppAccessSpec,
- DatabaseAccessSpec,
- WindowsDesktopAccessSpec,
+ AppAccess,
+ DatabaseAccess,
+ WindowsDesktopAccess,
} from './standardmodel';
import {
- AccessSpecValidationResult,
- ServerSpecValidationResult,
- KubernetesSpecValidationResult,
+ ResourceAccessValidationResult,
+ ServerAccessValidationResult,
+ KubernetesAccessValidationResult,
KubernetesResourceValidationResult,
- AppSpecValidationResult,
- DatabaseSpecValidationResult,
- WindowsDesktopSpecValidationResult,
+ AppAccessValidationResult,
+ DatabaseAccessValidationResult,
+ WindowsDesktopAccessValidationResult,
} from './validation';
-/** Maps access specification kind to UI component configuration. */
-export const specSections: Record<
- AccessSpecKind,
+/** Maps resource access kind to UI component configuration. */
+export const resourceAccessSections: Record<
+ ResourceAccessKind,
{
title: string;
tooltip: string;
@@ -69,37 +69,37 @@ export const specSections: Record<
kube_cluster: {
title: 'Kubernetes',
tooltip: 'Configures access to Kubernetes clusters',
- component: KubernetesAccessSpecSection,
+ component: KubernetesAccessSection,
},
node: {
title: 'Servers',
tooltip: 'Configures access to SSH servers',
- component: ServerAccessSpecSection,
+ component: ServerAccessSection,
},
app: {
title: 'Applications',
tooltip: 'Configures access to applications',
- component: AppAccessSpecSection,
+ component: AppAccessSection,
},
db: {
title: 'Databases',
tooltip: 'Configures access to databases',
- component: DatabaseAccessSpecSection,
+ component: DatabaseAccessSection,
},
windows_desktop: {
title: 'Windows Desktops',
tooltip: 'Configures access to Windows desktops',
- component: WindowsDesktopAccessSpecSection,
+ component: WindowsDesktopAccessSection,
},
};
/**
- * A generic access spec section. Details are rendered by components from the
- * `specSections` map.
+ * A generic resource section. Details are rendered by components from the
+ * `resourceAccessSections` map.
*/
-export const AccessSpecSection = <
- T extends AccessSpec,
- V extends AccessSpecValidationResult,
+export const ResourceAccessSection = <
+ T extends ResourceAccess,
+ V extends ResourceAccessValidationResult,
>({
value,
isProcessing,
@@ -109,9 +109,13 @@ export const AccessSpecSection = <
}: SectionProps & {
onRemove?(): void;
}) => {
- const { component: Body, title, tooltip } = specSections[value.kind];
+ const {
+ component: Body,
+ title,
+ tooltip,
+ } = resourceAccessSections[value.kind];
return (
-
-
+
);
};
-export function ServerAccessSpecSection({
+export function ServerAccessSection({
value,
isProcessing,
validation,
onChange,
-}: SectionProps) {
+}: SectionProps) {
return (
<>
@@ -165,12 +169,12 @@ export function ServerAccessSpecSection({
);
}
-export function KubernetesAccessSpecSection({
+export function KubernetesAccessSection({
value,
isProcessing,
validation,
onChange,
-}: SectionProps) {
+}: SectionProps) {
return (
<>
) {
+}: SectionProps) {
return (
@@ -369,12 +373,12 @@ export function AppAccessSpecSection({
);
}
-export function DatabaseAccessSpecSection({
+export function DatabaseAccessSection({
value,
isProcessing,
validation,
onChange,
-}: SectionProps) {
+}: SectionProps) {
return (
<>
@@ -443,12 +447,12 @@ export function DatabaseAccessSpecSection({
);
}
-export function WindowsDesktopAccessSpecSection({
+export function WindowsDesktopAccessSection({
value,
isProcessing,
validation,
onChange,
-}: SectionProps) {
+}: SectionProps) {
return (
<>
diff --git a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.test.tsx b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.test.tsx
index 525744c64146d..44d360ddeaf34 100644
--- a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.test.tsx
+++ b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.test.tsx
@@ -60,7 +60,7 @@ test('adding and removing sections', async () => {
expect(getAllSectionNames()).toEqual([]);
await user.click(
- screen.getByRole('button', { name: 'Add New Specifications' })
+ screen.getByRole('button', { name: 'Add New Resource Access' })
);
expect(getAllMenuItemNames()).toEqual([
'Kubernetes',
@@ -74,7 +74,7 @@ test('adding and removing sections', async () => {
expect(getAllSectionNames()).toEqual(['Servers']);
await user.click(
- screen.getByRole('button', { name: 'Add New Specifications' })
+ screen.getByRole('button', { name: 'Add New Resource Access' })
);
expect(getAllMenuItemNames()).toEqual([
'Kubernetes',
diff --git a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.tsx b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.tsx
index 8b4eecb36b365..d70c88f52e983 100644
--- a/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.tsx
+++ b/web/packages/teleport/src/Roles/RoleEditor/StandardEditor/StandardEditor.tsx
@@ -33,16 +33,16 @@ import {
hasModifiedFields,
RoleEditorModel,
StandardEditorModel,
- AccessSpecKind,
- AccessSpec,
- newAccessSpec,
+ ResourceAccessKind,
+ ResourceAccess,
+ newResourceAccess,
RuleModel,
OptionsModel,
} from './standardmodel';
import { validateRoleEditorModel } from './validation';
import { RequiresResetToStandard } from './RequiresResetToStandard';
import { MetadataSection } from './MetadataSection';
-import { AccessSpecSection, specSections } from './Resources';
+import { ResourceAccessSection, resourceAccessSections } from './Resources';
import { AccessRules } from './AccessRules';
import { Options } from './Options';
@@ -71,9 +71,9 @@ export const StandardEditor = ({
const { roleModel } = standardEditorModel;
const validation = validateRoleEditorModel(roleModel);
- /** All spec kinds except those that are already in the role. */
- const allowedSpecKinds = allAccessSpecKinds.filter(k =>
- roleModel.accessSpecs.every(as => as.kind !== k)
+ /** All resource access kinds except those that are already in the role. */
+ const allowedResourceAccessKinds = allResourceAccessKinds.filter(k =>
+ roleModel.resources.every(as => as.kind !== k)
);
enum StandardEditorTab {
@@ -112,29 +112,29 @@ export const StandardEditor = ({
});
}
- function addAccessSpec(kind: AccessSpecKind) {
+ function addResourceAccess(kind: ResourceAccessKind) {
handleChange({
...standardEditorModel.roleModel,
- accessSpecs: [
- ...standardEditorModel.roleModel.accessSpecs,
- newAccessSpec(kind),
+ resources: [
+ ...standardEditorModel.roleModel.resources,
+ newResourceAccess(kind),
],
});
}
- function removeAccessSpec(kind: AccessSpecKind) {
+ function removeResourceAccess(kind: ResourceAccessKind) {
handleChange({
...standardEditorModel.roleModel,
- accessSpecs: standardEditorModel.roleModel.accessSpecs.filter(
+ resources: standardEditorModel.roleModel.resources.filter(
s => s.kind !== kind
),
});
}
- function setAccessSpec(value: AccessSpec) {
+ function setResourceAccess(value: ResourceAccess) {
handleChange({
...standardEditorModel.roleModel,
- accessSpecs: standardEditorModel.roleModel.accessSpecs.map(original =>
+ resources: standardEditorModel.roleModel.resources.map(original =>
original.kind === value.kind ? value : original
),
});
@@ -185,7 +185,7 @@ export const StandardEditor = ({
controls: resourcesTabId,
status:
validator.state.validating &&
- validation.accessSpecs.some(s => !s.valid)
+ validation.resources.some(s => !s.valid)
? validationErrorTabStatus
: undefined,
},
@@ -238,16 +238,16 @@ export const StandardEditor = ({
}}
>
- {roleModel.accessSpecs.map((spec, i) => {
- const validationResult = validation.accessSpecs[i];
+ {roleModel.resources.map((res, i) => {
+ const validationResult = validation.resources[i];
return (
- setAccessSpec(value)}
- onRemove={() => removeAccessSpec(spec.kind)}
+ onChange={value => setResourceAccess(value)}
+ onRemove={() => removeResourceAccess(res.kind)}
/>
);
})}
@@ -266,18 +266,22 @@ export const StandardEditor = ({
buttonText={
<>
- Add New Specifications
+ Add New Resource Access
>
}
buttonProps={{
size: 'medium',
fill: 'filled',
- disabled: isProcessing || allowedSpecKinds.length === 0,
+ disabled:
+ isProcessing || allowedResourceAccessKinds.length === 0,
}}
>
- {allowedSpecKinds.map(kind => (
-