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

Commit c0ff909

Browse files
committed
Merge branch 'release/0.14.0'
2 parents 061d89f + b7900c9 commit c0ff909

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2826
-258
lines changed

app/js/App.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import React, { Component, PropTypes } from 'react'
33
import { bindActionCreators } from 'redux'
44
import { connect } from 'react-redux'
55
import { AccountActions } from './account/store/account'
6+
import { IdentityActions } from './profiles/store/identity'
67
import { SettingsActions } from './account/store/settings'
78
import WelcomeModal from './welcome/WelcomeModal'
89
import { getCoreAPIPasswordFromURL, getLogServerPortFromURL } from './utils/api-utils'
@@ -21,13 +22,19 @@ function mapStateToProps(state) {
2122
coreApiRunning: state.sanity.coreApiRunning,
2223
coreApiPasswordValid: state.sanity.coreApiPasswordValid,
2324
walletPaymentAddressUrl: state.settings.api.walletPaymentAddressUrl,
24-
coreAPIPassword: state.settings.api.coreAPIPassword
25+
coreAPIPassword: state.settings.api.coreAPIPassword,
26+
defaultIdentity: state.profiles.identity.default,
27+
localIdentities: state.profiles.identity.localIdentities
2528
}
2629
}
2730

2831
function mapDispatchToProps(dispatch) {
29-
return bindActionCreators(Object.assign({}, AccountActions,
30-
SanityActions, SettingsActions), dispatch)
32+
return bindActionCreators(Object.assign({},
33+
AccountActions,
34+
SanityActions,
35+
SettingsActions,
36+
IdentityActions,
37+
), dispatch)
3138
}
3239

3340
class App extends Component {
@@ -43,8 +50,10 @@ class App extends Component {
4350
isCoreRunning: PropTypes.func.isRequired,
4451
isCoreApiPasswordValid: PropTypes.func.isRequired,
4552
walletPaymentAddressUrl: PropTypes.string.isRequired,
46-
coreAPIPassword: PropTypes.string
47-
53+
coreAPIPassword: PropTypes.string,
54+
localIdentities: PropTypes.object,
55+
defaultIdentity: PropTypes.string,
56+
setDefaultIdentity: PropTypes.func.isRequired
4857
}
4958

5059
constructor(props) {
@@ -104,6 +113,15 @@ class App extends Component {
104113
coreConnected: nextProps.api.coreAPIPassword ? true : false,
105114
currentPath: nextPath
106115
})
116+
117+
// Only for backward-compatibility purpose.
118+
// Since we added a `default` field in state.profiles.identity, if the user
119+
// already had localIdentities but doesn't have a default one, we put the
120+
// default as his 1st one.
121+
const localIdentities = Object.keys(nextProps.localIdentities)
122+
if (!nextProps.defaultIdentity && localIdentities.length) {
123+
nextProps.setDefaultIdentity(nextProps.localIdentities[localIdentities[0]].domainName)
124+
}
107125
}
108126

109127

app/js/account/store/settings/default.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ const DEFAULT_API = {
2323
pgpKeyUrl: 'https://pgp.mit.edu/pks/lookup?search={identifier}&op=vindex&fingerprint=on',
2424
btcPriceUrl: 'https://www.bitstamp.net/api/v2/ticker/btcusd/',
2525
corePingUrl: 'http://localhost:6270/v1/node/ping',
26+
zoneFileUrl: 'http://localhost:6270/v1/names/{name}/zonefile',
27+
subdomains: {
28+
'foo.id': {
29+
registerUrl: 'http://localhost:7103/register'
30+
}
31+
},
2632
hostedDataLocation: DROPBOX,
2733
coreHost: 'localhost',
2834
corePort: 6270,

app/js/auth/components/AuthModal.js

Lines changed: 90 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const logger = log4js.getLogger('auth/components/AuthModal.js')
2020
function mapStateToProps(state) {
2121
return {
2222
localIdentities: state.profiles.identity.localIdentities,
23+
defaultIdentity: state.profiles.identity.default,
2324
identityKeypairs: state.account.identityAccount.keypairs,
2425
appManifest: state.auth.appManifest,
2526
appManifestLoading: state.auth.appManifestLoading,
@@ -42,6 +43,8 @@ class AuthModal extends Component {
4243
router: PropTypes.object
4344
}
4445
static propTypes = {
46+
defaultIdentity: PropTypes.string.isRequired,
47+
localIdentities: PropTypes.object.isRequired,
4548
loadAppManifest: PropTypes.func.isRequired,
4649
clearSessionToken: PropTypes.func.isRequired,
4750
getCoreSessionToken: PropTypes.func.isRequired,
@@ -55,6 +58,7 @@ class AuthModal extends Component {
5558
super(props)
5659

5760
this.state = {
61+
currentIdentity: null,
5862
authRequest: null,
5963
appManifest: null,
6064
coreSessionToken: null,
@@ -79,39 +83,52 @@ class AuthModal extends Component {
7983
componentWillReceiveProps(nextProps) {
8084
const storageConnected = this.props.api.dropboxAccessToken !== null
8185
this.setState({
82-
storageConnected
86+
storageConnected,
87+
currentIdentity: this.state.currentIdentity || nextProps.defaultIdentity || undefined
8388
})
8489

8590
const appDomain = this.state.decodedToken.payload.domain_name
8691
const localIdentities = nextProps.localIdentities
8792
const identityKeypairs = nextProps.identityKeypairs
88-
if (appDomain && nextProps.coreSessionTokens[appDomain]) {
89-
logger.trace('componentWillReceiveProps: received coreSessionToken')
90-
if (Object.keys(localIdentities).length > 0) {
91-
let userDomainName = Object.keys(localIdentities)[0]
92-
93-
let hasUsername = true
94-
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
95-
logger.debug(`login(): this profile ${userDomainName} has no username`)
96-
hasUsername = false
97-
}
98-
const blockchainId = (hasUsername ? userDomainName : null)
99-
const identity = localIdentities[userDomainName]
100-
const profile = identity.profile
101-
const privateKey = identityKeypairs[0].key
102-
const appsNodeKey = identityKeypairs[0].appsNodeKey
103-
const salt = identityKeypairs[0].salt
104-
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
105-
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
106-
107-
// TODO: what if the token is expired?
108-
const authResponse = makeAuthResponse(privateKey, profile, blockchainId,
109-
nextProps.coreSessionTokens[appDomain], appPrivateKey)
110-
111-
this.props.clearSessionToken(appDomain)
112-
redirectUserToApp(this.state.authRequest, authResponse)
113-
}
93+
if (!appDomain || !nextProps.coreSessionTokens[appDomain]) {
94+
return
95+
}
96+
97+
logger.trace('componentWillReceiveProps: received coreSessionToken')
98+
if (!Object.keys(localIdentities).length) {
99+
return
100+
}
101+
// Careful with this.state, as the above this.setState is async. But
102+
// there shouldn't be any problem with the above check.
103+
// TODO: Side-effects to avoid confusion.
104+
const userDomainName = this.state.currentIdentity
105+
106+
let hasUsername = true
107+
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
108+
logger.debug(`login(): this profile ${userDomainName} has no username`)
109+
hasUsername = false
114110
}
111+
112+
// Get keypair corresponding to the current user identity
113+
const profileSigningKeypair = identityKeypairs.find((keypair) => keypair.address === localIdentities[userDomainName].ownerAddress)
114+
115+
const blockchainId = (hasUsername ? userDomainName : null)
116+
const identity = localIdentities[userDomainName]
117+
const profile = identity.profile
118+
const privateKey = profileSigningKeypair.key
119+
const appsNodeKey = profileSigningKeypair.appsNodeKey
120+
const salt = profileSigningKeypair.salt
121+
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
122+
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
123+
124+
// TODO: what if the token is expired?
125+
const authResponse = makeAuthResponse(privateKey, profile, blockchainId,
126+
nextProps.coreSessionTokens[appDomain], appPrivateKey)
127+
128+
this.props.clearSessionToken(appDomain)
129+
130+
logger.trace(`login(): profile ${userDomainName} is logging in`)
131+
redirectUserToApp(this.state.authRequest, authResponse)
115132
}
116133

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

121138
login() {
122139
this.props.loginToApp()
123-
if (Object.keys(this.props.localIdentities).length > 0) {
124-
const localIdentities = this.props.localIdentities
125-
let userDomainName = Object.keys(localIdentities)[0]
126-
let hasUsername = true
127-
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
128-
logger.debug(`login(): this profile ${userDomainName} has no username`)
129-
hasUsername = false
130-
}
131-
const identity = localIdentities[userDomainName]
132-
const profile = identity.profile
133-
const profileSigningKeypair = this.props.identityKeypairs[0]
134-
const appDomain = this.state.decodedToken.payload.domain_name
135-
const scopes = this.state.decodedToken.payload.scopes
136-
const appsNodeKey = this.props.identityKeypairs[0].appsNodeKey
137-
const salt = this.props.identityKeypairs[0].salt
138-
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
139-
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
140-
const blockchainId = (hasUsername ? userDomainName : null)
141-
logger.trace(`login(): Calling setCoreStorageConfig()...`)
142-
setCoreStorageConfig(this.props.api, blockchainId,
143-
localIdentities[userDomainName].profile, profileSigningKeypair)
144-
.then(() => {
145-
logger.trace('login(): Core storage successfully configured.')
146-
logger.trace('login(): Calling getCoreSessionToken()...')
147-
this.props.getCoreSessionToken(this.props.coreHost,
148-
this.props.corePort, this.props.coreAPIPassword, appPrivateKey,
149-
appDomain, this.state.authRequest, blockchainId)
150-
})
140+
if (!Object.keys(this.props.localIdentities).length) {
141+
return
142+
}
143+
const localIdentities = this.props.localIdentities
144+
const userDomainName = this.state.currentIdentity
145+
146+
let hasUsername = true
147+
if (userDomainName === localIdentities[userDomainName].ownerAddress) {
148+
logger.debug(`login(): this profile ${userDomainName} has no username`)
149+
hasUsername = false
151150
}
151+
152+
// Get keypair corresponding to the current user identity
153+
const profileSigningKeypair = this.props.identityKeypairs.find((keypair) => keypair.address === localIdentities[userDomainName].ownerAddress)
154+
155+
const appDomain = this.state.decodedToken.payload.domain_name
156+
const scopes = this.state.decodedToken.payload.scopes
157+
const appsNodeKey = profileSigningKeypair.appsNodeKey
158+
const salt = profileSigningKeypair.salt
159+
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
160+
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
161+
const blockchainId = (hasUsername ? userDomainName : null)
162+
logger.trace(`login(): Calling setCoreStorageConfig()...`)
163+
setCoreStorageConfig(this.props.api, blockchainId,
164+
localIdentities[userDomainName].profile, profileSigningKeypair)
165+
.then(() => {
166+
logger.trace('login(): Core storage successfully configured.')
167+
logger.trace('login(): Calling getCoreSessionToken()...')
168+
this.props.getCoreSessionToken(this.props.coreHost,
169+
this.props.corePort, this.props.coreAPIPassword, appPrivateKey,
170+
appDomain, this.state.authRequest, blockchainId)
171+
})
152172
}
153173

154174
render() {
@@ -196,9 +216,21 @@ class AuthModal extends Component {
196216
<div>
197217
{ this.state.storageConnected ?
198218
<div>
199-
<p>
200-
Click below to log in.
201-
</p>
219+
<p>Choose a profile to log in with.</p>
220+
<select
221+
className="form-control profile-select"
222+
onChange={(event) => this.setState({ currentIdentity: event.target.value })}
223+
value={this.state.currentIdentity}
224+
>
225+
{Object.keys(this.props.localIdentities).map((domainName) => (
226+
<option
227+
key={domainName}
228+
value={this.props.localIdentities[domainName].domainName}
229+
>
230+
{this.props.localIdentities[domainName].domainName}
231+
</option>
232+
))}
233+
</select>
202234
<div>
203235
<button className="btn btn-primary btn-block" onClick={this.login}>
204236
Approve

app/js/profiles/AllProfilesPage.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const logger = log4js.getLogger('profiles/AllProfilesPage.js')
1616
function mapStateToProps(state) {
1717
return {
1818
localIdentities: state.profiles.identity.localIdentities,
19+
defaultIdentity: state.profiles.identity.default,
1920
namesOwned: state.profiles.identity.namesOwned,
2021
createProfileError: state.profiles.identity.createProfileError,
2122
identityAddresses: state.account.identityAccount.addresses,
@@ -32,13 +33,15 @@ function mapDispatchToProps(dispatch) {
3233
class IdentityPage extends Component {
3334
static propTypes = {
3435
localIdentities: PropTypes.object.isRequired,
36+
defaultIdentity: PropTypes.string.isRequired,
3537
createNewProfile: PropTypes.func.isRequired,
3638
refreshIdentities: PropTypes.func.isRequired,
3739
namesOwned: PropTypes.array.isRequired,
3840
api: PropTypes.object.isRequired,
3941
identityAddresses: PropTypes.array.isRequired,
4042
nextUnusedAddressIndex: PropTypes.number.isRequired,
4143
encryptedBackupPhrase: PropTypes.string.isRequired,
44+
setDefaultIdentity: PropTypes.string.isRequired,
4245
resetCreateNewProfileError: PropTypes.func.isRequired,
4346
createProfileError: PropTypes.string
4447
}
@@ -56,6 +59,7 @@ class IdentityPage extends Component {
5659
console.log(props)
5760

5861
this.onValueChange = this.onValueChange.bind(this)
62+
this.setDefaultIdentity = this.setDefaultIdentity.bind(this)
5963
this.createNewProfile = this.createNewProfile.bind(this)
6064
this.availableIdentityAddresses = this.availableIdentityAddresses.bind(this)
6165
this.openPasswordPrompt = this.openPasswordPrompt.bind(this)
@@ -77,7 +81,7 @@ class IdentityPage extends Component {
7781
this.setState({
7882
localIdentities: nextProps.localIdentities
7983
})
80-
if (!this.props.createProfileError && nextProps.createProfileError) {
84+
if (nextProps.createProfileError) {
8185
this.setState({
8286
processing: false
8387
})
@@ -101,6 +105,10 @@ class IdentityPage extends Component {
101105
})
102106
}
103107

108+
setDefaultIdentity(domainName) {
109+
this.props.setDefaultIdentity(domainName)
110+
}
111+
104112
createNewProfile(event) {
105113
logger.trace('createNewProfile')
106114
this.setState({
@@ -210,6 +218,8 @@ class IdentityPage extends Component {
210218
url={`/profiles/${identity.domainName}/local`}
211219
ownerAddress={identity.ownerAddress}
212220
canAddUsername={identity.canAddUsername}
221+
isDefault={identity.domainName === this.props.defaultIdentity}
222+
setDefaultIdentity={() => this.setDefaultIdentity(identity.domainName)}
213223
/>
214224
)
215225
} else {
@@ -220,7 +230,7 @@ class IdentityPage extends Component {
220230
</div>
221231
<div className="card-list-container m-t-30">
222232
<button
223-
className="btn btn-blue btn-lg" onClick={this.openPasswordPrompt}
233+
className="btn btn-electric-blue btn-lg" onClick={this.openPasswordPrompt}
224234
>
225235
+ Create
226236
</button>

0 commit comments

Comments
 (0)