Skip to content

Commit

Permalink
Merge branch 'master' into gzdunek/reissue-kube-certs
Browse files Browse the repository at this point in the history
  • Loading branch information
gzdunek authored Jan 14, 2025
2 parents 513db25 + 73abfe8 commit 9fdbf3d
Show file tree
Hide file tree
Showing 15 changed files with 736 additions and 249 deletions.
2 changes: 2 additions & 0 deletions integration/proxy/proxy_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,8 @@ func mustConnectWebAppGateway(ctx context.Context, t *testing.T, _ *daemon.Servi
require.Equal(t, http.StatusOK, resp.StatusCode)
}

type testGatewayConnectionFunc func(context.Context, *testing.T, *daemon.Service, gateway.Gateway)

func makeMustConnectMultiPortTCPAppGateway(wantMessage string, otherTargetPort int, otherWantMessage string) testGatewayConnectionFunc {
return func(ctx context.Context, t *testing.T, d *daemon.Service, gw gateway.Gateway) {
t.Helper()
Expand Down
2 changes: 0 additions & 2 deletions integration/proxy/teleterm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,6 @@ func testDBGatewayCertRenewal(ctx context.Context, t *testing.T, params dbGatewa
)
}

type testGatewayConnectionFunc func(context.Context, *testing.T, *daemon.Service, gateway.Gateway)

type generateAndSetupUserCredsFunc func(t *testing.T, tc *libclient.TeleportClient, ttl time.Duration)

type gatewayCertRenewalParams struct {
Expand Down
22 changes: 6 additions & 16 deletions web/packages/teleport/src/Roles/RoleEditor/RoleEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@ import { EditorHeader } from './EditorHeader';
import { EditorTab } from './EditorTabs';
import { StandardEditor } from './StandardEditor/StandardEditor';
import {
newRole,
roleEditorModelToRole,
roleToRoleEditorModel,
StandardEditorModel,
} from './StandardEditor/standardmodel';
import { useStandardModel } from './StandardEditor/useStandardModel';
import { YamlEditor } from './YamlEditor';
import { YamlEditorModel } from './yamlmodel';

Expand Down Expand Up @@ -65,16 +64,7 @@ export const RoleEditor = ({
const standardEditorId = `${idPrefix}-standard`;
const yamlEditorId = `${idPrefix}-yaml`;

const [standardModel, setStandardModel] = useState<StandardEditorModel>(
() => {
const role = originalRole?.object ?? newRole();
const roleModel = roleToRoleEditorModel(role, role);
return {
roleModel,
isDirty: !originalRole, // New role is dirty by default.
};
}
);
const [standardModel, dispatch] = useStandardModel(originalRole?.object);

const [yamlModel, setYamlModel] = useState<YamlEditorModel>({
content: originalRole?.yaml ?? '',
Expand Down Expand Up @@ -141,9 +131,9 @@ export const RoleEditor = ({
// Abort if there's an error. Don't switch the tab or set the model.
if (err) return;

setStandardModel({
roleModel,
isDirty: yamlModel.isDirty,
dispatch({
type: 'set-role-model',
payload: roleModel,
});
break;
}
Expand Down Expand Up @@ -213,7 +203,7 @@ export const RoleEditor = ({
onCancel={handleCancel}
standardEditorModel={standardModel}
isProcessing={isProcessing}
onChange={setStandardModel}
dispatch={dispatch}
/>
</Flex>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,29 @@ import { ResourceKind } from 'teleport/services/resources';

import { AccessRules } from './AccessRules';
import { RuleModel } from './standardmodel';
import { StatefulSection } from './StatefulSection';
import { AccessRuleValidationResult, validateAccessRule } from './validation';
import { StatefulSectionWithDispatch } from './StatefulSection';
import { AccessRuleValidationResult } from './validation';

describe('AccessRules', () => {
const setup = () => {
const onChange = jest.fn();
const modelRef = jest.fn();
let validator: Validator;
render(
<StatefulSection<RuleModel[], AccessRuleValidationResult[]>
<StatefulSectionWithDispatch<RuleModel[], AccessRuleValidationResult[]>
selector={m => m.roleModel.rules}
validationSelector={m => m.validationResult.rules}
component={AccessRules}
defaultValue={[]}
onChange={onChange}
validatorRef={v => {
validator = v;
}}
validate={rules => rules.map(validateAccessRule)}
modelRef={modelRef}
/>
);
return { user: userEvent.setup(), onChange, validator };
return { user: userEvent.setup(), modelRef, validator };
};

test('editing', async () => {
const { user, onChange } = setup();
const { user, modelRef } = setup();
await user.click(screen.getByRole('button', { name: 'Add New' }));
await selectEvent.select(screen.getByLabelText('Resources'), [
'db',
Expand All @@ -58,7 +58,7 @@ describe('AccessRules', () => {
'list',
'read',
]);
expect(onChange).toHaveBeenLastCalledWith([
expect(modelRef).toHaveBeenLastCalledWith([
{
id: expect.any(String),
resources: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { memo } from 'react';
import { components, MultiValueProps } from 'react-select';
import styled from 'styled-components';

Expand All @@ -29,9 +30,8 @@ import {
} from 'shared/components/FieldSelect';
import { precomputed } from 'shared/components/Validation/rules';

import { SectionBox, SectionProps } from './sections';
import { SectionBox, SectionPropsWithDispatch } from './sections';
import {
newRuleModel,
ResourceKindOption,
resourceKindOptions,
resourceKindOptionsMap,
Expand All @@ -40,20 +40,18 @@ import {
} from './standardmodel';
import { AccessRuleValidationResult } from './validation';

export function AccessRules({
/**
* Access rules tab. This component is memoized to optimize performance; make
* sure that the properties don't change unless necessary.
*/
export const AccessRules = memo(function AccessRules({
value,
isProcessing,
validation,
onChange,
}: SectionProps<RuleModel[], AccessRuleValidationResult[]>) {
dispatch,
}: SectionPropsWithDispatch<RuleModel[], AccessRuleValidationResult[]>) {
function addRule() {
onChange?.([...value, newRuleModel()]);
}
function setRule(rule: RuleModel) {
onChange?.(value.map(r => (r.id === rule.id ? rule : r)));
}
function removeRule(id: string) {
onChange?.(value.filter(r => r.id !== id));
dispatch({ type: 'add-access-rule' });
}
return (
<Flex flexDirection="column" gap={3}>
Expand All @@ -62,9 +60,8 @@ export function AccessRules({
key={rule.id}
isProcessing={isProcessing}
value={rule}
onChange={setRule}
validation={validation[i]}
onRemove={() => removeRule(rule.id)}
dispatch={dispatch}
/>
))}
<ButtonSecondary alignSelf="start" onClick={addRule}>
Expand All @@ -73,26 +70,29 @@ export function AccessRules({
</ButtonSecondary>
</Flex>
);
}
});

function AccessRule({
const AccessRule = memo(function AccessRule({
value,
isProcessing,
validation,
onChange,
onRemove,
}: SectionProps<RuleModel, AccessRuleValidationResult> & {
onRemove?(): void;
}) {
const { resources, verbs } = value;
dispatch,
}: SectionPropsWithDispatch<RuleModel, AccessRuleValidationResult>) {
const { id, resources, verbs } = value;
function setRule(rule: RuleModel) {
dispatch({ type: 'set-access-rule', payload: rule });
}
function removeRule() {
dispatch({ type: 'remove-access-rule', payload: { id } });
}
return (
<SectionBox
title="Access Rule"
tooltip="A rule that gives users access to certain kinds of resources"
removable
isProcessing={isProcessing}
validation={validation}
onRemove={onRemove}
onRemove={removeRule}
>
<ResourceKindSelect
components={{ MultiValue: ResourceKindMultiValue }}
Expand All @@ -101,7 +101,7 @@ function AccessRule({
isDisabled={isProcessing}
options={resourceKindOptions}
value={resources}
onChange={r => onChange?.({ ...value, resources: r })}
onChange={r => setRule({ ...value, resources: r })}
rule={precomputed(validation.fields.resources)}
/>
<FieldSelect
Expand All @@ -110,13 +110,13 @@ function AccessRule({
isDisabled={isProcessing}
options={verbOptions}
value={verbs}
onChange={v => onChange?.({ ...value, verbs: v })}
onChange={v => setRule({ ...value, verbs: v })}
rule={precomputed(validation.fields.verbs)}
mb={0}
/>
</SectionBox>
);
}
});

const ResourceKindSelect = styled(
FieldSelectCreatable<ResourceKindOption, true>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { useId } from 'react';
import { memo, useId } from 'react';
import styled, { useTheme } from 'styled-components';

import Box from 'design/Box';
Expand All @@ -35,7 +35,11 @@ import {
sessionRecordingModeOptions,
} from './standardmodel';

export function Options({
/**
* Options tab. This component is memoized to optimize performance; make sure
* that the properties don't change unless necessary.
*/
export const Options = memo(function Options({
value,
isProcessing,
onChange,
Expand Down Expand Up @@ -189,7 +193,7 @@ export function Options({
/>
</OptionsGridContainer>
);
}
});

const OptionsGridContainer = styled(Box)`
display: grid;
Expand Down
Loading

0 comments on commit 9fdbf3d

Please sign in to comment.