Browse Source

import encrypted private key and logout

master
Julian Steinwachs 8 years ago
parent
commit
ea0f8bdde7
  1. 1209
      build/app-bundle.js
  2. 16
      build/twister-lib.js
  3. 40
      jsx/App.js
  4. 6
      jsx/other/Accounts.js
  5. 43
      jsx/other/ExportAccountModalButton.js
  6. 46
      jsx/other/ImportAccountModalButton.js
  7. 67
      jsx/other/LogoutModalButton.js

1209
build/app-bundle.js

File diff suppressed because it is too large Load Diff

16
build/twister-lib.js

@ -32885,7 +32885,7 @@ TwisterPrivKey.prototype.encryptPrivateKey = function(passphrase,cbfunc,progress @@ -32885,7 +32885,7 @@ TwisterPrivKey.prototype.encryptPrivateKey = function(passphrase,cbfunc,progress
var privateKeyWif = thisResource._btcKey.toWIF()
var bip38 = new Bip38()
var bip38 = new Bip38();
var encrypted = bip38.encrypt(privateKeyWif, passphrase, thisResource._btcKey.getAddress(), progressfunc)
cbfunc(encrypted);
@ -32899,6 +32899,7 @@ TwisterPrivKey.prototype.decryptAndImportPrivateKey = function(encryptedKey,pass @@ -32899,6 +32899,7 @@ TwisterPrivKey.prototype.decryptAndImportPrivateKey = function(encryptedKey,pass
setTimeout(function(){
var bip38 = new Bip38();
var privateKeyWif = bip38.decrypt(encryptedKey, passphrase, progressfunc)
thisResource.setKey(privateKeyWif);
cbfunc(thisResource);
@ -34571,7 +34572,7 @@ Twister.importClientSideAccountFromEncryptedKey = function (name,encryptedKey,pa @@ -34571,7 +34572,7 @@ Twister.importClientSideAccountFromEncryptedKey = function (name,encryptedKey,pa
Twister._wallet[name] = new TwisterAccount(name,Twister);
Twister._wallet[name]._privkey.decryptAndImportPrivateKey(encryptPrivateKey,passphrase,function(){
Twister._wallet[name]._privkey.decryptAndImportPrivateKey(encryptedKey,passphrase,function(){
Twister._wallet[name]._privkey.verifyKey(function(key){
@ -34669,6 +34670,17 @@ Twister.checkUsernameAvailable = function(username,cbfunc){ @@ -34669,6 +34670,17 @@ Twister.checkUsernameAvailable = function(username,cbfunc){
}
/** @function
* @name checkUsernameAvailable
* @description checks if username is available by querying for its public key.
*/
Twister.removeAccount = function(username){
delete Twister._wallet[username];
}
/** @function
* @name serializeCache
* @description Flattens the complete cache into a nested object which can be used to reload the cache later.

40
jsx/App.js

@ -54,8 +54,8 @@ App = React.createClass({ @@ -54,8 +54,8 @@ App = React.createClass({
AppSettingsMixin,
SetIntervalMixin,
SafeStateChangeMixin,
EventListenerMixin('newaccountbyuser')],
EventListenerMixin('newaccountbyuser'),
EventListenerMixin('accountremovedbyuser')],
getInitialState: function () {
var state={};
@ -123,11 +123,18 @@ App = React.createClass({ @@ -123,11 +123,18 @@ App = React.createClass({
var thisComponent = this;
Twister.getAccount(newaccoutname).activateTorrents(function(){
var afterwards = function(){
thisComponent.setStateSafe({activeAccount: newaccoutname},function(){
localStorage.setItem("twister-react-activeAccount", newaccoutname);
});
});
}
if(newaccoutname){
Twister.getAccount(newaccoutname).activateTorrents(afterwards);
}else{
afterwards();
}
},
@ -153,6 +160,31 @@ App = React.createClass({ @@ -153,6 +160,31 @@ App = React.createClass({
},
onaccountremovedbyuser: function(event) {
console.log("catched onaccountremovedbyuser event !!!!! ",event,this.state)
this.saveCache();
this.setState(function(oldstate,props){
oldstate.accounts = oldstate.accounts.filter(function(acc){
return acc.name!=event.detail.username;
})
return oldstate;
})
if(this.state.activeAccount && this.state.activeAccount==event.detail.username){
this.switchAccount(this.state.accounts.find(function(acc){
return acc.name!=event.detail.username && acc.status=="confirmed";
})||null);
}
},
render: function() {
var route = this.props.location.pathname.split("/").filter(function(s){

6
jsx/other/Accounts.js

@ -5,8 +5,9 @@ var EventListenerMixin = require('../common/EventListenerMixin.js'); @@ -5,8 +5,9 @@ var EventListenerMixin = require('../common/EventListenerMixin.js');
var AppSettingsMixin = require('../common/AppSettingsMixin.js');
var ImportAccountModalButton = require('../other/ImportAccountModalButton.js');
var ExportAccountModalButton = require('../other/ExportAccountModalButton.js');
var GenerateAccountModalButton = require('../other/GenerateAccountModalButton.js');
var ExportAccountModalButton = require('../other/ExportAccountModalButton.js');
var LogoutModalButton = require('../other/LogoutModalButton.js');
var ReactBootstrap = require('react-bootstrap')
, NavItem = ReactBootstrap.NavItem
@ -43,7 +44,8 @@ module.exports = Accounts = React.createClass({ @@ -43,7 +44,8 @@ module.exports = Accounts = React.createClass({
<MiniProfile username={acc.name} pollIntervalProfile={thisComponent.props.pollIntervalProfile}/>
<p>
{acc.status}
<ExportAccountModalButton username={acc.name}/>
<ExportAccountModalButton username={acc.name} accountStatus={acc.status}/>
<LogoutModalButton username={acc.name} accountStatus={acc.status}/>
</p>
</div>
);

43
jsx/other/ExportAccountModalButton.js

@ -21,10 +21,10 @@ module.exports = ExportAccountModalButton = React.createClass({ @@ -21,10 +21,10 @@ module.exports = ExportAccountModalButton = React.createClass({
useEncryption: true,
passphrase1: "",
passphrase2: "",
setupComplete: false,
encryptionInProgess: false,
encryptionComplete: false,
encryptedKey: "",
publishedOnTiwster: false,
};
},
handleUseEncryptionChange: function(e) {
@ -32,6 +32,8 @@ module.exports = ExportAccountModalButton = React.createClass({ @@ -32,6 +32,8 @@ module.exports = ExportAccountModalButton = React.createClass({
useEncryption: e.target.checked,
encryptionInProgess: false,
encryptionComplete: false,
encryptedKey: "",
publishedOnTwister: false,
});
},
handlePassphrase1Change: function(e) {
@ -39,6 +41,8 @@ module.exports = ExportAccountModalButton = React.createClass({ @@ -39,6 +41,8 @@ module.exports = ExportAccountModalButton = React.createClass({
passphrase1: e.target.value,
encryptionInProgess: false,
encryptionComplete: false,
encryptedKey: "",
publishedOnTwister: false,
});
},
handlePassphrase2Change: function(e) {
@ -46,6 +50,8 @@ module.exports = ExportAccountModalButton = React.createClass({ @@ -46,6 +50,8 @@ module.exports = ExportAccountModalButton = React.createClass({
passphrase2: e.target.value,
encryptionInProgess: false,
encryptionComplete: false,
encryptedKey: "",
publishedOnTwister: false,
});
},
handleToggle: function () {
@ -83,6 +89,21 @@ module.exports = ExportAccountModalButton = React.createClass({ @@ -83,6 +89,21 @@ module.exports = ExportAccountModalButton = React.createClass({
return;
},
publishOnTwister: function() {
var thisComponent = this;
if(this.state.useEncryption && this.state.encryptedKey.length && this.state.encryptedKey.startsWith("6P")){
Twister.getAccount(this.props.username).updateProfileFields({bip38:this.state.encryptedKey},function(profile){
thisComponent.setStateSafe({publishedOnTwister: true});
})
}
},
render: function() {
var belowForm = (
@ -106,16 +127,32 @@ module.exports = ExportAccountModalButton = React.createClass({ @@ -106,16 +127,32 @@ module.exports = ExportAccountModalButton = React.createClass({
var mailToLink = "mailto:?body=" + encodeURIComponent(formattedBody) + "&subject=" + encodeURIComponent(subject);
var dataUrl = "data:text/plain;charset=utf-8;base64,"+btoa(this.state.encryptedKey);
var publishOnTwisterDisabled = this.props.accountStatus != "confirmed";
var publishedOnTwisterButtonStr = "Publish on Twister" + (this.state.publishedOnTwister?" ✓":"");
belowForm = (
<p>
{"Your encrypted key: "+this.state.encryptedKey}
<br/>
<Button download="twisterkey.txt" href={dataUrl}>Download</Button>
<Button href={mailToLink}>Send via Email</Button>
<Button onClick={this.publishOnTwister} disabled={publishOnTwisterDisabled}>{publishedOnTwisterButtonStr}</Button>
</p>
)
}else{
}else{
var dataUrl = "data:text/plain;charset=utf-8;base64,"+btoa(this.state.encryptedKey);
belowForm = (
<p>
{"Your private key: "+this.state.encryptedKey}
{"Your private key: "+this.state.encryptedKey}
<Button download="twisterkey.txt" href={dataUrl}>Download</Button>
<Button disabled>Send via Email</Button>
<Button disabled>Publish on Twister</Button>
</p>
)
}

46
jsx/other/ImportAccountModalButton.js

@ -12,11 +12,13 @@ var SafeStateChangeMixin = require('../common/SafeStateChangeMixin.js'); @@ -12,11 +12,13 @@ var SafeStateChangeMixin = require('../common/SafeStateChangeMixin.js');
var SetIntervalMixin = require("../common/SetIntervalMixin.js");
module.exports = ImportAccountModalButton = React.createClass({
mixins: [SafeStateChangeMixin],
getInitialState: function () {
return {
isModalOpen: false,
privkey: "",
username: "",
passphrase: "",
};
},
handlePrivkeyChange: function(e) {
@ -25,29 +27,56 @@ module.exports = ImportAccountModalButton = React.createClass({ @@ -25,29 +27,56 @@ module.exports = ImportAccountModalButton = React.createClass({
handleUsernameChange: function(e) {
this.setState({username: e.target.value});
},
handlePassphraseChange: function(e) {
this.setState({passphrase: e.target.value});
},
handleToggle: function () {
this.setState({
isModalOpen: !this.state.isModalOpen
});
},
pullFromTwister: function(){
var thisComponent = this;
Twister.getUser(this.state.username).doProfile(function(profile){
var key = profile.getField("bip38");
if(key) {
thisComponent.setStateSafe({privkey:key});
}
})
},
handleImportAccount: function (e) {
var thisComponent = this;
e.preventDefault();
var newprivkey = this.state.privkey;
var newusername = this.state.username;
var passphrase = this.state.passphrase;
Twister.importClientSideAccount(newusername,newprivkey,function(newaccount){
var success = function(newaccount){
console.log(newaccount._name);
var event = new CustomEvent('newaccountbyuser',{detail: newaccount});
//alert("scrolled to bottom")
window.dispatchEvent(event);
thisComponent.handleToggle();
})
this.handleToggle();
}
if(passphrase.length){
Twister.importClientSideAccountFromEncryptedKey(newusername,newprivkey,passphrase,success)
}else{
Twister.importClientSideAccount(newusername,newprivkey,success)
}
return;
},
@ -70,10 +99,17 @@ module.exports = ImportAccountModalButton = React.createClass({ @@ -70,10 +99,17 @@ module.exports = ImportAccountModalButton = React.createClass({
/>
<Input
type='text'
label='Private Key'
label='(Encrypted) Private Key'
value={this.state.privkey}
onChange={this.handlePrivkeyChange}
/>
<Button onClick={this.pullFromTwister}>Pull From Twister</Button>
<Input
type='password'
label='Passphrase (only for encrypted keys)'
value={this.state.passphrase}
onChange={this.handlePassphraseChange}
/>
<Input type='submit' value='Import Account' data-dismiss="modal" />
</form>
</Modal.Body>

67
jsx/other/LogoutModalButton.js

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
var ReactBootstrap = require('react-bootstrap')
, Button = ReactBootstrap.Button
, ButtonGroup = ReactBootstrap.ButtonGroup
, Glyphicon = ReactBootstrap.Glyphicon
, Modal = ReactBootstrap.Modal
, Input = ReactBootstrap.Input
var React = require('react');
var SafeStateChangeMixin = require('../common/SafeStateChangeMixin.js');
var SetIntervalMixin = require("../common/SetIntervalMixin.js");
module.exports = LogoutModalButton = React.createClass({
mixins: [
SafeStateChangeMixin
],
getInitialState: function () {
return {
isModalOpen: false,
};
},
handleToggle: function () {
this.setState({
isModalOpen: !this.state.isModalOpen
});
},
handleLogout: function (e) {
var thisComponent = this;
e.preventDefault();
var username = this.props.username;
Twister.removeAccount(this.props.username);
var event = new CustomEvent('accountremovedbyuser',{detail: {username:this.props.username}});
//alert("scrolled to bottom")
window.dispatchEvent(event);
thisComponent.handleToggle();
return;
},
render: function() {
return (
<Button onClick={this.handleToggle}>
Logout
<Modal show={this.state.isModalOpen} bsStyle='primary' onHide={this.handleToggle}>
<Modal.Header>
<Glyphicon glyph='export'/>
</Modal.Header>
<Modal.Body>
<form onSubmit={this.handleLogout}>
<p>
Are you sure you want to logout? Be sure that you exported your private key. Othervise your account will be lost.
</p>
<Input type='submit' value='Logout'/>
</form>
</Modal.Body>
</Modal>
</Button>
);
}
});
Loading…
Cancel
Save