Oso + PlanetScale
Published: 2024-02-23 13:29:59

---
title: Oso + PlanetScale
published: true
date: 2023-08-14 00:00:00 UTC
tags: 
canonical_url: https://lukicdejan.com/oso-planetscale/
---

_Originally written for Oso._

PlanetScale is a database platform designed to facilitate the management and scaling of distributed databases.

With a focus on simplicity and efficiency, PlanetScale aims to streamline the challenges of handling databases that span multiple regions.

By offering tools and features that prioritize data integrity and availability, PlanetScale provides developers with a practical solution for building and maintaining databases that can seamlessly operate in various geographic locations

PlanetScale does not inherently provide support for Role-Based Access Control (RBAC) or Attribute-Based Access Control (ABAC) as part of its default functionality.

RBAC establishes a framework for overseeing and implementing user permissions, contingent on the roles they hold within an organization. RBAC guarantees that users are restricted from accessing resources and executing actions pertinent to their designated roles.

ABAC operates comparably, enforcing user permissions by considering attributes such as user traits, properties of resources, and contextual circumstances. This approach permits a higher degree of precision when regulating access.

To implement RBAC or ABAC with PlanetScale in this guide, you will use Oso - a batteries-included authorization-as-a-service (AaaS) provider.

## Prerequisites

- Node.js installed
- An initialized PlanetScale project with a created database
- An [Oso account](https://www.osohq.com)

## Setting Up the Node.js Project

You will use Prisma - an Object Relational Mapping (ORM) library for this project.

Head over to your terminal and install the necessary dependencies:

```
npm i --save-dev prisma

```

This will install the Prisma CLI, necessary for pushing changes from schema to the database.

You will also need clients for Prisma and Oso.

```
npm i @prisma/client oso-cloud

```

Follow by initializing a Prisma project:

```
npx prisma init

```

Create a new file `index.js` which will serve as the main file in the project.

Continue by importing the dependencies:

```
import { PrismaClient } from '@prisma/client';
import { Oso } from 'oso-cloud';

```

Next, add Oso’s API key:

```
const osoApiKey = process.env.OSO\_API\_KEY || '';

```

> Note: These should be read from the environment variables. For that instance use the `dotenv` package.

## Setting Up Oso Rules

Next, you'll establish Oso Rules that will define which roles have permission to perform specific actions on arbitrary resources.

Access the [Oso Rules Editor](https://ui.osohq.com/rules-editor/) in the Workbench mode - a more visually pleasing way of implementing auhtorization.

![Oso Rules Editor](https://i.ibb.co/6t0jqNR/Untitled.png)

In the top section, it should say `Add a resource`. Next to the dropdown, enter the Resource name `Star`. Press the `+` button on the right side to create a new resource.

![Added resource in Oso Rules Editor](https://i.ibb.co/CzGHXFp/Untitled-1.png)

Resource `Star` will now be populated with the default roles and permissions. Since we will dynamically provide Oso with actions performed by an actor, they should match action names from Prisma.

For example, [CRUD operations in Prisma can be used](https://www.prisma.io/docs/concepts/components/prisma-client/crud).

Next, change the `view` permission to `findMany` and `edit` to `create`.

- `view` → `findMany`
- `edit` → `create`

![Permission showcase in Oso Rules Editor](https://i.ibb.co/89T5b3P/Untitled-2.png)

You can also create tests, automatically, by pressing `Create Test`. This will create a few edge-cases for you to visually see if the tests have passed.

![Test automation in Oso Dashboard](https://i.ibb.co/rZVPpW8/Untitled-3.png)

All of this resulted in the following Polar policy.

> Polar is a declarative policy language used for defining authorization rules in applications.

```
actor User {}

resource Star {
  roles = ["viewer", "owner"];
  permissions = ["findMany", "create"];

  "findMany" if "viewer";
  "create" if "owner";
  "viewer" if "owner";
}

test "Star roles and permissions" {
  setup {
    has_role(User{"alice"}, "viewer", Star{"example"});
    has_role(User{"bob"}, "owner", Star{"example"});
  }
  assert allow(User{"alice"}, "findMany", Star{"example"});
  assert allow(User{"bob"}, "findMany", Star{"example"});
  assert_not allow(User{"alice"}, "create", Star{"example"});
  assert allow(User{"bob"}, "create", Star{"example"});
}

```

## Integrating Oso in Prisma

You will now create a custom [Prisma Client query](https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries), that will be preformed prior to the original query, allowing for fine-grained authorization control.

### Setting Up Prisma Schema

In the `schema.prisma` file, located in the `prisma` folder, replace the code with the following snippet, allowing for MySQL usage.

```
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "mysql"
url= env("DATABASE\_URL")
}

```

Create an `.env` file, which will contain the `DATABASE_URL` from PlanetScale. Learn [how to connect a PlanetScale database](https://planetscale.com/docs/tutorials/connect-any-application).

> Make sure to append `&&sslaccept=strict` at the end of your database URL in the `.env` file.

Next, create a new model `Star` , containing basic attributes for testing.

```
model Star {
idInt@id @default(autoincrement())
createdAtDateTime @default(now())
updatedAtDateTime @updatedAt
nameString@db.VarChar(255)
constellation String@db.VarChar(255)
}

```

Complete it off by pushing the changes to the database with the following command:

```
npx prisma db push

```

### Extending a Prisma Query

Back in the Node.js project, let’s create an [extension](https://www.prisma.io/docs/concepts/components/prisma-client/client-extensions/query) of a [`findMany` query](https://www.prisma.io/docs/reference/api-reference/prisma-client-reference#findmany) which returns a list of records for a given model.

```
const xprisma = prisma.$extends({
    query: {
    	star: {
    		async findMany({ model, operation, args, query }) {
    			if (await oso.authorize(USER, operation, model)) return query(args);
        return new Error('Not authorized');
    		},
    	},
    },
});

```

> Replace `USER` with actual data.

The method will execute the `findMany` query on the `star` model (typings were automatically generated by Prisma in the previous steps), while performing an authorization check with Oso Cloud.

Method will return an object, containing arguments like model we’re querying and the operation we’re performing.

In this case, the arguments in the `oso.authorize()` method will be populated with the following data `(USER, "findMany", "Star")`.

If the action is authorized, the query will be executed and the results returned.

### Test the Integration

To test the integration of Oso and PlanetScale, we will first populate the table with some data.

```
await prisma.star.create({
data: {
name: 'Sirius',
constellation: 'Canis Major',
},
});

```

Then, we can call the `findMany` query from `xprisma` with the following method:

```
const stars = await xprisma.star.findMany();
console.log(stars);

```

If authorized, this should output the following:

![Positive query output](https://i.ibb.co/ZVcdk1x/Untitled-4.png)

And if not, an error will be thrown:

![Query error](https://i.ibb.co/Wg1SvjZ/Untitled-5.png)

## Next Steps and Resources

In this guide you learned how to integrate Oso and PlanetScale by using Prisma, a powerful ORM tool.

With Oso's adaptable policy language and PlanetScale's strong distributed database system, you can easily enforce strict access control and authorization rules while smoothly handling your data.

A good place to learn Oso from head to toe is the extensive [documentation](https://www.osohq.com/docs), [blog](https://www.osohq.com/developers/blog) containing tutorials, thought pieces and updates, or perhaps [Oso Academy](https://www.osohq.com/academy) - a series of technical guides for understanding and applying authorization.