diff --git a/DESCRIPTION b/DESCRIPTION
index 57e0cc5..86db39f 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: rAccess
Title: Access Control Module for 'shiny' Applications
-Version: 0.1.1.299
+Version: 0.1.3
Authors@R:
c(person(given = "Peyman",
family = "Eshghi",
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..6c0c077
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,7 @@
+# rAccess 0.1.1.3
+
+### Bug fixes
+ * Fixed a bug that prevented searching for users in deployed apps.
+
+# rAccess 0.1.1.2
+ * November 03, 2025 - Initial Release.
\ No newline at end of file
diff --git a/R/functions.R b/R/functions.R
index 3835af6..1fd878a 100644
--- a/R/functions.R
+++ b/R/functions.R
@@ -310,6 +310,7 @@ rAccess <- R6Class(
self$s3_bucket <- s3_bucket
self$s3_access_key <- s3_access_key
self$s3_secret_key <- s3_secret_key
+ self$use_rconnect_users <- use_rconnect_users
self$verbose <- verbose
self$user <- user
self$secure_mode <- secure_mode
diff --git a/R/module_sub_iam.R b/R/module_sub_iam.R
index 676f2fb..5456844 100644
--- a/R/module_sub_iam.R
+++ b/R/module_sub_iam.R
@@ -287,30 +287,26 @@ module_sub_iam_server <- function(id, access_panel_id, rAccess_obj) {
username_ <- input$txtUsername
if (nchar(trimws(username_)) >= 1) {
withProgress(message = "Fetching list of users...", {
- if (Sys.getenv("SHINY_PORT") == "") {
- if (!is.null(rAccess_obj$user_df)) {
- choices_ <- rAccess_obj$matched_users(username_)
- } else {
- choices_ <- NULL
- }
+ if (!is.null(rAccess_obj$user_df)) {
+ choices_ <- rAccess_obj$matched_users(username_)
} else {
- rconnect_choices_ <- rAccess::get_user_api(
- contact_info = username_,
- url = session$clientData$url_hostname,
- api_key = NULL
- )
- if (!is.null(rAccess_obj$user_df)) {
- userdf_choices_ <- rAccess_obj$matched_users(username_)
- } else {
- userdf_choices_ <- NULL
- }
+ choices_ <- NULL
+ }
+ userdf_choices_ <- choices_
+ if (Sys.getenv("SHINY_PORT") != "") {
if (rAccess_obj$use_rconnect_users) {
- choices_ <- unique(rbind(rconnect_choices_, userdf_choices_))
+ rconnect_choices_ <- rAccess::get_user_api(
+ contact_info = username_,
+ url = session$clientData$url_hostname,
+ api_key = NULL
+ )
+ choices_ <- rbind(rconnect_choices_, userdf_choices_)
} else {
choices_ <- userdf_choices_
}
}
if (!is.null(choices_)) {
+ choices_ <- choices_[!duplicated(tolower(choices_$userid)), ]
choices_temp <- choices_$userid
names(choices_temp) <- paste0(choices_$userid,
" (", choices_$username, ")")
diff --git a/README.md b/README.md
index 89a9221..220291d 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,81 @@
-# rAccess
+# rAccess
-[](https://github.com/johnsonandjohnson/rAccess/actions/workflows/test-coverage.yaml)
+
+[](https://github.com/johnsonandjohnson/rAccess/actions/workflows/test-coverage.yaml)
[](https://github.com/johnsonandjohnson/rAccess/actions/workflows/R-CMD-check.yaml)
-
-
-[](https://cran.r-project.org/package=rAccess)
-
-
-`rAccess` is an R package that offers a flexible framework for
-in-app access control, allowing local and/or remote storage, organization, and
-retrieval of access lists. It features a pluggable shiny module to create and
-manage access lists for individual Shiny applications. It is built on top of the
-Posit Connect Access Management, which means no credentials are collected or stored.
+[](https://cran.r-project.org/package=rAccess)
-A friendly user interface enables the app Admin to easily manage user access
-permission for respective access units.
+
-The parameters to the `rAccess` object can either be passed directly as arguments to the new
-instance of `rAccess` or could be defined within a configuration yaml file.
+`rAccess` is an R package that offers a flexible framework for in-app
+access control, allowing local and/or remote storage, organization, and
+retrieval of access lists. It features a pluggable shiny module to
+create and manage access lists for individual Shiny applications. It is
+built on top of the Posit Connect Access Management, which means no
+credentials are collected or stored.
+
+A friendly user interface enables the app Admin to easily manage user
+access permission for respective access units.
+
+The parameters to the `rAccess` object can either be passed directly as
+arguments to the new instance of `rAccess` or could be defined within a
+configuration yaml file.
+
+## Core Concepts
+
+**Access Panels** serve as organizational containers that group related *Access
+Units* together, enabling you to implement hierarchical access control
+structures. In the rAccess user interface, each *Access Panel* appears as a
+separate tab where administrators can navigate to configure permissions. This
+tabbed structure allows admins to logically organize access controls by
+functional areas - for example, having separate panels for "Data Visualization",
+ "Report Generation", and "Administrative Functions". Each panel can contain
+ multiple related units that share similar access requirements or belong to
+the same feature set.
+
+**Access Units** represent the most granular level of access control in your
+application - these are the specific elements that users can be granted or denied
+access to. They could be individual shiny modules, specific UI components (like
+download buttons or input panels), particular data views, or any discrete
+functionality within your application. In the rAccess user interface, *Access
+Units* appear as individual toggles or dropdown selections within their
+respective *Access Panel* tabs, allowing administrators to precisely control which
+ users can access each specific feature or component of the application.
## Installation
-```
+```
#install.packages("pak")
pak::pak("johnsonandjohnson/rAccess")
```
## Usage
-`rAccess` includes server and ui modules for access management tab which could
-be used within a main Shiny web application.
+`rAccess` includes server and ui modules for access management tab which
+could be used within a main Shiny web application.
-```
+```
library(rAccess)
```
## Adding rAccess config file
-The package includes a template configuration file, making it simple for users
-to get started. It contains all the necessary parameters for rAccess and can be
-customized to suit individual needs.
+The package includes a template configuration file, making it simple for
+users to get started. It contains all the necessary parameters for
+rAccess and can be customized to suit individual needs.
To add a config file template to your project directory, use:
-```
+
+```
rAccess::use_config(file_name = "rAccess.yml")
```
## Config file structure
-```
+
+```
module: rAccess
parameters:
app_name: # application name *
@@ -87,19 +114,24 @@ panel_str: # Panel structure to be defined by the develop
data: # datapath associated with access unit
```
-**For detailed description on the config file components refer vignette : Tutorial.**
+**For detailed description on the config file components refer vignette
+: Tutorial.**
### Creating a new instance of rAccess
-Once the configuration file is ready the user can create a new instance of
-rAccess as below:
-```
+Once the configuration file is ready the user can create a new instance
+of rAccess as below:
+
+```
newIAM <- rAccess$new(user = "UserID", config = "rAccess.yml")
```
+
### Creating a new instance of rAccess without a config file
-If there is no config file in place, user can also pass the rAccess parameters as
-arguments to the new instance of the `rAccess` object.
-```
+
+If there is no config file in place, user can also pass the rAccess
+parameters as arguments to the new instance of the `rAccess` object.
+
+```
access_panels <- list(
`ADMIN` = NULL,
`Access Panel 1` = c("Unit 1", "Unit 2"),
@@ -126,13 +158,17 @@ newIAM$access_panels
newIAM$access_units
newIAM$access_mode
```
+
### board_type options in rAccess
-There three pin board options available for the users: "local", "s3", and "rconnect".
-This can be specified with the parameter `board_type` of the rAccess object.
-* `"local"` : Local folder will be used as a pin_board. The user must also specify the "local_board_path".
+There three pin board options available for the users: "local", "s3",
+and "rconnect". This can be specified with the parameter `board_type` of
+the rAccess object.
-```
+- `"local"` : Local folder will be used as a pin_board. The user must
+ also specify the "local_board_path".
+
+```
newIAM <- rAccess$new(user = "",
app_name = "testApp",
board_type = "local",
@@ -143,9 +179,10 @@ newIAM <- rAccess$new(user = "",
user_df = user_df)
```
-* `"s3"` : S3 bucket will be used as a pin_board. When board_type is "s3", the user must give the s3 credentials.
+- `"s3"` : S3 bucket will be used as a pin_board. When board_type is
+ "s3", the user must give the s3 credentials.
-```
+```
newIAM <- rAccess$new(user = "",
app_name = "testApp",
board_type = "s3",
@@ -157,10 +194,11 @@ newIAM <- rAccess$new(user = "",
user_df = user_df)
```
-* `"rconnect"` : Posit Connect pin_board will be utilized. If the pin_board does not already exist,
-it will be created and deployed on the same Posit Connect server where the app is hosted.
+- `"rconnect"` : Posit Connect pin_board will be utilized. If the
+ pin_board does not already exist, it will be created and deployed on
+ the same Posit Connect server where the app is hosted.
-```
+```
newIAM <- rAccess$new(user = "",
app_name = "testApp",
board_type = "rconnect",
@@ -170,10 +208,14 @@ newIAM <- rAccess$new(user = "",
```
### Creating user list
-The user list for rAccess could either be supplied as the `user_df` argument of the `rAccess` object or could be fetched from the rconnect user list.
-**Creating user_df***
-```
+The user list for rAccess could either be supplied as the `user_df`
+argument of the `rAccess` object or could be fetched from the rconnect
+user list.
+
+**Creating user_df**\*
+
+```
user_df <- tibble::tribble(
~userid, ~username,
"UserId1", "User Name 1",
@@ -190,15 +232,13 @@ newIAM <- rAccess$new(user = "",
access_panels = access_panels,
access_mode = "default",
user_df = user_df)
-
```
-**Using API to fetch user data**
-If you have access to your organization’s user directory via an API,
-you might want to first fetch the data and then prepare the user_df,
-similar to the example below
+**Using API to fetch user data** If you have access to your
+organization’s user directory via an API, you might want to first fetch
+the data and then prepare the user_df, similar to the example below
-```
+```
api_url <- ""
users <- jsonlite::fromJSON(api_url)
user_df <- tibble::tibble(userid = users$USERID, username = users$USERNAME)
@@ -210,15 +250,15 @@ newIAM <- rAccess$new(user = "",
access_panels = access_panels,
access_mode = "default",
user_df = user_df)
-
```
**Using User list from rconnect**
-User list will be automatically fetched from the Posit Connect servers when
-deployed. Users must make sure that `use_rconnect_users` parameter is set as
-`TRUE` to get users from Posit Connect.
-```
+User list will be automatically fetched from the Posit Connect servers
+when deployed. Users must make sure that `use_rconnect_users` parameter
+is set as `TRUE` to get users from Posit Connect.
+
+```
# When deployed
newIAM <- rAccess$new(user = "",
app_name = "testApp",
@@ -228,9 +268,9 @@ newIAM <- rAccess$new(user = "",
use_rconnect_users = TRUE)
```
-## Example
+## Example
-```
+```
library(DT)
library(pins)
library(shiny)
@@ -322,3 +362,5 @@ server <- function(input, output, session) {
shinyApp(ui, server)
```
+
+
diff --git a/man/figures/readme_rAccess.gif b/man/figures/readme_rAccess.gif
new file mode 100644
index 0000000..d261095
Binary files /dev/null and b/man/figures/readme_rAccess.gif differ