Add client certificates
This commit is contained in:
@@ -42,7 +42,8 @@ export const loadConnectionSettings = () => async (dispatch: Dispatch<any>, getS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const selectCertificate = (connectionId: string) => async (
|
export type CertificateTypes = 'selfSignedCertificate' | 'clientCertificate' | 'clientKey'
|
||||||
|
export const selectCertificate = (type: CertificateTypes, connectionId: string) => async (
|
||||||
dispatch: Dispatch<any>,
|
dispatch: Dispatch<any>,
|
||||||
getState: () => AppState
|
getState: () => AppState
|
||||||
) => {
|
) => {
|
||||||
@@ -50,7 +51,7 @@ export const selectCertificate = (connectionId: string) => async (
|
|||||||
const certificate = await openCertificate()
|
const certificate = await openCertificate()
|
||||||
dispatch(
|
dispatch(
|
||||||
updateConnection(connectionId, {
|
updateConnection(connectionId, {
|
||||||
selfSignedCertificate: certificate,
|
[type]: certificate,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -147,6 +148,10 @@ export const toggleAdvancedSettings = (): Action => ({
|
|||||||
type: ActionTypes.CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS,
|
type: ActionTypes.CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const toggleCertificateSettings = (): Action => ({
|
||||||
|
type: ActionTypes.CONNECTION_MANAGER_TOGGLE_CERTIFICATE_SETTINGS,
|
||||||
|
})
|
||||||
|
|
||||||
export const deleteConnection = (connectionId: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
export const deleteConnection = (connectionId: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||||
const connectionIds = Object.keys(getState().connectionManager.connections)
|
const connectionIds = Object.keys(getState().connectionManager.connections)
|
||||||
const connectionIdLocation = connectionIds.indexOf(connectionId)
|
const connectionIdLocation = connectionIds.indexOf(connectionId)
|
||||||
|
|||||||
@@ -44,29 +44,6 @@ class ConnectionSettings extends React.Component<Props, State> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private renderCertificateInfo() {
|
|
||||||
if (!this.props.connection.selfSignedCertificate) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<Tooltip title={this.props.connection.selfSignedCertificate.name}>
|
|
||||||
<Typography className={this.props.classes.certificateName}>
|
|
||||||
<ClearAdornment action={this.clearCertificate} value={this.props.connection.selfSignedCertificate.name} />
|
|
||||||
{this.props.connection.selfSignedCertificate.name}
|
|
||||||
</Typography>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private clearCertificate = () => {
|
|
||||||
this.props.managerActions.updateConnection(this.props.connection.id, {
|
|
||||||
selfSignedCertificate: undefined,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
private renderSubscriptions() {
|
private renderSubscriptions() {
|
||||||
const connection = this.props.connection
|
const connection = this.props.connection
|
||||||
return connection.subscriptions.map(subscription => (
|
return connection.subscriptions.map(subscription => (
|
||||||
@@ -122,16 +99,15 @@ class ConnectionSettings extends React.Component<Props, State> {
|
|||||||
</Grid>
|
</Grid>
|
||||||
<Grid item={true} xs={3} className={classes.gridPadding}>
|
<Grid item={true} xs={3} className={classes.gridPadding}>
|
||||||
<div>
|
<div>
|
||||||
<Tooltip title="Select certificate to verify authenticity of a self-signed certificate" placement="top">
|
<Tooltip title="Manage tls connection certificates" placement="top">
|
||||||
<Button
|
<Button
|
||||||
variant="contained"
|
variant="contained"
|
||||||
className={classes.button}
|
className={classes.button}
|
||||||
onClick={() => this.props.managerActions.selectCertificate(this.props.connection.id)}
|
onClick={() => this.props.managerActions.toggleCertificateSettings()}
|
||||||
>
|
>
|
||||||
<Lock /> Certificate
|
<Lock /> Certificates
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{this.renderCertificateInfo()}
|
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item={true} xs={2} className={classes.gridPadding}>
|
<Grid item={true} xs={2} className={classes.gridPadding}>
|
||||||
|
|||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import Add from '@material-ui/icons/Add'
|
||||||
|
import ClearAdornment from '../helper/ClearAdornment'
|
||||||
|
import Delete from '@material-ui/icons/Delete'
|
||||||
|
import Lock from '@material-ui/icons/Lock'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
import { Button, Theme, Tooltip, Typography } from '@material-ui/core'
|
||||||
|
import { CertificateParameters, ConnectionOptions } from '../../model/ConnectionOptions'
|
||||||
|
import { CertificateTypes } from '../../actions/ConnectionManager'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { connectionManagerActions } from '../../actions'
|
||||||
|
import { withStyles } from '@material-ui/styles'
|
||||||
|
|
||||||
|
function CertificateFileSelection(props: {
|
||||||
|
certificateType: CertificateTypes
|
||||||
|
title: string
|
||||||
|
certificate?: CertificateParameters
|
||||||
|
classes: any
|
||||||
|
actions: {
|
||||||
|
connectionManager: typeof connectionManagerActions
|
||||||
|
}
|
||||||
|
connection: ConnectionOptions
|
||||||
|
}) {
|
||||||
|
const clearCertificate = React.useCallback(() => {
|
||||||
|
props.actions.connectionManager.updateConnection(props.connection.id, {
|
||||||
|
[props.certificateType]: undefined,
|
||||||
|
})
|
||||||
|
}, [props.connection, props.certificateType])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
<Tooltip title="Select certificate" placement="top">
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className={props.classes.button}
|
||||||
|
onClick={() => props.actions.connectionManager.selectCertificate(props.certificateType, props.connection.id)}
|
||||||
|
>
|
||||||
|
<Lock /> {props.title}
|
||||||
|
</Button>
|
||||||
|
</Tooltip>
|
||||||
|
<ClearCertificate classes={props.classes} certificate={props.certificate} action={clearCertificate} />
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ClearCertificate(props: { classes: any; certificate?: CertificateParameters; action: () => void }) {
|
||||||
|
if (!props.certificate) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={props.certificate.name}>
|
||||||
|
<Typography className={props.classes.certificateName}>
|
||||||
|
<ClearAdornment action={props.action} value={props.certificate.name} />
|
||||||
|
{props.certificate.name}
|
||||||
|
</Typography>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch: any) => {
|
||||||
|
return {
|
||||||
|
actions: {
|
||||||
|
connectionManager: bindActionCreators(connectionManagerActions, dispatch),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = (theme: Theme) => ({
|
||||||
|
certificateName: {
|
||||||
|
width: '100%',
|
||||||
|
height: 'calc(1em + 4px)',
|
||||||
|
overflow: 'hidden' as 'hidden',
|
||||||
|
whiteSpace: 'nowrap' as 'nowrap',
|
||||||
|
textOverflow: 'ellipsis' as 'ellipsis',
|
||||||
|
color: theme.palette.text.hint,
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
marginTop: theme.spacing(3),
|
||||||
|
marginRight: theme.spacing(2),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
undefined,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(withStyles(styles)(CertificateFileSelection))
|
||||||
107
app/src/components/ConnectionSetup/Certificates.tsx
Normal file
107
app/src/components/ConnectionSetup/Certificates.tsx
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import * as React from 'react'
|
||||||
|
import CertificateFileSelection from './CertificateFileSelection'
|
||||||
|
import Undo from '@material-ui/icons/Undo'
|
||||||
|
import { bindActionCreators } from 'redux'
|
||||||
|
import { Button, Grid } from '@material-ui/core'
|
||||||
|
import { connect } from 'react-redux'
|
||||||
|
import { connectionManagerActions } from '../../actions'
|
||||||
|
import { ConnectionOptions } from '../../model/ConnectionOptions'
|
||||||
|
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
connection: ConnectionOptions
|
||||||
|
classes: any
|
||||||
|
managerActions: typeof connectionManagerActions
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
subscription: string
|
||||||
|
}
|
||||||
|
|
||||||
|
class Certificates extends React.Component<Props, State> {
|
||||||
|
constructor(props: any) {
|
||||||
|
super(props)
|
||||||
|
this.state = { subscription: '' }
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleChange = (name: string) => (event: any) => {
|
||||||
|
this.props.managerActions.updateConnection(this.props.connection.id, {
|
||||||
|
[name]: event.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private renderCertificateInfo() {
|
||||||
|
if (!this.props.connection.selfSignedCertificate) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return <span />
|
||||||
|
}
|
||||||
|
|
||||||
|
public render() {
|
||||||
|
const { classes } = this.props
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<form noValidate={true} autoComplete="off">
|
||||||
|
<Grid container={true} spacing={3}>
|
||||||
|
<Grid item={true} xs={12} className={classes.gridPadding}>
|
||||||
|
<CertificateFileSelection
|
||||||
|
connection={this.props.connection}
|
||||||
|
certificate={this.props.connection.selfSignedCertificate}
|
||||||
|
title="Server Certificate (CA)"
|
||||||
|
certificateType="selfSignedCertificate"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item={true} xs={12} className={classes.gridPadding}>
|
||||||
|
<CertificateFileSelection
|
||||||
|
connection={this.props.connection}
|
||||||
|
certificate={this.props.connection.clientCertificate}
|
||||||
|
title="Client Certificate"
|
||||||
|
certificateType="clientCertificate"
|
||||||
|
/>
|
||||||
|
<CertificateFileSelection
|
||||||
|
connection={this.props.connection}
|
||||||
|
certificate={this.props.connection.clientKey}
|
||||||
|
title="Client Key"
|
||||||
|
certificateType="clientKey"
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
<Grid item={true} xs={2} className={classes.gridPadding}>
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
className={classes.button}
|
||||||
|
onClick={this.props.managerActions.toggleCertificateSettings}
|
||||||
|
>
|
||||||
|
<Undo /> Back
|
||||||
|
</Button>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch: any) => {
|
||||||
|
return {
|
||||||
|
managerActions: bindActionCreators(connectionManagerActions, dispatch),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const styles = (theme: Theme) => ({
|
||||||
|
fullWidth: {
|
||||||
|
width: '100%',
|
||||||
|
},
|
||||||
|
gridPadding: {
|
||||||
|
padding: '0 12px !important',
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
marginTop: theme.spacing(3),
|
||||||
|
marginRight: theme.spacing(2),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export default connect(
|
||||||
|
undefined,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(withStyles(styles)(Certificates))
|
||||||
@@ -9,6 +9,7 @@ import { ConnectionOptions, toMqttConnection } from '../../model/ConnectionOptio
|
|||||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||||
import { Modal, Paper, Toolbar, Typography, Collapse } from '@material-ui/core'
|
import { Modal, Paper, Toolbar, Typography, Collapse } from '@material-ui/core'
|
||||||
import AdvancedConnectionSettings from './AdvancedConnectionSettings'
|
import AdvancedConnectionSettings from './AdvancedConnectionSettings'
|
||||||
|
import Certificates from './Certificates'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
actions: any
|
actions: any
|
||||||
@@ -16,6 +17,7 @@ interface Props {
|
|||||||
connection?: ConnectionOptions
|
connection?: ConnectionOptions
|
||||||
visible: boolean
|
visible: boolean
|
||||||
showAdvancedSettings: boolean
|
showAdvancedSettings: boolean
|
||||||
|
showCertificateSettings: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConnectionSetup extends React.Component<Props, {}> {
|
class ConnectionSetup extends React.Component<Props, {}> {
|
||||||
@@ -24,19 +26,22 @@ class ConnectionSetup extends React.Component<Props, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private renderSettings() {
|
private renderSettings() {
|
||||||
const { connection, showAdvancedSettings } = this.props
|
const { connection, showAdvancedSettings, showCertificateSettings } = this.props
|
||||||
if (!connection) {
|
if (!connection) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Collapse in={!showAdvancedSettings}>
|
<Collapse in={!showAdvancedSettings && !showCertificateSettings}>
|
||||||
<ConnectionSettings connection={connection} />
|
<ConnectionSettings connection={connection} />
|
||||||
</Collapse>
|
</Collapse>
|
||||||
<Collapse in={showAdvancedSettings}>
|
<Collapse in={showAdvancedSettings && !showCertificateSettings}>
|
||||||
<AdvancedConnectionSettings connection={connection} />
|
<AdvancedConnectionSettings connection={connection} />
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
<Collapse in={showCertificateSettings}>
|
||||||
|
<Certificates connection={connection} />
|
||||||
|
</Collapse>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -115,6 +120,7 @@ const mapStateToProps = (state: AppState) => {
|
|||||||
return {
|
return {
|
||||||
visible: !state.connection.connected,
|
visible: !state.connection.connected,
|
||||||
showAdvancedSettings: state.connectionManager.showAdvancedSettings,
|
showAdvancedSettings: state.connectionManager.showAdvancedSettings,
|
||||||
|
showCertificateSettings: state.connectionManager.showCertificateSettings,
|
||||||
connection: state.connectionManager.selected
|
connection: state.connectionManager.selected
|
||||||
? state.connectionManager.connections[state.connectionManager.selected]
|
? state.connectionManager.connections[state.connectionManager.selected]
|
||||||
: undefined,
|
: undefined,
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ export interface ConnectionOptions {
|
|||||||
encryption: boolean
|
encryption: boolean
|
||||||
certValidation: boolean
|
certValidation: boolean
|
||||||
selfSignedCertificate?: CertificateParameters
|
selfSignedCertificate?: CertificateParameters
|
||||||
|
clientCertificate?: CertificateParameters
|
||||||
|
clientKey?: CertificateParameters
|
||||||
clientId?: string
|
clientId?: string
|
||||||
subscriptions: Array<string>
|
subscriptions: Array<string>
|
||||||
}
|
}
|
||||||
@@ -38,6 +40,8 @@ export function toMqttConnection(options: ConnectionOptions): MqttOptions | unde
|
|||||||
certValidation: options.certValidation,
|
certValidation: options.certValidation,
|
||||||
subscriptions: options.subscriptions,
|
subscriptions: options.subscriptions,
|
||||||
certificateAuthority: options.selfSignedCertificate ? options.selfSignedCertificate.data : undefined,
|
certificateAuthority: options.selfSignedCertificate ? options.selfSignedCertificate.data : undefined,
|
||||||
|
clientCertificate: options.clientCertificate ? options.clientCertificate.data : undefined,
|
||||||
|
clientKey: options.clientKey ? options.clientKey.data : undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,14 @@ export interface ConnectionManagerState {
|
|||||||
connections: { [s: string]: ConnectionOptions }
|
connections: { [s: string]: ConnectionOptions }
|
||||||
selected?: string
|
selected?: string
|
||||||
showAdvancedSettings: boolean
|
showAdvancedSettings: boolean
|
||||||
|
showCertificateSettings: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: ConnectionManagerState = {
|
const initialState: ConnectionManagerState = {
|
||||||
connections: {},
|
connections: {},
|
||||||
selected: undefined,
|
selected: undefined,
|
||||||
showAdvancedSettings: false,
|
showAdvancedSettings: false,
|
||||||
|
showCertificateSettings: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action =
|
export type Action =
|
||||||
@@ -21,6 +23,7 @@ export type Action =
|
|||||||
| AddConnection
|
| AddConnection
|
||||||
| DeleteConnection
|
| DeleteConnection
|
||||||
| ToggleAdvancedSettings
|
| ToggleAdvancedSettings
|
||||||
|
| ToggleCertificateSettings
|
||||||
| DeleteSubscription
|
| DeleteSubscription
|
||||||
| AddSubscription
|
| AddSubscription
|
||||||
|
|
||||||
@@ -31,6 +34,7 @@ export enum ActionTypes {
|
|||||||
CONNECTION_MANAGER_ADD_CONNECTION = 'CONNECTION_MANAGER_ADD_CONNECTION',
|
CONNECTION_MANAGER_ADD_CONNECTION = 'CONNECTION_MANAGER_ADD_CONNECTION',
|
||||||
CONNECTION_MANAGER_DELETE_CONNECTION = 'CONNECTION_MANAGER_DELETE_CONNECTION',
|
CONNECTION_MANAGER_DELETE_CONNECTION = 'CONNECTION_MANAGER_DELETE_CONNECTION',
|
||||||
CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS = 'CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS',
|
CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS = 'CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS',
|
||||||
|
CONNECTION_MANAGER_TOGGLE_CERTIFICATE_SETTINGS = 'CONNECTION_MANAGER_TOGGLE_CERTIFICATE_SETTINGS',
|
||||||
CONNECTION_MANAGER_ADD_SUBSCRIPTION = 'CONNECTION_MANAGER_ADD_SUBSCRIPTION',
|
CONNECTION_MANAGER_ADD_SUBSCRIPTION = 'CONNECTION_MANAGER_ADD_SUBSCRIPTION',
|
||||||
CONNECTION_MANAGER_DELETE_SUBSCRIPTION = 'CONNECTION_MANAGER_DELETE_SUBSCRIPTION',
|
CONNECTION_MANAGER_DELETE_SUBSCRIPTION = 'CONNECTION_MANAGER_DELETE_SUBSCRIPTION',
|
||||||
}
|
}
|
||||||
@@ -77,6 +81,10 @@ export interface ToggleAdvancedSettings {
|
|||||||
type: ActionTypes.CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS
|
type: ActionTypes.CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ToggleCertificateSettings {
|
||||||
|
type: ActionTypes.CONNECTION_MANAGER_TOGGLE_CERTIFICATE_SETTINGS
|
||||||
|
}
|
||||||
|
|
||||||
export const connectionManagerReducer = createReducer(initialState, {
|
export const connectionManagerReducer = createReducer(initialState, {
|
||||||
CONNECTION_MANAGER_SET_CONNECTIONS: setConnections,
|
CONNECTION_MANAGER_SET_CONNECTIONS: setConnections,
|
||||||
CONNECTION_MANAGER_SELECT_CONNECTION: selectConnection,
|
CONNECTION_MANAGER_SELECT_CONNECTION: selectConnection,
|
||||||
@@ -84,6 +92,7 @@ export const connectionManagerReducer = createReducer(initialState, {
|
|||||||
CONNECTION_MANAGER_ADD_CONNECTION: addConnection,
|
CONNECTION_MANAGER_ADD_CONNECTION: addConnection,
|
||||||
CONNECTION_MANAGER_DELETE_CONNECTION: deleteConnection,
|
CONNECTION_MANAGER_DELETE_CONNECTION: deleteConnection,
|
||||||
CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS: toggleAdvancedSettings,
|
CONNECTION_MANAGER_TOGGLE_ADVANCED_SETTINGS: toggleAdvancedSettings,
|
||||||
|
CONNECTION_MANAGER_TOGGLE_CERTIFICATE_SETTINGS: toggleCertificateSettings,
|
||||||
CONNECTION_MANAGER_DELETE_SUBSCRIPTION: deleteSubscription,
|
CONNECTION_MANAGER_DELETE_SUBSCRIPTION: deleteSubscription,
|
||||||
CONNECTION_MANAGER_ADD_SUBSCRIPTION: addSubscription,
|
CONNECTION_MANAGER_ADD_SUBSCRIPTION: addSubscription,
|
||||||
})
|
})
|
||||||
@@ -109,6 +118,16 @@ function toggleAdvancedSettings(state: ConnectionManagerState, action: ToggleAdv
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleCertificateSettings(
|
||||||
|
state: ConnectionManagerState,
|
||||||
|
action: ToggleCertificateSettings
|
||||||
|
): ConnectionManagerState {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
showCertificateSettings: !state.showCertificateSettings,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function addConnection(state: ConnectionManagerState, action: AddConnection): ConnectionManagerState {
|
function addConnection(state: ConnectionManagerState, action: AddConnection): ConnectionManagerState {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ export interface MqttOptions {
|
|||||||
clientId?: string
|
clientId?: string
|
||||||
subscriptions: Array<string>
|
subscriptions: Array<string>
|
||||||
certificateAuthority?: string
|
certificateAuthority?: string
|
||||||
|
clientCertificate?: string
|
||||||
|
clientKey?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MqttSource implements DataSource<MqttOptions> {
|
export class MqttSource implements DataSource<MqttOptions> {
|
||||||
@@ -44,8 +46,10 @@ export class MqttSource implements DataSource<MqttOptions> {
|
|||||||
username: options.username,
|
username: options.username,
|
||||||
password: options.password,
|
password: options.password,
|
||||||
clientId: options.clientId,
|
clientId: options.clientId,
|
||||||
servername: options.tls ? url.host : undefined,
|
servername: options.tls ? url.hostname : undefined,
|
||||||
ca: options.certificateAuthority ? Buffer.from(options.certificateAuthority, 'base64') : undefined,
|
ca: options.certificateAuthority ? Buffer.from(options.certificateAuthority, 'base64') : undefined,
|
||||||
|
cert: options.clientCertificate ? Buffer.from(options.clientCertificate, 'base64') : undefined,
|
||||||
|
key: options.clientKey ? Buffer.from(options.clientKey, 'base64') : undefined,
|
||||||
} as any)
|
} as any)
|
||||||
|
|
||||||
this.client = client
|
this.client = client
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import 'mocha'
|
import { Edge, TreeNodeFactory } from '../'
|
||||||
|
|
||||||
import { Edge, TreeNode, TreeNodeFactory } from '../'
|
|
||||||
|
|
||||||
import { expect } from 'chai'
|
import { expect } from 'chai'
|
||||||
|
import 'mocha'
|
||||||
|
|
||||||
describe('Edge', () => {
|
describe('Edge', () => {
|
||||||
it('should contain a name', () => {
|
it('should contain a name', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user