# Managing User Data

# Overview

Now that you know how to upload data and onboard users, it's time to walk through how to manage data on behalf of end users.

With Parcel, you can store data such that your users retain full ownership and control. With user permission, you can still use their data to power analyses and features in your application.

You will recall that you specified permissions for your application when you registered your app in the Parcel developer portal. This tutorial will show you how these permissions enable you to work with user data without sacrificing security or privacy.

# Document Owners

Each document always has an owner. This owner is a Parcel identity, which can represent a user, a developer, or an application.

By default, the document owner is the identity that uploads the document:

const acmeIdentity = await parcel.getCurrentIdentity();
console.log(`Uploading data with identity: ${acmeIdentity.id}`);

const data = 'The weather will be sunny tomorrow and cloudy on Tuesday.';
const documentDetails = { title: 'Weather forecast summary', tags: ['english'] };
const acmeDocument = await parcel.uploadDocument(data, {
  details: documentDetails,
  toApp: undefined,
}).finished;
console.log(`Created document ${acmeDocument.id} with owner ${acmeDocument.owner}`);
Uploading data with identity: IPoxXkdvFsrqzDdU7h3QqSs
Created document DLPfSu1yGKGpxbD9RAnKEtk with owner IPoxXkdvFsrqzDdU7h3QqSs

A document owner always has the right to:

  • download the document
  • add or remove access to the document
console.log(`Downloading document ${acmeDocument.id} with identity ${acmeIdentity.id}`);
let download = parcel.downloadDocument(acmeDocument.id);
let saver = fs.createWriteStream(`./acme_document`);
await download.pipeTo(saver);
console.log(`Document ${acmeDocument.id} downloaded to ./acme_document`);

const acmeData = fs.readFileSync('./acme_document', 'utf-8');
console.log(`Here's the data: ${acmeData}`);
Downloading document DLPfSu1yGKGpxbD9RAnKEtk with identity IPoxXkdvFsrqzDdU7h3QqSs
Document DLPfSu1yGKGpxbD9RAnKEtk downloaded to ./acme_document
Here's the data: The weather will be sunny tomorrow and cloudy on Tuesday.

# Uploading User Data

Parcel allows your application to upload documents on behalf of other users, or identities, on the platform.

To do so, you specify the IDs of both the new document's intended owner and your app at the time of upload:

const bobId = process.env.BOB_IDENTITY_ID! as IdentityId; // REPLACE ME
const appId = process.env.ACME_APP_ID! as AppId; // REPLACE ME
console.log(`Uploading data for end user Bob (ID: ${bobId}) for your app (ID: ${appId})`);
const bobDocument = await parcel.uploadDocument(data, {
  details: documentDetails,
  owner: bobId,
  toApp: appId,
}).finished;
console.log(`Created document ${bobDocument.id} with owner ${bobDocument.owner}`);
Uploading data for end user Bob (ID: IJ2UnsgTss9GZw2EXKXagmj) for your app (ID: AVNidsM1HR76CFTJvGrrTrd)
Created document D5k3PDwawHhNgE8oNFgkhmV with owner IJ2UnsgTss9GZw2EXKXagmj

For testing, you can log in to Steward and retrieve your end user's identity address by clicking on your name:

steward_user_menu

If you upload the document with your user as the owner, you should then see it listed under your application's Your Data tab:

steward_your_data

# Accessing User Data

By default, only document owners are able to access their documents.

If we try to access our end user's document using our application's credentials:

download = parcel.downloadDocument(bobDocument.id);
saver = fs.createWriteStream(`./bob_data_by_acme`);
try {
  console.log(`Attempting to access Bob's document without permission...`);
  await download.pipeTo(saver);
} catch (error: any) {
  console.log(`ACME was not able to access Bob's data (this was expected): ${error}`);
}

We see an error because we do not have permission

ACME was not able to access Bob's data (this was expected)

We need our end users to open Steward and explicitly give us permission to access their user data.

We can redirect them to the Steward permission screen directly from our app:

const appId = 'AVNidsM1HR76CFTJvGrrTrd'; // REPLACE ME
location.assign(`https://steward.oasislabs.com/apps/${appId}/join`);

They will see a prompt to accept our application permission:

steward_join_app

Like account linking, you can specify a redirect URL for seamless embedding within your onboarding or account settings:

const appId = 'AVNidsM1HR76CFTJvGrrTrd';           // REPLACE ME
const nextOnboardingPage = 'https://app.acme.com/onboarding/2'; // REPLACE ME
location.assign(`https://steward.oasislabs.com/apps/${appId}/join?redirect_uri=${encodeURIComponent(nextOnboardingPage)}`);

Now, with user permission, we are able to access the document:

console.log(`Attempting to access Bob's document with ACME identity ${acmeIdentity.id}`);
download = parcel.downloadDocument(bobDocument.id);
saver = fs.createWriteStream(`./bob_data_by_acme`);
await download.pipeTo(saver);
console.log(`Document ${bobDocument.id} has been downloaded to ./bob_data_by_acme`);
const bobData = fs.readFileSync('./bob_data_by_acme', 'utf-8');
console.log(`Here's the data: ${bobData}`);
Attempting to access Bob's document with ACME identity IPoxXkdvFsrqzDdU7h3QqSs
Document D5k3PDwawHhNgE8oNFgkhmV has been downloaded to ./bob_data_by_acme
Here's the data: The weather will be sunny tomorrow and cloudy on Tuesday.

You can view the full example in the Parcel Examples repository.

Next, we will show you how you can run analyses on user data in our secure computing workers so you never need to directly access or download raw user data.