@@ -7,8 +7,10 @@ import React, { useEffect, useState } from 'react';
77import ReactDOM from 'react-dom' ;
88import { useObservable } from 'react-use' ;
99import { HashRouter as Router , Redirect , Switch , Route , RouteProps } from 'react-router-dom' ;
10+ import { i18n } from '@kbn/i18n' ;
1011import { FormattedMessage } from '@kbn/i18n/react' ;
11- import { EuiErrorBoundary } from '@elastic/eui' ;
12+ import styled from 'styled-components' ;
13+ import { EuiErrorBoundary , EuiPanel , EuiEmptyPrompt , EuiCode } from '@elastic/eui' ;
1214import { CoreStart , AppMountParameters } from 'src/core/public' ;
1315import { EuiThemeProvider } from '../../../../../legacy/common/eui_styled_components' ;
1416import {
@@ -22,7 +24,7 @@ import { Loading, Error } from './components';
2224import { IngestManagerOverview , EPMApp , AgentConfigApp , FleetApp , DataStreamApp } from './sections' ;
2325import { CoreContext , DepsContext , ConfigContext , setHttpClient , useConfig } from './hooks' ;
2426import { PackageInstallProvider } from './sections/epm/hooks' ;
25- import { sendSetup } from './hooks/use_request/setup ' ;
27+ import { useCore , sendSetup , sendGetPermissionsCheck } from './hooks' ;
2628import { FleetStatusProvider } from './hooks/use_fleet_status' ;
2729import './index.scss' ;
2830
@@ -39,86 +41,175 @@ export const ProtectedRoute: React.FunctionComponent<ProtectedRouteProps> = ({
3941 return isAllowed ? < Route { ...routeProps } /> : < Redirect to = { { pathname : restrictedPath } } /> ;
4042} ;
4143
44+ const Panel = styled ( EuiPanel ) `
45+ max-width: 500px;
46+ margin-right: auto;
47+ margin-left: auto;
48+ ` ;
49+
50+ const ErrorLayout = ( { children } : { children : JSX . Element } ) => (
51+ < EuiErrorBoundary >
52+ < DefaultLayout showSettings = { false } >
53+ < WithoutHeaderLayout > { children } </ WithoutHeaderLayout >
54+ </ DefaultLayout >
55+ </ EuiErrorBoundary >
56+ ) ;
57+
4258const IngestManagerRoutes = ( { ...rest } ) => {
4359 const { epm, fleet } = useConfig ( ) ;
60+ const { notifications } = useCore ( ) ;
4461
62+ const [ isPermissionsLoading , setIsPermissionsLoading ] = useState < boolean > ( false ) ;
63+ const [ permissionsError , setPermissionsError ] = useState < string > ( ) ;
4564 const [ isInitialized , setIsInitialized ] = useState ( false ) ;
4665 const [ initializationError , setInitializationError ] = useState < Error | null > ( null ) ;
4766
4867 useEffect ( ( ) => {
4968 ( async ( ) => {
69+ setIsPermissionsLoading ( false ) ;
70+ setPermissionsError ( undefined ) ;
5071 setIsInitialized ( false ) ;
5172 setInitializationError ( null ) ;
5273 try {
53- const res = await sendSetup ( ) ;
54- if ( res . error ) {
55- setInitializationError ( res . error ) ;
74+ setIsPermissionsLoading ( true ) ;
75+ const permissionsResponse = await sendGetPermissionsCheck ( ) ;
76+ setIsPermissionsLoading ( false ) ;
77+ if ( permissionsResponse . data ?. success ) {
78+ try {
79+ const setupResponse = await sendSetup ( ) ;
80+ if ( setupResponse . error ) {
81+ setInitializationError ( setupResponse . error ) ;
82+ }
83+ } catch ( err ) {
84+ setInitializationError ( err ) ;
85+ }
86+ setIsInitialized ( true ) ;
87+ } else {
88+ setPermissionsError ( permissionsResponse . data ?. error || 'REQUEST_ERROR' ) ;
5689 }
5790 } catch ( err ) {
58- setInitializationError ( err ) ;
91+ setPermissionsError ( 'REQUEST_ERROR' ) ;
5992 }
60- setIsInitialized ( true ) ;
6193 } ) ( ) ;
6294 // eslint-disable-next-line react-hooks/exhaustive-deps
6395 } , [ ] ) ;
6496
97+ if ( isPermissionsLoading || permissionsError ) {
98+ return (
99+ < ErrorLayout >
100+ { isPermissionsLoading ? (
101+ < Loading />
102+ ) : permissionsError === 'REQUEST_ERROR' ? (
103+ < Error
104+ title = {
105+ < FormattedMessage
106+ id = "xpack.ingestManager.permissionsRequestErrorMessageTitle"
107+ defaultMessage = "Unable to check permissions"
108+ />
109+ }
110+ error = { i18n . translate ( 'xpack.ingestManager.permissionsRequestErrorMessageDescription' , {
111+ defaultMessage : 'There was a problem checking Ingest Manager permissions' ,
112+ } ) }
113+ />
114+ ) : (
115+ < Panel >
116+ < EuiEmptyPrompt
117+ iconType = "securityApp"
118+ title = {
119+ < h2 >
120+ { permissionsError === 'MISSING_SUPERUSER_ROLE' ? (
121+ < FormattedMessage
122+ id = "xpack.ingestManager.permissionDeniedErrorTitle"
123+ defaultMessage = "Permission denied"
124+ />
125+ ) : (
126+ < FormattedMessage
127+ id = "xpack.ingestManager.securityRequiredErrorTitle"
128+ defaultMessage = "Security is not enabled"
129+ />
130+ ) }
131+ </ h2 >
132+ }
133+ body = {
134+ < p >
135+ { permissionsError === 'MISSING_SUPERUSER_ROLE' ? (
136+ < FormattedMessage
137+ id = "xpack.ingestManager.permissionDeniedErrorMessage"
138+ defaultMessage = "You are not authorized to access Ingest Manager. Ingest Manager requires {roleName} privileges."
139+ values = { { roleName : < EuiCode > superuser</ EuiCode > } }
140+ />
141+ ) : (
142+ < FormattedMessage
143+ id = "xpack.ingestManager.securityRequiredErrorMessage"
144+ defaultMessage = "You must enable security in Kibana and Elasticsearch to use Ingest Manager."
145+ />
146+ ) }
147+ </ p >
148+ }
149+ />
150+ </ Panel >
151+ ) }
152+ </ ErrorLayout >
153+ ) ;
154+ }
155+
65156 if ( ! isInitialized || initializationError ) {
66157 return (
67- < EuiErrorBoundary >
68- < DefaultLayout >
69- < WithoutHeaderLayout >
70- { initializationError ? (
71- < Error
72- title = {
73- < FormattedMessage
74- id = "xpack.ingestManager.initializationErrorMessageTitle"
75- defaultMessage = "Unable to initialize Ingest Manager"
76- />
77- }
78- error = { initializationError }
158+ < ErrorLayout >
159+ { initializationError ? (
160+ < Error
161+ title = {
162+ < FormattedMessage
163+ id = "xpack.ingestManager.initializationErrorMessageTitle"
164+ defaultMessage = "Unable to initialize Ingest Manager"
79165 />
80- ) : (
81- < Loading />
82- ) }
83- </ WithoutHeaderLayout >
84- </ DefaultLayout >
85- </ EuiErrorBoundary >
166+ }
167+ error = { initializationError }
168+ />
169+ ) : (
170+ < Loading />
171+ ) }
172+ </ ErrorLayout >
86173 ) ;
87174 }
88175
89176 return (
90- < EuiErrorBoundary >
91- < Router { ...rest } >
92- < Switch >
93- < ProtectedRoute path = { EPM_PATH } isAllowed = { epm . enabled } >
94- < DefaultLayout section = "epm" >
95- < EPMApp />
96- </ DefaultLayout >
97- </ ProtectedRoute >
98- < Route path = { AGENT_CONFIG_PATH } >
99- < DefaultLayout section = "agent_config" >
100- < AgentConfigApp />
101- </ DefaultLayout >
102- </ Route >
103- < Route path = { DATA_STREAM_PATH } >
104- < DefaultLayout section = "data_stream" >
105- < DataStreamApp />
106- </ DefaultLayout >
107- </ Route >
108- < ProtectedRoute path = { FLEET_PATH } isAllowed = { fleet . enabled } >
109- < DefaultLayout section = "fleet" >
110- < FleetApp />
111- </ DefaultLayout >
112- </ ProtectedRoute >
113- < Route exact path = "/" >
114- < DefaultLayout section = "overview" >
115- < IngestManagerOverview />
116- </ DefaultLayout >
117- </ Route >
118- < Redirect to = "/" />
119- </ Switch >
120- </ Router >
121- </ EuiErrorBoundary >
177+ < PackageInstallProvider notifications = { notifications } >
178+ < FleetStatusProvider >
179+ < EuiErrorBoundary >
180+ < Router { ...rest } >
181+ < Switch >
182+ < ProtectedRoute path = { EPM_PATH } isAllowed = { epm . enabled } >
183+ < DefaultLayout section = "epm" >
184+ < EPMApp />
185+ </ DefaultLayout >
186+ </ ProtectedRoute >
187+ < Route path = { AGENT_CONFIG_PATH } >
188+ < DefaultLayout section = "agent_config" >
189+ < AgentConfigApp />
190+ </ DefaultLayout >
191+ </ Route >
192+ < Route path = { DATA_STREAM_PATH } >
193+ < DefaultLayout section = "data_stream" >
194+ < DataStreamApp />
195+ </ DefaultLayout >
196+ </ Route >
197+ < ProtectedRoute path = { FLEET_PATH } isAllowed = { fleet . enabled } >
198+ < DefaultLayout section = "fleet" >
199+ < FleetApp />
200+ </ DefaultLayout >
201+ </ ProtectedRoute >
202+ < Route exact path = "/" >
203+ < DefaultLayout section = "overview" >
204+ < IngestManagerOverview />
205+ </ DefaultLayout >
206+ </ Route >
207+ < Redirect to = "/" />
208+ </ Switch >
209+ </ Router >
210+ </ EuiErrorBoundary >
211+ </ FleetStatusProvider >
212+ </ PackageInstallProvider >
122213 ) ;
123214} ;
124215
@@ -142,11 +233,7 @@ const IngestManagerApp = ({
142233 < DepsContext . Provider value = { { setup : setupDeps , start : startDeps } } >
143234 < ConfigContext . Provider value = { config } >
144235 < EuiThemeProvider darkMode = { isDarkMode } >
145- < PackageInstallProvider notifications = { coreStart . notifications } >
146- < FleetStatusProvider >
147- < IngestManagerRoutes basepath = { basepath } />
148- </ FleetStatusProvider >
149- </ PackageInstallProvider >
236+ < IngestManagerRoutes basepath = { basepath } />
150237 </ EuiThemeProvider >
151238 </ ConfigContext . Provider >
152239 </ DepsContext . Provider >
0 commit comments