Skip to content

Commit

Permalink
Update connection form to better reflect aura usage (#1235)
Browse files Browse the repository at this point in the history
* Update connection form to better reflect aura usage

* Update unit test

* Move auth methods for consistency

* Update unit test

* Update messages on migth require auth
  • Loading branch information
OskarDamkjaer authored Nov 4, 2020
1 parent 2646b32 commit f1e4bb8
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 39 deletions.
54 changes: 33 additions & 21 deletions src/browser/modules/Stream/Auth/ConnectForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ import { toKeyString } from 'services/utils'
import { stripScheme, getScheme } from 'services/boltscheme.utils'

type AuthenticationMethod = typeof NATIVE | typeof NO_AUTH
const authMethods: AuthenticationMethod[] = [NATIVE, NO_AUTH]
const readableauthenticationMethods: Record<AuthenticationMethod, string> = {
[NATIVE]: 'Username / Password',
[NO_AUTH]: 'No authentication'
}

interface ConnectFormProps {
allowedSchemes: string[]
allowedAuthMethods: AuthenticationMethod[]
authenticationMethod: string
host: string
onAuthenticationMethodChange: () => void
Expand Down Expand Up @@ -102,16 +102,27 @@ export default function ConnectForm(props: ConnectFormProps): JSX.Element {
props.onConnectClick(() => setConnecting(false))
}

const hasSecureSchemes = ['neo4j+s', 'bolt+s'].every(scheme =>
props.allowedSchemes.includes(scheme)
)
const hoverText = `Pick neo4j${
hasSecureSchemes ? '+s' : ''
}:// for a routed connection, bolt${
hasSecureSchemes ? '+s' : ''
}:// for a direct connection to a DBMS instance.`

const schemeRestriction = props.allowedSchemes.length > 0

return (
<StyledConnectionForm onSubmit={onConnectClick}>
<StyledConnectionFormEntry>
<StyledConnectionLabel
htmlFor="url-input"
title="Pick neo4j:// for a routed connection, bolt:// for a direct connection to a DBMS instance."
title={schemeRestriction ? hoverText : ''}
>
Connect URL
</StyledConnectionLabel>
{props.allowedSchemes && props.allowedSchemes.length ? (
{schemeRestriction ? (
<>
<StyledSegment>
<StyledConnectionSelect
Expand All @@ -137,8 +148,7 @@ export default function ConnectForm(props: ConnectFormProps): JSX.Element {
/>
</StyledSegment>
<StyledBoltUrlHintText className="url-hint-text">
Pick neo4j:// for a routed connection, bolt:// for a direct
connection to a DBMS.
{hoverText}
</StyledBoltUrlHintText>
</>
) : (
Expand All @@ -162,22 +172,24 @@ export default function ConnectForm(props: ConnectFormProps): JSX.Element {
</StyledConnectionFormEntry>
)}

<StyledConnectionFormEntry>
<StyledConnectionLabel>
Authentication type
<StyledConnectionSelect
data-testid="authenticationMethod"
onChange={props.onAuthenticationMethodChange}
value={props.authenticationMethod}
>
{authMethods.map(auth => (
<option value={auth} key={auth}>
{readableauthenticationMethods[auth]}
</option>
))}
</StyledConnectionSelect>
</StyledConnectionLabel>
</StyledConnectionFormEntry>
{props.allowedAuthMethods.length > 1 && (
<StyledConnectionFormEntry>
<StyledConnectionLabel>
Authentication type
<StyledConnectionSelect
data-testid="authenticationMethod"
onChange={props.onAuthenticationMethodChange}
value={props.authenticationMethod}
>
{props.allowedAuthMethods.map(auth => (
<option value={auth} key={auth}>
{readableauthenticationMethods[auth]}
</option>
))}
</StyledConnectionSelect>
</StyledConnectionLabel>
</StyledConnectionFormEntry>
)}

{props.authenticationMethod === NATIVE && (
<StyledConnectionFormEntry>
Expand Down
17 changes: 12 additions & 5 deletions src/browser/modules/Stream/Auth/ConnectionForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ import { NATIVE, NO_AUTH } from 'services/bolt/boltHelpers'
import ConnectForm from './ConnectForm'
import ConnectedView from './ConnectedView'
import ChangePasswordForm from './ChangePasswordForm'
import { getAllowedBoltSchemes } from 'shared/modules/app/appDuck'
import {
getAllowedAuthSchemes,
getAllowedBoltSchemes,
inCloudEnv
} from 'shared/modules/app/appDuck'
import { FOCUS } from 'shared/modules/editor/editorDuck'
import {
generateBoltUrl,
Expand Down Expand Up @@ -293,7 +297,7 @@ export class ConnectionForm extends Component {
} else if (
this.props.isConnected &&
this.props.activeConnectionData &&
this.props.activeConnectionData.authEnabled === false // excplicit false = auth disabled for sure
this.props.activeConnectionData.authEnabled === false // explicit false = auth disabled for sure
) {
view = (
<StyledConnectionBody>
Expand All @@ -315,10 +319,11 @@ export class ConnectionForm extends Component {
username={this.state.username}
password={this.state.password}
database={this.state.requestedUseDb}
authenticationMethod={this.state.authenticationMethod}
supportsMultiDb={this.state.supportsMultiDb}
used={this.state.used}
allowedSchemes={this.props.allowedSchemes}
supportsMultiDb={this.state.supportsMultiDb}
allowedAuthMethods={this.props.allowedAuthMethods}
authenticationMethod={this.state.authenticationMethod}
/>
)
}
Expand All @@ -334,7 +339,8 @@ const mapStateToProps = state => {
playImplicitInitCommands: getPlayImplicitInitCommands(state),
storeCredentials: shouldRetainConnectionCredentials(state),
isConnected: isConnected(state),
allowedSchemes: getAllowedBoltSchemes(state)
allowedSchemes: getAllowedBoltSchemes(state),
allowedAuthMethods: getAllowedAuthSchemes(state)
}
}

Expand All @@ -356,6 +362,7 @@ const mergeProps = (stateProps, dispatchProps, ownProps) => {
storeCredentials: stateProps.storeCredentials,
isConnected: stateProps.isConnected,
allowedSchemes: stateProps.allowedSchemes,
allowedAuthMethods: stateProps.allowedAuthMethods,
...ownProps,
...dispatchProps,
executeInitCmd: () => {
Expand Down
4 changes: 4 additions & 0 deletions src/browser/modules/Stream/Auth/ConnectionForm.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import React from 'react'
import { render, fireEvent } from '@testing-library/react'
import { ConnectionForm } from './ConnectionForm'
import { NATIVE, NO_AUTH } from 'services/bolt/boltHelpers'

test('should print correct state for retaining credentials', async () => {
const bus = {
Expand Down Expand Up @@ -53,6 +54,7 @@ test('should print correct state for retaining credentials', async () => {
executeInitCmd={executeInitCmd}
isConnected={false}
allowedSchemes={['neo4j']}
allowedAuthMethods={[NATIVE, NO_AUTH]}
/>
)

Expand Down Expand Up @@ -84,6 +86,7 @@ test('should print correct state for retaining credentials', async () => {
executeInitCmd={executeInitCmd}
isConnected={true}
allowedSchemes={['neo4j']}
allowedAuthMethods={[NATIVE, NO_AUTH]}
/>
)

Expand All @@ -108,6 +111,7 @@ test('should print correct state for retaining credentials', async () => {
executeInitCmd={executeInitCmd}
isConnected={true}
allowedSchemes={['neo4j']}
allowedAuthMethods={[NATIVE, NO_AUTH]}
/>
)

Expand Down
36 changes: 24 additions & 12 deletions src/browser/modules/Stream/Auth/ConnectionFrame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ import { Lead } from 'browser-components/Text'

import Render from 'browser-components/Render'
import { StyledConnectionAside, StyledConnectionBodyContainer } from './styled'
import { connect } from 'react-redux'
import { getAllowedAuthSchemes } from 'shared/modules/app/appDuck'
import { NO_AUTH } from 'services/bolt/boltHelpers'

export class ConnectionFrame extends Component {
constructor(props) {
Expand Down Expand Up @@ -58,20 +61,23 @@ export class ConnectionFrame extends Component {
contents={
<>
<StyledConnectionAside>
<Render if={!this.state.success}>
<React.Fragment>
{this.state.success ? (
<>
<H3>Connected to Neo4j</H3>
<Lead>Nice to meet you.</Lead>
</>
) : (
<>
<H3>Connect to Neo4j</H3>
<Lead>
Database access might require an authenticated connection.
Database access
{this.props.mightRequireAuth
? ' might require '
: ' requires '}
an authenticated connection
</Lead>
</React.Fragment>
</Render>
<Render if={this.state.success}>
<React.Fragment>
<H3>Connected to Neo4j</H3>
<Lead>Nice to meet you.</Lead>
</React.Fragment>
</Render>
</>
)}
</StyledConnectionAside>
<StyledConnectionBodyContainer>
<ConnectionForm
Expand All @@ -87,4 +93,10 @@ export class ConnectionFrame extends Component {
}
}

export default ConnectionFrame
const mapStateToProps = state => {
return {
mightRequireAuth: getAllowedAuthSchemes(state).includes(NO_AUTH)
}
}

export default connect(mapStateToProps)(ConnectionFrame)
10 changes: 10 additions & 0 deletions src/shared/modules/app/appDuck.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import { NATIVE, NO_AUTH } from 'services/bolt/boltHelpers'

// Action type constants
export const NAME = 'app'
export const APP_START = `${NAME}/APP_START`
Expand All @@ -39,8 +41,16 @@ export const getEnv = state => (state[NAME] || {}).env || WEB
export const hasDiscoveryEndpoint = state =>
[WEB, CLOUD].includes(getEnv(state))
export const inWebEnv = state => getEnv(state) === WEB
export const inCloudEnv = state => getEnv(state) === CLOUD
export const inWebBrowser = state => [WEB, CLOUD].includes(getEnv(state))
export const getAllowedAuthSchemes = state =>
inCloudEnv(state) ? [] : [NATIVE, NO_AUTH]

export const getAllowedBoltSchemes = (state, encryptionFlag) => {
if (inCloudEnv(state) /* Aura only allows neo4j+s */) {
return ['neo4j+s']
}

const isHosted = inWebBrowser(state)
const hostedUrl = getHostedUrl(state)
return !isHosted
Expand Down
2 changes: 1 addition & 1 deletion src/shared/modules/discovery/discoveryDuck.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ describe('discoveryOnStartupEpic cloud env', () => {
})
test('listens on APP_START and finds a bolt host and dispatches an action with the found host in cloud env', done => {
// Given
const expectedHost = 'bolt://myhost:7777'
const expectedHost = 'neo4j+s://myhost:7777'
const action = { type: APP_START, env: CLOUD }
nock(getDiscoveryEndpoint())
.get('/')
Expand Down

0 comments on commit f1e4bb8

Please sign in to comment.