Skip to content

Commit

Permalink
Editing and saving vault items now works
Browse files Browse the repository at this point in the history
  • Loading branch information
cakenggt committed Oct 26, 2016
1 parent a9df67f commit cf3bf5c
Show file tree
Hide file tree
Showing 9 changed files with 504 additions and 81 deletions.
21 changes: 19 additions & 2 deletions app/actions.js
@@ -1,8 +1,12 @@
import sjcl from 'sjcl';

/* Uploads vault and returns a Promise<JSON> */
export function uploadVault(vault, password, jwt){
return function(dispatch){
export function uploadVault(){
return function(dispatch, getState){
var state = getState();
var vault = state.vault;
var password = state.connect.password;
var jwt = state.connect.jwt;
var encrypted = sjcl.encrypt(
password,
JSON.stringify(vault)
Expand Down Expand Up @@ -32,6 +36,19 @@ export function uploadVault(vault, password, jwt){
};
}

export function saveVaultItem(itemId, item){
return function(dispatch){
dispatch({
type: 'SAVE_VAULT_ITEM',
data: {
item: item,
itemId: itemId
}
});
dispatch(uploadVault());
};
}

export function login(email, password, router, totp){
return function(dispatch){
fetch('/api/v1/login', {
Expand Down
81 changes: 67 additions & 14 deletions app/components/VaultItemView.jsx
@@ -1,36 +1,69 @@
import React from 'react';
import {connect} from 'react-redux';
import {withRouter} from 'react-router';
import {uploadVault} from '../actions';
import {saveVaultItem} from '../actions';
import uuid from 'uuid';

var VaultItemView = withRouter(React.createClass({
propTypes: {
vault: React.PropTypes.object
},
render: function(){
getInitialState: function(){
var item = this.props.vault[this.props.params.itemId];
if (!item){
item = {
name: '',
passwordArray: [],
password: '',
username: ''
};
}
var key = this.props.params.itemId ?
this.props.params.itemId :
'newVaultItem';
else{
//populate virtual password field
item.password = item.passwordArray[item.passwordArray.length-1];
}
return item;
},
render: function(){
var key = this.props.params.itemId;
var controlledComponentGenerator = (stateAttr) => {
return (event) => {
let newState = {};
newState[stateAttr] = event.target.value;
this.setState(newState);
};
};
return (
<div
className="modal"
key={key}>
<div
className="modal-content">
<div>Name: {item.name}</div>
<div>Password: {item.passwordArray[item.passwordArray.length-1]}</div>
<div>Password Array: {item.passwordArray}</div>
<div>Username: {item.username}</div>
<div
onClick={this.cancel}>Cancel</div>
<div>
Name
<input
value={this.state.name}
onChange={controlledComponentGenerator('name')}/>
</div>
<div>
Password:
<input
value={this.state.password}
onChange={controlledComponentGenerator('password')}/>
</div>
<div>
Password History: <span>{JSON.stringify(this.state.passwordArray)}</span>
</div>
<div>
Username:
<input
value={this.state.username}
onChange={controlledComponentGenerator('username')}/>
</div>
<span
onClick={this.cancel}>Cancel</span>
<span
onClick={this.save}>Save</span>
</div>
</div>
);
Expand All @@ -39,8 +72,19 @@ var VaultItemView = withRouter(React.createClass({
this.props.router.goBack();
},
save: function(){
//TODO if no itemId is given, then create a new entry, else modify old one
//Then modify state and upload vault using an action creator
var itemId = this.props.params.itemId;
var item = Object.assign({}, this.state);
//push password onto passwordArray and delete virtual attribute
var lastPassword = item.passwordArray[item.passwordArray.length-1];
if (lastPassword != item.password){
item.passwordArray.push(item.password);
}
delete item.password;
if (itemId == 'NEW'){
itemId = uuid.v4();
}
this.props.saveVaultItem(itemId, item);
this.props.router.goBack();
}
}));

Expand All @@ -50,6 +94,15 @@ var mapStateToProps = function(state){
}
}

var mapDispatchToProps = function(dispatch){
return {
saveVaultItem: function(itemId, item){
dispatch(saveVaultItem(itemId, item));
}
};
}

export default connect(
mapStateToProps
mapStateToProps,
mapDispatchToProps
)(VaultItemView);
58 changes: 34 additions & 24 deletions app/components/VaultView.jsx
@@ -1,6 +1,6 @@
import React from 'react';
import {connect} from 'react-redux';
import {Link, IndexLink} from 'react-router';
import {Link, IndexLink, withRouter} from 'react-router';
import sjcl from 'sjcl';
import {uploadVault} from '../actions';
import FocusComponent from './FocusComponent.jsx';
Expand All @@ -10,47 +10,57 @@ var VaultView = React.createClass({
var className = this.props.children ?
'focus blur' :
'focus';
var vaultItemIds = Object.keys(this.props.vault);
var vaultEntries = vaultItemIds.map((elem)=>{
var entry = this.props.vault[elem];
return <VaultEntry entry={entry} itemId={elem} key={elem}/>
});
return (
<div>
<div
className={className}>
Vault
<div
onClick={this.uploadVault}>Upload</div>
<Link to="/vault/item/x">Add Item</Link>
<Link to="/vault/item/NEW">Add Item</Link>
<table>
<tbody>
{vaultEntries}
</tbody>
</table>
</div>
<FocusComponent>
{this.props.children}
</FocusComponent>
</div>
);
},
uploadVault: function(){
this.props.uploadVault(
this.props.vault,
this.props.password,
this.props.jwt
);
}
});

var mapStateToProps = function(state){
return {
vault: state.vault,
jwt: state.connect.jwt,
password: state.connect.password
};
}
var VaultEntry = withRouter(React.createClass({
render: function(){
var entry = this.props.entry;
return (
<tr
onClick={this.goToVaultItem}>
<td>
{entry.name}
</td>
<td>
{entry.username}
</td>
</tr>
)
},
goToVaultItem: function(){
this.props.router.push('/vault/item/'+this.props.itemId);
}
}));

var mapDispatchToProps = function(dispatch){
var mapStateToProps = function(state){
return {
uploadVault: function(vault, password, jwt){
dispatch(uploadVault(vault, password, jwt));
}
vault: state.vault
};
}

export default connect(
mapStateToProps,
mapDispatchToProps
mapStateToProps
)(VaultView);
6 changes: 6 additions & 0 deletions app/reducers/vaultReducer.js
Expand Up @@ -3,6 +3,12 @@ export default function(state = {}, action){
switch (action.type){
case 'LOGIN_SUCCESSFUL':
return action.data.vault;
case 'SAVE_VAULT_ITEM':
let item = action.data.item;
let itemId = action.data.itemId;
let change = {};
change[itemId] = item;
return Object.assign({}, state, change);
default:
return state;
}
Expand Down
2 changes: 1 addition & 1 deletion models.js
Expand Up @@ -30,7 +30,7 @@ module.exports = function(sequelize, DataTypes) {
allowNull: false
},
store: {
type: DataTypes.STRING
type: DataTypes.TEXT
},
lastLoginFail: {
type: DataTypes.DATE
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -29,6 +29,7 @@
"sequelize": "^3.24.1",
"sjcl": "^1.0.6",
"speakeasy": "^2.0.0",
"uuid": "^2.0.3",
"webpack": "^1.13.2"
},
"name": "frost-password-manager",
Expand Down
2 changes: 1 addition & 1 deletion public/css/stylesheet.css
Expand Up @@ -8,7 +8,7 @@ h1 {
margin: 0 auto;
}
.focus {
transition: all 1s ease;
transition: all 500ms ease;
filter: blur(0px) opacity(100%);
}
.blur {
Expand Down

0 comments on commit cf3bf5c

Please sign in to comment.