如何在Shinymanager中使用SQL数据库实现管理员模式。

huangapple go评论69阅读模式
英文:

How to make admin mode available for Shinymanager with SQL database

问题

我有一个使用postgres数据库托管在AWS上的工作中的Rshiny应用程序,使用shinymanager。
我想知道是否有办法在此应用程序中启用管理员模式。
根据shinymanager文档,管理员模式仅适用于具有某些限制的sqlite数据库,用于托管在shinyapps.io上的应用程序。

其次,是否可以使用shinymanager添加基于Cookie的身份验证,以使用户无需在每次页面刷新时重新输入凭据。

英文:

I have a working Rshiny app with shinymanager using postgres database hosted on AWS.
I wonder if there is any way to make the admin mode available in this app.
According to shinymanager documentation, admin mode is available only with sqlite database which has certain limitations for apps hosted on shinyapps.io

secondly, it is possible to add cookie-based authentication with shinymanager so that the users don't have to retype credentials every time the page gets refreshed.

require(RPostgreSQL)
library(shiny)
library(shinymanager)
library(DBI)
library(glue)

dbname = "*****"
host = "localhost"
port = *****
user = "*****"
password = "******"

con <- dbConnect(dbDriver("PostgreSQL"), dbname = dbname , host = host, port = port ,
                 user = user, password = password )


DBI::dbWriteTable(con, "my_table", overwrite = TRUE,
                  data.frame(user = c("shiny", "admin"),
                             password = c("shiny", "admin"),
                             admin = c(FALSE, TRUE),
                             stringsAsFactors = FALSE))

# or a config .yml file or others arguments
my_custom_check_creds <- function(dbname, host, port, db_user, db_password) {
  
 # finally one function of user and password
  function(user, password) {
    
    con <- dbConnect(dbDriver("PostgreSQL"), dbname = dbname, 
                     host = host, port = port,
                     user = db_user, password = db_password)
    
    on.exit(dbDisconnect(con))
    
    req <- glue_sql("SELECT * FROM my_table WHERE \"user\" = ({user}) AND \"password\" = ({password})", 
             user = user, password = password, .con = con
    )
    
    req <- dbSendQuery(con, req)
    res <- dbFetch(req)
    if (nrow(res) > 0) {
      list(result = TRUE, user_info = list(user = user, something = 123))
    } else {
      list(result = FALSE)
    }
  }
}

ui <- fluidPage(
  tags$h2("My secure application"),
  verbatimTextOutput("auth_output")
)
ui <- secure_app(ui)


server <- function(input, output, session) {
  res_auth <- secure_server(
    check_credentials = my_custom_check_creds(
      dbname = "******",
      host = "*****",
      port = ****,
      db_user = "*****",
      db_password = "*******"
    )
  )  
  auth_output <- reactive({
    reactiveValuesToList(res_auth)
  })
  
  # access info
  observe({
    print(auth_output())
  })
}

shinyApp(ui, server)

答案1

得分: 2

当前版本的shinymanager包只支持带有SQLite的管理员页面。要使此功能在基于SQL的数据库中可用,需要大量工作来使其正常运行。

我已经更新了shinymanager包,添加了新的功能,可以在使用像PostgreSQL这样的SQL数据库时添加管理员页面功能。

我已经添加了一个拉取请求来对主要包进行额外的更新。同时,您可以从这里安装R包:

remotes::install_github("devops-qubits/shinymanager")

您需要在conn中添加自己的数据库凭据。

library(RPostgres)
library(shiny)
library(shinymanager)
library(DBI)

conn <- DBI::dbConnect(RPostgres::Postgres(),
                       host   = "localhost",
                       dbname = "postgres_db",
                       user = "postgres_user",
                       password = "postgres_user",
                       port = 5432)

凭证数据框架:

credentials <- data.frame(
   user = c("shiny", "admin"),
   password = c("shiny", "admin"),
   start = c(NA, NA),
   expire = c(NA, NA),
   admin = c(FALSE, TRUE),
   stringsAsFactors = FALSE)

写入SQL表格:

create_sql_tables(conn,
                  credentials_data = credentials,
                  passphrase = NULL
)

UI部分:

ui <- fluidPage(
  h2("My secure application"),
  verbatimTextOutput("auth_output")
)

安全应用:

ui <- secure_app(ui, enable_admin = TRUE)

服务器部分:

server <- function(input, output, session) {

  res_auth <- secure_server(
    check_credentials = check_credentials(conn, passphrase = NULL, sql = TRUE)
  )

  output$auth_output <- renderPrint({ reactiveValuesToList(res_auth) })

}

shinyApp(ui, server)
英文:

The current version of the shinymanager package supports the admin page with SQLite only. Making this functionality available in SQL-based databases require a significant amount of work to make this work.

I have updated the shinymanager package with new functions to add admin page capability while using SQL databases like PostgreSQL.

I have added a pull request to add additional updates to the main package. In the meantime, you can install the R-Package from here:

remotes::install_github(&quot;devops-qubits/shinymanager&quot;)

You would need to add your own DB creds in the conn.

library(RPostgres)
library(shiny)
library(shinymanager)
library(DBI)



conn &lt;- DBI::dbConnect(RPostgres::Postgres(),
                       host   = &quot;localhost&quot;,
                       dbname = &quot;postgres_db&quot;,
                       user = &quot;postgres_user&quot;,
                       password = &quot;postgres_user&quot;,
                       port = 5432)

 

## Credentials data.frame
credentials &lt;- data.frame(
   user = c(&quot;shiny&quot;, &quot;admin&quot;),
   password = c(&quot;shiny&quot;, &quot;admin&quot;),
   start = c(NA, NA),
   expire = c(NA, NA),
   admin = c(FALSE, TRUE),
   stringsAsFactors = FALSE)

 

## Write SQL tables
create_sql_tables(conn,
                  credentials_data = credentials,
                  passphrase = NULL
)

 

ui &lt;- fluidPage(
  h2(&quot;My secure application&quot;),
  verbatimTextOutput(&quot;auth_output&quot;)
)

 

ui &lt;- secure_app(ui, enable_admin = TRUE)

 


server &lt;- function(input, output, session) {

  res_auth &lt;- secure_server(
    check_credentials = check_credentials(conn, passphrase = NULL, sql = TRUE)
  )

  output$auth_output &lt;- renderPrint({ reactiveValuesToList(res_auth) })

}

 

shinyApp(ui, server)

答案2

得分: -1

我想尝试这个

library(shiny)
library(shinymanager)

# 定义凭据(将这些替换为您的实际用户名和密码)
credentials <- data.frame(
  user = c("admin", "user"),
  password = c("adminpass", "userpass"),
  stringsAsFactors = FALSE
)

# 定义Shiny应用的用户界面
ui <- fluidPage(
  # 使用secure_app()包装您的应用界面
  secure_app(
    # 使用secure_ui()包装需要身份验证的应用部分
    secure_ui(
      fluidPage(
        titlePanel("我的Shiny应用"),
        # 您的应用内容放在这里
        # ...
      )
    )
  )
)

# 定义Shiny应用的服务器
server <- function(input, output, session) {
  # 使用secure_server()包装您的应用服务器
  secure_server(
    function(input, output, session) {
      # 您的应用服务器逻辑放在这里
      # ...
    },
    # 将凭据传递给secure_server()
    user_data = credentials
  )
}

# 运行Shiny应用
shinyApp(ui, server)
英文:

I think to try this

library(shiny)
library(shinymanager)

# Define credentials (replace these with your actual username and password)
credentials &lt;- data.frame(
  user = c(&quot;admin&quot;, &quot;user&quot;),
  password = c(&quot;adminpass&quot;, &quot;userpass&quot;),
  stringsAsFactors = FALSE
)

# Define your Shiny app UI
ui &lt;- fluidPage(
  # Wrap your app UI with secure_app()
  secure_app(
    # Wrap the parts of your app that require authentication with secure_ui()
    secure_ui(
      fluidPage(
        titlePanel(&quot;My Shiny App&quot;),
        # Your app content goes here
        # ...
      )
    )
  )
)

# Define your Shiny app server
server &lt;- function(input, output, session) {
  # Wrap your app server with secure_server()
  secure_server(
    function(input, output, session) {
      # Your app server logic goes here
      # ...
    },
    # Pass the credentials to secure_server()
    user_data = credentials
  )`enter code here`
}

# Run the Shiny app
shinyApp(ui, server)

答案3

得分: -4

为了在使用PostgreSQL数据库的Shiny Manager中启用管理员模式,您可以在PostgreSQL数据库中创建一个单独的表格来存储管理员用户的凭据,并实现检查管理员权限的必要逻辑在my_custom_check_creds函数中。以下是实现这一目标的步骤:

  1. 在您的PostgreSQL数据库中创建一个新的表格来存储管理员用户的凭据。您可以将这个表格命名为"admin_table"或任何您喜欢的名称。
# 在PostgreSQL数据库中创建一个新表格"admin_table"
DBI::dbWriteTable(con, "admin_table", data.frame(
  user = c("admin"),     # 添加管理员用户名
  password = c("123"),   # 添加管理员密码
  isAdmin = TRUE,        # 添加一个标记管理员用户的列
  stringsAsFactors = FALSE
))
  1. 修改my_custom_check_creds函数以检查管理员权限。
my_custom_check_creds <- function(dbname, host, port, db_user, db_password) {

  function(user, password) {

    con <- dbConnect(dbDriver("PostgreSQL"), dbname = dbname, 
                     host = host, port = port,
                     user = db_user, password = db_password)

    on.exit(dbDisconnect(con))

    # 检查用户是否是管理员
    admin_req <- glue_sql("SELECT * FROM admin_table WHERE \"user\" = ({user}) AND \"password\" = ({password})",
                          user = user, password = password, .con = con)

    admin_req <- dbSendQuery(con, admin_req)
    admin_res <- dbFetch(admin_req)
    isAdmin <- nrow(admin_res) > 0

    # 检查用户是否是普通用户
    req <- glue_sql("SELECT * FROM my_table WHERE \"user\" = ({user}) AND \"password\" = ({password})",
                    user = user, password = password, .con = con)

    req <- dbSendQuery(con, req)
    res <- dbFetch(req)

    if (nrow(res) > 0) {
      list(result = TRUE, user_info = list(user = user, isAdmin = isAdmin))
    } else {
      list(result = FALSE)
    }
  }
}
  1. 现在,在您的server函数中,您可以访问用户信息并检查管理员权限。根据用户的角色(管理员或普通用户),您可以在Shiny应用程序中显示或隐藏某些元素。
server <- function(input, output, session) {
  res_auth <- secure_server(
    check_credentials = my_custom_check_creds(
      dbname = "******",
      host = "*****",
      port = ****,
      db_user = "*****",
      db_password = "*******"
    )
  )

  auth_output <- reactive({
    reactiveValuesToList(res_auth)
  })

  # 访问信息
  observe({
    user_info <- auth_output()$user_info
    if (!is.null(user_info)) {
      user <- user_info$user
      isAdmin <- user_info$isAdmin
      print(paste("User:", user, "isAdmin:", isAdmin))
      # 根据isAdmin值实现您的逻辑(例如,显示/隐藏某些UI元素)
    }
  })
}

至于您问题的第二部分,关于添加基于Cookie的身份验证以避免重新输入凭据,您可以使用shinymanager::shinymanager_auth函数并使用cookie = TRUE参数来启用基于Cookie的身份验证。shinymanager_auth函数可以在设置Shiny应用程序的UI和服务器之前使用。

# 在设置UI和服务器之前
shinymanager::shinymanager_auth(
  appTitle = "My Secure Application",
  check_credentials = my_custom_check_creds(
    dbname = "******",
    host = "*****",
    port = ****,
    db_user = "*****",
    db_password = "*******"
  ),
  cookie = TRUE  # 启用基于Cookie的身份验证
)

这将允许用户在页面刷新和会话之间保持身份验证状态。

请确保根据您的特定PostgreSQL设置和要求调整代码。

英文:

To enable admin mode with Shiny Manager using a PostgreSQL database, you can create a separate table in your PostgreSQL database to store admin user credentials and implement the necessary logic to check for admin rights in the my_custom_check_creds function. Below are the steps to achieve this:

  1. Create a new table in your PostgreSQL database to store admin user credentials. You can call this table "admin_table" or any other name you prefer.
# Create a new table &quot;admin_table&quot; in the PostgreSQL database
DBI::dbWriteTable(con, &quot;admin_table&quot;, data.frame(
  user = c(&quot;admin&quot;),     # Add the admin username(s)
  password = c(&quot;123&quot;),   # Add the admin password(s)
  isAdmin = TRUE,        # Add a column to mark admin users
  stringsAsFactors = FALSE
))
  1. Modify the my_custom_check_creds function to check for admin rights.
my_custom_check_creds &lt;- function(dbname, host, port, db_user, db_password) {

  function(user, password) {

    con &lt;- dbConnect(dbDriver(&quot;PostgreSQL&quot;), dbname = dbname, 
                     host = host, port = port,
                     user = db_user, password = db_password)

    on.exit(dbDisconnect(con))

    # Check if the user is an admin
    admin_req &lt;- glue_sql(&quot;SELECT * FROM admin_table WHERE \&quot;user\&quot; = ({user}) AND \&quot;password\&quot; = ({password})&quot;,
                          user = user, password = password, .con = con)

    admin_req &lt;- dbSendQuery(con, admin_req)
    admin_res &lt;- dbFetch(admin_req)
    isAdmin &lt;- nrow(admin_res) &gt; 0

    # Check if the user is a regular user
    req &lt;- glue_sql(&quot;SELECT * FROM my_table WHERE \&quot;user\&quot; = ({user}) AND \&quot;password\&quot; = ({password})&quot;,
                    user = user, password = password, .con = con)

    req &lt;- dbSendQuery(con, req)
    res &lt;- dbFetch(req)

    if (nrow(res) &gt; 0) {
      list(result = TRUE, user_info = list(user = user, isAdmin = isAdmin))
    } else {
      list(result = FALSE)
    }
  }
}
  1. Now, in your server function, you can access the user information and check for admin rights. Based on the user's role (admin or regular user), you can show or hide certain elements in the Shiny app.
server &lt;- function(input, output, session) {
  res_auth &lt;- secure_server(
    check_credentials = my_custom_check_creds(
      dbname = &quot;******&quot;,
      host = &quot;*****&quot;,
      port = ****,
      db_user = &quot;*****&quot;,
      db_password = &quot;*******&quot;
    )
  )

  auth_output &lt;- reactive({
    reactiveValuesToList(res_auth)
  })

  # access info
  observe({
    user_info &lt;- auth_output()$user_info
    if (!is.null(user_info)) {
      user &lt;- user_info$user
      isAdmin &lt;- user_info$isAdmin
      print(paste(&quot;User:&quot;, user, &quot;isAdmin:&quot;, isAdmin))
      # Implement your logic based on isAdmin value (e.g., show/hide certain UI elements)
    }
  })
}

Regarding the second part of your question about adding cookie-based authentication to avoid re-typing credentials, you can use the shinymanager::shinymanager_auth function with the cookie = TRUE argument to enable cookie-based authentication. The shinymanager_auth function can be used before setting up your Shiny app's UI and server.

# Before setting up the UI and server
shinymanager::shinymanager_auth(
  appTitle = &quot;My Secure Application&quot;,
  check_credentials = my_custom_check_creds(
    dbname = &quot;******&quot;,
    host = &quot;*****&quot;,
    port = ****,
    db_user = &quot;*****&quot;,
    db_password = &quot;*******&quot;
  ),
  cookie = TRUE  # Enable cookie-based authentication
)

This will allow users to stay authenticated across page refreshes and sessions.

Please make sure to adapt the code according to your specific PostgreSQL setup and requirements.

huangapple
  • 本文由 发表于 2023年7月14日 09:13:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/76684132.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定