diff --git a/vignettes/working-with-grant-based-roles.Rmd b/vignettes/working-with-grant-based-roles.Rmd index 925790e..8a56503 100644 --- a/vignettes/working-with-grant-based-roles.Rmd +++ b/vignettes/working-with-grant-based-roles.Rmd @@ -33,7 +33,7 @@ library(purrr) ## Introduction to user roles -This tutorial will provide a quick introduction on how to work with [grant-based roles and permissions](https://www.activityinfo.org/support/docs/permissions/explanation.html) using the [*ActivityInfo R Package*](https://www.activityinfo.org/support/docs/R/index.html) and secure your database and ensure user's can access exactly what they need. +This tutorial will provide a quick introduction on how to work with [grant-based roles and permissions](https://www.activityinfo.org/support/docs/permissions/explanation.html) using the [*ActivityInfo R Package*](https://www.activityinfo.org/support/docs/R/index.html) and secure your database and ensure user's can access exactly what they need. For a quick introduction, see "[Understanding grant-based roles](https://www.activityinfo.org/support/docs/permissions/understanding-roles.html)". Note: in order to fully follow this tutorial you must have an ActivityInfo user account or a trial account with the permission to add a new database. Setup a free trial here: @@ -216,7 +216,7 @@ List of 8 $ grantBased : logi TRUE ``` -#### Inspect database user roles +#### Inspect invited user role assignments We can also inspect which roles have been assigned to each user. This will not list the database owner. @@ -230,13 +230,19 @@ dbUserRoles <- getDatabaseUsers(dbTree$databaseId) |> unnest_wider(role, names_s There are a number of helper functions that make the creation of user roles straightforward. -There are few important principles: - The role object is created and then added to the database - There are separate functions for adding a new role `addRole()` and for updating an existing role `updateRole()` - When granting access to a resource, a resource id must be provided. Resource ids are not validated during role creation. +There are few important principles: + +- The role object is first created and then added to the database + +- There are separate functions for adding a new role `addRole()` and for updating an existing role `updateRole()` + +- When granting access to a resource, a resource id must be provided. Note that resource ids are not validated during role creation. ### Resource-level access -A simple role that gives resource-level access can be quickly created using a few helper functions. +A simple role that gives resource-level access can be quickly created. -This first example role grants access to a single data entry form. It does so by defining a grant and the operations available to edit and view a form. The operations are defined in the `resourcePermissions()` function. +This example grants access to a single data entry form. It does so by defining a grant to the form and the operations available to edit and view the form. The operations are defined with the `resourcePermissions()` function. In R use `??resourcePermissions` to see the function definition. ```{r eval=FALSE, include=TRUE} @@ -316,6 +322,8 @@ addRole(dbTree$databaseId, adminRoleNoAutomation) ``` +#### Update role with optional access to another form + We can modify our role so that we can optionally give access to another form. To modify a role, we need to change the definition and then use the `updateRole()` function to change the role in our database. ```{r eval=FALSE, include=TRUE} @@ -362,6 +370,8 @@ See the documentation for `role()`, `grant()`, `resourcePermissions()` for the f Sometimes, it is necessary to be able to specify exactly which operations are available on a row by row basis. For example, a reporting partner may be able to use a form to submit reports and they may also have the ability to view and edit their own reports. However, they should not be able to view or edit reports of other partners. +Role creation in a single database with record-level permission filters is easiest within the ActivityInfo user-interface. See "[Add your first parameter to a role](https://www.activityinfo.org/support/docs/permissions/add-your-first-parameter-to-a-role.html)". + #### Create partner form and reporting forms We will create a list all reporting partners that we will use to assign a partner to users. We will also create a form for submitting reports. @@ -405,7 +415,7 @@ We can examine the form records with `getRecords(partnerForm)`: 3 c6lra77m37c3f5icoi 1730985535 Partner C ``` -Next we create our reporting form. +Next we create our reporting form. We will add a Partner field which references the partner form and fill it with the partner ids. Next we have to get the partner ids that were generated in the partner form so we can fill the reference field. ```{r eval=FALSE, include=TRUE} # create a reporting table with a reporting partner field @@ -428,8 +438,8 @@ addForm(reportingForm) # get list of partner ids partnerTbl <- getRecords(partnerForm) |> collect() - partnerIds <- partnerTbl[["_id"]] + partnerReports <- paste0("This is a report from ", partnerTbl[["Partner name"]], ".") # create a reports table @@ -461,7 +471,7 @@ We can examine the form table using `getRecords(reportingForm)`: #### Defining a reporting partner role -Using ActivityInfo formulas, we can specify row-level access rules. We assign each user a `partner` parameter in the role definition in order to do this. This parameter will be available in formulas using `@user.partner` +Using ActivityInfo formulas, we can specify row-level access rules. We assign each user a `partner` parameter in the role definition in order to do this. This parameter will be available in formulas using `@user.partner`. ```{r eval=FALSE, include=TRUE} @@ -469,9 +479,11 @@ partnerParameter <- parameter(id = "partner", label = "Partner", range = partner ``` -We can then add this parameter to a "Reporting Partner" role that has access to view the partner form so that they can choose their own organization when creating a report. +The "Reporting Partner" role will also have access to view the partner reference form so that they can choose their own organization when creating a report. + +They will have restricted row-level access to the reporting form for submitting and editing only their own reports. We'll use a formula to restrict access to the rows where the reporting partner is correct (`rp == @user.partner`). -Additionally, they have row-level access to the reporting form for submitting and editing only their own reports. Optionally, they can be provided full access to the partner form and manage the full list of partners. +We will also define an optional partner form grant, so the administrator can decide if they should have full access to the partner form and manage the full list of partners. ```{r eval=FALSE, include=TRUE} roleId <- "rp" @@ -524,7 +536,7 @@ addRole(dbTree$databaseId, reportingPartnerRole) #### Assigning users a reporting partner role -We will assign a new users to the database and give them the reporting partner roles: +We can assign new users to the database and give them reporting partner roles: - **User A**: Assign to Reporting Partner A so they can view and edit Partner A reports only @@ -562,6 +574,8 @@ userB <- addDatabaseUser( ## Add users and assign roles +Adding users and assigning a role can be quickly achieved using `addDatabaseUser()`. + ```{r eval=FALSE, include=TRUE} addDatabaseUser( @@ -586,6 +600,8 @@ dbUsers ``` +For a fuller example using optional grants and parameters for row-level access, see the previous section on creating roles. There are also advanced tutorials for [bulk adding users with grants and parameters](advanced-user-management.html). + ## List roles across all databases It is also possible to compile a list of all roles across all databases at once. @@ -628,6 +644,8 @@ allRoles <- purrr::pmap_dfr(databases, function(databaseId, label, ...) { ## List all users and their roles across all databases +To list all users and all roles across all databases to which you have access, we first need to make a function that uses `getDatabaseUsers()` to collect the list of users. It is setup to fail gracefully if one does not have permission to get the database users for any of the databases. + ```{r eval=FALSE, include=TRUE} # get a list of database ids @@ -686,7 +704,7 @@ userOperations %>% filter(operation == "EDIT_RECORD") ## Find users with legacy roles -It is important to update all roles so that users with legacy roles have grant-based roles from 2025 when legacy roles will be phased out. It is simple to find all users with legacy roles by doing the following with the `allUserRoles` and `allRoles` variables defined in the previous two sections. +Legacy roles are marked for deprecation in the near future. Before legacy roles are phased out, it is important to migrate users with legacy roles to grant-based roles. Thankfully, it is simple to find all users with legacy roles by doing the following with the `allUserRoles` and `allRoles` variables defined in the previous two sections. ```{r eval=FALSE, include=TRUE}