Skip to content

Instantly share code, notes, and snippets.

@dirkschumacher
Last active June 12, 2020 19:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dirkschumacher/20789ab24a93457999c0071a5eaedc6a to your computer and use it in GitHub Desktop.
Save dirkschumacher/20789ab24a93457999c0071a5eaedc6a to your computer and use it in GitHub Desktop.

Role based access control as a logic program

Inspired by this article

# remotes::install_github("dirkschumacher/logician")
# a role based access control
library(logician)
role_database <- logician_database(
  role(user),
  role(moderator),
  role(admin),
  
  # Role A inherits from B
  inherits_role(admin, moderator),
  inherits_role(moderator, user),
  
  # role action ressource
  # e.g. user can store results
  permission(user, see, results),
  permission(moderator, delete, results),
  permission(admin, delete, users),
  permission(admin, add, users),
  permission(admin, edit, users),
  
  # this is the main rule for inference
  # can Role do Action on Ressource?
  can(Role, Action, Resource) := permission(Role, Action, Resource),
  can(Role, Action, Resource) := inherits_role(Role, R) && 
    can(R, Action, Resource)
)

# we check if the moderator role can see results (a property of the user role)
iter <- logician_query(role_database, can(moderator, see, results))
iter$next_value()
#> TRUE

# what roles can delete results?
iter <- logician_query(role_database, can(Role, delete, results))
iter$next_value()
#> TRUE
#> Role = moderator.
iter$next_value()
#> TRUE
#> Role = admin.

# and what can admin's do?
iter <- logician_query(role_database, can(admin, Action, Resource))
iter$next_value()
#> TRUE
#> Action = delete;
#> Resource = users.
iter$next_value()
#> TRUE
#> Action = add;
#> Resource = users.
iter$next_value()
#> TRUE
#> Action = edit;
#> Resource = users.
iter$next_value()
#> TRUE
#> Action = delete;
#> Resource = results.
iter$next_value()
#> TRUE
#> Action = see;
#> Resource = results.
iter$next_value()
#> FALSE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment