Skip to content
This repository has been archived by the owner on Apr 17, 2023. It is now read-only.

Commit

Permalink
Merge branch 'release/0.14.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
larrysalibra committed Aug 24, 2017
2 parents 061d89f + b7900c9 commit c0ff909
Show file tree
Hide file tree
Showing 45 changed files with 2,826 additions and 258 deletions.
28 changes: 23 additions & 5 deletions app/js/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { AccountActions } from './account/store/account'
import { IdentityActions } from './profiles/store/identity'
import { SettingsActions } from './account/store/settings'
import WelcomeModal from './welcome/WelcomeModal'
import { getCoreAPIPasswordFromURL, getLogServerPortFromURL } from './utils/api-utils'
Expand All @@ -21,13 +22,19 @@ function mapStateToProps(state) {
coreApiRunning: state.sanity.coreApiRunning,
coreApiPasswordValid: state.sanity.coreApiPasswordValid,
walletPaymentAddressUrl: state.settings.api.walletPaymentAddressUrl,
coreAPIPassword: state.settings.api.coreAPIPassword
coreAPIPassword: state.settings.api.coreAPIPassword,
defaultIdentity: state.profiles.identity.default,
localIdentities: state.profiles.identity.localIdentities
}
}

function mapDispatchToProps(dispatch) {
return bindActionCreators(Object.assign({}, AccountActions,
SanityActions, SettingsActions), dispatch)
return bindActionCreators(Object.assign({},
AccountActions,
SanityActions,
SettingsActions,
IdentityActions,
), dispatch)
}

class App extends Component {
Expand All @@ -43,8 +50,10 @@ class App extends Component {
isCoreRunning: PropTypes.func.isRequired,
isCoreApiPasswordValid: PropTypes.func.isRequired,
walletPaymentAddressUrl: PropTypes.string.isRequired,
coreAPIPassword: PropTypes.string

coreAPIPassword: PropTypes.string,
localIdentities: PropTypes.object,
defaultIdentity: PropTypes.string,
setDefaultIdentity: PropTypes.func.isRequired
}

constructor(props) {
Expand Down Expand Up @@ -104,6 +113,15 @@ class App extends Component {
coreConnected: nextProps.api.coreAPIPassword ? true : false,
currentPath: nextPath
})

// Only for backward-compatibility purpose.
// Since we added a `default` field in state.profiles.identity, if the user
// already had localIdentities but doesn't have a default one, we put the
// default as his 1st one.
const localIdentities = Object.keys(nextProps.localIdentities)
if (!nextProps.defaultIdentity && localIdentities.length) {
nextProps.setDefaultIdentity(nextProps.localIdentities[localIdentities[0]].domainName)
}
}


Expand Down
6 changes: 6 additions & 0 deletions app/js/account/store/settings/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ const DEFAULT_API = {
pgpKeyUrl: 'https://pgp.mit.edu/pks/lookup?search={identifier}&op=vindex&fingerprint=on',
btcPriceUrl: 'https://www.bitstamp.net/api/v2/ticker/btcusd/',
corePingUrl: 'http://localhost:6270/v1/node/ping',
zoneFileUrl: 'http://localhost:6270/v1/names/{name}/zonefile',
subdomains: {
'foo.id': {
registerUrl: 'http://localhost:7103/register'
}
},
hostedDataLocation: DROPBOX,
coreHost: 'localhost',
corePort: 6270,
Expand Down
148 changes: 90 additions & 58 deletions app/js/auth/components/AuthModal.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const logger = log4js.getLogger('auth/components/AuthModal.js')
function mapStateToProps(state) {
return {
localIdentities: state.profiles.identity.localIdentities,
defaultIdentity: state.profiles.identity.default,
identityKeypairs: state.account.identityAccount.keypairs,
appManifest: state.auth.appManifest,
appManifestLoading: state.auth.appManifestLoading,
Expand All @@ -42,6 +43,8 @@ class AuthModal extends Component {
router: PropTypes.object
}
static propTypes = {
defaultIdentity: PropTypes.string.isRequired,
localIdentities: PropTypes.object.isRequired,
loadAppManifest: PropTypes.func.isRequired,
clearSessionToken: PropTypes.func.isRequired,
getCoreSessionToken: PropTypes.func.isRequired,
Expand All @@ -55,6 +58,7 @@ class AuthModal extends Component {
super(props)

this.state = {
currentIdentity: null,
authRequest: null,
appManifest: null,
coreSessionToken: null,
Expand All @@ -79,39 +83,52 @@ class AuthModal extends Component {
componentWillReceiveProps(nextProps) {
const storageConnected = this.props.api.dropboxAccessToken !== null
this.setState({
storageConnected
storageConnected,
currentIdentity: this.state.currentIdentity || nextProps.defaultIdentity || undefined
})

const appDomain = this.state.decodedToken.payload.domain_name
const localIdentities = nextProps.localIdentities
const identityKeypairs = nextProps.identityKeypairs
if (appDomain && nextProps.coreSessionTokens[appDomain]) {
logger.trace('componentWillReceiveProps: received coreSessionToken')
if (Object.keys(localIdentities).length > 0) {
let userDomainName = Object.keys(localIdentities)[0]

let hasUsername = true
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
logger.debug(`login(): this profile ${userDomainName} has no username`)
hasUsername = false
}
const blockchainId = (hasUsername ? userDomainName : null)
const identity = localIdentities[userDomainName]
const profile = identity.profile
const privateKey = identityKeypairs[0].key
const appsNodeKey = identityKeypairs[0].appsNodeKey
const salt = identityKeypairs[0].salt
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()

// TODO: what if the token is expired?
const authResponse = makeAuthResponse(privateKey, profile, blockchainId,
nextProps.coreSessionTokens[appDomain], appPrivateKey)

this.props.clearSessionToken(appDomain)
redirectUserToApp(this.state.authRequest, authResponse)
}
if (!appDomain || !nextProps.coreSessionTokens[appDomain]) {
return
}

logger.trace('componentWillReceiveProps: received coreSessionToken')
if (!Object.keys(localIdentities).length) {
return
}
// Careful with this.state, as the above this.setState is async. But
// there shouldn't be any problem with the above check.
// TODO: Side-effects to avoid confusion.
const userDomainName = this.state.currentIdentity

let hasUsername = true
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
logger.debug(`login(): this profile ${userDomainName} has no username`)
hasUsername = false
}

// Get keypair corresponding to the current user identity
const profileSigningKeypair = identityKeypairs.find((keypair) => keypair.address === localIdentities[userDomainName].ownerAddress)

const blockchainId = (hasUsername ? userDomainName : null)
const identity = localIdentities[userDomainName]
const profile = identity.profile
const privateKey = profileSigningKeypair.key
const appsNodeKey = profileSigningKeypair.appsNodeKey
const salt = profileSigningKeypair.salt
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()

// TODO: what if the token is expired?
const authResponse = makeAuthResponse(privateKey, profile, blockchainId,
nextProps.coreSessionTokens[appDomain], appPrivateKey)

this.props.clearSessionToken(appDomain)

logger.trace(`login(): profile ${userDomainName} is logging in`)
redirectUserToApp(this.state.authRequest, authResponse)
}

closeModal() {
Expand All @@ -120,35 +137,38 @@ class AuthModal extends Component {

login() {
this.props.loginToApp()
if (Object.keys(this.props.localIdentities).length > 0) {
const localIdentities = this.props.localIdentities
let userDomainName = Object.keys(localIdentities)[0]
let hasUsername = true
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
logger.debug(`login(): this profile ${userDomainName} has no username`)
hasUsername = false
}
const identity = localIdentities[userDomainName]
const profile = identity.profile
const profileSigningKeypair = this.props.identityKeypairs[0]
const appDomain = this.state.decodedToken.payload.domain_name
const scopes = this.state.decodedToken.payload.scopes
const appsNodeKey = this.props.identityKeypairs[0].appsNodeKey
const salt = this.props.identityKeypairs[0].salt
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
const blockchainId = (hasUsername ? userDomainName : null)
logger.trace(`login(): Calling setCoreStorageConfig()...`)
setCoreStorageConfig(this.props.api, blockchainId,
localIdentities[userDomainName].profile, profileSigningKeypair)
.then(() => {
logger.trace('login(): Core storage successfully configured.')
logger.trace('login(): Calling getCoreSessionToken()...')
this.props.getCoreSessionToken(this.props.coreHost,
this.props.corePort, this.props.coreAPIPassword, appPrivateKey,
appDomain, this.state.authRequest, blockchainId)
})
if (!Object.keys(this.props.localIdentities).length) {
return
}
const localIdentities = this.props.localIdentities
const userDomainName = this.state.currentIdentity

let hasUsername = true
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
logger.debug(`login(): this profile ${userDomainName} has no username`)
hasUsername = false
}

// Get keypair corresponding to the current user identity
const profileSigningKeypair = this.props.identityKeypairs.find((keypair) => keypair.address === localIdentities[userDomainName].ownerAddress)

const appDomain = this.state.decodedToken.payload.domain_name
const scopes = this.state.decodedToken.payload.scopes
const appsNodeKey = profileSigningKeypair.appsNodeKey
const salt = profileSigningKeypair.salt
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
const blockchainId = (hasUsername ? userDomainName : null)
logger.trace(`login(): Calling setCoreStorageConfig()...`)
setCoreStorageConfig(this.props.api, blockchainId,
localIdentities[userDomainName].profile, profileSigningKeypair)
.then(() => {
logger.trace('login(): Core storage successfully configured.')
logger.trace('login(): Calling getCoreSessionToken()...')
this.props.getCoreSessionToken(this.props.coreHost,
this.props.corePort, this.props.coreAPIPassword, appPrivateKey,
appDomain, this.state.authRequest, blockchainId)
})
}

render() {
Expand Down Expand Up @@ -196,9 +216,21 @@ class AuthModal extends Component {
<div>
{ this.state.storageConnected ?
<div>
<p>
Click below to log in.
</p>
<p>Choose a profile to log in with.</p>
<select
className="form-control profile-select"
onChange={(event) => this.setState({ currentIdentity: event.target.value })}
value={this.state.currentIdentity}
>
{Object.keys(this.props.localIdentities).map((domainName) => (
<option
key={domainName}
value={this.props.localIdentities[domainName].domainName}
>
{this.props.localIdentities[domainName].domainName}
</option>
))}
</select>
<div>
<button className="btn btn-primary btn-block" onClick={this.login}>
Approve
Expand Down
14 changes: 12 additions & 2 deletions app/js/profiles/AllProfilesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const logger = log4js.getLogger('profiles/AllProfilesPage.js')
function mapStateToProps(state) {
return {
localIdentities: state.profiles.identity.localIdentities,
defaultIdentity: state.profiles.identity.default,
namesOwned: state.profiles.identity.namesOwned,
createProfileError: state.profiles.identity.createProfileError,
identityAddresses: state.account.identityAccount.addresses,
Expand All @@ -32,13 +33,15 @@ function mapDispatchToProps(dispatch) {
class IdentityPage extends Component {
static propTypes = {
localIdentities: PropTypes.object.isRequired,
defaultIdentity: PropTypes.string.isRequired,
createNewProfile: PropTypes.func.isRequired,
refreshIdentities: PropTypes.func.isRequired,
namesOwned: PropTypes.array.isRequired,
api: PropTypes.object.isRequired,
identityAddresses: PropTypes.array.isRequired,
nextUnusedAddressIndex: PropTypes.number.isRequired,
encryptedBackupPhrase: PropTypes.string.isRequired,
setDefaultIdentity: PropTypes.string.isRequired,
resetCreateNewProfileError: PropTypes.func.isRequired,
createProfileError: PropTypes.string
}
Expand All @@ -56,6 +59,7 @@ class IdentityPage extends Component {
console.log(props)

this.onValueChange = this.onValueChange.bind(this)
this.setDefaultIdentity = this.setDefaultIdentity.bind(this)
this.createNewProfile = this.createNewProfile.bind(this)
this.availableIdentityAddresses = this.availableIdentityAddresses.bind(this)
this.openPasswordPrompt = this.openPasswordPrompt.bind(this)
Expand All @@ -77,7 +81,7 @@ class IdentityPage extends Component {
this.setState({
localIdentities: nextProps.localIdentities
})
if (!this.props.createProfileError && nextProps.createProfileError) {
if (nextProps.createProfileError) {
this.setState({
processing: false
})
Expand All @@ -101,6 +105,10 @@ class IdentityPage extends Component {
})
}

setDefaultIdentity(domainName) {
this.props.setDefaultIdentity(domainName)
}

createNewProfile(event) {
logger.trace('createNewProfile')
this.setState({
Expand Down Expand Up @@ -210,6 +218,8 @@ class IdentityPage extends Component {
url={`/profiles/${identity.domainName}/local`}
ownerAddress={identity.ownerAddress}
canAddUsername={identity.canAddUsername}
isDefault={identity.domainName === this.props.defaultIdentity}
setDefaultIdentity={() => this.setDefaultIdentity(identity.domainName)}
/>
)
} else {
Expand All @@ -220,7 +230,7 @@ class IdentityPage extends Component {
</div>
<div className="card-list-container m-t-30">
<button
className="btn btn-blue btn-lg" onClick={this.openPasswordPrompt}
className="btn btn-electric-blue btn-lg" onClick={this.openPasswordPrompt}
>
+ Create
</button>
Expand Down
Loading

0 comments on commit c0ff909

Please sign in to comment.