diff --git a/data/config/securitySettings.json b/data/config/securitySettings.json index 4d169f0..ce6cb6a 100644 --- a/data/config/securitySettings.json +++ b/data/config/securitySettings.json @@ -1,16 +1,15 @@ { "jwt_secret":"esp8266-react", - "roles": ["admin", "guest"], "users": [ { "username": "admin", "password": "admin", - "role": "admin" + "admin": true }, { "username": "guest", "password": "guest", - "role": "guest" + "admin": false } ] } \ No newline at end of file diff --git a/interface/src/forms/ManageUsersForm.js b/interface/src/forms/ManageUsersForm.js index e86cd4a..21c2d5d 100644 --- a/interface/src/forms/ManageUsersForm.js +++ b/interface/src/forms/ManageUsersForm.js @@ -1,7 +1,7 @@ import React from 'react'; import PropTypes from 'prop-types'; -import { TextValidator, ValidatorForm } from 'react-material-ui-form-validator'; +import { ValidatorForm } from 'react-material-ui-form-validator'; import { withStyles } from '@material-ui/core/styles'; import Button from '@material-ui/core/Button'; @@ -13,14 +13,16 @@ import TableCell from '@material-ui/core/TableCell'; import TableFooter from '@material-ui/core/TableFooter'; import TableHead from '@material-ui/core/TableHead'; import TableRow from '@material-ui/core/TableRow'; -import Chip from '@material-ui/core/Chip'; import EditIcon from '@material-ui/icons/Edit'; import DeleteIcon from '@material-ui/icons/Delete'; +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'; const styles = theme => ({ loadingSettings: { @@ -30,26 +32,15 @@ const styles = theme => ({ margin: theme.spacing.unit * 4, textAlign: "center" }, - switchControl: { - width: "100%", - marginTop: theme.spacing.unit * 2, - marginBottom: theme.spacing.unit - }, - textField: { - width: "100%" - }, button: { marginRight: theme.spacing.unit * 2, marginTop: theme.spacing.unit * 2, }, - chip: { - margin: theme.spacing.unit, - }, table: { '& td, & th': { padding: theme.spacing.unit } }, actions: { - color: theme.palette.text.secondary, + whiteSpace: "nowrap" } }); @@ -76,7 +67,7 @@ class ManageUsersForm extends React.Component { user: { username: "", password: "", - roles: [] + admin: true } }); }; @@ -85,8 +76,8 @@ class ManageUsersForm extends React.Component { return !this.props.userData.users.find(u => u.username === username); } - usersValid = username => { - return !!this.props.userData.users.find(u => u.roles.includes("admin")); + noAdminConfigured = () => { + return !this.props.userData.users.find(u => u.admin); } startEditingUser = user => { @@ -102,10 +93,6 @@ class ManageUsersForm extends React.Component { }); } - sortedUsers(users) { - return users.sort(compareUsers); - } - doneEditingUser = () => { const { user } = this.state; const { userData } = this.props; @@ -120,17 +107,29 @@ class ManageUsersForm extends React.Component { handleUserValueChange = name => event => { const { user } = this.state; - if (user) { - this.setState({ - user: { - ...user, [name]: event.target.value - } - }); - } + this.setState({ + user: { + ...user, [name]: event.target.value + } + }); }; + handleUserCheckboxChange = name => event => { + const { user } = this.state; + this.setState({ + user: { + ...user, [name]: event.target.checked + } + }); + } + + onSubmit = () => { + this.props.onSubmit(); + this.props.authenticationContex.refresh(); + } + render() { - const { classes, userData, userDataFetched, errorMessage, onSubmit, onReset, handleValueChange } = this.props; + const { classes, userData, userDataFetched, errorMessage, onReset } = this.props; const { user, creating } = this.state; return ( @@ -148,33 +147,31 @@ class ManageUsersForm extends React.Component { : - + Username - Role(s) + Admin? Action - {this.sortedUsers(userData.users).map(user => ( + {userData.users.sort(compareUsers).map(user => ( {user.username} { - user.roles.map(role => ( - - )) + user.admin ? : } @@ -192,7 +189,7 @@ class ManageUsersForm extends React.Component { { - !this.usersValid() && + this.noAdminConfigured() && You must have at least one admin user configured. @@ -206,7 +203,7 @@ class ManageUsersForm extends React.Component {
- @@ -102,11 +83,11 @@ UserForm.propTypes = { classes: PropTypes.object.isRequired, user: PropTypes.object.isRequired, creating: PropTypes.bool.isRequired, - roles: PropTypes.array.isRequired, onDoneEditing: PropTypes.func.isRequired, onCancelEditing: PropTypes.func.isRequired, uniqueUsername: PropTypes.func.isRequired, - handleValueChange: PropTypes.func.isRequired + handleValueChange: PropTypes.func.isRequired, + handleCheckboxChange: PropTypes.func.isRequired }; export default withStyles(styles)(UserForm); diff --git a/src/SecurityManager.cpp b/src/SecurityManager.cpp index 52a2c3a..fd5a549 100644 --- a/src/SecurityManager.cpp +++ b/src/SecurityManager.cpp @@ -7,26 +7,11 @@ void SecurityManager::readFromJsonObject(JsonObject& root) { // secret _jwtSecret = root["jwt_secret"] | DEFAULT_JWT_SECRET; - // roles - _roles.clear(); - if (root["roles"].is()) { - JsonArray roles = root["roles"]; - for (JsonVariant role : roles) { - _roles.push_back(role.as()); - } - } - // users _users.clear(); if (root["users"].is()) { for (JsonVariant user : root["users"].as()) { - std::list roles; - if (user["roles"].is()) { - for (JsonVariant role : user["roles"].as()) { - roles.push_back(role.as()); - } - } - _users.push_back(User(user["username"], user["password"], roles)); + _users.push_back(User(user["username"], user["password"], user["admin"])); } } } @@ -36,22 +21,13 @@ void SecurityManager::writeToJsonObject(JsonObject& root) { // secret root["jwt_secret"] = _jwtSecret; - // roles - JsonArray roles = root.createNestedArray("roles"); - for (String _role : _roles) { - roles.add(_role); - } - // users JsonArray users = root.createNestedArray("users"); for (User _user : _users) { JsonObject user = users.createNestedObject(); user["username"] = _user.getUsername(); user["password"] = _user.getPassword(); - JsonArray roles = user.createNestedArray("roles"); - for (String _role : _user.getRoles()){ - roles.add(_role); - } + user["admin"] = _user.isAdmin(); } } @@ -100,10 +76,7 @@ Authentication SecurityManager::authenticate(String username, String password) { inline void populateJWTPayload(JsonObject &payload, User *user) { payload["username"] = user->getUsername(); - JsonArray roles = payload.createNestedArray("roles"); - for (String _role : user->getRoles()){ - roles.add(_role); - } + payload["admin"] = user -> isAdmin(); } boolean SecurityManager::validatePayload(JsonObject &parsedPayload, User *user) { diff --git a/src/SecurityManager.h b/src/SecurityManager.h index f12ac0a..cfd7712 100644 --- a/src/SecurityManager.h +++ b/src/SecurityManager.h @@ -28,17 +28,17 @@ class User { private: String _username; String _password; - std::list _roles; + bool _admin; public: - User(String username, String password, std::list roles): _username(username), _password(password), _roles(roles) {} + User(String username, String password, bool admin): _username(username), _password(password), _admin(admin) {} String getUsername() { return _username; } String getPassword() { return _password; } - std::list getRoles() { - return _roles; + bool isAdmin() { + return _admin; } }; @@ -97,7 +97,6 @@ class SecurityManager : public SettingsService { // access point settings String _jwtSecret; - std::list _roles; std::list _users; // endpoint functions