Creating User and Team Roles with the Compose API

Published

Do you want to assign roles to users and teams for your database deployment right from the terminal? We'll show you how using the powerful Compose API and some NodeJS.

In Creating Users and Teams with the Compose API, we showed you how to create, list, update and delete users and teams by building a NodeJS command-line tool using the Compose API. In this article, we'll add a couple more features to the command-line tool that will allow us to set roles for users and teams for each database deployment.

If you're eager and want to take a look at all the code from the previous article and this one together, you can peruse the apiUsersTeamsRoles.js file which is located in our Github repository.

A little about roles

Granting roles to users or teams lets the admin or account owner decide who has access to deployment-wide features. The roles that we're concerned with here are deployment-specific roles. If you're the account owner or an admin, there are three roles you can grant users and teams: admin, manager, and developer.

Depending on the role, users and teams are able to access parts of the database deployment. For example, the admin role has complete control over a deployment, including the manager and developer permissions, giving them the ability to deprovision it while also controlling access granted to other users and teams. The manager role grants users the ability to set the deployment controls like scaling and adding and removing portals, while the developer role has access to connection strings, logs, and other essentials. Our documentation describes the access controls for each role in more detail.

Listing deployment user roles

To list the deployment roles that have been assigned to users, you'll have to choose one of your database deployments then get its id. For this example, we'll use the deployment id for a Compose PostgreSQL database. As with all Compose databases, the deployment id is found at the bottom of the deployment's Settings view, which is accessed from the Settings button located on left-hand menu of your deployment's Overview page.

Selecting the PostgreSQL deployment id, we can fetch all the user roles associated with that deployment. To do that, we'll make an HTTP request to the GET /2016-07/deployments/:id/roles endpoint using the PostgreSQL deployment id.

let listUserRoles = (deploymentId) => {  
    fetch(`${apibase}/deployments/${deploymentId}/roles`, { headers: apiheaders })
    .then(res => {
        return res.json();
    })
    .then(json => {
        let roles = json["_embedded"].roles;
        for (let role of roles) {
            console.log(`${role.name} ${JSON.stringify(role.users)}`)
        }
    })
    .catch(err => {
        console.log(err);
    });
}

The format of this function is similar to the others we've been creating. The function takes the deployment id required by the API endpoint, and again we get back from the JSON response the _embedded element getting an array of roles for the deployment. Then we loop through those and print out each role with and an array of assigned users.

If you haven't assigned users roles, then what you'll get back will be something like the following with the account owner's name and id as the deployment's admin. The account owner is the default admin for all deployments.

admin [{"id":"7g89sc0dce45vt3000260045","name":"Abdullah Alger"}]  

To make this a little more interesting, let's assign more users and roles to this deployment.

Assigning deployment user roles

Assigning individual users a role for a deployment allows administrators to control what users can access. If you're the account owner or admin, you can assign any role to users who are members of your account. The endpoint that we used to list all the user roles on a deployment, is the same endpoint that we'll use to assign user roles. However, the function that we'll write will instead make an HTTP POST request to that endpoint /2016-07/deployments/:id/roles and have a request body attached containing a user id and role: admin, manager, or developer.

let assignUserRole = (deploymentId, userId, roleName) => {  
    let userRole = JSON.stringify({"role": {"name": roleName, "user_id": userId}});
    fetch(`${apibase}/deployments/${deploymentId}/roles`, { headers: apiheaders, method: 'POST', body: userRole })
    .then(res => {
        return res.json();
    })
    .then(json => {
        console.log(`User Role Assigned: ${json.name} ${JSON.stringify(json.users)}`)
    })
    .catch(err => {
        console.log(err);
    });
}

The function will take in a deployment id, user id, and role. We attach the role and user id to the request body that we save into the userRole variable. That variable is placed inside the request body field and we add POST to the method field. When the JSON response is returned, we'll get back the name of the user role and an array listing all the users assigned to that role - not just the user we've added.

However, before running this function, you'll need to know the id of the user you want to assign a role to. We've already written a command with yargs to do that in part one of this article. So, using the command-line tool, we can run the following command users with your account id to get the users and ids listed on your account:

./apiUsersTeams users 7g89sc0dce45vt3000260044

5a0b5d97e51d0000148ad4ec Jon Snow  
5a03793a50087c00138f0ad6 William Wallace  
5783c6fce83b160026000024 Abdullah Alger  
5a037a9dc9b952000f0b4a83 Robert Bruce  
5a037ab9883ca20014863797 Henry Tudor  
5a037a78c9b95200130b4a85 Marvin Martian  

For this example, let's select Marvin Martian and add him as a developer to the PostgreSQL deployment we used as an example above. Using the PostgreSQL deployment id 7a0a09b4b7d6f87619b6ae2s, Marvin Martian's user id 9a737r78c9b95200130b4a85, and the role "developer", in the assignUserRole function, we'll get back:

User Role Assigned: developer [{"id":"5a037a78c9b95200130b4a85","name":"Marvin Martian"}]  

If we look back and list the roles assigned to the PostgreSQL deployment again, that will give us users assigned to both the developer and admin roles:

developer [{"id":"5a037a78c9b95200130b4a85","name":"Marvin Martian"}]  
admin [{"id":"5783c6fce83b160026000024","name":"Abdullah Alger"}]  

And it's as simple as that ...

Removing deployment user roles

Removing users from a deployment is similar to assigning a role except you change the HTTP request to DELETE /2016-07/deployments/:id/roles. So instead of using POST in the function's method field, you just write DELETE. And the function will look almost identical as assignUserRole.

let removeUserRole = (deploymentId, userId, roleName) => {  
    let userRole = JSON.stringify({"role": {"name": roleName, "user_id": userId}});
    fetch(`${apibase}/deployments/${deploymentId}/roles`, { headers: apiheaders, method: 'DELETE', body: userRole })
    .then(res => {
        if (res.ok) {
            console.log('Removed user role');
        }
    })
    .catch(err => {
        console.log(err);
    });
}

The major difference in the function above is in the first then() method which gives us the response from fetch. Since this HTTP DELETE API endpoint doesn't return any data as a response to the user, we simply check to see if the response property ok is true. If it is, then we print out a string that states that the role of that user has been removed. You can always go back and list the deployment roles again just to check if the role was deleted.

Adding deployment roles for teams

In the previous article, we looked at creating, updating, removing, and adding users to teams and mentioned that the benefit of using teams is to assign roles to groups of users, or multiple users, rather than assigning the same role multiple times individual users and trying to keeping track of them all.

Let's start by creating two teams for PostgreSQL developers and managers. Using the command-line tool we created previously, we could use the following commands to create two teams using add-team followed by a team name:

./apiUsersTeams add-team PostgreSQL-devs
Team Created: 5a0bb3d636ad20000faa261f PostgreSQL-devs

./apiUsersTeams add-team PostgreSQL-managers
Team Created: 5a0bb3ece51d0000148ad599 PostgreSQL-managers  

With two groups created, we'll also assign some users to those groups using the command-line tool. For the PostgreSQL managers team we'll assign the users Jon Snow and Henry Tudor, and for the PostgreSQL developers team, we'll assign the users Marvin Martian, Robert Bruce, and William Wallace.

Assigning Jon Snow and Henry Tudor to the PostgreSQL managers team, we'll use the add-team-users command followed by the team id 5a0bb3ece51d0000148ad599 and the ids of those users:

./apiUsersTeams add-team-users 5a0bb3yce9td7830148ad599 5a0b5d97e51d0000148ad4ec 5a037ab9883ca20014863797

This will respond with the team id, team name, and the users assigned to that team:

5a0bb3yce9td7830148ad599 PostgreSQL-managers [{"id":"5a0b5d97e51d0000148ad4ec","name":"Jon Snow"},{"id":"5a037ab9883ca20014863797","name":"Henry Tudor"}]  

Next, we'll do the same for the PostgreSQL developers team that has the id 5a03b3r636ad27y20faa261f and assign Marvin Martian, Robert Bruce, and William Wallace using the same command format as above:

./apiUsersTeams add-team-users 5a0bb3d636ad20000faa261f 5a037a78c9b95200130b4a85 5a037a9dc9b952000f0b4a83 5a03793a50087c00138f0ad6

This will give us:

5a0bb3d636ad20000faa261f PostgreSQL-devs [{"id":"5a037a78c9b95200130b4a85","name":"Marvin Martian"},{"id":"5a037a9dc9b952000f0b4a83","name":"Robert Bruce"},{"id":"5a03793a50087c00138f0ad6","name":"William Wallace"}]  

With the teams populated with users, we can assign the teams their appropriate roles on the PostgreSQL deployment. The function that we'll write makes an HTTP request to the POST /2016-07/deployments/:id/team_roles endpoint using the PostgreSQL deployment id. The request body that will be sent will contain the role (admin, manager, or developer) as well as the team id, which is similar to the request body we created when assigning roles to users.

let assignTeamRole = (deploymentId, teamId, roleName) => {  
    let teamRole = JSON.stringify({"team_role": {"name": roleName, "team_id": teamId}});
    fetch(`${apibase}/deployments/${deploymentId}/team_roles`, { headers: apiheaders, method: 'POST', body: teamRole })
    .then(res => {
        return res.json();
    })
    .then(json => {
        console.log(`Team Role Assigned: ${json.name} ${JSON.stringify(json.teams)}`)
    })
    .catch(err => {
        console.log(err);
    });
}

Similar to the assignUserRole function we wrote above, we create a variable called teamRole as the request body that stores the roleName and teamId that will be sent with the HTTP POST request. Once we receive the JSON response from the API call, we'll print out the role and an array of the teams assigned to that role.

So, assigning the manager and developer roles to the PostgreSQL teams we've created will look like:

Team Role Assigned: manager [{"id":"5a0bb3ece51d0000148ad599","name":"PostgreSQL-managers"}]

Team Role Assigned: developer [{"id":"5a0bb3d636ad20000faa261f","name":"PostgreSQL-devs"}]  

Listing deployment team roles

That takes us to listing the team roles for a deployment. Since we've added roles to the two PostgreSQL teams, we can verify that their roles have been added to the PostgreSQL deployment. All we'll do is make an HTTP GET request to the same endpoint /2016-07/deployments/:id/team_roles that we assigned team roles to just using the PostgreSQL deployment id.

let listTeamRoles = (deploymentId) => {  
    fetch(`${apibase}/deployments/${deploymentId}/team_roles`, { headers: apiheaders })
    .then(res => {
        return res.json();
    })
    .then(json => {
        let teamRoles = json["_embedded"].team_roles;
        for (let role of teamRoles) {
            console.log(`${role.name} ${JSON.stringify(role.teams)}`)            
        }
    })
    .catch(err => {
        console.log(err);
    });
}

Again, we'll access all the roles for the PostgreSQL deployment from the _embedded element and get an array of team roles from that. We'll then loop through the array of roles and print out each role with the array of teams assigned to that team role.

developer [{"id":"5a0bb3d636ad20000faa261f","name":"PostgreSQL-devs"}]  
manager [{"id":"5a0bb3ece51d0000148ad599","name":"PostgreSQL-managers"}]  

Deleting deployment team roles

Finally, if we want to delete the team roles we created, we just have to create a new function like the assignTeamRole function above and use the HTTP DELETE method.

let removeTeamRole = (deploymentId, teamId, roleName) => {  
    let teamRole = JSON.stringify({"team_role": {"name": roleName, "team_id": teamId}});
    fetch(`${apibase}/deployments/${deploymentId}/team_roles`, { headers: apiheaders, method: 'DELETE', body: teamRole })
    .then(res => {
        if (res.ok) {
            console.log('Removed team role');
        }
    })
    .catch(err => {
        console.log(err);
    });
}

Since sending an HTTP request to the DELETE /2016-07/deployments/:id/team_roles endpoint doesn't return data in the response, we again check to see if res.ok returns true and then print out that the team has been removed. If we delete the manager team role on the PostgreSQL deployment, we'd simply get the string back. However, from there you'd want to go back and list the deployment's team roles to make sure that the role was in fact deleted.

Updating the yargs commands

Since we've been using yargs to develop the command-line tooling, we'll simply add the seven functions we've written above as new commands below.

yargs.version("0.0.2")  
    .usage("Usage: ./apiUsersTeamsRoles.js <command>")
    .command("accounts", "List user account numbers", {}, (argv) => userAccounts())
    .command("users <accountid>", "Get users of an account", {}, (argv) => listUsers(argv.accountid))
    .command("add-user <accountid> <name> <email> [phone]", "Add user to an account", {}, (argv) => createUser(argv.accountid, argv.name, argv.email, argv.phone))
    .command("remove-user <accountid> <userid>", "Remove user of an account", {}, (argv) => removeUser(argv.accountid, argv.userid))
    .command("teams", "List teams", {}, (argv) => listTeams())
    .command("add-team <name>", "Create a team", {}, (argv) => createTeam(argv.name))
    .command("update-team <teamid> <name>", "Update a team", {}, (argv) => updateTeam(argv.teamid, argv.name))
    .command("remove-team <teamid>", "Remove a team", {}, (argv) => removeTeam(argv.teamid))
    .command("add-team-users <teamid> <userids..>", "Add users to a team", {}, (argv) => addTeamUser(argv.teamid, argv.userids))
// added commands
    .command("user-roles <deploymentId>", "Lists deployment user roles", {}, (argv) => listUserRoles(argv.deploymentId))
    .command("assign-user-role <deploymentId> <userId> <role>", "Assigns a user role for deployment", {}, (argv) => assignUserRole(argv.deploymentId, argv.userId, argv.role))
    .command("remove-user-role <deploymentId> <userId> <role>", "Removes a user role from deployment", {}, (argv) => removeUserRole(argv.deploymentId, argv.userId, argv.role))
    .command("team-roles <deploymentId>", "Lists deployment team roles", {}, (argv) => listTeamRoles(argv.deploymentId))
    .command("assign-team-role <deploymentId> <teamId> <role>", "Assigns a team role for a deployment", {}, (argv) => assignTeamRole(argv.deploymentId, argv.teamId, argv.role))
    .command("remove-team-role <deploymentId> <teamId> <role>" , "Removes a team role from a deployment", {}, (argv) => removeTeamRole(argv.deploymentId, argv.teamId, argv.role))
    .help()
    .argv;

Now you should have a functional command-line tool that you can use to access the Compose API to create users, teams, and roles for users and teams on your database deployments.

Summing up

In the previous article, we looked at creating a command-line tool that will access the Compose API to create users and teams of users. This article expanded on that tool by introducing the creation of deployment roles for users and teams through the API. The command-line tool we built is a basic example but it shows the simplicity of interacting with the Compose API. Go ahead and try it out, modify the code, or expand the tool.


Read more articles about Compose databases - use our Curated Collections Guide for articles on each database type. If you have any feedback about this or any other Compose article, drop the Compose Articles team a line at articles@compose.com. We're happy to hear from you.

attribution Scott Rodgerson

Abdullah Alger
Abdullah Alger is a former University lecturer who likes to dig into code, show people how to use and abuse technology, talk about GIS, and fish when the conditions are right. Coffee is in his DNA. Love this article? Head over to Abdullah Alger’s author page to keep reading.

Conquer the Data Layer

Spend your time developing apps, not managing databases.