adding and fetching docs

This commit is contained in:
2018-09-19 20:29:48 +02:00
parent d9aa8deb16
commit 8d93af6552
11 changed files with 416 additions and 270 deletions

View File

@ -1,11 +1,14 @@
import React, {Component} from 'react';
import { observer, inject } from 'mobx-react';
import jss from 'jss';
import preset from 'jss-preset-default';
import { Segment, Container, Header, Form, Input, Button, Icon } from 'semantic-ui-react';
import alertify from 'alertify.js';
/*
* Functions import
*/
import { encrypt } from '../../stores/functions/encryption';
/*
* Component imports
@ -13,6 +16,11 @@ import { Segment, Container, Header, Form, Input, Button, Icon } from 'semantic-
jss.setup(preset());
//Firebase
var firebase = require('../../stores/fb').fb;
// Initialize Cloud Firestore through Firebase
var db = firebase.firestore();
/*
###############################
@ -28,54 +36,61 @@ Components -- END
class New extends Component {
constructor(props){
super(props);
//Add a new password window
const New = inject("rootStore") ( observer(
class New extends Component {
constructor(props){
super(props);
//Add a new password window
/*
* Expected props
* - open: bool
* display component or not
* - toggleNewWindow: function
* toggles window: open and close
* - encryptionkey: String
* encryption key of the password
*/
/*
* Expected props
* - open: bool
* display component or not
* - toggleNewWindow: function
* toggles window: open and close
* - encryptionkey: String
* encryption key of the password
*/
this.state = {
url: '',
login: '',
password: this.generatePassword(),
loading: false
}
//Stored information
this.stores = this.props.rootStore.stores;
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
componentWillReceiveProps(nextProps) {
if(nextProps.open !== this.props.open) {
this.setState({
this.state = {
url: '',
login: '',
password: this.generatePassword()
});
password: this.generatePassword(),
loading: false
}
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
}
componentWillReceiveProps(nextProps) {
if(nextProps.open !== this.props.open) {
this.setState({
url: '',
login: '',
password: this.generatePassword()
});
}
}
}
componentWillUnmount() {
this.sheet.detach()
}
componentWillUnmount() {
this.sheet.detach()
}
generatePassword() {
generatePassword() {
//Creates a unique id for each chat bubble so that the animation can be triggered
var random = "";
@ -89,78 +104,111 @@ class New extends Component {
return random;
}
}
}
handleChange(e, {name}) {
this.setState({
[name]: e.target.value
});
}
render() {
if(this.props.open) {
return(
<div className={this.classes.box}>
<Container text>
<Segment padded="very">
<Form onSubmit={this.handleSubmit}>
<Header as="h2">
Add a password
</Header>
<Form.Field>
<label>Application / URL:</label>
<Input iconPosition='left' placeholder='http://exmple.com'>
<input value={this.state.url} type="text" name="url" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<Form.Field>
<label>Username / email adress:</label>
<Input iconPosition='left' placeholder='example@example.com'>
<input value={this.state.login} type="text" name="login" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<Form.Field>
<label>Password:</label>
<Input iconPosition='left' placeholder='********'>
<input value={this.state.password} type="text" name="password" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<p>The encryption key for this entry is '<b>{this.props.encryptionkey}</b>'</p>
<Button loading={this.state.loading} type='submit' primary>Add</Button>
<Button loading={this.state.loading} onClick={this.props.toggleNewWindow}><Icon name="x" />Cancel</Button>
</Form>
</Segment>
</Container>
</div>
);
} else {
return null;
}
}
getStyles() {
return {
box: {
width: '100vw',
height: '100vh',
position: 'fixed',
zIndex: 1000,
top: 0,
left: 0,
backgroundColor: 'rgba(255,255,255,0.9)',
paddingTop: '5%'
handleChange(e) {
this.setState({
[e.target.name]: e.target.value
});
}
handleSubmit() {
const url = this.state.url;
const login = encrypt(this.state.login, this.props.encryptionkey);
const password = encrypt(this.state.password, this.props.encryptionkey);
const uid = this.stores.authStore.userData.uid;
db.collection("passwords").add({
uid: uid,
url: url,
login: login,
password: password,
time: new Date()
})
.then((docRef) => {
console.log("Document written with ID: ", docRef.id);
alertify.success("Document successfully added!");
this.props.toggleNewWindow();
})
.catch(function(error) {
console.error("Error adding document: ", error);
alertify.error("Something went wrong! Please check your internet connection");
this.setState({
loading: false
});
});
this.setState({
loading: true
});
}
render() {
if(this.props.open) {
return(
<div className={this.classes.box}>
<Container text>
<Segment padded="very">
<Form onSubmit={this.handleSubmit}>
<Header as="h2">
Add a password
</Header>
<Form.Field>
<label>Application / URL:</label>
<Input iconPosition='left' placeholder='http://exmple.com'>
<input value={this.state.url} type="text" name="url" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<Form.Field>
<label>Username / email adress:</label>
<Input iconPosition='left' placeholder='example@example.com'>
<input value={this.state.login} type="text" name="login" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<Form.Field>
<label>Password:</label>
<Input iconPosition='left' placeholder='********'>
<input value={this.state.password} type="text" name="password" onChange={this.handleChange} autoComplete="off" required />
</Input>
</Form.Field>
<p>The encryption key for this entry is '<b>{this.props.encryptionkey}</b>'</p>
<Button loading={this.state.loading} type='submit' primary>Add</Button>
<Button loading={this.state.loading} onClick={this.props.toggleNewWindow}><Icon name="x" />Cancel</Button>
</Form>
</Segment>
</Container>
</div>
);
} else {
return null;
}
}
getStyles() {
return {
box: {
width: '100vw',
height: '100vh',
position: 'fixed',
zIndex: 1000,
top: 0,
left: 0,
backgroundColor: 'rgba(255,255,255,0.9)',
paddingTop: '5%'
}
}
}
}
}
));
export default New;

View File

@ -1,20 +1,28 @@
import React, {Component} from 'react';
import { observer, inject } from 'mobx-react';
import jss from 'jss';
import preset from 'jss-preset-default';
import { Menu, Segment, Dropdown, Table, Button, Icon, Header } from 'semantic-ui-react';
import { Menu, Segment, Dropdown, Table, Button, Loader, Icon, Header, Input } from 'semantic-ui-react';
import alertify from 'alertify.js';
/*
* Functions import
*/
import { decrypt } from '../../stores/functions/encryption';
/*
* Component imports
*/
import New from './New';
import Headline from '../../components/Headline';
jss.setup(preset());
//Firebase
var firebase = require('../../stores/fb').fb;
// Initialize Cloud Firestore through Firebase
var db = firebase.firestore();
/*
###############################
@ -30,151 +38,201 @@ Components -- END
class PasswordManager extends Component {
constructor(props){
super(props);
//Password Manager page
const PasswordManager = inject("rootStore") ( observer(
class PasswordManager extends Component {
constructor(props){
super(props);
//Password Manager page
/*
* Expected props
* - /
*/
/*
* Expected props
* - /
*/
this.toggleNewWindow = this.toggleNewWindow.bind(this);
this.onChangeInput = this.onChangeInput.bind(this);
//Stored information
this.stores = this.props.rootStore.stores;
this.state = {
newWindowOpen: false,
key: '',
search: ''
this.toggleNewWindow = this.toggleNewWindow.bind(this);
this.onChangeInput = this.onChangeInput.bind(this);
this.state = {
newWindowOpen: false,
key: '',
search: '',
data: [],
loading: true
}
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
}
//Styles
this.styles = this.getStyles();
this.sheet = jss.createStyleSheet(this.styles);
const {classes} = this.sheet.attach();
this.classes = classes;
//Styles
}
componentDidMount() {
this.fetchData();
}
componentWillUnmount() {
this.sheet.detach()
}
componentWillUnmount() {
this.sheet.detach()
}
onChangeInput(e) {
//Encryption key and search input
onChangeInput(e) {
//Encryption key and search input
this.setState({
[e.target.name]: e.target.value
});
}
toggleNewWindow() {
//Add new password window
if(this.state.key !== '')
{
alertify.log("Encryption key: '" + this.state.key + "'");
this.setState({
newWindowOpen: !this.state.newWindowOpen
[e.target.name]: e.target.value
});
} else {
alertify.error("Please set an encryption key!");
}
toggleNewWindow() {
//Open window to add a new password doc
if(this.state.key !== '')
{
this.setState({
newWindowOpen: !this.state.newWindowOpen
});
} else {
alertify.error("Please set an encryption key!");
}
}
fetchData() {
//Gets password list from firestore and
//Writes in this.state
const uid = this.stores.authStore.userData.uid;
db.collection("passwords").where("uid", "==", uid).orderBy("time", "desc").get().then((querySnapshot) => {
var arr = [];
querySnapshot.forEach((doc) => {
const data = doc.data();
arr.push(data);
});
this.setState({
data: arr,
loading: false
});
});
}
displayData(dataList) {
//Returns array with all table row components
var components = [];
dataList.forEach((element, index) => {
components.push(
<Table.Row key={index}>
<Table.Cell>{element.url}</Table.Cell>
<Table.Cell>{decrypt(element.login, this.state.key)}</Table.Cell>
<Table.Cell>
<Button icon>
<Icon name='copy' />
</Button>
</Table.Cell>
<Table.Cell>{decrypt(element.password, this.state.key)}</Table.Cell>
<Table.Cell>
<Button icon>
<Icon name='copy' />
</Button>
</Table.Cell>
</Table.Row>
);
});
return components;
}
render() {
const tableRows = this.displayData(this.state.data)
return(
<div>
<New encryptionkey={this.state.key} open={this.state.newWindowOpen} toggleNewWindow={this.toggleNewWindow} />
<Headline black="Password " red="manager" />
<Input icon placeholder='Search...'>
<input type='text' placeholder='Search...' name="search" onChange={this.onChangeInput} autoComplete="off" />
<Icon name='search' />
</Input>
<Menu attached='top'>
<Dropdown item icon='wrench' simple>
<Dropdown.Menu>
<Dropdown.Item onClick={this.toggleNewWindow}>
New
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Menu.Menu position='right'>
<div className='ui right aligned category search item'>
<div className='ui transparent icon input'>
<input className='prompt' type='text' placeholder='Encryption key...' name="key" onChange={this.onChangeInput} autoComplete="off" />
<i className='key icon' />
</div>
</div>
</Menu.Menu>
</Menu>
<Segment attached='bottom'>
<Table celled striped>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={4}>Application / URL</Table.HeaderCell>
<Table.HeaderCell width={5}>Username / Email adress</Table.HeaderCell>
<Table.HeaderCell width={1}>Copy</Table.HeaderCell>
<Table.HeaderCell width={5}>Password</Table.HeaderCell>
<Table.HeaderCell width={1}>Copy</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
{tableRows}
</Table.Body>
</Table>
<Loader active={this.state.loading} />
</Segment>
<Header as="h3">
How does it work? Is it safe?
</Header>
<p>
I ask you to give an encryption key. Once you set that key you can create a new password which is then encrypted with that key.
</p>
<p>
The password is then saved in the encrypted form on the database in the internet, which means that nobody (not even me) can read your password unless that person knows the key. In other words: <b>The password is completely safe and solely accessible by you and only you!</b>
</p>
<p>
To decrypt your passwords simply type in the encryption key and all your passwords in your list are displayed correctly and readable in the form you had set them.
</p>
<hr />
<p>
<b>I advise you to choose one encryption key and use it for all your passwords in your list.</b> Why? Using the same key makes decrypting easier for you because <b>all</b> entries are being decrypted correctly at the same time by using one single key.
</p>
</div>
);
}
getStyles() {
return {
}
}
}
render() {
return(
<div>
<New encryptionkey={this.state.key} open={this.state.newWindowOpen} toggleNewWindow={this.toggleNewWindow} />
<Menu attached='top'>
<Dropdown item icon='wrench' simple>
<Dropdown.Menu>
<Dropdown.Item onClick={this.toggleNewWindow}>
New
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Menu.Menu position='right'>
<div className='ui right aligned category search item'>
<div className='ui transparent icon input'>
<input className='prompt' type='text' placeholder='Encryption key...' name="key" onChange={this.onChangeInput} autoComplete="off" />
<i className='key icon' />
</div>
</div>
<div className='ui right aligned category search item'>
<div className='ui transparent icon input'>
<input className='prompt' type='text' placeholder='Search...' name="search" onChange={this.onChangeInput} autoComplete="off" />
<i className='search icon' />
</div>
</div>
</Menu.Menu>
</Menu>
<Segment attached='bottom'>
<Table celled striped>
<Table.Header>
<Table.Row>
<Table.HeaderCell width={4}>Application / URL</Table.HeaderCell>
<Table.HeaderCell width={5}>Username / Email adress</Table.HeaderCell>
<Table.HeaderCell width={1}>Copy</Table.HeaderCell>
<Table.HeaderCell width={5}>Password</Table.HeaderCell>
<Table.HeaderCell width={1}>Copy</Table.HeaderCell>
</Table.Row>
</Table.Header>
<Table.Body>
<Table.Row>
<Table.Cell>cell</Table.Cell>
<Table.Cell>cell</Table.Cell>
<Table.Cell>
<Button icon>
<Icon name='copy' />
</Button>
</Table.Cell>
<Table.Cell>cell</Table.Cell>
<Table.Cell>
<Button icon>
<Icon name='copy' />
</Button>
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
</Segment>
<Header as="h3">
How does it work?
</Header>
<p>
I ask you to give an encryption key. Once you set that key you can create a new password which is then encrypted with that key.
</p>
<p>
The password is then saved in the encrypted form on the database in the internet, which means that nobody (not even me) can read your password unless that person knows the key. In other words: <b>The password is completely safe and solely accessible by you and only you!</b>
</p>
<p>
To decrypt your passwords simply type in the encryption key and all your passwords in your list are displayed correctly and readable in the form you had set them.
</p>
<hr />
<p>
I advise you to choose one encryption key and use it for all your passwords in your list. Why? Using the same key makes decrypting easier for you because <b>all</b> entries are being decrypted correctly at the same time by using one single key.
</p>
</div>
);
}
getStyles() {
return {
}
}
}
));
export default PasswordManager;