DEV Community

Cover image for Modeling Google Docs Access Management Using Permify
Ege Aytin for Permify

Posted on • Originally published at permify.co

Modeling Google Docs Access Management Using Permify

Introduction

Welcome to our in-depth exploration of the Google Docs authorization model. Collaboration lies at the heart of Google Docs, allowing multiple users to seamlessly collaborate on projects, share ideas, and edit documents in real-time. However, with such collaborative capabilities, it becomes essential to establish a robust authorization framework that ensures the right level of access is granted to the right individuals, groups, or organizations.

In this article, we will discuss the key components of the Google Docs authorization model, including entity, relations, and permissions. We will explore the various levels of access control available, ranging from view-only permissions to full editing capabilities. We will also delve into how this model, permissions, and access controls logic can be implemented using Permify.

By the end of this article, we want to help you understand how to use Permify effectively to set up the permission system in a documentation application.

Let's gain a deeper understanding of the Google Docs authorization model together.

Google Docs and Its Access Control

Google Docs is a powerful cloud-based document collaboration platform that enables users to create, edit, and share documents in real time. It provides robust access control features to ensure secure document sharing and collaboration.

And the platform offers a Relationship-Based Access Control that allows users to define who can access and interact with their documents. This permission system leverages the relationships between entities to determine access levels.

In Google Docs, users can assign different roles and permissions to individuals or groups for each document. Roles such as owner, editor, viewer, or commenter determine the level of access and actions allowed. Owners have full control over the document, editors can make changes, viewers can only view the document, and commenters can add comments. They can also specify whether others can view, comment, or edit the document. Additionally, document owners can revoke or modify permissions at any time.

The use of ReBAC and the permission system in Google Docs provides a flexible and granular approach to access control. It allows users to collaborate effectively while maintaining control over their documents and ensuring data security.

Implementation with Permify

The very first step to building an Authorization model with Permify is defining and creating entities using Permify Schema.

Defining Entities & Relations between them

If we carefully analyze and look into the permission system (especially the sharing settings) of the Google Docs platform, we would realize that the following four (4) entities are involved:

  1. Document entity represents the file or digital content being created, stored, and shared. It has a relation to represent the organization the document belongs to, the viewer of the document, and the manager of the document.

  2. User entity represents a user in the system.

  3. Group entity represents a group of users who can be granted permission to access a document. It has relations including manager and direct member to represent managers and members of a group respectively.

  4. Organization entity represents an organization that can contain groups, users, and documents. It has relations to represent group, document, administrator, and direct member.

These relationships allow for efficient management of access control within the authorization model, ensuring that users, groups, organizations, and documents are appropriately connected for effective collaboration and secure document sharing.

Now that we have described our entities and the relations they have with words, let’s create the corresponding model for it using the Permify schema.

// Represents a user
entity user {}

// Represents an Organization
entity organization {
    // Relation to represent the groups within the organization
    relation group @group

    // Relation to represent the administrator of the organization
    relation administrator @user @group#direct_member @group#manager

    // Relation to represent the direct members of the organization
    relation direct_member @user
}

// Represents a group of users
entity group {
    // Relation to represent the managers of the group
    relation manager @user @group#direct_member @group#manager

    // Relation to represent the direct members of the group
    relation direct_member @user @group#direct_member @group#manager
}

// Definition of the document entity
entity document {
    // Relation to represent the organization the document belongs to
    relation org @organization

    // Relation to represent the viewers of  the document
    relation viewer  @user  @group#direct_member @group#manager

    // Relation to represent the manager of the document
    relation manager @user @group#direct_member @group#manager
}
Enter fullscreen mode Exit fullscreen mode

Defining Permissions

We have several actions attached to the entities, which are limited by certain permissions. Let’s form permission for viewing a document.

To view document X, a user can either be a viewer/manager of that document or the user should have an admin role in the organization document X belongs to.

Permify Schema language supports and, or, and not operators to achieve permission union, intersection and exclusion. The keywords action or permission can be used with those operators to form rules for your authorization logic.

So if we specify the view document action as view, then the action can be included in the schema definition by adding this: action view = viewer or manager or org.admin

Also, let’s form permission for editing a document.

A user will be granted access to edit a document X if the user meets any of these criteria:

  1. Is the manager of the document
  2. Is the administrator of the organization the document belongs to

Now, let’s translate the above criteria to an authorization logic in the Permify schema. We can use the or operator to enforce the ‘any’ rule. To this end, if we specify the edit document action as edit, then the action can be included in the schema definition by adding this: action edit = manager or org.admin.

Based on the two actions added, the document definition can be updated as follows:

entity document {
    relation org @organization

    relation viewer  @user  @group#direct_member @group#manager
    relation manager @user @group#direct_member @group#manager

    action edit = manager or org.admin
    action view = viewer or manager or org.admin
}
Enter fullscreen mode Exit fullscreen mode

Complete Schema

To maintain simplicity in this post, I will not delve into a detailed breakdown of each individual permission. Instead, let us proceed by incorporating the remaining permissions and finalizing our schema.

entity user {}

entity organization {
    relation group @group

    relation administrator @user @group#direct_member @group#manager
    relation direct_member @user

    permission admin = administrator
    permission member = direct_member or administrator or group.member
}

entity group {
    relation manager @user @group#direct_member @group#manager
    relation direct_member @user @group#direct_member @group#manager

    permission member = direct_member or manager
}

entity document {
    relation org @organization

    relation viewer  @user  @group#direct_member @group#manager
    relation manager @user @group#direct_member @group#manager

    action edit = manager or org.admin
    action view = viewer or manager or org.admin
}
Enter fullscreen mode Exit fullscreen mode

Creating Sample Authorization Data

In order to thoroughly test the authorization model we have developed thus far, it is essential to have relevant data that accurately represent the relationships between entities, objects, and users. This data serves as the foundation for constructing a comprehensive collection of access control lists (ACLs), enabling us to assess the efficacy and reliability of the authorization system.

In Permify, we use a specific form to represent object-to-object and object-to-subject relations. It’s called relational tuples.

The simplest form of a relational tuple is structured as entity # relation @ subject. Each relational tuple represents an action that a specific user or user set can do on a resource and takes the form of user U has relation R to object O, where user U could be a simple user or a user set such as group X members.

Here are some relational tuples according to our Google Docs example,

// Assign users to different groups
group:tech#manager@user:ashley
group:tech#direct_member@user:david
group:marketing#manager@user:john
group:marketing#direct_member@user:jenny
group:hr#manager@user:josh
group:hr#direct_member@user:joe

// Assign groups to other groups
group:tech#direct_member@group:marketing#direct_member
group:tech#direct_member@group:hr#direct_member

// Connect groups to organization
organization:acme#group@group:tech
organization:acme#group@group:marketing
organization:acme#group@group:hr

// Add some documents under the organization
organization:acme#document@document:product_database
organization:acme#document@document:marketing_materials
organization:acme#document@document:hr_documents

// Assign a user and members of a group as administrators for the organization
organization:acme#administrator@group:tech#manager
organization:acme#administrator@user:jenny

// Set the permissions on some documents
document:product_database#manager@group:tech#manager
document:product_database#viewer@group:tech#direct_member
document:marketing_materials#viewer@group:marketing#direct_member
document:hr_documents#manager@group:hr#manager
document:hr_documents#viewer@group:hr#direct_member
Enter fullscreen mode Exit fullscreen mode

Note: The relational tuples created will be used to test and validate our authorization model and logic in the next section

Test & Validation

Finally, let's test our authorization logic to ensure we have modeled the schema and permission system correctly.

Can User:jenny view document:hr_documents?

According to what we have defined for the view action, only viewers, managers, and admins of the organization to which the document belongs can view the hr_documents. In this case, the Permify engine will check if the subject - user:jenny has any viewer relation within document:hr_documents. Since user:jenny has no viewer relation to document:hr_documents, the first check will result in a false. And because the or operator is used, the permify engine will then check if user:jenny has a manager relation to document:hr_documents.

Jenny doesn't have any manager relation to document:hr_documents and neither is she an admin in the acme organization the hr_documents belongs to. As a result, the Permify engine having ‘ORed’ the false returned from each check will finally return false. Therefore, the user:jenny view document:hr_documents check request should yield a false response.

Let’s try another one!

Can User:jenny edit document:marketing_materials?

According to what we have defined for the edit action only managers and admins of the organization to which the document belongs, can edit marketing_materials. In this context, the Permify engine will check if the subject - user:jenny has any direct or indirect manager relation within document:marketing_materials. Consecutively it will check does user:jenny has admin relation in the Acme Org - organization:acme#document@document:marketing_materials.

Jenny has an administrator relation to the Acme Org (organization:acme#administrator@user:jenny) and we have defined that admin of organization the document belongs to can edit the document:marketing_materials. Therefore, the user:jenny edit document:marketing_materials check request should yield a true response.

Let's test these two access checks on our local using the Permify validator. We'll use the below schema for the validation YAML file.

schema: >-
    entity user {}

    entity organization {
        relation group @group

        relation administrator @user @group#direct_member @group#manager
        relation direct_member @user

        permission admin = administrator
        permission member = direct_member or administrator or group.member
    }

    entity group {
        relation manager @user @group#direct_member @group#manager
        relation direct_member @user @group#direct_member @group#manager

        permission member = direct_member or manager
    }

    entity document {
        relation org @organization

        relation viewer  @user  @group#direct_member @group#manager
        relation manager @user @group#direct_member @group#manager

        action edit = manager or org.admin
        action view = viewer or manager or org.admin
    }

relationships:
  - group:tech#manager@user:ashley
  - group:tech#direct_member@user:david
  - group:marketing#manager@user:john
  - group:marketing#direct_member@user:jenny
  - group:hr#manager@user:josh
  - group:hr#direct_member@user:joe

  - group:tech#direct_member@group:marketing#direct_member
  - group:tech#direct_member@group:hr#direct_member

  - organization:acme#group@group:tech
  - organization:acme#group@group:marketing
  - organization:acme#group@group:hr
  - organization:acme#administrator@group:tech#manager
  - organization:acme#administrator@user:jenny

  - document:marketing_materials#org@organization:acme

  - document:product_database#manager@group:tech#manager
  - document:product_database#viewer@group:tech#direct_member
  - document:marketing_materials#viewer@group:marketing#direct_member
  - document:hr_documents#manager@group:hr#manager
  - document:hr_documents#viewer@group:hr#direct_member


scenarios:
  - name: "scenario 1"
    description: "test description"
    checks:
      - entity: "document:hr_documents"
        subject: "user:jenny"
        assertions:
          view: false
      - entity: "document:marketing_materials"
        subject: "user:jenny"
        assertions:
          edit: true
Enter fullscreen mode Exit fullscreen mode

To use the Permify Validate function, follow the steps below.

First, Permify needs to be installed on your system. You can accomplish this using the Brew package manager. After Brew is installed, input the following command in your terminal to install Permify:

brew install permify
Enter fullscreen mode Exit fullscreen mode

Upon successfully installing Permify, create a new YAML file in your local directory. This YAML file will contain the schema, relationships and assertions against which your data will be validated.

touch your-schema-file.yaml
Enter fullscreen mode Exit fullscreen mode

Then, open the file with your preferred text editor to paste the schema, relationships and assertions.

Now that Permify is installed and your schema is ready, it's time to run the Validate function. Execute the appropriate command in your terminal, directing it to your schema file.

permify validate your-schema-file.yaml
Enter fullscreen mode Exit fullscreen mode

Result:

Image description

Conclusion

We have reached the end of our demonstration and implementation of the authorization model for Google Docs using Permify. You can find this example on our playground to explore it in your browser.

If you are interested in delving deeper into our solution or believe it could be valuable for your organization, we encourage you to join our community on Discord. We are excited to engage in discussions and exchange insights with you.

Top comments (0)