joyent-portal/packages/instance-steps/src/firewall/index.js

218 lines
6.8 KiB
JavaScript

import React, { Fragment } from 'react';
import { withTheme } from 'styled-components';
import { Margin } from 'styled-components-spacing';
import Flex, { FlexItem } from 'styled-flex-component';
import { compose, graphql } from 'react-apollo';
import { Link } from 'react-router-dom';
import ReduxForm from 'declarative-redux-form';
import { connect } from 'react-redux';
import { change } from 'redux-form';
import get from 'lodash.get';
import forceArray from 'force-array';
import Step, {
Header as StepHeader,
Description as StepDescription,
Preview as StepPreview,
Outlet as StepOutlet
} from 'joyent-ui-resource-step';
import { H3, Button, P, FirewallIcon } from 'joyent-ui-toolkit';
import {
TagRules,
DefaultRules,
ToggleFirewallForm,
ToggleInactiveForm,
Empty
} from 'joyent-ui-resource-widgets';
import { Forms, Values } from '../constants';
import { Preview } from './components';
import ListFwRules from '../graphql/list-fw-rules.gql';
const { IR_FW_F_ENABLED, IR_FW_F_INACTIVE } = Forms;
const { IR_TAG_V_TAGS } = Values;
const Firewall = ({
handleGetValue,
preview = {},
defaultRules = [],
tagRules = [],
loading = false,
enabled = false,
showInactiveRules = null,
showInactive = false,
theme = {},
...props
}) => {
const mobile = theme.screen === 'mobile';
return (
<Step name="firewall" getValue={handleGetValue} {...props}>
<StepHeader icon={<FirewallIcon />}>Firewall rules</StepHeader>
<StepDescription href="https://docs.joyent.com/public-cloud/network/firewall">
Cloud firewall rules secure instances by defining network traffic rules,
controlling incoming and outgoing traffic. Enabling the firewall applies
only rules which match your instance. Although these rules are created
in the firewall console, the addition of tags can alter the firewall
rules.
</StepDescription>
<StepPreview>
<Margin top="3">
<Preview {...preview} />
</Margin>
</StepPreview>
<StepOutlet>
{({ next }) => (
<Fragment>
<Margin top="5">
<Flex column={mobile}>
<FlexItem>
<ReduxForm
form={IR_FW_F_ENABLED}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
>
{props => (
<Margin right="5" bottom={mobile ? '2' : '0'}>
<ToggleFirewallForm {...props} submitting={loading} />
</Margin>
)}
</ReduxForm>
</FlexItem>
<FlexItem>
<ReduxForm
form={IR_FW_F_INACTIVE}
destroyOnUnmount={false}
forceUnregisterOnUnmount={true}
>
{props =>
enabled && !loading ? (
<ToggleInactiveForm {...props} />
) : null
}
</ReduxForm>
</FlexItem>
</Flex>
</Margin>
{enabled && !loading && !defaultRules.length && !tagRules.length ? (
<Margin top="5">
<Empty borderTop>
<Fragment>
<H3>No Firewall rules found</H3>
<Margin top="1">
<P>
Try viewing inactive rules instead to see firewalls that
can potentially affect your instance
</P>
</Margin>
<Margin top="2">
<Button
secondary
onClick={showInactiveRules}
disabled={showInactive}
>
View Inactive Rules
</Button>
</Margin>
</Fragment>
</Empty>
</Margin>
) : null}
{!loading && enabled && defaultRules.length ? (
<Margin top="5">
<DefaultRules rules={defaultRules} />
</Margin>
) : null}
{!loading && enabled && tagRules.length ? (
<Margin top="5">
<TagRules rules={tagRules} />
</Margin>
) : null}
{!loading && enabled && (tagRules.length || defaultRules.length) ? (
<Margin top="5">
<P>
*Other firewall rules may apply as defined by wildcard(s),
IP(s), subnet(s), tag(s) or VM(s). Please see{' '}
<a
href="https://apidocs.joyent.com/cloudapi/#firewall-rule-syntax"
target="_blank"
rel="noopener noreferrer"
>
firewall rule list
</a>{' '}
for more details.
</P>
</Margin>
) : null}
<Margin top="5">
<Button
id="next-button-firewall"
type="button"
component={Link}
to={next}
fluid={mobile}
>
Next
</Button>
</Margin>
</Fragment>
)}
</StepOutlet>
</Step>
);
};
export default compose(
connect(({ form, values }, ownProps) => ({
...ownProps,
enabled: get(form, `${IR_FW_F_ENABLED}.values.enabled`, false),
showInactive: get(form, `${IR_FW_F_INACTIVE}.values.inactive`, false),
tags: get(values, IR_TAG_V_TAGS, [])
})),
graphql(ListFwRules, {
options: ({ tags, expanded, enabled }) => ({
ssr: false,
fetchPolicy: expanded && enabled ? 'cache-first' : 'cache-only',
variables: {
tags: tags.map(({ name, value }) => ({ name, value }))
}
}),
props: ({ ownProps, data }) => {
const { enabled, showInactive } = ownProps;
const {
firewall_rules_create_machine = [],
loading,
error,
refetch
} = data;
const rules = forceArray(firewall_rules_create_machine).filter(
({ enabled }) => enabled || showInactive
);
const defaultRules = rules.filter(
({ rule_obj = {} }) => rule_obj.isWildcard
);
const tagRules = rules.filter(
({ rule_obj = {} }) => rule_obj.tags.length
);
return {
defaultRules,
tagRules,
loading,
error,
refetch,
handleGetValue: () => ({ enabled, defaultRules, tagRules })
};
}
}),
connect(null, (dispatch, { ...args }) => ({
showInactiveRules: () =>
dispatch(change(IR_FW_F_INACTIVE, 'inactive', true))
}))
)(withTheme(({ ...rest }) => <Firewall {...rest} />));