Skip to main content

Shareable Content

If you're building an application that supports user-generated content (docs, notes, images etc), chances are that you'll also need to build functionality that allows users to share and collaborate on that content. Building such a system can get very complicated very fast.

In this guide, we'll go over how you can use Warrant to quickly augment your existing application to add sharing and collaboration functionality.

Prerequisites

This guide exclusively uses the Warrant API and thus assumes you have a Warrant account with API keys. If you don't, please first follow the Quickstart to set up your account.

Creating Object Types for Each Content Type

Each explicit 'content type' (ex. document, note, image) in our application will require an object type definition in Warrant. Let's say for example that we're building a simplified version of Google Docs. This simplified version has exactly 1 type of content: document. Each 'document' has an 'owner', 'editor(s)' and 'viewer(s)'. Using these relations, we can easily define who can read and/or modify a specific document in our application.

For each distinct 'content type' in your application, you should create an object type with 'owner', 'editor' and 'viewer' relationships. Note that these permissions cascade, with owners having editor and viewer privileges and editors also having viewer privileges:

{
"type": "document",
"relations": {
"owner": {},
"editor": {
"inheritIf": "owner"
}
"viewer": {
"inheritIf": "editor"
}
}
}

Granting Permissions

With our object types defined, we can create warrants that grant 'editor' and 'viewer' access to specific objects. For example, let's say that we have a 'document' in our application with id 'doc1'. We can grant a user (user1) 'editor' access to this document by creating the following warrant:

const newWarrant = await warrantClient.Warrant.create({
object: {
objectType: "document",
objectId: "doc1",
},
relation: "editor",
subject: {
objectType: "user"
objectId: "user1"
},
});

Checking Permissions

With our content permissions defined via warrants, we can start to enforce access to content directly in the app.

For example, if we wanted to check whether 'user1' had the ability to 'edit' 'doc1', we would add the following check in our application code:

const isAuthorized = await warrantClient.Authorization.check({
warrants: [
{
object: {
objectType: "document",
objectId: "doc1",
},
relation: "editor",
subject: {
objectType: "user",
objectId: "user1",
},
},
],
});
if (isAuthorized) {
// 'user1' can edit doc1
} else {
// Fail request
}

Summary

In this guide, we went over how you can use Warrant to quickly implement an access model for 'shareable content'. By assigning each object type an 'owner', 'editor(s)' and 'viewer(s)', we can easily implement logic in our application to manage and enforce content permissions at runtime.