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

Extract NeoDash auth module to an abstract interface to allow for different providers #767

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
2869c23
Added abstract class for connection module
nielsdejong Jan 25, 2024
20a154c
first iteration on abstracting connection layer
alfredorubin96 Jan 25, 2024
ee20346
first iteration on abstracting connection layer
alfredorubin96 Jan 25, 2024
70361e8
completely detached runCypherQuery from the application
alfredorubin96 Jan 26, 2024
f22745c
renaming auth module to connection
alfredorubin96 Jan 28, 2024
200701c
deleted old extensions
alfredorubin96 Jan 28, 2024
04d52e7
using Context objext to store current configuration
alfredorubin96 Jan 29, 2024
c602292
cleaning code
alfredorubin96 Jan 29, 2024
26ee2e6
cleaning code
alfredorubin96 Jan 29, 2024
6877693
Merge branch 'develop' into feature/auth-module
alfredorubin96 Mar 11, 2024
6ca2e4b
Merge branch 'develop' into feature/auth-module
alfredorubin96 Mar 11, 2024
e7d7d98
merging with develop
alfredorubin96 Mar 11, 2024
ee8a7de
plugged parsed to chart, to test
alfredorubin96 Mar 13, 2024
d7c250b
to continue testing only on table, report action work
alfredorubin96 Mar 13, 2024
cbc47b5
changing from fields to _fields to make the property private
alfredorubin96 Mar 13, 2024
efd14e5
Merge branch 'develop' into feature/auth-module
nielsdejong Mar 15, 2024
50f16e8
unplugging record parsing from report.tsx and added comments for conn…
alfredorubin96 Mar 28, 2024
0f14d87
Merge branch 'feature/auth-module' of https://github.com/neo4j-labs/n…
alfredorubin96 Mar 28, 2024
4895d8b
cleaning code following sonarqube
alfredorubin96 Mar 28, 2024
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
"mui-color": "^2.0.0-beta.2",
"mui-nested-menu": "^3.2.1",
"neo4j-client-sso": "^1.2.2",
"neo4j-driver": "^5.18.0",
"openai": "^3.3.0",
"postcss": "^8.4.21",
"postcss-loader": "^7.2.4",
Expand Down
128 changes: 69 additions & 59 deletions src/application/Application.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { Suspense, useEffect } from 'react';
import React, { createContext, Suspense, useContext, useEffect } from 'react';
import NeoWelcomeScreenModal from '../modal/WelcomeScreenModal';
import { connect } from 'react-redux';
import {
Expand Down Expand Up @@ -45,6 +45,8 @@ import { downloadComponentAsImage } from '../chart/ChartUtils';
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { resetSessionStorage } from '../sessionStorage/SessionStorageActions';
import { getDashboardTheme } from '../dashboard/DashboardSelectors';
import { ConnectionModuleState } from '../connection/ConnectionModule';
import { getConnectionModule } from '../connection/utils';

const NeoUpgradeOldDashboardModal = React.lazy(() => import('../modal/UpgradeOldDashboardModal'));
const NeoLoadSharedDashboardModal = React.lazy(() => import('../modal/LoadSharedDashboardModal'));
Expand All @@ -53,6 +55,12 @@ const NeoNotificationModal = React.lazy(() => import('../modal/NotificationModal
const NeoAboutModal = React.lazy(() => import('../modal/AboutModal'));
const Dashboard = React.lazy(() => import('../dashboard/Dashboard'));

const ConnectionModuleContext = createContext<ConnectionModuleState>(getConnectionModule());

export function useConnectionModuleContext() {
return useContext<ConnectionModuleState>(ConnectionModuleContext);
}

/**
* This is the main application component for NeoDash.
* It contains:
Expand Down Expand Up @@ -125,66 +133,68 @@ const Application = ({
ref={ref}
className={`n-bg-palette-neutral-bg-default n-h-screen n-w-screen n-flex n-flex-col n-overflow-hidden`}
>
{connected ? (
<ConnectionModuleContext.Provider value={getConnectionModule()}>
{connected ? (
<Suspense fallback=''>
<Dashboard
onDownloadDashboardAsImage={(_) => downloadComponentAsImage(ref)}
onAboutModalOpen={onAboutModalOpen}
resetApplication={resetApplication}
></Dashboard>
</Suspense>
) : (
<NeoDashboardPlaceholder></NeoDashboardPlaceholder>
)}
{/* TODO - move all models into a pop-ups (or modals) component. */}
<Suspense fallback=''>
<NeoAboutModal open={aboutModalOpen} handleClose={onAboutModalClose} getDebugState={getDebugState} />
</Suspense>
<NeoConnectionModal
open={connectionModalOpen}
connected={connected}
dismissable={!standalone}
connection={connection}
ssoSettings={ssoSettings}
standalone={standaloneSettings.standalone}
standaloneSettings={standaloneSettings}
createConnection={createConnection}
onSSOAttempt={onSSOAttempt}
setConnectionProperties={setConnectionDetails}
onConnectionModalClose={onConnectionModalClose}
setWelcomeScreenOpen={setWelcomeScreenOpen}
></NeoConnectionModal>
<NeoWelcomeScreenModal
welcomeScreenOpen={welcomeScreenOpen}
setWelcomeScreenOpen={setWelcomeScreenOpen}
hasCachedDashboard={hasCachedDashboard}
hasNeo4jDesktopConnection={hasNeo4jDesktopConnection}
onConnectionModalOpen={onConnectionModalOpen}
createConnectionFromDesktopIntegration={createConnectionFromDesktopIntegration}
onAboutModalOpen={onAboutModalOpen}
resetDashboard={resetDashboard}
></NeoWelcomeScreenModal>
<Suspense fallback=''>
<NeoUpgradeOldDashboardModal
open={oldDashboard}
text={oldDashboard}
loadDashboard={loadDashboard}
clearOldDashboard={clearOldDashboard}
/>
</Suspense>
<Suspense fallback=''>
<NeoLoadSharedDashboardModal
shareDetails={shareDetails}
onResetShareDetails={onResetShareDetails}
onConfirmLoadSharedDashboard={onConfirmLoadSharedDashboard}
/>
</Suspense>
<Suspense fallback=''>
<NeoReportHelpModal open={reportHelpModalOpen} handleClose={onReportHelpModalClose} />
</Suspense>
<Suspense fallback=''>
<Dashboard
onDownloadDashboardAsImage={(_) => downloadComponentAsImage(ref)}
onAboutModalOpen={onAboutModalOpen}
resetApplication={resetApplication}
></Dashboard>
<NeoNotificationModal></NeoNotificationModal>
</Suspense>
) : (
<NeoDashboardPlaceholder></NeoDashboardPlaceholder>
)}
{/* TODO - move all models into a pop-ups (or modals) component. */}
<Suspense fallback=''>
<NeoAboutModal open={aboutModalOpen} handleClose={onAboutModalClose} getDebugState={getDebugState} />
</Suspense>
<NeoConnectionModal
open={connectionModalOpen}
connected={connected}
dismissable={!standalone}
connection={connection}
ssoSettings={ssoSettings}
standalone={standaloneSettings.standalone}
standaloneSettings={standaloneSettings}
createConnection={createConnection}
onSSOAttempt={onSSOAttempt}
setConnectionProperties={setConnectionDetails}
onConnectionModalClose={onConnectionModalClose}
setWelcomeScreenOpen={setWelcomeScreenOpen}
></NeoConnectionModal>
<NeoWelcomeScreenModal
welcomeScreenOpen={welcomeScreenOpen}
setWelcomeScreenOpen={setWelcomeScreenOpen}
hasCachedDashboard={hasCachedDashboard}
hasNeo4jDesktopConnection={hasNeo4jDesktopConnection}
onConnectionModalOpen={onConnectionModalOpen}
createConnectionFromDesktopIntegration={createConnectionFromDesktopIntegration}
onAboutModalOpen={onAboutModalOpen}
resetDashboard={resetDashboard}
></NeoWelcomeScreenModal>
<Suspense fallback=''>
<NeoUpgradeOldDashboardModal
open={oldDashboard}
text={oldDashboard}
loadDashboard={loadDashboard}
clearOldDashboard={clearOldDashboard}
/>
</Suspense>
<Suspense fallback=''>
<NeoLoadSharedDashboardModal
shareDetails={shareDetails}
onResetShareDetails={onResetShareDetails}
onConfirmLoadSharedDashboard={onConfirmLoadSharedDashboard}
/>
</Suspense>
<Suspense fallback=''>
<NeoReportHelpModal open={reportHelpModalOpen} handleClose={onReportHelpModalClose} />
</Suspense>
<Suspense fallback=''>
<NeoNotificationModal></NeoNotificationModal>
</Suspense>
</ConnectionModuleContext.Provider>
</div>
);
};
Expand Down
30 changes: 18 additions & 12 deletions src/application/ApplicationThunks.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { createDriver } from 'use-neo4j';
import { initializeSSO } from '../component/sso/SSOUtils';
import { DEFAULT_SCREEN, Screens } from '../config/ApplicationConfig';
import { setDashboard } from '../dashboard/DashboardActions';
Expand All @@ -11,7 +10,6 @@ import {
upgradeDashboardVersion,
} from '../dashboard/DashboardThunks';
import { createNotificationThunk } from '../page/PageThunks';
import { runCypherQuery } from '../report/ReportQueryRunner';
import {
setPageNumberThunk,
updateParametersToNeo4jTypeThunk,
Expand Down Expand Up @@ -48,6 +46,8 @@ import { applicationIsStandalone } from './ApplicationSelectors';
import { applicationGetLoggingSettings } from './logging/LoggingSelectors';
import { createLogThunk } from './logging/LoggingThunk';
import { createUUID } from '../utils/uuid';
import { QueryCallback, QueryParams } from '../connection/interfaces';
import { getConnectionModule } from '../connection/utils';

/**
* Application Thunks (https://redux.js.org/usage/writing-logic-thunks) handle complex state manipulations.
Expand All @@ -69,7 +69,15 @@ export const createConnectionThunk =
const loggingSettings = applicationGetLoggingSettings(loggingState);
const neodashMode = applicationIsStandalone(loggingState) ? 'Standalone' : 'Editor';
try {
const driver = createDriver(protocol, url, port, username, password, { userAgent: `neodash/v${version}` });
const { connectionModule } = getConnectionModule();
const driver = connectionModule.createDriver({
scheme: protocol,
host: url,
port,
username,
password,
config: { userAgent: `neodash/v${version}` },
});
// eslint-disable-next-line no-console
console.log('Attempting to connect...');
const validateConnection = (records) => {
Expand Down Expand Up @@ -165,15 +173,13 @@ export const createConnectionThunk =
};
const query = 'RETURN true as connected';
const parameters = {};
runCypherQuery(
driver,
database,
query,
parameters,
1,
() => {},
(records) => validateConnection(records)
);
const queryParams: QueryParams = { query, database, parameters, rowLimit: 1 };

let queryCallback: QueryCallback = {
setRecords: (records) => validateConnection(records),
};

connectionModule.runQuery(driver, queryParams, queryCallback);
} catch (e) {
dispatch(createNotificationThunk('Unable to establish connection', e));
}
Expand Down
21 changes: 10 additions & 11 deletions src/application/logging/LoggingThunk.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { createNotificationThunk } from '../../page/PageThunks';
import { runCypherQuery } from '../../report/ReportQueryRunner';
import { setLogErrorNotification } from './LoggingActions';
import { applicationGetLoggingSettings } from './LoggingSelectors';
import { createUUID } from '../../utils/uuid';
import { QueryCallback, QueryParams } from '../../connection/interfaces';
import { getConnectionModule } from '../../connection/utils';

// Thunk to handle log events.

export const createLogThunk =
(loggingDriver, loggingDatabase, neodashMode, logUser, logAction, logDatabase, logDashboard = '', logMessage) =>
(dispatch: any, getState: any) => {
try {
const { connectionModule } = getConnectionModule();
const uuid = createUUID();
// Generate a cypher query to save the log.
const query =
Expand All @@ -24,14 +26,10 @@ export const createLogThunk =
logDashboard: logDashboard,
logMessage: logMessage,
};
runCypherQuery(
loggingDriver,
loggingDatabase,
query,
parameters,
1,
() => {},
(records) => {

const queryParams: QueryParams = { query, database: loggingDatabase, parameters, rowLimit: 1 };
const queryCallback: QueryCallback = {
setRecords: (records) => {
if (records && records[0] && records[0]._fields && records[0]._fields[0] && records[0]._fields[0] == uuid) {
console.log(`log created: ${uuid}`);
} else {
Expand All @@ -53,8 +51,9 @@ export const createLogThunk =
LogErrorNotificationNum -= 1;
dispatch(setLogErrorNotification(LogErrorNotificationNum.toString()));
}
}
);
},
};
connectionModule.runQuery(loggingDriver, queryParams, queryCallback);
} catch (e) {
// we only show error notification 3 times
const state = getState();
Expand Down
5 changes: 2 additions & 3 deletions src/chart/ChartUtils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import domtoimage from 'dom-to-image';
import { Date as Neo4jDate } from 'neo4j-driver-core/lib/temporal-types.js';
import { QueryResult, Record as Neo4jRecord } from 'neo4j-driver';
import { RenderSubValue } from '../report/ReportRecordProcessing';

/**
* Converts a neo4j record entry to a readable string representation.
Expand Down Expand Up @@ -249,9 +251,6 @@ export const downloadComponentAsImage = (ref) => {
});
};

import { QueryResult, Record as Neo4jRecord } from 'neo4j-driver';
import { RenderSubValue } from '../report/ReportRecordProcessing';

/**
* Function to cast a value received from the Neo4j Driver to its TS native type
* @param input Value to cast
Expand Down
28 changes: 18 additions & 10 deletions src/chart/parameter/ParameterSelectCardSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@

import React, { useCallback, useContext, useEffect } from 'react';
import { RUN_QUERY_DELAY_MS } from '../../config/ReportConfig';
import { QueryStatus, runCypherQuery } from '../../report/ReportQueryRunner';
import { Neo4jContext, Neo4jContextState } from 'use-neo4j/dist/neo4j.context';
import { Autocomplete, debounce, TextField } from '@mui/material';
import NeoField from '../../component/field/Field';
import { Dropdown } from '@neo4j-ndl/react';
import NeoCodeEditorComponent from '../../component/editor/CodeEditorComponent';
import { QueryCallback, QueryParams, QueryStatus } from '../../connection/interfaces';
import { useConnectionModuleContext } from '../../application/Application';

type ParameterId = string | undefined | null;

Expand All @@ -18,10 +19,11 @@ const ParameterSelectCardSettings = ({ query, database, settings, onReportSettin
'`driver` not defined. Have you added it into your app as <Neo4jContext.Provider value={{driver}}> ?'
);
}
const { connectionModule } = useConnectionModuleContext();

const [queryText, setQueryText] = React.useState(query);
const debouncedQueryUpdate = useCallback(debounce(onQueryUpdate, 250), []);
const debouncedRunCypherQuery = useCallback(debounce(runCypherQuery, RUN_QUERY_DELAY_MS), []);
const debouncedRunQuery = useCallback(debounce(connectionModule.runQuery, RUN_QUERY_DELAY_MS), []);

const { manualPropertyNameSpecification } = settings;
const [labelInputText, setLabelInputText] = React.useState(settings.entityType);
Expand Down Expand Up @@ -60,21 +62,27 @@ const ParameterSelectCardSettings = ({ query, database, settings, onReportSettin

onReportSettingUpdate('parameterName', parameterName);
}
// Define query callback to allow reports to get extra data on interactions.

const queryCallback = useCallback(
(query, parameters, setRecords) => {
debouncedRunCypherQuery(
driver,
let queryParams: QueryParams = {
database,
query,
parameters,
10,
(status) => {
rowLimit: 10,
fields: [],
};

let queryCallback: QueryCallback = {
setStatus: (status) => {
status == QueryStatus.NO_DATA ? setRecords([]) : () => {};
},
(result) => setRecords(result),
() => {}
);
setRecords,
setFields: () => {},
setSchema: () => {},
};

debouncedRunQuery(driver, queryParams, queryCallback);
},
[database]
);
Expand Down
Loading
Loading