adding and fetching docs
This commit is contained in:
parent
d9aa8deb16
commit
8d93af6552
Binary file not shown.
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.1 KiB |
@ -10,9 +10,12 @@
|
||||
<title>Ninja</title>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Alexander Bell, all rights reserved -->
|
||||
<noscript>
|
||||
You need to enable JavaScript to run this app.
|
||||
</noscript>
|
||||
<!-- Alexander Bell, all rights reserved -->
|
||||
<div id="root"></div>
|
||||
<!-- Alexander Bell, all rights reserved -->
|
||||
</body>
|
||||
</html>
|
||||
|
@ -42,7 +42,7 @@ const App = inject("rootStore") ( observer(
|
||||
const body = document.getElementsByTagName('body')[0];
|
||||
body.style.margin = '0';
|
||||
body.style.padding = '0';
|
||||
body.style.overflow = 'hidden';
|
||||
body.style.overflow = 'auto';
|
||||
|
||||
//Load app
|
||||
this.stores.rootStore.loadApp();
|
||||
|
17
src/components/Headline.js
Normal file
17
src/components/Headline.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
|
||||
export default function(props) {
|
||||
/*
|
||||
* Expected props
|
||||
* - black: String
|
||||
* the text in black
|
||||
* - red: String
|
||||
* the text in red
|
||||
*/
|
||||
|
||||
return(
|
||||
<h2 style={{padding: '20px'}}>
|
||||
{props.black}<span style={{color: '#DA3821'}}>{props.red}</span>
|
||||
</h2>
|
||||
)
|
||||
}
|
@ -113,9 +113,7 @@ const Main = inject("rootStore") ( observer(
|
||||
</Menu.Item>
|
||||
</Menu.Menu>
|
||||
</Menu>
|
||||
<div style={{minHeight: '100vh'}}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
@ -123,35 +121,33 @@ const Main = inject("rootStore") ( observer(
|
||||
//Mobile sidebar
|
||||
|
||||
return(
|
||||
<div>
|
||||
<Sidebar.Pushable>
|
||||
<Sidebar
|
||||
as={Menu}
|
||||
animation='overlay'
|
||||
onHide={this.handleSidebarHide}
|
||||
visible={this.state.visible}
|
||||
vertical
|
||||
width='thin'
|
||||
>
|
||||
<Menu.Item header>
|
||||
<img alt="" src={require('../../files/images/logo.svg')} style={{display: 'block', width: '60px', height: '45px'}} />
|
||||
</Menu.Item>
|
||||
<Sidebar.Pushable>
|
||||
<Sidebar
|
||||
as={Menu}
|
||||
animation='overlay'
|
||||
onHide={this.handleSidebarHide}
|
||||
visible={this.state.visible}
|
||||
vertical
|
||||
width='thin'
|
||||
>
|
||||
<Menu.Item header>
|
||||
<img alt="" src={require('../../files/images/logo.svg')} style={{display: 'block', width: '60px', height: '45px'}} />
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item name="Home" active={activeItem === 'Home'} onClick={this.handleItemClick} as='a'>
|
||||
Home
|
||||
</Menu.Item>
|
||||
<Menu.Item name="/" active={activeItem === '/'} onClick={this.handleItemClick} as='a'>
|
||||
Home
|
||||
</Menu.Item>
|
||||
|
||||
<Menu.Item name="Password manager" active={activeItem === 'Password manager'} onClick={this.handleItemClick} as='a'>
|
||||
Password manager
|
||||
</Menu.Item>
|
||||
</Sidebar>
|
||||
<Menu.Item name="/passwords" active={activeItem === '/passwords'} onClick={this.handleItemClick} as='a'>
|
||||
Password manager
|
||||
</Menu.Item>
|
||||
</Sidebar>
|
||||
|
||||
<Sidebar.Pusher dimmed={this.state.visible}>
|
||||
<Icon className={this.classes.burgerButton} link color="red" size="huge" name="bars" onClick={this.handleButtonClick} />
|
||||
{this.props.children}
|
||||
</Sidebar.Pusher>
|
||||
</Sidebar.Pushable>
|
||||
</div>
|
||||
<Sidebar.Pusher dimmed={this.state.visible}>
|
||||
<Icon className={this.classes.burgerButton} link color="red" size="huge" name="bars" onClick={this.handleButtonClick} />
|
||||
{this.props.children}
|
||||
</Sidebar.Pusher>
|
||||
</Sidebar.Pushable>
|
||||
)
|
||||
}
|
||||
|
||||
|
1
src/files/images/ninja.svg
Normal file
1
src/files/images/ninja.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 13 KiB |
@ -78,6 +78,7 @@ class Main extends Component {
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route path="/passwords" component={PasswordManager} />
|
||||
</Switch>
|
||||
<img alt="" style={{width: '100px', marginBottom: '-20px', marginTop: '30px', marginLeft: '20px'}} src={require('../files/images/ninja.svg')} />
|
||||
</Segment>
|
||||
</Container>
|
||||
</Menu>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, {Component} from 'react';
|
||||
import jss from 'jss';
|
||||
import preset from 'jss-preset-default';
|
||||
import { Container } from 'semantic-ui-react';
|
||||
|
||||
/*
|
||||
* Functions import
|
||||
@ -9,6 +10,7 @@ import preset from 'jss-preset-default';
|
||||
/*
|
||||
* Component imports
|
||||
*/
|
||||
import Headline from '../../components/Headline';
|
||||
|
||||
jss.setup(preset());
|
||||
|
||||
@ -53,9 +55,16 @@ class Home extends Component {
|
||||
|
||||
render() {
|
||||
return(
|
||||
<div>
|
||||
Home
|
||||
</div>
|
||||
<Container text>
|
||||
<Headline black="alexbell." red="ninja" />
|
||||
|
||||
<p>
|
||||
You are signed in on alexbell.ninja. <b>What can you do here?</b><br />
|
||||
Well, I like developing software in my freetime, mainly applications
|
||||
for my personal use. They might also be of advantage for you, so feel free
|
||||
to browse around a little and try some of what you can find here :)
|
||||
</p>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
13
src/stores/functions/encryption.js
Normal file
13
src/stores/functions/encryption.js
Normal file
@ -0,0 +1,13 @@
|
||||
function norm_to_ascii(string){return unescape(encodeURIComponent(string))};
|
||||
function norm_to_unicode(string){return decodeURIComponent(escape(string))};
|
||||
function crypt_sym(string,k){return String.fromCharCode.apply(undefined,string.split("").map(function(c){return c.charCodeAt(0)^(k||13)}))};
|
||||
|
||||
export function encrypt(string, key) {
|
||||
//Encrypt a string
|
||||
return btoa(crypt_sym(norm_to_ascii(string), key));
|
||||
}
|
||||
|
||||
export function decrypt(string, key) {
|
||||
//Decrypt a string
|
||||
return crypt_sym(norm_to_unicode(atob(string)), key);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user