Four Ways To Establish User Access Control With Macrometa
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.
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.