What is Tankman?
Tankman is a service which offers a REST API to do the following:
- Manage organizations, roles, users, resources and permissions
- Assign roles to users
- Assign user permissions and role permissions to various resources
- Attach custom properties to Orgs, Roles, Users and query them
It's important to note that Tankman does not function as an Identity and Authentication server. However, it can work well with popular open-source identity solutions such as Ory Kratos, various OAuth-based providers, or even your own custom authentication mechanism.
Tankman is available on GitHub under the MIT license. You can download it as a binary for your platform; and it utilizes PostgreSQL as its underlying database.
📢 📢 📢 Better formatted documentation can be found on the Tankman Website - tankman.dev.
Install Tankman
Download binaries for your platform
- For most Linux distros Linux x86-64
- For Linux distros using musl Linux x86-64
- For ARM 64 bit Linux distros Linux ARM64
- macOS M1
- macOS x64
- Windows x86-64 (untested)
Configuring Tankman
Step 1: Create a new database for tankman on your PostgreSQL server. Call it whatever you want, but most people call it tankmandb.
Step 2: Initialize the database. You can do that with the following command:
./tankman --initdb --dbhost YOUR_PG_HOST --dbport YOUR_PG_PORT --dbuser YOUR_PG_USER --dbpass YOUR_PG_PASSWORD
That's it. You're ready to roll.
Running Tankman
The following command will start tankman on localhost:1989
./tankman --dbhost YOUR_PG_HOST --dbport YOUR_PG_PORT --dbuser YOUR_PG_USER --dbpass YOUR_PG_PASSWORD
You can change the hostname and port with the --host
and --port
CLI options.
./tankman --host 127.0.0.1 --port 1990 --dbhost YOUR_PG_HOST --dbport YOUR_PG_PORT --dbuser YOUR_PG_USER --dbpass YOUR_PG_PASSWORD
Configuring via Environment Variables
Instead of using CLI options as given above, you may use $TANKMAN_HOST (instead of --host
), $TANKMAN_PORT (instead of --port
) and $TANKMAN_CONN_STR (instead of --dbhost
, --dbport
, --dbuser
, --dbpass
) environment variables.
Like this:
TANKMAN_HOST=localhost
TANKMAN_PORT=1990
TANKMAN_CONN_STR=Server=localhost;Port=5432;Database=tankmandb;User Id=postgres;Password=postgres
# run tankman!
./tankman
⚠️ Caution
Tankman is an internal service which should be accessible only from your backend apps. Make sure that you don't expose Tankman ports publicly.
Organizations
Organizations are at the root of the entity hierarchy, and should be the first thing you should create. You may create as many orgs are you need.
Create an Organization
HTTP POST /orgs
Payload:
{
"id": "example.com",
"data": "data for example.com"
}
Response:
{
"data": {
"id": "example.com",
"createdAt": "2023-07-02T01:32:18.4557911Z",
"data": "data for example.com",
"properties": {}
}
}
Get Organizations
HTTP GET /orgs
Response:
{
"data": [
{
"id": "example.com",
"createdAt": "2023-07-02T01:38:18.764642Z",
"data": "data for example.com",
"properties": {}
},
{
"id": "agilehead.com",
"createdAt": "2023-07-01T01:38:18.764642Z",
"data": "some other data",
"properties": {}
}
]
}
Pagination is done with the from
and limit
query parameters.
HTTP GET /orgs?from=10&limit=100
To get a single organization (as a list with one item), specify the Org's id.
HTTP GET /orgs/{orgId}
# For example
HTTP GET /orgs/example.com
You can specify multiple Org ids.
HTTP GET /orgs/{orgId1,orgId2}
# For example
HTTP GET /orgs/example.com,northwind
Update an Organization
HTTP PUT /orgs/{orgId}
# For example:
HTTP PUT /orgs/example.com
Payload:
{
"data": "new data for example.com"
}
Response:
{
"data": {
"id": "example.com",
"createdAt": "2023-07-02T01:38:18.764642Z",
"data": "new data for example.com",
"properties": {}
}
}
Delete an Organization
Deleting an organization will delete everything associated with it - resources, roles, users, permissions etc. This is indeed a very destructive operation.
HTTP DELETE /orgs/{orgId}
# For example:
HTTP DELETE /orgs/example.com
Since it can cause a lot of damage, there's an CLI option to require a safetyKey for deleting organizations.
You need to start tankman like this:
./tankman --safety-key $SAFETY_KEY
# For example:
./tankman --safety-key NOFOOTGUN
With the --safety-key
option, HTTP DELETE should specify the safetyKey parameter as a query string.
HTTP DELETE /orgs/{orgId}?safetyKey=$SAFETY_KEY
# For example
HTTP DELETE /orgs/example.com?safetyKey=NOFOOTGUN
Add a Custom Property
You can add custom string properties to an Organization entity.
HTTP PUT /orgs/{orgId}/properties/{propertyName}
For example:
HTTP PUT /orgs/example.com/properties/country
Payload:
{
"value": "India"
}
Response:
{
"data": {
"name": "country",
"value": "India",
"hidden": false,
"createdAt": "2023-07-02T02:19:15.499711Z"
}
}
When properties are added to an Org, they are returned when the Org is fetched.
For example, GET /orgs/example.com
will retrieve the following response. Note the added properties object.
{
"data": [
{
"id": "example.com",
"createdAt": "2023-07-02T01:38:18.764642Z",
"data": "data for example.com",
"properties": {
"country": "India"
}
}
]
}
Get the value of a property
Properties are usually read as a part of the fetching entity; Org in this case. But if you need to get a list of properties without fetching the entity you can use the following API.
HTTP GET /orgs/{orgId}/properties/{propertyName}
# For example:
HTTP GET /orgs/example.com/properties/country
Response:
{
"data": [
{
"name": "country",
"value": "India",
"hidden": false,
"createdAt": "2023-07-02T02:19:15.499711Z"
}
]
}
Delete a Custom Property
HTTP DELETE /orgs/{orgId}/properties/{propertyName}
# For example:
HTTP DELETE /orgs/example.com/properties/country
Creating Hidden Properties
When a property is hidden, it will not be included when the organization is fetched. To create a hidden property, add the hidden flag when creating the property.
To create a Hidden Property:
HTTP PUT /orgs/{orgId}/properties/{propertyName}
# For example:
HTTP PUT /orgs/example.com/properties/revenue
Payload should include the hidden
attribute:
{
"value": "2340000",
"hidden": true
}
To include a hidden property when querying Orgs, it should be explicitly mentioned. Note that properties which aren't hidden are always included.
HTTP GET /orgs?properties={propertyName}
For example:
HTTP GET /orgs?properties={revenue}
Response:
{
"data": [
{
"id": "example.com",
"createdAt": "2023-07-02T01:38:18.764642Z",
"data": "new data for example.com",
"properties": {
"country": "India",
"revenue": "2340000"
}
}
]
}
Filtering by Property
Organizations may be filtered by the custom property.
HTTP GET /orgs?properties.{propertyName}={propertyValue}
# For example, fetch orgs with country = India
HTTP GET /orgs?properties.country=India
Roles
Roles belong to an Organization. Users can be assigned Roles. Roles can have Permissions to various Resources.
Create a Role
HTTP POST /orgs/{orgId}/roles
# For example:
HTTP POST /orgs/example.com/roles
Payload:
{
"id": "admins",
"data": "data for admins"
}
Response:
{
"data": {
"id": "admins",
"data": "data for admins",
"createdAt": "2023-07-02T08:31:59.7931788Z",
"orgId": "example.com",
"properties": {}
}
}
Get Roles
HTTP GET /orgs/{orgId}/roles/
For example:
HTTP GET /orgs/example.com/roles/
Response:
{
"data": [
{
"id": "admins",
"data": "data for admins",
"createdAt": "2023-06-30T17:01:13.525215Z",
"orgId": "agilehead.com",
"properties": {
"prop1": "value1"
}
},
{
"id": "devs",
"data": "data for devs",
"createdAt": "2023-07-01T11:56:04.039094Z",
"orgId": "agilehead.com",
"properties": {}
}
]
}
To get a single role (as a list with one item), specify the Role's id.
HTTP GET /orgs/{orgId}/roles/{roleId}
# For example
HTTP GET /orgs/example.com/roles/admins
You can specify multiple Role ids.
HTTP GET /orgs/{orgId}/roles/{roleId}
# For example
HTTP GET /orgs/example.com/roles/admins,devops
Update a Role
HTTP PUT /orgs/{orgId}/roles/{roleId}
# For example:
HTTP PUT /orgs/example.com/roles/admins
Payload:
{
"data": "new data for admins"
}
Response:
{
"data": {
"id": "admins",
"data": "new data for admins",
"createdAt": "2023-07-02T08:31:59.793178Z",
"orgId": "example.com",
"properties": {}
}
}
Delete a Role
Deleting a role will also delete associated permissions.
HTTP DELETE /orgs/{orgId}/roles/{roleId}
# For example:
HTTP DELETE /orgs/example.com/roles/admins
Add a Custom Property
You can add custom string properties to an Role entity.
HTTP PUT: /orgs/{orgId}/roles/{roleId}/properties/{propertyName}
For example:
HTTP PUT: /orgs/example.com/roles/admins/properties/privileged
Payload:
{
"value": "yes"
}
Response:
{
"data": {
"name": "country",
"value": "India",
"hidden": false,
"createdAt": "2023-07-02T02:19:15.499711Z"
}
}
When properties are added to an Role, they are returned when the Role is fetched.
For example, GET /orgs/example.com/roles/admins
will retrieve the following response. Note the added properties object.
{
"data": [
{
"id": "example.com",
"createdAt": "2023-07-02T01:38:18.764642Z",
"data": "data for admins",
"properties": {
"privileged": "yes"
}
}
]
}
Get the value of a property
Properties are usually read as a part of the fetching entity; Role in this case. But if you need to get a list of properties without fetching the entity you can use the following API.
HTTP GET /orgs/{orgId}/roles/{roleId}/properties/{propertyName}
# For example:
HTTP GET /orgs/example.com/properties/roles/roles/admins/privileged
Response:
{
"data": [
{
"roleId": "admins",
"orgId": "example.com",
"name": "privileged",
"value": "yes",
"hidden": false,
"createdAt": "2023-07-02T12:31:01.978925Z"
}
]
}
Delete a Custom Property
HTTP DELETE: /orgs/{orgId}/roles/{roleId}/properties/{propertyName}
# For example:
HTTP DELETE: /orgs/example.com/roles/admins/properties/privileged
Creating Hidden Properties
When a property is hidden, it will not be included when the Role is fetched. To create a hidden property, add the hidden flag when creating the property.
To create a Hidden Property:
HTTP PUT: /orgs/{orgId}/roles/{roleId}/properties/{propertyName}
# For example:
HTTP PUT: /orgs/example.com/roles/admins/properties/active
Payload should include the hidden
attribute:
{
"active": "yes",
"hidden": true
}
To include a hidden property when querying Roles, it should be explicitly mentioned. Note that properties which aren't hidden are always included.
HTTP GET /orgs/{orgId}/roles?properties={propertyName}
For example:
HTTP GET /orgs/example.com/roles?properties=active
Response:
{
"data": [
{
"id": "admins",
"data": "data for admins",
"createdAt": "2023-07-02T12:30:55.981226Z",
"orgId": "example.com",
"properties": {
"active": "yes",
"privileged": "yes"
}
}
]
}
Filtering by Property
Roles may be filtered by the custom property.
HTTP GET /orgs/{orgId}/roles?properties.{propertyName}={propertyValue}
# For example, fetch roles with active = yes
HTTP GET /orgs/example.com/roles?properties.active=yes
Finds users in a Role
See a list of users who have a specific Role.
HTTP GET /orgs/{orgId}/roles/{roleId}/users
# For example, fetch roles with active = yes
HTTP GET /orgs/example.com/roles/admins/users
Users
Users belong to an organization. Users may belong to Roles, and can have Permissions to various Resources.
Create a User
HTTP POST /orgs/{orgId}/users
# For example:
HTTP POST /orgs/example.com/users
Payload:
{
"id": "user3",
"identityProviderUserId": "jeswinpk@agilehead.com",
"identityProvider": "Google",
"data": "data for aser3"
}
Response:
{
"data": {
"roleIds": [],
"properties": {},
"id": "user3",
"data": "data for aser3",
"identityProvider": "Google",
"identityProviderUserId": "jeswinpk@agilehead.com",
"createdAt": "2023-07-06T13:01:26.6594794Z",
"orgId": "example.com"
}
}
Get Users
HTTP GET /orgs/{orgId}/users/
For example:
HTTP GET /orgs/example.com/users/
Response:
{
"data": [
{
"roleIds": [],
"properties": {},
"id": "user3",
"data": "data for aser3",
"identityProvider": "Google",
"identityProviderUserId": "jeswinpk@agilehead.com",
"createdAt": "2023-07-06T13:01:26.659479Z",
"orgId": "example.com"
}
]
}
To get a single user (as a list with one item), specify the user's id.
HTTP GET /orgs/{orgId}/users/{userId}
# For example
HTTP GET /orgs/example.com/users/user3
You can specify multiple user ids.
HTTP GET /orgs/{orgId}/users/{userId}
# For example
HTTP GET /orgs/example.com/users/user3,user5
Update a user
HTTP PUT /orgs/{orgId}/users/{userId}
# For example:
HTTP PUT /orgs/example.com/users/user3
Payload:
{
"identityProviderUserId": "jeswinpk@agilehead.com",
"identityProvider": "Google",
"data": "new data for user3"
}
Response:
{
"data": {
"roleIds": [],
"properties": {},
"id": "user3",
"data": "new data for user3",
"identityProvider": "Google",
"identityProviderUserId": "jeswinpk@agilehead.com",
"createdAt": "2023-07-06T13:01:26.659479Z",
"orgId": "example.com"
}
}
Delete a user
Deleting a user will also delete associated user permissions.
HTTP DELETE /orgs/{orgId}/users/{userId}
# For example:
HTTP DELETE /orgs/example.com/users/user3
Assiging Roles
HTTP POST /orgs/{orgId}/users/{userId}/roles
# For example:
HTTP DELETE /orgs/example.com/users/user3/roles
Payload:
{
"roleId": "admins"
}
Response:
{
"data": {
"userId": "user3",
"roleId": "admins",
"createdAt": "2023-07-01T11:57:54.0264874Z",
"orgId": "agilehead.com"
}
}
Unassigning Roles
HTTP DELETE /orgs/{orgId}/users/{userId}/roles/{roleId}
# For example:
HTTP DELETE /orgs/example.com/users/user3/roles/admins
Finds users in a Role
See a list of users who have a specific Role.
HTTP GET /orgs/{orgId}/roles/{roleId}/users
# For example, fetch roles with active = yes
HTTP GET /orgs/example.com/roles/admins/users
Add a Custom Property
You can add custom string properties to an user entity.
HTTP PUT: /orgs/{orgId}/users/{userId}/properties/{propertyName}
For example:
HTTP PUT: /orgs/example.com/users/user3/properties/firstName
Payload:
{
"value": "Jeswin"
}
Response:
{
"data": {
"name": "firstName",
"value": "Jeswin",
"hidden": false,
"createdAt": "2023-07-06T13:07:41.8782012Z"
}
}
When properties are added to an user, they are returned when the user is fetched.
For example, GET /orgs/example.com/users/user3
will retrieve the following response. Note the added properties object.
{
"data": [
{
"roleIds": [],
"properties": {
"firstName": "Jeswin"
},
"id": "user3",
"data": "new data for user3",
"identityProvider": "Google",
"identityProviderUserId": "jeswinpk@agilehead.com",
"createdAt": "2023-07-06T13:01:26.659479Z",
"orgId": "example.com"
}
]
}
Get the value of a property
Properties are usually read as a part of the fetching entity; user in this case. But if you need to get a list of properties without fetching the entity you can use the following API.
HTTP GET /orgs/{orgId}/users/{userId}/properties/{propertyName}
# For example:
HTTP GET /orgs/example.com/properties/users/users/user3/firstName
Response:
{
"data": [
{
"userId": "user3",
"orgId": "example.com",
"name": "firstName",
"value": "Jeswin",
"hidden": false,
"createdAt": "2023-07-06T13:07:41.878201Z"
}
]
}
Delete a Custom Property
HTTP DELETE: /orgs/{orgId}/users/{userId}/properties/{propertyName}
# For example:
HTTP DELETE: /orgs/example.com/users/user3/properties/firstName
Creating Hidden Properties
When a property is hidden, it will not be included when the user is fetched. To create a hidden property, add the hidden flag when creating the property.
To create a Hidden Property:
HTTP PUT: /orgs/{orgId}/users/{userId}/properties/{propertyName}
# For example:
HTTP PUT: /orgs/example.com/users/user3/properties/active
Payload should include the hidden
attribute:
{
"active": "yes",
"hidden": true
}
To include a hidden property when querying users, it should be explicitly mentioned. Note that properties which aren't hidden are always included.
HTTP GET /orgs/{orgId}/users?properties={propertyName}
For example:
HTTP GET /orgs/example.com/users?properties=active
Response:
{
"data": [
{
"roleIds": [],
"properties": {
"active": "yes",
"firstName": "Jeswin"
},
"id": "user3",
"data": "new data for user3",
"identityProvider": "Google",
"identityProviderUserId": "jeswinpk@agilehead.com",
"createdAt": "2023-07-06T13:01:26.659479Z",
"orgId": "example.com"
}
]
}
Filtering by Property
users may be filtered by the custom property.
HTTP GET /orgs/{orgId}/users?properties.{propertyName}={propertyValue}
# For example, fetch users with active = yes
HTTP GET /orgs/example.com/users?properties.active=yes
Response:
{
"data": [
{
"roleIds": [],
"properties": {
"firstName": "Jeswin"
},
"id": "user3",
"data": "new data for user3",
"identityProvider": "Google",
"identityProviderUserId": "jeswinpk@agilehead.com",
"createdAt": "2023-07-06T13:01:26.659479Z",
"orgId": "example.com"
}
]
}
Resources
Resources belong to Organizations - and they're names of various entities in the Organization. We use Unix-like paths to represent entities in an organization.
Let's see some examples.
Here's how you'd store some file paths.
- /files/legal/abc.doc
- /files/marketing/another.html
But anything can be a path. For example, if you wanted to control access to a feature, you could define a path as follows and check a user's permissions to it.
- /features/sellbitcoin
- /features/bulkbuy
Create a Resource
HTTP POST /orgs/{orgId}/resources
For example:
HTTP POST /orgs/example.com/resources
Payload:
{
"id": "/root/drives/c/home",
"data": "data for /root/drives/c/home"
}
Response:
{
"data": {
"id": "/root/drives/c/home",
"data": "data for /root/drives/c/home",
"createdAt": "2023-07-06T13:40:03.4217161Z",
"orgId": "example.com"
}
}
Get Resources
HTTP GET /orgs/{orgId}/resources
For example:
HTTP GET /orgs/example.com/resources
Response:
{
"data": [
{
"id": "/root/drives/c/home",
"data": "data for /root/drives/c/home",
"createdAt": "2023-07-06T13:40:03.421716Z",
"orgId": "example.com"
}
]
}
Pagination is done with the from
and limit
query parameters.
HTTP GET /orgs/example.com/resources?from=10&limit=100
To get a single resource (as a list with one item), specific the Resource's path.
HTTP GET /orgs/{orgId}/resources/{resourcePath}
# For example
HTTP GET /orgs/example.com/resources/root/drives/c/home
Wildcard searches
A wildcard search allows you to search for all resources starting with a certain path. The wildcard character to use is a tilde(~).
HTTP GET /orgs/{orgId}/resources/{basePath}/~
# For example
HTTP GET /orgs/example.com/resources/root/drives/~
Assume you have the following resources:
- /orgs/example.com/resources/root/drives/c/home
- /orgs/example.com/resources/root/drives/d/home
The request HTTP GET /orgs/example.com/resources/root/drives/~
will fetch both since they start with /root/drives/
.
Update a Resource
HTTP PUT /orgs/{orgId}/resources/{resourcePath}
For example:
HTTP PUT /orgs/example.com/resources/root/drives/c/home
Payload:
{
"data": "new data for /root/drives/c/home"
}
Response:
{
"id": "/root/drives/c/home",
"data": "new data for /root/drives/c/home",
"createdAt": "2023-06-30T13:39:29.182724Z",
"orgId": "agilehead.com"
}
DELETE a Resource
HTTP DELETE /orgs/{orgId}/resources/{resourcePath}
For example:
HTTP DELETE /orgs/example.com/resources/root/drives/c/home
Permissions
Permissions are entities which determine whether a Role or a User has access to a Resource. Permissions also have an "action" property which specifies what the Role or User is allowed to do with the Resource.
Creating a Role Permission
HTTP POST /orgs/{orgId}/roles/{roleId}/permissions
For example:
HTTP POST /orgs/example.com/roles/admins/permissions
Payload:
{
"resourceId": "/root/drives/c/home",
"roleId": "admins",
"action": "write"
}
Response:
{
"roleId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-06-30T14:04:17.919562Z",
"orgId": "agilehead.com"
}
The example above specifies that the role "admins" can "write" to the resource "/root/drives/c/home". Note that the resource should already exist.
Creating a User Permission
HTTP POST /orgs/{orgId}/users/{userId}/permissions
For example:
HTTP POST /orgs/example.com/users/user3/permissions
Payload:
{
"resourceId": "/root/drives/c/home",
"userId": "user3",
"action": "read"
}
Response:
{
"userId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-06-30T14:04:17.919562Z",
"orgId": "agilehead.com"
}
The example above specifies that the user "user3" can "read" the resource "/root/drives/c/home".
Getting Effective Permissions for a User
Effective Permissions for a user is the combined list of all user permissions defined for the specifc user, and role permissions for the roles in which the user is a member.
For example, if the user "john" is a member of roles "admins" and "devops", effective permissions to a resource is the combined list of john's permissions to the specific resource, the role "admins" permissions to the resource, and the role "devops" permissions to the resource.
HTTP GET /orgs/{orgId}/users/{userId}/effective-permissions/{action}/{resourceId}
For example:
HTTP GET /orgs/example.com/users/user3/effective-permissions/write/root/drives/c/home
Response:
[
{
"roleId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-06-30T14:04:17.919562Z",
"orgId": "agilehead.com"
}
]
Wildcard actions
You can specify a wildcard (tilde "~", by default) to get all permissions irrespective of action.
For example, the following will fetch read and write actions:
HTTP GET /orgs/example.com/users/user3/effective-permissions/~/root/drives/c/home
Response:
[
{
"userId": "user3",
"resourceId": "/root/drives/c/home",
"action": "read",
"createdAt": "2023-06-30T14:04:01.837162Z",
"orgId": "agilehead.com"
},
{
"roleId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-06-30T14:04:17.919562Z",
"orgId": "agilehead.com"
}
]
Wildcard Resource Paths
You can specify a wildcard in the resource path as well.
For example, the following will return all resources starting with "/root/drives". Note that we've used a wild card action as well.
HTTP GET /orgs/example.com/users/user3/effective-permissions/~/root/drives/~
Getting just Role Permissions
You can get permissions for a role to a resource thus.
HTTP GET /orgs/{orgId}/roles/{roleId}/permissions
For example:
HTTP GET /orgs/example.com/roles/admins/permissions
Response:
{
"data": {
"roleId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-07-06T14:35:31.3918132Z",
"orgId": "example.com"
}
}
Getting just User Permissions
You can get permissions for a user to a resource thus.
HTTP GET /orgs/{orgId}/users/{userId}/permissions
For example:
HTTP GET /orgs/example.com/users/user3/permissions
Response:
{
"data": {
"userId": "user3",
"resourceId": "/root/drives/c/home",
"action": "read",
"createdAt": "2023-07-06T14:35:31.3918132Z",
"orgId": "example.com"
}
}
Deleting Role Permissions
You can delete permissions for a role to a resource thus.
HTTP DELETE /orgs/{orgId}/roles/{roleId}/permissions/{action}/{resourceId}
For example:
HTTP DELETE /orgs/example.com/roles/admins/permissions/read/root/drives/c/home
Response:
{
"data": {
"roleId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-07-06T14:35:31.3918132Z",
"orgId": "example.com"
}
}
Deleting User Permissions
You can delete permissions for a user to a resource thus.
HTTP DELETE /orgs/{orgId}/users/{userId}/permissions/{action}/{resourceId}
For example:
HTTP DELETE /orgs/example.com/users/admins/permissions/read/root/drives/c/home
Response:
{
"data": {
"userId": "admins",
"resourceId": "/root/drives/c/home",
"action": "write",
"createdAt": "2023-07-06T14:35:31.3918132Z",
"orgId": "example.com"
}
}
Help Wanted
- Test Suite. We need to build a full test suite. This is our highest priority item.
- Publish to Docker Hub
- Docker compose file with PostgreSQL
- Clean up the Documentation
- Document patterns to use for Authorization.