Announcing PhotonIQ: The New AI CDN For Accelerating Apps, APIs, Websites and Services
Tutorial

Four Ways To Establish User Access Control With Macrometa

Post Image

While companies today want to collaborate throughout their organization and work closely with business partners, they might need to limit access to documents in a collection to meet security, privacy, and quality control requirements. Access control is a fundamental component to help protect confidential information and minimize risk to your business or organization. In this blog, we go over the details of the User Access Control feature and how to set up who can view or modify data at the document-level and collection-level.

There are multiple ways admins can apply User Access Control attributes to their Macrometa Global Data Network (GDN) user accounts and API keys. These attributes can ‌limit access to documents at run time in Query Workers by applying the four following options.

Use document-level access control to:

  • Manage who can view documents.
  • Determine who can modify documents.

Use collection-level access control to:

  • Manage who has access to collections.
  • Govern access by both users and API keys.

Document-level and collection-level access control with attributes

Let's use an example to illustrate how you can use attributes to implement document-level access control and collection-level access control. We have a fulfillment company that is made up of partners and employees. Partners have items they want the fulfillment company to fill, and the employees fulfill the orders of their partner's items.

Image

For these examples, we have three collections:

  • Items: The items that the partners want the fulfillment company to ship.
  • Orders: The orders that the fulfillment company has to fill.
  • Employees: List of all the fulfillment employees.

And the fulfillment company wants to provide some queries that their partners and employees can use:

  • Partners can only see their items, but can't update them.
  • Partners can see their orders and update orders when filled.
  • Partners can’t see employees.
  • Store employees can see all items and orders, but can’t update them.

Every partner has a unique API key. This key is used to authenticate them and restrict access to their information. Employees use their credentials for authentication and access control.

Let's add some data to the collections:

Partner #1: ACME Company -- API Key: acme_key.897b6e...

Partner #2: General Hardware Store - API Key: generalhw.28bc97…

Each API Key is being assigned a partner attribute:

acme_key.897b6e...: attribute: partner{acme}
generalhw.28bc97...: attribute: partner{generalhw}

We have three employees, one is an admin.

Joe: attribute: employee("staff")
Jane: attribute: employee{"admin"}
Bob: attribute: employee("staff")

We have the employees collection:

{
   { "name": "Joe" },
   { "name": "Jane" },
   { "name": "Bob" },
}

We have several hardware items in our items collection:

{
   { "item": "hammer", "price": 5.99, "count": 55, "partner": "acme" },
   { "item": "screw driver", "price": 3.99, "count": 15, "partner": "acme" },
   { "item": "pliers", "price": 4.95, "count": 28, "partner": "generalhw" },
   { "item": "drill", "price": 42.90, "count": 5, "partner": "generalhw" }
}

And finally, we have two orders in our orders collection:

{
   { "customer": 1, "item": "hammer", "ordered": 2, "partner": "acme" },
   { "customer": 2, "item": "drill", "ordered": 1, "partner": "generalhw" }
}

Query Worker examples

In this section, we are creating four Query Workers to implement the queries mentioned above.

Partners can only see their items, but can't update them

Query Name: PartnerItems

FOR doc IN items
  FILTER doc.partner == CURRENT_APIKEY_ATTRIBUTE("partner")
  RETURN doc

When we execute this Query Worker, we only see items for this partner:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/PartnerItems>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: apikey acme_key.897b6e...' \\
  -d '{ "bindVars": {}}'

Query Result:

{
   { "item": "hammer", "price": 5.99, "count": 55, "partner": "acme" },
   { "item": "screw driver", "price": 3.99, "count": 15, "partner": "acme" },
}

This shows how document-level access control is used to control who can view documents.

Partners can see their orders and update orders when filled

Query Name: PartnerOrders

FOR doc IN orders
  FILTER doc.partner == CURRENT_APIKEY_ATTRIBUTE("partner")
  RETURN doc

Query Name: PartnerOrdersUpdate

FOR doc IN orders
  FILTER doc.partner == CURRENT_APIKEY_ATTRIBUTE("partner") AND
         doc.customer == @customer
  UPDATE doc WITH {"ordered": doc.ordered + 1} IN orders
  RETURN NEW

Executing the PartnerOrders query only returns the orders for that partner:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/PartnerOrders>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: apikey acme_key.897b6e...' \\
  -d '{ "bindVars": {}}'

Query Result:

{
   { "customer": 1, "item": "hammer", "ordered": 2, "partner": "acme" }
}

And updating an ACME order:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/PartnerOrders>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: apikey acme_key.897b6e...' \\
  -d '{ "bindVars": { "customer": 1}}'

Query Result:

{
   { "customer": 1, "item": "hammer", "ordered": 2, "partner": "acme" },
}

Now updating another partner order (Customer 2):

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/PartnerOrders>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: apikey acme_key.897b6e...' \\
  -d '{ "bindVars": { "customer": 2}}'

Query Result:

{
   {}
}

This does not update any orders and shows how document-level access control can ‌control who can change documents.

Partners can not see employees

Query Name: Employees

FOR doc IN employees
  FILTER CURRENT_APIKEY_ATTRIBUTE("partner") == null
  RETURN doc

Query Result:

{
   {}
}

And here partners cannot view employee data. This shows how collection-level access control can ‌control who has access to collections.

Store employees can see all items and orders, but cannot update them

We are enhancing our previous PartnerOrders and PartnerOrdersUpdate Query Worker to accommodate employees. We want all valid partners and employees to ‌view orders and all valid partners and employees who are admins to update orders.

Query Name: ViewOrders

OR doc IN orders
  FILTER doc.partner == CURRENT_APIKEY_ATTRIBUTE("partner") OR 
         CURRENT_USER_ATTRIBUTE("employee") == "admin" OR
         CURRENT_USER_ATTRIBUTE("employee") == "staff"
  RETURN doc

Query Name: OrdersUpdate

FOR doc IN orders
  FILTER doc.customer == @customer AND
         doc.partner == CURRENT_APIKEY_ATTRIBUTE("partner") OR
         CURRENT_USER_ATTRIBUTE("employee") == "admin"
  UPDATE doc WITH {"ordered": doc.ordered + 1} IN orders
 RETURN NEW

Executing the ViewOrders query by a partner returns the orders for that partner:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/ViewOrders>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: apikey acme_key.897b6e...' \\
  -d '{ "bindVars": {}}'

Query Result:

{
   { "customer": 1, "item": "hammer", "ordered": 2, "partner": "acme" }
}

And executing the ViewOrders by an employee returns all orders:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/ViewOrders>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cC...' \\
  -d '{ "bindVars": {}}'

Query Result:

{
   { "customer": 1, "item": "hammer", "ordered": 2, "partner": "acme" },
   { "customer": 2, "item": "drill", "ordered": 1, "partner": "generalhw" }
}

A valid partner can update an ACME order:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/OrdersUpdate>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: apikey acme_key.897b6e...' \\
  -d '{ "bindVars": { "customer": 1}}'

Updates the order:

{
   { "customer": 1, "item": "hammer", "ordered": 3, "partner": "acme" }
}

An employee admin can also update an ACME order:

curl -X 'POST' \\
  '<https://fulfillment.eng.macrometa.io/_fabric/_system/_api/restql/execute/OrdersUpdate>' \\
  -H 'accept: application/json' \\
  -H 'Content-Type: application/json' \\
  -H 'Authorization: bearer eyJhbGciOiJIUzI1NiIsInR5cC...' \\
  -d '{ "bindVars": { "customer": 1}}'

Updates the order:

{
   { "customer": 1, "item": "hammer", "ordered": 4, "partner": "acme" }
}

This shows how document-level access control can be controlled by API key attributes and user attributes at the same time.

Next steps

User and API attributes are powerful tools to help with access control decisions on queries. Whether you are trying to limit documents or collections – or limit the viewing or modification of data – user and API attributes can address your requirements. After viewing these examples, you can quickly get started and apply attributes within your own GDN — based on your access control requirements. If you are new to Macrometa and would like to try out User Access Control or other features, request a trial and see everything you can do in one platform.

Photo by Phil on Unsplash

Join our newsletter and get the latest posts to your inbox
Form loading...





Featured Posts

Related Posts

Recent Posts

Platform

PhotonIQ
Join the Newsletter