diff --git a/interface/.env.development b/interface/.env.development index b7c5d93..a5bcdb0 100644 --- a/interface/.env.development +++ b/interface/.env.development @@ -1 +1 @@ -REACT_APP_ENDPOINT_ROOT=http://192.168.0.16/rest/ +REACT_APP_ENDPOINT_ROOT=http://192.168.0.11/rest/ diff --git a/interface/src/AppRouting.js b/interface/src/AppRouting.js index cda03d2..4d7c4fc 100644 --- a/interface/src/AppRouting.js +++ b/interface/src/AppRouting.js @@ -31,7 +31,7 @@ class AppRouting extends Component { - + diff --git a/interface/src/components/MenuAppBar.js b/interface/src/components/MenuAppBar.js index 625ad58..f5d0b49 100644 --- a/interface/src/components/MenuAppBar.js +++ b/interface/src/components/MenuAppBar.js @@ -137,7 +137,7 @@ class MenuAppBar extends React.Component { - + diff --git a/interface/src/containers/ManageUsers.js b/interface/src/containers/ManageUsers.js index 1a69f1f..3541728 100644 --- a/interface/src/containers/ManageUsers.js +++ b/interface/src/containers/ManageUsers.js @@ -3,6 +3,7 @@ import React, { Component } from 'react'; import { USERS_ENDPOINT } from '../constants/Endpoints'; import { restComponent } from '../components/RestComponent'; import ManageUsersForm from '../forms/ManageUsersForm'; +import SectionContent from '../components/SectionContent'; class ManageUsers extends Component { @@ -13,15 +14,17 @@ class ManageUsers extends Component { render() { const { data, fetched, errorMessage } = this.props; return ( - + + + ) } diff --git a/interface/src/containers/Security.js b/interface/src/containers/Security.js index 0eaf6d6..f6222cf 100644 --- a/interface/src/containers/Security.js +++ b/interface/src/containers/Security.js @@ -1,15 +1,35 @@ import React, { Component } from 'react'; +import { Redirect, Switch } from 'react-router-dom' + +import Tabs from '@material-ui/core/Tabs'; +import Tab from '@material-ui/core/Tab'; + +import AuthenticatedRoute from '../authentication/AuthenticatedRoute'; import MenuAppBar from '../components/MenuAppBar'; import ManageUsers from './ManageUsers'; +import SecuritySettings from './SecuritySettings'; class Security extends Component { + + handleTabChange = (event, path) => { + this.props.history.push(path); + }; + render() { return ( - - - + + + + + + + + + + + ) } } -export default Security +export default Security; diff --git a/interface/src/containers/SecuritySettings.js b/interface/src/containers/SecuritySettings.js new file mode 100644 index 0000000..642c9fb --- /dev/null +++ b/interface/src/containers/SecuritySettings.js @@ -0,0 +1,32 @@ +import React, { Component } from 'react'; + +import { USERS_ENDPOINT } from '../constants/Endpoints'; +import { restComponent } from '../components/RestComponent'; +import SecuritySettingsForm from '../forms/SecuritySettingsForm'; +import SectionContent from '../components/SectionContent'; + +class SecuritySettings extends Component { + + componentDidMount() { + this.props.loadData(); + } + + render() { + const { data, fetched, errorMessage } = this.props; + return ( + + + + ) + } + +} + +export default restComponent(USERS_ENDPOINT, SecuritySettings); diff --git a/interface/src/forms/ManageUsersForm.js b/interface/src/forms/ManageUsersForm.js index 75e1bb3..7702cde 100644 --- a/interface/src/forms/ManageUsersForm.js +++ b/interface/src/forms/ManageUsersForm.js @@ -21,7 +21,6 @@ import CloseIcon from '@material-ui/icons/Close'; import CheckIcon from '@material-ui/icons/Check'; import IconButton from '@material-ui/core/IconButton'; -import SectionContent from '../components/SectionContent'; import UserForm from './UserForm'; import { withAuthenticationContext } from '../authentication/Context'; @@ -138,108 +137,101 @@ class ManageUsersForm extends React.Component { const { classes, userData, userDataFetched, errorMessage, onReset } = this.props; const { user, creating } = this.state; return ( - - { - !userDataFetched ? -
- - - Loading... - -
- : - userData ? - - - - - - Username - Admin? - - - - - {userData.users.sort(compareUsers).map(user => ( - - - {user.username} - - - { - user.admin ? : - } - - - this.removeUser(user)}> - - - this.startEditingUser(user)}> - - - - - ))} - - - - - - - - - -
- { - this.noAdminConfigured() && - - - You must have at least one admin user configured. - - - } - - -
- { - user && - - - - } -
- : - - - {errorMessage} + !userDataFetched ? +
+ + + Loading... + +
+ : + userData ? + + + + + + Username + Admin? + + + + + {userData.users.sort(compareUsers).map(user => ( + + + {user.username} + + + { + user.admin ? : + } + + + this.removeUser(user)}> + + + this.startEditingUser(user)}> + + + + + ))} + + + + + + + + + +
+ { + this.noAdminConfigured() && + + + You must have at least one admin user configured. + - -
- } -
+ } + + + + { + user && + + } + + : +
+ + {errorMessage} + + +
); } } ManageUsersForm.propTypes = { - authenticationContext: PropTypes.object.isRequired, classes: PropTypes.object.isRequired, userData: PropTypes.object, userDataFetched: PropTypes.bool.isRequired, @@ -247,7 +239,8 @@ ManageUsersForm.propTypes = { onSubmit: PropTypes.func.isRequired, onReset: PropTypes.func.isRequired, setData: PropTypes.func.isRequired, - handleValueChange: PropTypes.func.isRequired + handleValueChange: PropTypes.func.isRequired, + authenticationContext: PropTypes.object.isRequired, }; export default withAuthenticationContext(withStyles(styles)(ManageUsersForm)); diff --git a/interface/src/forms/SecuritySettingsForm.js b/interface/src/forms/SecuritySettingsForm.js new file mode 100644 index 0000000..32c16e7 --- /dev/null +++ b/interface/src/forms/SecuritySettingsForm.js @@ -0,0 +1,97 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { ValidatorForm } from 'react-material-ui-form-validator'; + +import { withStyles } from '@material-ui/core/styles'; +import Button from '@material-ui/core/Button'; +import LinearProgress from '@material-ui/core/LinearProgress'; +import Typography from '@material-ui/core/Typography'; +import Box from '@material-ui/core/Box'; + +import PasswordValidator from '../components/PasswordValidator'; +import { withAuthenticationContext } from '../authentication/Context'; + +const styles = theme => ({ + loadingSettings: { + margin: theme.spacing.unit, + }, + loadingSettingsDetails: { + margin: theme.spacing.unit * 4, + textAlign: "center" + }, + textField: { + width: "100%" + }, + button: { + marginRight: theme.spacing.unit * 2, + marginTop: theme.spacing.unit * 2, + } +}); + +class SecuritySettingsForm extends React.Component { + + onSubmit = () => { + this.props.onSubmit(); + this.props.authenticationContext.refresh(); + } + + render() { + const { classes, securitySettingsFetched, securitySettings, errorMessage, handleValueChange, onReset } = this.props; + return ( + !securitySettingsFetched ? +
+ + + Loading... + +
+ : + securitySettings ? + + + + + If you modify the JWT Secret, all users will be logged out. + + + + + + : +
+ + {errorMessage} + + +
+ ); + } +} + +SecuritySettingsForm.propTypes = { + classes: PropTypes.object.isRequired, + securitySettingsFetched: PropTypes.bool.isRequired, + securitySettings: PropTypes.object, + errorMessage: PropTypes.string, + onSubmit: PropTypes.func.isRequired, + onReset: PropTypes.func.isRequired, + handleValueChange: PropTypes.func.isRequired, + authenticationContext: PropTypes.object.isRequired, +}; + +export default withAuthenticationContext(withStyles(styles)(SecuritySettingsForm)); diff --git a/interface/src/forms/UserForm.js b/interface/src/forms/UserForm.js index a0b6adc..225a0bf 100644 --- a/interface/src/forms/UserForm.js +++ b/interface/src/forms/UserForm.js @@ -44,7 +44,7 @@ class UserForm extends React.Component { return ( - {creating ? 'Create' : 'Modify'} User + {creating ? 'Add' : 'Modify'} User ()) { JsonObject parsedPayload = payloadDocument.as(); String username = parsedPayload["username"]; @@ -91,5 +89,5 @@ String SecurityManager::generateJWT(User *user) { DynamicJsonDocument _jsonDocument(MAX_JWT_SIZE); JsonObject payload = _jsonDocument.to(); populateJWTPayload(payload, user); - return jwtHandler.buildJWT(payload); + return _jwtHandler.buildJWT(payload); } diff --git a/src/SecurityManager.h b/src/SecurityManager.h index cfd7712..d3ac577 100644 --- a/src/SecurityManager.h +++ b/src/SecurityManager.h @@ -93,7 +93,7 @@ class SecurityManager : public SettingsService { private: // jwt handler - ArduinoJsonJWT jwtHandler = ArduinoJsonJWT(DEFAULT_JWT_SECRET); + ArduinoJsonJWT _jwtHandler = ArduinoJsonJWT(DEFAULT_JWT_SECRET); // access point settings String _jwtSecret;