Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ingest] Address #59376 feedback #59961

Merged
merged 7 commits into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
} from '@elastic/eui';
import { Error } from '../../../components';
import { AGENT_CONFIG_PATH } from '../../../constants';
import { useLink } from '../../../hooks';
import { useCore, useLink } from '../../../hooks';
import { AgentConfig, PackageInfo, GetAgentConfigsResponseItem } from '../../../types';
import { useGetPackageInfoByKey, useGetAgentConfigs, sendGetOneAgentConfig } from '../../../hooks';

Expand All @@ -30,6 +30,7 @@ export const StepSelectConfig: React.FunctionComponent<{
cancelUrl: string;
onNext: () => void;
}> = ({ pkgkey, updatePackageInfo, agentConfig, updateAgentConfig, cancelUrl, onNext }) => {
const core = useCore();
// Selected config state
const [selectedConfigId, setSelectedConfigId] = useState<string | undefined>(
agentConfig ? agentConfig.id : undefined
Expand Down Expand Up @@ -134,7 +135,12 @@ export const StepSelectConfig: React.FunctionComponent<{
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonEmpty iconType="plusInCircle" href={CREATE_NEW_CONFIG_URI} size="s">
<EuiButtonEmpty
isDisabled={!core.application.capabilities.ingestManager.write}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personal opinion: I found this verbose, should we have a hook that hide some of this complexity.
Maybe something like const hasWriteCapabilites = useWriteCapabilites()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's wordy, but would like to hold off generalizing it until we have a better idea of our permissions model and workflows

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I wrote made sense to me at the time, but I now agree we should just pack this up into a hook. I'll send a commit soon.

iconType="plusInCircle"
href={CREATE_NEW_CONFIG_URI}
size="s"
>
<FormattedMessage
id="xpack.ingestManager.createDatasource.StepSelectConfig.createNewConfigButtonText"
defaultMessage="Create new configuration"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
} from '@elastic/eui';
import { Props as EuiTabProps } from '@elastic/eui/src/components/tabs/tab';
import styled from 'styled-components';
import { useGetOneAgentConfig } from '../../../hooks';
import { useCore, useGetOneAgentConfig } from '../../../hooks';
import { Datasource } from '../../../types';
import { Loading } from '../../../components';
import { WithHeaderLayout } from '../../../layouts';
Expand Down Expand Up @@ -57,6 +57,7 @@ export const AgentConfigDetailsLayout: React.FunctionComponent = () => {
const {
params: { configId, tabId = '' },
} = useRouteMatch<{ configId: string; tabId?: string }>();
const core = useCore();
const agentConfigRequest = useGetOneAgentConfig(configId);
const agentConfig = agentConfigRequest.data ? agentConfigRequest.data.item : null;
const { isLoading, error, sendRequest: refreshAgentConfig } = agentConfigRequest;
Expand Down Expand Up @@ -318,7 +319,12 @@ export const AgentConfigDetailsLayout: React.FunctionComponent = () => {
</h2>
}
actions={
<EuiButton fill iconType="plusInCircle" href={URI.ADD_DATASOURCE}>
<EuiButton
isDisabled={!core.application.capabilities.ingestManager.write}
fill
iconType="plusInCircle"
href={URI.ADD_DATASOURCE}
>
<FormattedMessage
id="xpack.ingestManager.configDetails.addDatasourceButtonText"
defaultMessage="Create data source"
Expand All @@ -330,7 +336,11 @@ export const AgentConfigDetailsLayout: React.FunctionComponent = () => {
}
search={{
toolsRight: [
<EuiButton iconType="plusInCircle" href={URI.ADD_DATASOURCE}>
<EuiButton
isDisabled={!core.application.capabilities.ingestManager.write}
iconType="plusInCircle"
href={URI.ADD_DATASOURCE}
>
<FormattedMessage
id="xpack.ingestManager.configDetails.addDatasourceButtonText"
defaultMessage="Create data source"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ interface Props {
}

export const CreateAgentConfigFlyout: React.FunctionComponent<Props> = ({ onClose }) => {
const { notifications } = useCore();
const { application, notifications } = useCore();

const [agentConfig, setAgentConfig] = useState<NewAgentConfig>({
name: '',
Expand Down Expand Up @@ -93,7 +93,11 @@ export const CreateAgentConfigFlyout: React.FunctionComponent<Props> = ({ onClos
<EuiButton
fill
isLoading={isLoading}
disabled={isLoading || Object.keys(validation).length > 0}
isDisabled={
!application.capabilities.ingestManager.write ||
isLoading ||
Object.keys(validation).length > 0
}
onClick={async () => {
setIsLoading(true);
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
} from '../../../constants';
import { WithHeaderLayout } from '../../../layouts';
import {
useCore,
useGetAgentConfigs,
usePagination,
useLink,
Expand Down Expand Up @@ -87,6 +88,7 @@ const DangerEuiContextMenuItem = styled(EuiContextMenuItem)`

const RowActions = React.memo<{ config: AgentConfig; onDelete: () => void }>(
({ config, onDelete }) => {
const core = useCore();
const DETAILS_URI = useLink(`${AGENT_CONFIG_DETAILS_PATH}${config.id}`);
const ADD_DATASOURCE_URI = `${DETAILS_URI}/add-datasource`;

Expand Down Expand Up @@ -120,6 +122,7 @@ const RowActions = React.memo<{ config: AgentConfig; onDelete: () => void }>(
</EuiContextMenuItem>,

<EuiContextMenuItem
disabled={!core.application.capabilities.ingestManager.write}
icon="plusInCircle"
href={ADD_DATASOURCE_URI}
key="createDataSource"
Expand All @@ -130,7 +133,7 @@ const RowActions = React.memo<{ config: AgentConfig; onDelete: () => void }>(
/>
</EuiContextMenuItem>,

<EuiContextMenuItem icon="copy" disabled={true} key="copyConfig">
<EuiContextMenuItem icon="copy" key="copyConfig">
jfsiii marked this conversation as resolved.
Show resolved Hide resolved
<FormattedMessage
id="xpack.ingestManager.agentConfigList.copyConfigActionText"
defaultMessage="Copy configuration"
Expand Down Expand Up @@ -162,6 +165,7 @@ const RowActions = React.memo<{ config: AgentConfig; onDelete: () => void }>(

export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
// Config information
const core = useCore();
const {
fleet: { enabled: isFleetEnabled },
} = useConfig();
Expand Down Expand Up @@ -309,6 +313,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
<EuiButton
fill
iconType="plusInCircle"
isDisabled={!core.application.capabilities.ingestManager.write}
onClick={() => setIsCreateAgentConfigFlyoutOpen(true)}
>
<FormattedMessage
Expand All @@ -317,7 +322,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
/>
</EuiButton>
),
[setIsCreateAgentConfigFlyoutOpen]
[core.application.capabilities.ingestManager.write, setIsCreateAgentConfigFlyoutOpen]
);

const emptyPrompt = useMemo(
Expand All @@ -331,7 +336,7 @@ export const AgentConfigListPage: React.FunctionComponent<{}> = () => {
/>
</h2>
}
actions={createAgentConfigButton}
actions={false ?? createAgentConfigButton}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update this with the correct core.application...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure to understand this expression it's not always going to return createAgentConfigButton?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't mean to add that. Will fix

/>
),
[createAgentConfigButton]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { FormattedMessage } from '@kbn/i18n/react';
import { EuiFlexGroup, EuiFlexItem, EuiPage, EuiTitle, IconType, EuiButton } from '@elastic/eui';
import { PackageInfo } from '../../../../types';
import { EPM_PATH } from '../../../../constants';
import { useLink } from '../../../../hooks';
import { useCore, useLink } from '../../../../hooks';
import { IconPanel } from '../../components/icon_panel';
import { NavButtonBack } from '../../components/nav_button_back';
import { Version } from '../../components/version';
Expand All @@ -34,6 +34,7 @@ type HeaderProps = PackageInfo & { iconType?: IconType };

export function Header(props: HeaderProps) {
const { iconType, name, title, version } = props;
const core = useCore();
const { toListView } = useLinks();
// useBreadcrumbs([{ text: PLUGIN.TITLE, href: toListView() }, { text: title }]);

Expand Down Expand Up @@ -61,7 +62,11 @@ export function Header(props: HeaderProps) {
<RightColumn>
<EuiFlexGroup justifyContent="flexEnd">
<EuiFlexItem grow={false}>
<EuiButton iconType="plusInCircle" href={ADD_DATASOURCE_URI}>
<EuiButton
isDisabled={!core.application.capabilities.ingestManager.write}
iconType="plusInCircle"
href={ADD_DATASOURCE_URI}
>
<FormattedMessage
id="xpack.ingestManager.epm.addDatasourceButtonText"
defaultMessage="Create data source"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import { EuiButton } from '@elastic/eui';
import React, { Fragment, useCallback, useMemo, useState } from 'react';
import { PackageInfo, InstallStatus } from '../../../../types';
import { useCore } from '../../../../hooks';
import { useDeletePackage, useGetPackageInstallStatus, useInstallPackage } from '../../hooks';
import { ConfirmPackageDelete } from './confirm_package_delete';
import { ConfirmPackageInstall } from './confirm_package_install';
Expand All @@ -16,6 +17,7 @@ interface InstallationButtonProps {

export function InstallationButton(props: InstallationButtonProps) {
const { assets, name, title, version } = props.package;
const core = useCore();
const installPackage = useInstallPackage();
const deletePackage = useDeletePackage();
const getPackageInstallStatus = useGetPackageInstallStatus();
Expand Down Expand Up @@ -86,10 +88,10 @@ export function InstallationButton(props: InstallationButtonProps) {
/>
);

return (
return core.application.capabilities.ingestManager.write ? (
<Fragment>
{isInstalled ? installedButton : installButton}
{isModalVisible && (isInstalled ? deletionModal : installationModal)}
</Fragment>
);
) : null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useAgentRefresh } from '../hooks';
import { AgentMetadataFlyout } from './metadata_flyout';
import { Agent } from '../../../../types';
import { AgentHealth } from '../../components/agent_health';
import { useGetOneAgentConfig } from '../../../../hooks';
import { useCore, useGetOneAgentConfig } from '../../../../hooks';
import { Loading } from '../../../../components';
import { ConnectedLink } from '../../components';
import { AgentUnenrollProvider } from '../../components/agent_unenroll_provider';
Expand Down Expand Up @@ -53,6 +53,7 @@ interface Props {
agent: Agent;
}
export const AgentDetailSection: React.FunctionComponent<Props> = ({ agent }) => {
const core = useCore();
const metadataFlyout = useFlyout();
const refreshAgent = useAgentRefresh();

Expand Down Expand Up @@ -125,7 +126,7 @@ export const AgentDetailSection: React.FunctionComponent<Props> = ({ agent }) =>
<AgentUnenrollProvider>
{unenrollAgentsPrompt => (
<EuiButton
disabled={!agent.active}
disabled={!core.application.capabilities.ingestManager.write || !agent.active}
onClick={() => {
unenrollAgentsPrompt([agent.id], 1, refreshAgent);
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { useEnrollmentApiKeys, useEnrollmentApiKey } from './hooks';
import { ConfirmDeleteModal } from './confirm_delete_modal';
import { CreateApiKeyForm } from './create_api_key_form';
import { EnrollmentAPIKey } from '../../../../../types';
import { useCore } from '../../../../../hooks';
import { enrollmentAPIKeyRouteService } from '../../../../../services';
export { useEnrollmentApiKeys, useEnrollmentApiKey } from './hooks';

Expand Down Expand Up @@ -98,13 +99,18 @@ export const EnrollmentApiKeysTable: React.FunctionComponent<{
export const CreateApiKeyButton: React.FunctionComponent<{ onChange: () => void }> = ({
onChange,
}) => {
const core = useCore();
const [isOpen, setIsOpen] = React.useState(false);

return (
<EuiPopover
ownFocus
button={
<EuiLink onClick={() => setIsOpen(true)} color="primary">
<EuiLink
disabled={!core.application.capabilities.ingestManager.write}
onClick={() => setIsOpen(true)}
color="primary"
>
<FormattedMessage
id="xpack.ingestManager.enrollmentApiKeyList.createNewButton"
defaultMessage="Create a new key"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const statusFilters = [
] as Array<{ label: string; status: string }>;

const RowActions = React.memo<{ agent: Agent; refresh: () => void }>(({ agent, refresh }) => {
const core = useCore();
const DETAILS_URI = useLink(FLEET_AGENT_DETAIL_PATH);
const [isOpen, setIsOpen] = useState(false);
const handleCloseMenu = useCallback(() => setIsOpen(false), [setIsOpen]);
Expand Down Expand Up @@ -118,6 +119,7 @@ const RowActions = React.memo<{ agent: Agent; refresh: () => void }>(({ agent, r
<AgentUnenrollProvider>
{unenrollAgentsPrompt => (
<EuiContextMenuItem
disabled={!core.application.capabilities.ingestManager.write}
icon="cross"
onClick={() => {
unenrollAgentsPrompt([agent.id], 1, () => {
Expand Down
30 changes: 18 additions & 12 deletions x-pack/plugins/ingest_manager/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ import { SecurityPluginSetup } from '../../security/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
import {
PLUGIN_ID,
OUTPUT_SAVED_OBJECT_TYPE,
AGENT_CONFIG_SAVED_OBJECT_TYPE,
DATASOURCE_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
AGENT_EVENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
Expand Down Expand Up @@ -49,6 +53,16 @@ export interface IngestManagerAppContext {
savedObjects: SavedObjectsServiceStart;
}

const allSavedObjectTypes = [
OUTPUT_SAVED_OBJECT_TYPE,
AGENT_CONFIG_SAVED_OBJECT_TYPE,
DATASOURCE_SAVED_OBJECT_TYPE,
PACKAGES_SAVED_OBJECT_TYPE,
AGENT_SAVED_OBJECT_TYPE,
AGENT_EVENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
];

export class IngestManagerPlugin implements Plugin {
private config$: Observable<IngestManagerConfigType>;
private security: SecurityPluginSetup | undefined;
Expand All @@ -73,26 +87,18 @@ export class IngestManagerPlugin implements Plugin {
app: [PLUGIN_ID, 'kibana'],
privileges: {
all: {
api: [PLUGIN_ID],
api: [`${PLUGIN_ID}-read`, `${PLUGIN_ID}-all`],
savedObject: {
all: [
AGENT_SAVED_OBJECT_TYPE,
AGENT_EVENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
],
all: allSavedObjectTypes,
read: [],
},
ui: ['show', 'read', 'write'],
},
read: {
api: [PLUGIN_ID],
api: [`${PLUGIN_ID}-read`],
savedObject: {
all: [],
read: [
AGENT_SAVED_OBJECT_TYPE,
AGENT_EVENT_SAVED_OBJECT_TYPE,
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
],
read: allSavedObjectTypes,
},
ui: ['show', 'read'],
},
Expand Down
Loading