【问题标题】:How to block or restrict access when a user is already using a Shiny app当用户已经在使用 Shiny 应用程序时如何阻止或限制访问
【发布时间】:2023-03-26 19:51:01
【问题描述】:

我有一个使用 Ace 编辑器的 Shiny 应用程序。现在我想拥有它,以便当第一个用户使用此编辑器时,其他用户无法编辑文档,而只能查看文档。

如何实现?

代码是:

library(shiny)
library(shinyAce)
library(stringi)

ui <- fluidPage(
  br(),
  uiOutput("aceEditor1"),
  downloadButton('save1', 'Save editor content')
)

server <- function(input, output, session)
{
  output$aceEditor1 <- renderUI(
  {
    aceEditor(outputId = "ace1", 
              value = paste(stri_rand_lipsum(3), collapse="\n\n"),
              mode = "r", 
              height = "500px", 
              fontSize = 17, 
              theme = "chrome", 
              wordWrap = TRUE)
  })

  output$save1 <- downloadHandler (
    filename = function() 
    { 
      "result.txt" 
    },

    content = function(file) 
    { 
       write.table(x = input$ace1, file = file, sep = "", row.names = FALSE, col.names = FALSE, quote = FALSE) 
    }
  )
}

shinyApp(ui = ui, server = server)

【问题讨论】:

  • 也许您可以定义一个全局变量(在 server 函数之外),当有人进入/退出编辑器时更改 T/F(我不熟悉该小部件的细节)。然后在进入编辑器之前检查变量,如果其他人没有退出,则不允许。见rstudio.github.io/shiny/tutorial/#scoping
  • Ace 编辑器的使用是您可以在线编辑的一个示例。但重要的是,当有人在编辑器中编辑文档时,其他用户不能干预并同时开始编辑该文档。其实代码不是一个很好的例子,要编辑的文档应该是存储在服务器某处的文档。

标签: r shiny privileges ace-editor


【解决方案1】:

您可以通过引入键来实现这一点。本质上,我们创建了一个对所有会话可见的全局键变量。当会话启动时,它会获取密钥并将全局变量设置为不可用。

当一个新会话连接并尝试获取密钥,但它不可用时。

在服务器函数中,我们可以在执行“关键部分”代码之前进行检查。

这基本上是半量标志如何工作的基础知识。

最后,当第一个会话结束时,它会将密钥返回给全局变量。

我们还可以更进一步,使用invalidateLater()定期检查密钥是否可用。

要运行下面的虚拟示例,首先运行它,

write_csv(mtcars,"~/Desktop/data.csv")

应用如下:

library(shiny)


key_available <- TRUE

ui <- fluidPage(
  br(),
  textInput(inputId = "text_input","Text Input"),
  actionButton(inputId = "add_col","Add Column"),
  dataTableOutput("table_output"),
  downloadButton('save1', 'Save editor content')
)

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

  onSessionEnded(function() key_available <<- TRUE)

  # Session starts, Read data in
  have_key <- FALSE

  observe({
    invalidateLater(1000)

    if(key_available){
      key_available <<- FALSE
      have_key <<- TRUE
    }

  })

  data_reactive <- eventReactive(c(input$add_col),{
    data <- read_csv("~/Desktop/data.csv")
    if(have_key){
      data[[input$text_input]] <- NA
      write_csv(data,"~/Desktop/data.csv")
    }

    return(data)
  })


  output$table_output <- renderDataTable({
    req(data_reactive())
    data_reactive()
    })


}

shinyApp(ui = ui, server = server)

打开第一个浏览器窗口,在文本框中添加一个列名,然后单击“添加列”。

您会注意到该列已添加。您可以继续执行此操作,因为此会话具有密钥。

同时打开一个新的浏览器窗口,并尝试执行上述操作将不成功。但是,如果您关闭第一个浏览器窗口,您现在可以在第二个浏览器窗口上进行编辑。

【讨论】:

  • 这是在 Shiny 中使用 &lt;&lt;- 似乎合理的少数情况之一。 +1。但是,如果我没记错的话,对象不会在不同的 R 进程之间共享,所以如果同一个 R 进程支持多个用户会话,这应该可以正常工作,但如果启动一个新的 R 进程来支持任何其他用户,这将无法正常工作。我认为在 R 之外的文件/数据库中管理该密钥会更加健壮。见Scoping Rules for shiny apps
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
  • 2012-07-29
相关资源
最近更新 更多