Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Priv #13

Open
wants to merge 51 commits into
base: main
Choose a base branch
from
Open

Priv #13

Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
5b16f20
#3 privileges work
sckott Oct 21, 2024
3892677
#3 #4 added brainstorming code for policies as real code, fixed a tes…
sckott Oct 24, 2024
304dd47
only run examples if interactive
sckott Oct 29, 2024
5b4b5a9
#5 add with_db_user fxn
sckott Oct 29, 2024
65159c4
remove pkg loading messages/warnings
sckott Nov 4, 2024
b3ee90e
docs url fix
sckott Nov 4, 2024
f7c607d
add fxn rls_privileges to get overview of table and column level priv…
sckott Nov 4, 2024
14bfa57
run on all branches
sckott Nov 5, 2024
14b5fe5
add new vignette with basic important info on privileges and policies…
sckott Nov 5, 2024
b49b76a
gitignore s7 file
sckott Nov 8, 2024
898d48a
dont check system clock in r cmd check
sckott Nov 8, 2024
2ad5c83
limit to 4 sql commands we support in vignette
sckott Nov 8, 2024
6fd941a
#4 rework privilege methods
sckott Nov 8, 2024
564d0b2
styling
sckott Nov 8, 2024
0c1ae51
update man files
sckott Nov 8, 2024
2754bf9
added row policy fns
sckott Nov 12, 2024
5d98b0a
make passwd table setup example actually work from scratch
sckott Nov 12, 2024
b0f8b7b
#4 more tabular work for privileges and row policies
sckott Nov 12, 2024
de0687c
add as_con s3 method for privilege class
sckott Nov 13, 2024
45a156e
cleanup translate_privilege, add fxn rls policy exists, add test help…
sckott Nov 13, 2024
8c362fd
organize pkgdown config file
sckott Nov 13, 2024
e6304a9
overwrite = true in all dbWriteTable in test
sckott Nov 13, 2024
c6f8653
add helper fxn from tests for dropping all policies to pkg fxn, make …
sckott Nov 14, 2024
4da1d2b
add clean command to Makefile to clean out check folder and targz man…
sckott Nov 14, 2024
020da39
removed tests for old rls fxns, added some new tests
sckott Nov 14, 2024
8038f3b
move old rls create and construct fxns to inst/ignore; fix some small…
sckott Nov 14, 2024
75a0933
moved as_con to a separate R file
sckott Nov 14, 2024
66fa7fa
update vignette to use current fxns for row and column level stuff
sckott Nov 14, 2024
c5a9a4a
#10 make more examples self contained and clean up, not done yet
sckott Nov 15, 2024
b4cfcdc
fix #10 all examples i think are self contained and clean up
sckott Nov 15, 2024
d7b02b7
Merge branch 'priv' into with
sckott Dec 6, 2024
221da97
Merge pull request #11 from getwilds/with
sckott Dec 6, 2024
537fd89
fix namespace and with_db_user
sckott Dec 6, 2024
5533fd5
pkgdown config: remove some, add one
sckott Dec 6, 2024
86d8284
add lightswitch for dark/light toggle in pkgdown docs
sckott Dec 6, 2024
f706160
add more info on current_user here and there
sckott Dec 10, 2024
0673c25
fix #15 add restrictive fxn for as part of RLS policy; update vignette
sckott Dec 11, 2024
062efa6
change rls_run to rls_perform, fix missing param def for restrictive fun
sckott Dec 11, 2024
2076fa0
fix pkgdown reference for perform fxn
sckott Dec 11, 2024
66698eb
change output of rls_perform to a tibble upon success; remains error …
sckott Dec 11, 2024
7922b36
add rls_role_exists to easily check for roles or users
sckott Dec 11, 2024
c0ef212
drop NSE for row policy existing and new functions, just use sql input
sckott Dec 11, 2024
a738528
inject helper message into postgres default check for each test run w…
sckott Jan 3, 2025
b09b3cc
added PGPASSWORD to postgres helper for running tests
sckott Feb 3, 2025
977b9f4
replace all uses of rls_run with rls_perform
sckott Feb 3, 2025
aac9db2
improve revoke and grant egs
sckott Feb 3, 2025
ef01ab8
update docs and egs for privileges fxns: grant, revoke, to, from, tra…
sckott Feb 4, 2025
180f152
policies.R functions: tweaks and such
sckott Feb 4, 2025
c0ebbad
remove code in print.row_policy that was a hold over from copy/paste …
sckott Feb 4, 2025
c06d138
examples tweaks, update docs
sckott Feb 4, 2025
915b0ea
improve with_db_user example reproducibilty
sckott Feb 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
cleanup translate_privilege, add fxn rls policy exists, add test help…
…er for drop oplicies
sckott committed Nov 13, 2024
commit 45a156e12e0ed08911f372e9ad797e9b9cfdae94
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ export(rls_enable)
export(rls_list_roles)
export(rls_permissions)
export(rls_policies)
export(rls_policy_exists)
export(rls_privileges)
export(rls_run)
export(rls_table_privileges)
@@ -41,6 +42,7 @@ export(rows_new)
export(setup_example_table)
export(to)
export(translate_privilege)
export(translate_row_policy)
import(dbplyr)
importFrom(DBI,dbExecute)
importFrom(DBI,dbGetQuery)
4 changes: 2 additions & 2 deletions R/drop.R
Original file line number Diff line number Diff line change
@@ -40,8 +40,8 @@ rls_drop_policy <- function(con, policy = NULL, name = NULL, table = NULL) {
name <- policy$name
table <- policy$table
} else {
if (is.null(name) && is.null(table)) {
rlang::abort("if `policy` is NULL, name & table must be non-NULL")
if (is.null(name) || is.null(table)) {
rlang::abort("if `policy` is NULL, `name` & `table` must be non-NULL")
}
}
invisible(dbExecute(con, glue("{drop_statement} POLICY {name} ON {table}")))
33 changes: 33 additions & 0 deletions R/exists.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#' Check if a row level security policy exists
#'
#' @export
#' @param con a DBI database connection object. required. supports only
#' postgres and redshift connections
#' @param name (character) a policy name. required
#' @return scalar boolean, `TRUE` or `FALSE`
#' @examplesIf has_postgres()
#' library(DBI)
#' library(RPostgres)
#' con <- dbConnect(Postgres())
#' dbWriteTable(con, "attitude", attitude)
#' policy <- rls_tbl(con, "attitude") %>%
#' row_policy(name = "some_policy") %>%
#' commands(update) %>%
#' rows_existing(TRUE) %>%
#' to(jane)
#' policy
#' rls_run(policy)
#' rls_policies(con)
#' rls_policy_exists(con, "some_policy")
#' rls_drop_policy(con, name = "some_policy", table = "attitude")
#' rls_policy_exists(con, "some_policy")
#' dbRemoveTable(con, "attitude")
#' dbDisconnect(con)
rls_policy_exists <- function(con, name) {
is_conn(con)
pols <- rls_policies(con)
if (NROW(pols) == 0) {
return(FALSE)
}
name %in% pols$policyname
}
14 changes: 10 additions & 4 deletions R/privileges.R
Original file line number Diff line number Diff line change
@@ -100,9 +100,10 @@ from <- to
#' Translate privilege
#'
#' @export
#' @param priv an object of class `privilege`, required
#' @keywords internal
#' @param priv an S3 object of class `privilege`, required
#' @param con DBI connection object, required
#' @examplesIf interactive() && rlang::is_installed("dbplyr")
#' @examplesIf interactive()
#' library(tibble)
#' library(RPostgres)
#' library(DBI)
@@ -112,16 +113,18 @@ from <- to
#' apples = c("pink lady", "cortland", "mcintosh"),
#' strawberries = c("alice", "albion", "alaska pioneer")
#' )
#' DBI::dbWriteTable(con, "fruits", dat)
#' dbWriteTable(con, "fruits", dat)
#' dbExecute(con, "CREATE ROLE jane")
#' auto_pipe(FALSE)
#'
#' # GRANT SELECT
#' # ON fruits
#' # TO jane
#' priv <-
#' rls_tbl(con, "fruits") %>%
#' rls_tbl(con, "flights") %>%
#' grant(select) %>%
#' to(jane)
#' priv
#' translate_privilege(priv, con)
#'
#' # REVOKE SELECT
@@ -131,6 +134,7 @@ from <- to
#' rls_tbl(con, "fruits") %>%
#' revoke(select) %>%
#' from(jane)
#' priv
#' translate_privilege(priv, con)
#'
#' # GRANT SELECT
@@ -141,10 +145,12 @@ from <- to
#' rls_tbl(con, "fruits") %>%
#' grant(select, cols = c("apples", "strawberries")) %>%
#' to(jane)
#' priv
#' sql <- translate_privilege(priv, con)
#' dbExecute(con, sql)
translate_privilege <- function(priv, con) {
assert_is(priv, "privilege")
is_conn(con)

template <- priv_templates[[priv$type]]

32 changes: 29 additions & 3 deletions R/row_policy.R
Original file line number Diff line number Diff line change
@@ -34,7 +34,7 @@ row_policy <- function(.data, name) {
#' setup_example_table(con, "passwd")
#' }
#' rls_tbl(con, "passwd") %>%
#' row_policy("my_policy") %>%
#' row_policy("their_policy") %>%
#' commands(update)
commands <- function(.data, ...) {
pipe_autoexec(toggle = rls_env$auto_pipe)
@@ -58,7 +58,7 @@ commands <- function(.data, ...) {
#' setup_example_table(con, "passwd")
#' }
#' rls_tbl(con, "passwd") %>%
#' row_policy("my_policy") %>%
#' row_policy("a_good_policy") %>%
#' commands(update) %>%
#' rows_existing(sql = 'current_user = "user_name"')
rows_existing <- function(.data, using = NULL, sql = NULL) {
@@ -100,7 +100,7 @@ rows_existing <- function(.data, using = NULL, sql = NULL) {
#' to(jane)
#'
#' rls_tbl(con, "passwd") %>%
#' row_policy("my_policy") %>%
#' row_policy("that_policy") %>%
#' commands(update) %>%
#' rows_existing(sql = 'current_user = "user_name"') %>%
#' rows_new(home_phone == "098-765-4321") %>%
@@ -147,6 +147,32 @@ express <- function(x) {
glue("({ifelse(x == 'TRUE', tolower(x), x)})")
}

#' Translate row policy
#'
#' @export
#' @keywords internal
#' @param policy an S3 object of class `row_policy`, required
#' @param con DBI connection object, required
#' @examplesIf interactive()
#' library(RPostgres)
#' library(DBI)
#' con <- dbConnect(Postgres())
#' setup_example_table(con)
#'
#' if (rls_policy_exists(con, "blue_policy")) {
#' rls_drop_policy(con, name = "blue_policy", table = "passwd")
#' }
#'
#' policy <- rls_tbl(con, "passwd") %>%
#' row_policy(name = "blue_policy") %>%
#' commands(update) %>%
#' rows_existing(TRUE) %>%
#' rows_new(TRUE) %>%
#' to(jane)
#' policy
#' sql <- translate_row_policy(policy, con)
#' sql
#' dbExecute(con, sql)
translate_row_policy <- function(policy, con) {
is_conn(con)
create_statement <- switch(class(con),
2 changes: 1 addition & 1 deletion man/commands.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 41 additions & 0 deletions man/rls_policy_exists.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/rows_existing.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/rows_new.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 9 additions & 4 deletions man/translate_privilege.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 40 additions & 0 deletions man/translate_row_policy.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions tests/testthat/helper-rls.R
Original file line number Diff line number Diff line change
@@ -9,3 +9,14 @@ with_database_connection <- function(expr, con = RPostgres::postgresDefault()) {
context <- list2env(list(con = con), parent = parent.frame())
eval(substitute(expr), envir = context)
}

drop_all_rls_policies <- function(con) {
pols <- rls_policies(con)
if (NROW(pols) == 0) return()
for (i in seq_len(NROW(pols))) {
rls_drop_policy(con,
name = pols$policyname[i],
table = pols$tablename[i]
)
}
}
1 change: 1 addition & 0 deletions tests/testthat/test-rls_drop_policy.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
test_that("rls_drop_policy", {
with_database_connection({
drop_all_rls_policies(con)
DBI::dbWriteTable(con, "usarrests", USArrests, temporary = TRUE)
on.exit(DBI::dbRemoveTable(con, "usarrests"), add = TRUE)