Quick Start: Notes Application

This guide will show you how to create your account and build a simple application on top of TrueVault. We will create TrueNotes, an app where you will be able to log in, create secure notes that are stored in TrueVault, and list your previously created notes.

Note: This app is only supported with latest Chrome.

TrueVault Management Console Setup

1. Create an account

First, you’ll need to create a TrueVault account.

Create account

Tip: Every account starts out as a development account which means you should not store any Protected Health Information in TrueVault until you have activated your account and you have executed a Business Associate Agreement. You can email us (help@truevault.com) for a copy of the Business Associate Agreement before you sign up.

Once you create an account you will be taken to the Management Console Dashboard.

Dashboard

2. Create a vault

Next, we will create a Vault to store notes. You can think of a Vault as a collection of TrueVault documents and BLOBs. Once logged in, click on the Explorer menu item on the top menu bar and then click the Create New Vault button in the bottom left. Name the Vault quickstart then click Save. Now a Vault is created and it’s ready to store any JSON or BLOB objects.

Create vault

3. Create a user

Next, we need to create a user in TrueVault. This is an end-user, an actual person who will log in and create notes with the application. Click on the Users menu item on the top menu bar then click the Add + button. Name the new user quickstart with a password then click Save.

Create User

4. Create a group

By default, Users don’t have permission to do anything in TrueVault. In order to grant Users access to data, we must first create a Group with a desired Group Policy and add the User to it.

To do so, click the Groups menu item on the top menu bar, then click the Add + button in the left sidebar. Name the group quickstart and add the policy with resource Vault::VAULT_ID::Document::$[Owner=self] (replace VAULT_ID with the ID of the Vault we created in step 2). Click the Create and Read Access buttons. Now any user in this group will be able to create documents with themselves as the owner, and read any of their owned documents within that vault.

Create Group

5. Add a user to a group

In order for the user to be granted access, we need to add it to the group we created. You can find the User’s ID by clicking on the quickstart user on the Users page and looking at the user info in the middle section.

User ID location

Copy that ID, navigate to the Groups page, click the quickstart group, and click the Add + button at the top of the right sidebar. Paste in the user ID and click Save to add the user to the group.

Add user button location

Add a user to a group

Project Setup

Now that we’ve created the necessary resources in TrueVault, it’s time to start coding. Clone the truevault-quick-start repo:

git clone https://github.com/truevault/truevault-quick-start.git
cd truevault-quick-start

The master branch contains the complete application if you want to preview what we’ll be building or reference it in case your changes diverge. Let’s begin by checking out the first commit which contains the base app skeleton:

git checkout e15a7839fe5a330faa6aeaaf6dbabec308be2a65

This skeleton only contains HTML, CSS, and Bootstrap, which we will build off of to create the full app.

Before running the app, you will need to copy the tv-config.js.template file to tv-config.js and fill in you account ID and the ID of the vault you created previously.

You can find your account ID by clicking your account username at the very right of the top navigation bar and clicking Account. At the top left of this account page you will see your account ID. Fill this in for TV_ACCOUNT_ID in tv-config.js.

Account ID Location

You can find the ID of the vault you created by going clicking the Explorer button on the top navigation bar, clicking the vault in the sidebar, and copying the UUID from the URI in your browser’s navigation bar. Fill this in for TV_VAULT_ID in tv-config.js.

Vault ID Location

Running the app

You can run the app by serving the root directory. An easy way of doing this if you have python installed is by running python -m SimpleHTTPServer in the root directory and navigating to localhost:8000 in a browser. You will need to refresh the page after making any changes to the code. At this point all you should see is the top navigation bar of the TrueNotes app.

App skeleton

Add the TrueVault JavaScript SDK

The easiest way of interacting with TrueVault is by using the TrueVault JavaScript SDK. Let’s include this in our project by adding this script tag to the body of index.html:

<script src="https://unpkg.com/truevault@0.9.0/build/index.js"></script>

Add a login form

In order for our application to authenticate a user, we need to create a login form. This will use the login endpoint in TrueVault, with which the end user will send a username and password and receive back a user access token. This user access token will be used to make subsequent TrueVault requests.

First we’ll add some HTML and CSS to the skeleton for our login form. Add this snippet to the container div in index.html:

<div class="container">
  <form id="auth-form" class="form-horizontal">
    <div class="form-group">
      <label for="username" class="control-label">Username</label>
      <input type="text" class="form-control" id="username" name="username" placeholder="Username">
    </div>
    <div class="form-group">
      <label for="password" class="control-label">Password</label>
      <input type="password" class="form-control" id="password" name="password" placeholder="Password">
    </div>
    <div class="form-group">
      <button type="submit" class="btn btn-default" id="auth-submit">Login</button>
    </div>
  </form>
</div>

Add styling for the login form to index.css:

#auth-form {
    width: 400px;
    margin-left: auto;
    margin-right: auto;
}

.form-group{
    margin-bottom: 20px;
}

.form-horizontal .control-label {
    padding-top: 0px;
    margin-bottom: 5px;
}

.btn {
    width: 200px;
    border-radius: 100px;
    background-color: #4ba8ff;
    box-shadow: 0 2px 7px 0 rgba(0,0,0,.2);
    color: #fff;
    border: none;
    display: block;
    margin-top: 10px;
    margin-left: auto;
    margin-right: auto;
    margin-bottom: 40px;
    padding: 10px;
    padding-left: 16px;
    padding-right: 16px;
    font-size: 16px;
}

.btn:hover {
    background-color: #7ec1ff;
    color: #fff;
}

Refreshing the page should now look like this:

Login screen

Now let’s make the login button log in the quickstart user in TrueVault. Add this snippet to the index.js file:

const authFormEl = document.getElementById("auth-form");

authFormEl.addEventListener("submit", async e => {
    e.preventDefault();

    const tvClient = await TrueVaultClient.login(TV_ACCOUNT_ID, this.username.value, this.password.value);

    console.log('Auth header:', tvClient.authHeader);
});

If you open the Chrome console and log in with the quickstart user’s credentials, you should see a user access token logged to the console. We will use the tvClient object which saves this user access token to make all subsequent requests to TrueVault for this user.

Adding the notes screen

Now that we can log in with TrueVault, let’s create a screen to land on. Add this to the container div after the auth-form div in index.html:

<button class="btn btn-large" id="add-note">Add a new note</button>

Of course we don’t want to see both the new note button and the login screen at the same time. Most JavaScript MV* frameworks have a way of handling page routing, but for this example we’ll use a bit of pure JavaScript. Replace the contents of index.js with this snippet and refresh the page:

const authFormEl = document.getElementById('auth-form');
const addNoteButtonEl = document.getElementById('add-note');

let tvClient = null;

const setState = async (newState) => {
    authFormEl.style.display = 'none';
    addNoteButtonEl.style.display = 'none';

    switch (newState) {
        case '#notes':
            addNoteButtonEl.style.display = '';
            break;
        case '#login':
        default:
            authFormEl.style.display = '';
            break;
    }
};

authFormEl.addEventListener('submit', async e => {
    e.preventDefault();

    tvClient = await TrueVaultClient.login(TV_ACCOUNT_ID, this.username.value, this.password.value);
    location.hash = '#notes';
});


window.onpopstate = async () => setState(location.hash);

const refreshState = async () => {
    await setState(location.hash);
};

refreshState();

Now when you log in, the login form should be replaced with an “Add a new note” button:

Add note button

Add note creation screen

Now let’s get the “Add a new note” button to open a note creation module. First let’s add a note creation form to the container div in index.html:

<form id="add-note-form" class="form-horizontal">
  <div class="form-group">
    <label for="note" class="control-label">Note</label>
    <textarea id="note" class="form-control" rows="3" placeholder="Enter note here"></textarea>
  </div>
  <div class="form-group">
    <button type="submit" class="btn btn-default" id="add-note-submit">Add note</button>
  </div>
</form>

And let’s style it by adding this to index.css:

#add-note-form {
    width: 400px;
    margin-left: auto;
    margin-right: auto;
}

Let’s add code to display the note creation module only when we’ve clicked the Add a new note button. Let’s create a reference to the #add-note-form div at the top of index.js:

const addNoteFormEl = document.getElementById('add-note-form');

Let’s also add a new case in setState for the screen to add a note:

const setState = async (newState) => {
    authFormEl.style.display = 'none';
    addNoteButtonEl.style.display = 'none';
    addNoteFormEl.style.display = 'none';

    switch (newState) {
        case '#notes':
            addNoteButtonEl.style.display = '';
            break;
        case '#add-note':
            addNoteFormEl.style.display = '';
            break;
        case '#login':
        default:
            authFormEl.style.display = '';
            break;
    }
};

Finally let’s add an event listener to change the screen when clicking the Add a new note button:

addNoteButtonEl.addEventListener('click', async e => {
    e.preventDefault();

    location.hash = '#add-note';
});

The note creation screen should look like this:

Note creation screen

Creating a new note

When we create a new note, we want to store it in the quickstart vault in TrueVault. Let’s add a form submission handler to index.js that does just that.

We need to create a document setting the owner_id to the current user’s in order to be able to list all of their previously stored documents. In order to get the user ID of the current user, we user tvClient.readCurrentUser in the login handler to retrieve the user ID and store it in tvUserId. Update index.js to declare the tvUserId variable and update the authFormEl submit handler as follows:

let tvClient = null;
let tvUserId = null;

...

authFormEl.addEventListener('submit', async e => {
    e.preventDefault();

    tvClient = await TrueVaultClient.login(TV_ACCOUNT_ID, this.username.value, this.password.value);
    const response = await tvClient.readCurrentUser();
    tvUserId = response.id;
    location.hash = '#notes';
});

Now we can add a submit event listener to create a new document:

addNoteFormEl.addEventListener('submit', async e => {
    e.preventDefault();

    const document = {'note': this.note.value};
    await tvClient.createDocument(TV_VAULT_ID, null, document, tvUserId);

    this.note.value = '';
    location.hash = '#notes';
});

The user is able to make themselves the owner of a created document because they have Create permission on Vault::VAULT_ID::Document::$[Owner=self]. If the user tries creating a document with an owner_id other than their own, TrueVault will respond with an error message.

Note: Clear the path and fragment in your browser url (so it just reads localhost:8000) when you reload. The simple state management in this quickstart app isn’t smart enough to redirect you back to login (and you’ll have to login each time you reload).

Viewing the notes

Now that we are able to create a notes in TrueVault, let’s enhance the #notes view by showing all the notes we’ve created. First let’s add a notes-list div to container in index.html:

<div id="notes-list"></div>

And let’s style the notes view:

#notes-list {
    width: 500px;
    margin-right: auto;
    margin-left: auto;
}

.note {
    border: solid #e4e4e4 1px;
    box-shadow: 0 2px 7px 0 rgba(0,0,0,.1);
    padding: 20px;
    margin-bottom: 30px;
}

When we load the #notes view, we need to make a request to TrueVault to list all of the vault’s note documents. Let’s add this TrueVault request to the #notes switch case.

First let’s create a new reference to the #notes-list div:

const notesListEl = document.getElementById('notes-list');

Then let’s modify the #notes case to list the documents in the vault:

const setState = async (newState) => {
    authFormEl.style.display = 'none';
    addNoteButtonEl.style.display = 'none';
    addNoteFormEl.style.display = 'none';
    notesListEl.style.display = 'none';

    switch (newState) {
        case '#notes':
            const response = await tvClient.listDocuments(TV_VAULT_ID, true);
            if (response.items.length > 0) {
                notesListEl.innerHTML = response.items.map(
                    item => `<div >${item.document.note}</div>`
                ).join('');
            }
            notesListEl.style.display = '';
            addNoteButtonEl.style.display = '';
            break;
        case '#add-note':
            addNoteFormEl.style.display = '';
            break;
        case '#login':
        default:
            authFormEl.style.display = '';
            break;
    }
};

We call the document list endpoint from TrueVault and create note divs for each of them. The end user is able to list all the documents they own because they have Read permission on Vault::VAULT_ID::Document::$[Owner=self]. Note that they won’t be able to see any other user’s documents. This is a common example of how you can use TrueVault permissions to prevent users from accessing data they are not supposed to.

The final notes screen should look like this:

Notes screen

To try out the entire flow of the app, change the url back to localhost:8000 and reload. You should be able to log in and create notes. As a bonus exercise, go back to the TrueVault Management Console and create another user, adding it to the same group. Try logging in as that user. The two users won’t be able to see each other’s notes (even if they requested them by id).

Conclusion

We have completed our first application using TrueVault. It should look the exact same as the master branch of the truevault-quick-start repo we cloned. You can switch back to master by running git checkout master.

By now you should have an understanding of the basics to creating an application using TrueVault. For more a more in-depth example application, check out our more advanced React Sample App which demonstrates a more complex and realistic application architecture. If you would like to learn more about how to build your project using TrueVault, please contact us at help@truevault.com or ask a question on StackOverflow with the tag truevault.