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

Commit 839f2a6

Browse files
committed
Merge branch 'release/0.21.6'
2 parents b5668bf + 58d2217 commit 839f2a6

File tree

9 files changed

+253
-272
lines changed

9 files changed

+253
-272
lines changed

app/js/HomeScreenPage.js

Lines changed: 17 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ import React, { Component, PropTypes } from 'react'
22
import { bindActionCreators } from 'redux'
33
import { connect } from 'react-redux'
44
import Navbar from './components/Navbar'
5-
import ToolTip from './components/ToolTip'
65
import { AppsActions } from './store/apps'
76
import appList from './data/apps'
8-
import { isWebAppBuild, isCoreEndpointDisabled } from './utils/window-utils'
7+
import { isWebAppBuild } from './utils/window-utils'
98

109
function mapStateToProps(state) {
1110
return {
@@ -21,48 +20,24 @@ function mapDispatchToProps(dispatch) {
2120
return bindActionCreators(Object.assign({}, AppsActions), dispatch)
2221
}
2322

24-
const AppIcon = (props) => {
25-
const disabledForCore = isCoreEndpointDisabled() && props.storageRequired
26-
return (
27-
<div className="container-fluid app-box-wrap">
28-
<ToolTip id="coreDisabled">
29-
<div>
30-
<div>
31-
This app requires Gaia storage, which is not supported in the webapp build.
32-
Feature coming soon!
33-
</div>
34-
</div>
35-
</ToolTip>
36-
{disabledForCore ?
37-
<div
38-
className="app-box"
39-
data-tip
40-
data-for="coreDisabled"
41-
>
42-
<img
43-
src={`/images/${props.iconImage}`}
44-
alt={props.displayName}
45-
/>
46-
</div>
47-
:
48-
<a
49-
href={props.launchLink}
50-
className="app-box-container"
51-
>
52-
<div className="app-box">
53-
<img
54-
src={`/images/${props.iconImage}`}
55-
alt={props.displayName}
56-
/>
57-
</div>
58-
</a>
59-
}
60-
<div className="app-text-container">
61-
<h3>{props.displayName}</h3>
23+
const AppIcon = (props) => (
24+
<div className="container-fluid app-box-wrap">
25+
<a
26+
href={props.launchLink}
27+
className="app-box-container"
28+
>
29+
<div className="app-box">
30+
<img
31+
src={`/images/${props.iconImage}`}
32+
alt={props.displayName}
33+
/>
6234
</div>
35+
</a>
36+
<div className="app-text-container">
37+
<h3>{props.displayName}</h3>
6338
</div>
64-
)
65-
}
39+
</div>
40+
)
6641

6742
const disclaimerWeb = `The Blockstack Tokens are a crypto asset that is currently being
6843
developed by Blockstack Token LLC, a Delaware limited liability
Lines changed: 7 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,23 @@
11
// @flow
22
import log4js from 'log4js'
3-
import bitcoin from 'bitcoinjs-lib'
4-
import bigi from 'bigi'
5-
const logger = log4js.getLogger('account/utils/blockstack-inc.js')
6-
7-
export type GaiaHubConfig = {
8-
address: string,
9-
token: string,
10-
server: string
11-
}
3+
import { uploadToGaiaHub, connectToGaiaHub, GaiaHubConfig } from 'blockstack'
124

13-
function uploadToGaiaHub(hubConfig: GaiaHubConfig, filename: string, contents: any,
14-
contentType: string = 'application/octet-stream'): Promise<*> {
15-
return new Promise((resolve) => {
16-
logger.debug(`uploadToGaiaHub: uploading ${filename} to ${hubConfig.server}`)
17-
return fetch(`${hubConfig.server}/store/${hubConfig.address}/${filename}`,
18-
{ method: 'POST',
19-
headers: {
20-
'Content-Type': contentType,
21-
Authorization: `bearer ${hubConfig.token}`
22-
},
23-
body: contents })
24-
.then((response) => response.text())
25-
.then((responseText) => JSON.parse(responseText))
26-
.then((responseJSON) => {
27-
resolve(responseJSON.publicURL)
28-
})
29-
})
30-
}
5+
const logger = log4js.getLogger('account/utils/blockstack-inc.js')
316

327
export function uploadPhotoToGaiaHub(api: {gaiaHubConfig: GaiaHubConfig },
338
identityIndex: number, identityAddress: string, photoFile: any, photoIndex: number) {
349
logger.trace('uploadPhotoToGaiaHub')
3510
const hubConfig = api.gaiaHubConfig
3611
const filename = `${identityIndex}/avatar-${photoIndex}`
37-
return uploadToGaiaHub(hubConfig, filename, photoFile)
12+
return uploadToGaiaHub(filename, photoFile, hubConfig)
3813
}
3914

4015
export function uploadProfileToGaiaHub(api: {gaiaHubConfig: GaiaHubConfig},
4116
identityIndex: number, identityAddress: string, signedProfileTokenData: string) {
4217
logger.trace('uploadProfileToGaiaHub')
4318
const hubConfig = api.gaiaHubConfig
4419
const filename = `${identityIndex}/profile.json`
45-
return uploadToGaiaHub(hubConfig, filename, signedProfileTokenData, 'application/json')
46-
}
47-
48-
export function connectToGaiaHub(gaiaHubUrl: string, challengeSignerHex: string): Promise<*> {
49-
logger.debug(`connectToGaiaHub: ${gaiaHubUrl}/hub_info`)
50-
const challengeSigner = new bitcoin.ECPair(
51-
bigi.fromHex(challengeSignerHex))
52-
return new Promise((resolve) => {
53-
fetch(`${gaiaHubUrl}/hub_info`)
54-
.then((response) => response.text())
55-
.then((responseText) => JSON.parse(responseText))
56-
.then((responseJSON) => {
57-
const readURL = responseJSON.read_url_prefix
58-
const challenge = responseJSON.challenge_text
59-
const digest = bitcoin.crypto.sha256(challenge)
60-
const signature = challengeSigner.sign(digest)
61-
.toDER().toString('hex')
62-
const publickey = challengeSigner.getPublicKeyBuffer()
63-
.toString('hex')
64-
const token = new Buffer(JSON.stringify(
65-
{ publickey, signature })).toString('base64')
66-
const address = challengeSigner.getAddress()
67-
resolve({ url_prefix: readURL,
68-
address,
69-
token,
70-
server: gaiaHubUrl }
71-
) }) })
20+
return uploadToGaiaHub(filename, signedProfileTokenData, hubConfig, 'application/json')
7221
}
7322

7423
export function redirectToConnectToGaiaHub() {
@@ -77,3 +26,6 @@ export function redirectToConnectToGaiaHub() {
7726
const host = location.hostname
7827
window.top.location.href = `http://${host}:${port}/account/storage#gaiahub`
7928
}
29+
30+
export { connectToGaiaHub, GaiaHubConfig }
31+

app/js/auth/components/AuthModal.js

Lines changed: 46 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@ import { AuthActions } from '../store/auth'
66
import { Link } from 'react-router'
77
import { decodeToken } from 'jsontokens'
88
import {
9-
makeAuthResponse, getAuthRequestFromURL, Person, redirectUserToApp
9+
makeAuthResponse, getAuthRequestFromURL, Person, redirectUserToApp,
10+
isLaterVersion
1011
} from 'blockstack'
1112
import Image from '../../components/Image'
1213
import { AppsNode } from '../../utils/account-utils'
1314
import { setCoreStorageConfig } from '../../utils/api-utils'
1415
import { isCoreEndpointDisabled, isWindowsBuild } from '../../utils/window-utils'
1516
import { getTokenFileUrlFromZoneFile } from '../../utils/zone-utils'
1617
import { HDNode } from 'bitcoinjs-lib'
17-
import { validateScopes } from '../utils'
18+
import { validateScopes, appRequestSupportsDirectHub } from '../utils'
1819
import log4js from 'log4js'
1920

2021
const logger = log4js.getLogger('auth/components/AuthModal.js')
@@ -90,7 +91,7 @@ class AuthModal extends Component {
9091
invalidScopes: false,
9192
sendEmail: false,
9293
blockchainId: null,
93-
noStorage: false,
94+
noCoreStorage: false,
9495
responseSent: false,
9596
requestingEmail: false
9697
}
@@ -139,7 +140,7 @@ class AuthModal extends Component {
139140
const localIdentities = nextProps.localIdentities
140141
const identityKeypairs = nextProps.identityKeypairs
141142
if ((!appDomain || !nextProps.coreSessionTokens[appDomain])) {
142-
if (this.state.noStorage) {
143+
if (this.state.noCoreStorage) {
143144
logger.debug('componentWillReceiveProps: no core session token expected')
144145
} else {
145146
logger.debug('componentWillReceiveProps: no app domain or no core session token')
@@ -151,7 +152,7 @@ class AuthModal extends Component {
151152

152153
const coreSessionToken = nextProps.coreSessionTokens[appDomain]
153154
let decodedCoreSessionToken = null
154-
if (!this.state.noStorage) {
155+
if (!this.state.noCoreStorage) {
155156
logger.debug('componentWillReceiveProps: received coreSessionToken')
156157
decodedCoreSessionToken = decodeToken(coreSessionToken)
157158
} else {
@@ -206,9 +207,6 @@ class AuthModal extends Component {
206207
}
207208

208209
// TODO: what if the token is expired?
209-
// TODO: use a semver check -- or pass payload version to
210-
// makeAuthResponse
211-
let authResponse
212210

213211
let profileResponseData
214212
if (this.state.decodedToken.payload.do_not_include_profile) {
@@ -217,19 +215,22 @@ class AuthModal extends Component {
217215
profileResponseData = profile
218216
}
219217

220-
if (this.state.decodedToken.payload.version === '1.1.0' &&
221-
this.state.decodedToken.payload.public_keys.length > 0) {
222-
const transitPublicKey = this.state.decodedToken.payload.public_keys[0]
218+
let transitPublicKey = undefined
219+
let hubUrl = undefined
223220

224-
authResponse = makeAuthResponse(privateKey, profileResponseData, blockchainId,
225-
metadata,
226-
coreSessionToken, appPrivateKey,
227-
undefined, transitPublicKey)
228-
} else {
229-
authResponse = makeAuthResponse(privateKey, profileResponseData, blockchainId,
230-
metadata,
231-
coreSessionToken, appPrivateKey)
221+
const requestVersion = this.state.decodedToken.payload.version
222+
if (isLaterVersion(requestVersion, '1.1.0') &&
223+
this.state.decodedToken.payload.public_keys.length > 0) {
224+
transitPublicKey = this.state.decodedToken.payload.public_keys[0]
232225
}
226+
if (appRequestSupportsDirectHub(this.state.decodedToken.payload)) {
227+
hubUrl = this.props.api.gaiaHubConfig.server
228+
}
229+
230+
const authResponse = makeAuthResponse(privateKey, profileResponseData, blockchainId,
231+
metadata, coreSessionToken, appPrivateKey,
232+
undefined, transitPublicKey, hubUrl)
233+
233234

234235
this.props.clearSessionToken(appDomain)
235236

@@ -304,6 +305,7 @@ class AuthModal extends Component {
304305
const appsNode = new AppsNode(HDNode.fromBase58(appsNodeKey), salt)
305306
const appPrivateKey = appsNode.getAppNode(appDomain).getAppPrivateKey()
306307
const blockchainId = (hasUsername ? identity.username : null)
308+
const needsCoreStorage = !appRequestSupportsDirectHub(this.state.decodedToken.payload)
307309

308310
const scopesJSONString = JSON.stringify(scopes)
309311

@@ -320,7 +322,7 @@ class AuthModal extends Component {
320322
sendEmail: !!scopes.includes('email')
321323
})
322324
const requestingStoreWrite = !!scopes.includes('store_write')
323-
if (requestingStoreWrite) {
325+
if (requestingStoreWrite && needsCoreStorage) {
324326
logger.trace('login(): Calling setCoreStorageConfig()...')
325327
setCoreStorageConfig(this.props.api, identityIndex, identity.ownerAddress,
326328
identity.profile, profileSigningKeypair)
@@ -331,10 +333,16 @@ class AuthModal extends Component {
331333
this.props.corePort, this.props.coreAPIPassword, appPrivateKey,
332334
appDomain, this.state.authRequest, blockchainId)
333335
})
336+
} else if (requestingStoreWrite && !needsCoreStorage) {
337+
logger.trace('login(): app can communicate directly with gaiahub, not setting up core.')
338+
this.setState({
339+
noCoreStorage: true
340+
})
341+
this.props.noCoreSessionToken(appDomain)
334342
} else {
335343
logger.trace('login(): No storage access requested.')
336344
this.setState({
337-
noStorage: true
345+
noCoreStorage: true
338346
})
339347
this.props.noCoreSessionToken(appDomain)
340348
}
@@ -347,14 +355,15 @@ class AuthModal extends Component {
347355
const processing = this.state.processing
348356
const invalidScopes = this.state.invalidScopes
349357
const decodedToken = this.state.decodedToken
350-
const noStorage = (decodedToken
351-
&& decodedToken.payload.scopes
352-
&& !decodedToken.payload.scopes.includes('store_write'))
358+
const noCoreStorage = (decodedToken
359+
&& decodedToken.payload.scopes
360+
&& (!decodedToken.payload.scopes.includes('store_write')
361+
|| appRequestSupportsDirectHub(decodedToken.payload)))
353362

354363
const coreShortCircuit = (!appManifestLoading
355364
&& appManifest !== null
356365
&& !invalidScopes
357-
&& !noStorage
366+
&& !noCoreStorage
358367
&& isCoreEndpointDisabled())
359368
if (coreShortCircuit) {
360369
let appText
@@ -377,9 +386,19 @@ class AuthModal extends Component {
377386
>
378387
<h3>Sign In Request</h3>
379388
<div>
389+
{appManifest.hasOwnProperty('icons') ?
390+
<p>
391+
<Image
392+
src={appManifest.icons[0].src}
393+
style={{ width: '128px', height: '128px' }}
394+
fallbackSrc="/images/app-icon-hello-blockstack.png"
395+
/>
396+
</p>
397+
: null}
380398
<p>
381-
This application requires using Gaia storage, which is not supported yet
382-
in our {appText}. Feature coming soon!
399+
This application uses an older Gaia storage library, which is not supported
400+
in our {appText}. Once the application updates its library, you will be
401+
able to use it.
383402
</p>
384403
</div>
385404
</Modal>

app/js/auth/utils.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// @flow
22

33
import log4js from 'log4js'
4+
import { isLaterVersion } from 'blockstack'
45

56
const logger = log4js.getLogger('auth/components/util.js')
67

@@ -10,6 +11,19 @@ const VALID_SCOPES = {
1011
email: true
1112
}
1213

14+
export function appRequestSupportsDirectHub(requestPayload: Object): boolean {
15+
let version = '0'
16+
let supportsHubUrl = false
17+
if (requestPayload.hasOwnProperty('version')) {
18+
version = requestPayload.version
19+
}
20+
if (requestPayload.hasOwnProperty('supports_hub_url')) {
21+
supportsHubUrl = requestPayload.supports_hub_url
22+
}
23+
24+
return isLaterVersion(version, '1.2.0') || !!supportsHubUrl
25+
}
26+
1327
export function validateScopes(scopes: Array<string>): boolean {
1428
logger.trace('validateScopes')
1529

docs/release-checklist.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Browser release checklist
22

3-
- [ ] `git flow release start 0.14.0` where 0.14.0 is the version of the release
3+
- [ ] `git flow release start 0.14.0` where 0.14.0 is the version of the release (make sure the version prefix `v` is set for git flow)
44
- [ ] `git flow release publish` (optional, shares release branch)
55
- [ ] update version in `/package.json`
66
- [ ] update version and build number in xcode

native/macos/Blockstack/Blockstack/Info.plist

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
<key>CFBundlePackageType</key>
1818
<string>APPL</string>
1919
<key>CFBundleShortVersionString</key>
20-
<string>0.21.5</string>
20+
<string>0.21.6</string>
2121
<key>CFBundleURLTypes</key>
2222
<array>
2323
<dict>
@@ -30,7 +30,7 @@
3030
</dict>
3131
</array>
3232
<key>CFBundleVersion</key>
33-
<string>80</string>
33+
<string>81</string>
3434
<key>LSApplicationCategoryType</key>
3535
<string>public.app-category.utilities</string>
3636
<key>LSMinimumSystemVersion</key>

0 commit comments

Comments
 (0)