By default, authentication requests include the `store_write` scope which
By default, authentication requests include the `store_write` scope which
enables storage. This is what allows you to store information to Gaia.
enables storage. This is what allows you to store information to Gaia. Adding
the `publish_data` scope allows your app to share data between users.
3. Save your changes.
4. Save your changes.
4. Go back to your app at `http://localhost:8080/`.
5. Go back to your app at `http://localhost:8080/`.
5. Log out and sign in again.
6. Log out and sign in again.
The authentication request now prompts the user for permission to **Publish
The authentication request now prompts the user for permission to **Publish
data stored for the app**.
data stored for the app**.
@ -197,10 +192,10 @@ Modify your authentication request to include the `publish_data` scope.
## Understand Gaia storage methods
## Understand Gaia storage methods
Once you authenticate a user with `store_write` and `publish_data`, you can
Once you authenticate a user with `store_write` and `publish_data`, you can
begin to manage data for your users. Blockstack JS provides two methods
begin to manage data for your users. Blockstack JS provides two methods within
`getFile()` and `putFile()` for interacting with Gaia storage. The storage
the `UserSession` class, `UserSession.getFile` and `UserSession.putFile` for
methods support all file types. This means you can store SQL, Markdown, JSON, or
interacting with Gaia storage. The storage methods support all file types.
even a custom format.
This means you can store markdown, JSON, or even a custom format.
You can create a meaningful and complex data layer using these two methods.
You can create a meaningful and complex data layer using these two methods.
Before creating an application, consider fundamental data architecture and make
Before creating an application, consider fundamental data architecture and make
@ -250,29 +245,12 @@ or remove a grocery list; updating a list has no impact.
## Add support for user status submission and lookup
## Add support for user status submission and lookup
In this step, you add three `blockstack.js` methods that support posting of "statuses". These are the `putFile()`, `getFile()`, and `lookupProfile()` methods.
In this step, you add three `blockstack.js` methods that support posting of "statuses".
These are the `UserSession.putFile`, `UserSession.getFile`, and `lookupProfile` methods.
1. Open the `src/components/Profile.jsx` file.
1. Open the `src/components/Profile.jsx` file.
2. Expand the `import from blockstack` statement with data methods.
2. Replace the initial state in the `constructor()` method so that it holds the key properties required by the app.
The `Person` object holds a Blockstack profile. Add `putFile`, `getFile`,
and `lookupProfile` after `Person`.
When you are done, the import statement should look like the following:
```javascript
import {
isSignInPending,
loadUserData,
Person,
getFile,
putFile,
lookupProfile
} from 'blockstack';
```
3. Replace the `constructor()` initial state so that it holds the key properties required by the app.
This code constructs a Blockstack `Person` object to hold the profile. Your constructor should look like this:
This code constructs a Blockstack `Person` object to hold the profile. Your constructor should look like this:
@ -299,20 +277,20 @@ In this step, you add three `blockstack.js` methods that support posting of "sta
```
```
4. Locate the `render()` method.
3. Locate the `render()` method.
5. Modify the `render()` method to add a text input and submit button to the application.
4. Modify the `render()` method to add a text input and submit button to the application.
The following code echos the `person.name` and `person.avatarURL`
The following code renders the `person.name` and `person.avatarURL`
This sets up a route and captures the route parameter the app will use as the profile lookup username.
This sets up a route and captures the route path in the URL as the profile lookup username.
11. Save and close the the `src/components/App.jsx` file.
11. Save and close the the `src/components/App.jsx` file.
### Add a rule to process URL paths with . (dot)
### Add a rule to process URL paths with . (dot)
You also need to add a rule to your webpack config so that you can properly
You also need to add a rule to your app's webpack config so that you can properly
process URL paths that contain the `.` (dot) character for example,
process URL paths that contain the `.` (dot) character for example,
`http://localhost:8080/other_user.id`
`http://localhost:8080/other_user.id`
@ -641,8 +629,22 @@ process URL paths that contain the `.` (dot) character for example,
3. Save and close the `webpack.config.js` file.
3. Save and close the `webpack.config.js` file.
4. Edit the `src/components/Profile.jsx` file.
4. Open the `src/components/Profile.jsx` file.
5. Add a single method that determines if the app is viewing the local user's profile or another user's profile.
5. Expand the `import from blockstack` statement to include the `lookupProfile` method.
Add `lookupProfile` after `Person`.
When you are done, the import statement should look like the following:
```javascript
import {
Person,
lookupProfile
} from 'blockstack';
```
6. Add a single method to the `Profile` class that determines if the app is viewing the local user's profile or another user's profile.
```javascript
```javascript
isLocal() {
isLocal() {
@ -652,19 +654,20 @@ process URL paths that contain the `.` (dot) character for example,
You use `isLocal()` to check if the user is viewing the local user profile or another user's profile. If it's the local user profile, the app runs the `getFile()` function you added in an earlier step. Otherwise, the app looks up the profile belonging to the `username` using the `lookupProfile()` method.
You use `isLocal()` to check if the user is viewing the local user profile or another user's profile. If it's the local user profile, the app runs the `getFile()` function you added in an earlier step. Otherwise, the app looks up the profile belonging to the `username` using the `lookupProfile()` method.
6. Modify the `fetchData()` method like so:
7. Modify the `fetchData()` method like so:
```javascript
```javascript
fetchData() {
fetchData() {
const { userSession } = this.props
this.setState({ isLoading: true })
this.setState({ isLoading: true })
if (this.isLocal()) {
if (this.isLocal()) {
const options = { decrypt: false }
const options = { decrypt: false }
getFile('statuses.json', options)
userSession.getFile('statuses.json', options)
.then((file) => {
.then((file) => {
var statuses = JSON.parse(file || '[]')
var statuses = JSON.parse(file || '[]')
this.setState({
this.setState({
person: new Person(loadUserData().profile),
person: new Person(userSession.loadUserData().profile),
username: loadUserData().username,
username: userSession.loadUserData().username,
statusIndex: statuses.length,
statusIndex: statuses.length,
statuses: statuses,
statuses: statuses,
})
})
@ -696,11 +699,11 @@ process URL paths that contain the `.` (dot) character for example,
documentation](http://blockstack.github.io/blockstack.js/#getfile) for
documentation](http://blockstack.github.io/blockstack.js/#getfile) for
details.
details.
7. Add the following block to `fetchData()` right after the call to `lookupProfile(username)... catch((error)=>{..}` block:
8. Add the following block to `fetchData()` right after the call to `lookupProfile(username)... catch((error)=>{..}` block:
@ -720,16 +723,16 @@ process URL paths that contain the `.` (dot) character for example,
Finally, you must conditionally render the logout button, status input textbox, and submit button so they don't show up when viewing another user's profile.
Finally, you must conditionally render the logout button, status input textbox, and submit button so they don't show up when viewing another user's profile.
8. Replace the `render()` method with the following:
9. Replace the `render()` method with the following:
@ -790,22 +793,28 @@ process URL paths that contain the `.` (dot) character for example,
}
}
```
```
### This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
This checks to ensure that users are viewing their own profile, by wrapping the **Logout** button and inputs with the `{isLocal() && ...}` condition.
### Put it all together
### Put it all together
1. Stop the running application by sending a CTL-C.
1. Stop the running application in terminal by sending a CTRL-C.
2. Restart the application so that the disabling of the `.` (dot) rule takes effect.
2. Restart the application so that the disabling of the `.` (dot) rule takes effect.
```bash
```bash
npm start
npm start
```
```
3. Point your browser to `http://localhost:8080/your_blockstack.id` to see the final application.
3. Point your browser to `http://localhost:8080/your_username.id.blockstack` to see the final application.
## Wrapping up
## Wrapping up
Congratulations, you are all done! We hope you've enjoyed learning a bit more
Congratulations, you are all done! We hope you've enjoyed learning a bit more
about Blockstack.
about Blockstack.
A few things to note, you'll notice that in our `putFile()` and `getFile()` calls, we chose not to encrypt/decrypt because our app is meant to share statuses publicly. By default, `putFile()` and `getFile()` will encrypt all data stored, making it unreadable by everyone except the logged in user.