How to use shinymanager along with session$onSessionEnded() to close the app upon browser close

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

How to use shinymanager along with session$onSessionEnded() to close the app upon browser close

问题

I can provide the translated part of your text:

我有一个使用shinymanager库进行用户登录的应用程序。我想使用session$onSessionEnded()在浏览器关闭时关闭我的应用程序,正如Joe Chang的建议中所示。

没有使用shinymanager时,应用程序运行正常。有什么想法为什么会发生这种情况?

示例代码:

library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinymanager)

credentials <- data.frame(
  user = c("admin", "shinymanager"), # 必填
  password = c("admin", "12345"), # 必填
  start = c("2022-04-15"), # 可选(其他都是必填项)
  expire = c(NA, "2026-12-31"),
  admin = c(TRUE, TRUE),
  comment = "简单且安全的身份验证机制,适用于单个'Shiny'应用程序。",
  stringsAsFactors = FALSE
)

ui <- fluidPage(
  sliderInput("n", "观察次数", 2, 1000, 500),
  plotOutput("plot")
)

ui <- secure_app(ui)

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

  res_auth <- secure_server(
    check_credentials = check_credentials(credentials)
  )

  session$onSessionEnded(function() {
    stopApp()
  })

  observe({
    # 每隔1000毫秒重新执行此响应式表达式
    invalidateLater(1000, session)
    print(paste("输入$n的值为", isolate(input$n)))
  })
  output$plot <- renderPlot({
    # 每隔2000毫秒重新执行此响应式表达式
    invalidateLater(2000)
    hist(rnorm(isolate(input$n)))
  })
}

shinyApp(ui, server)

有人可以为我提供一个解决方法吗?

请注意,我只提供了代码部分的翻译,没有回答您关于翻译的问题。

英文:

I have an application which uses the shinymanager library for user login. I want to use the session$onSessionEnded() to close my app once the browser is closed as suggested in the link Close Shiny App upon Browser close by Joe Chang

App is working fine without using the shinymanager. Any idea why this is happening ?

sample code:

library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinymanager)

credentials &lt;- data.frame(
  user = c(&quot;admin&quot;, &quot;shinymanager&quot;), # mandatory
  password = c(&quot;admin&quot;, &quot;12345&quot;), # mandatory
  start = c(&quot;2022-04-15&quot;), # optinal (all others)
  expire = c(NA, &quot;2026-12-31&quot;),
  admin = c(TRUE, TRUE),
  comment = &quot;Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.&quot;,
  stringsAsFactors = FALSE
)


ui &lt;- fluidPage(
  sliderInput(&quot;n&quot;, &quot;Number of observations&quot;, 2, 1000, 500),
  plotOutput(&quot;plot&quot;)
)

ui &lt;- secure_app(ui)

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

  res_auth &lt;- secure_server(
    check_credentials = check_credentials(credentials)
  )
  
  session$onSessionEnded(function() {
    stopApp()
  })

  observe({
    # Re-execute this reactive expression after 1000 milliseconds
    invalidateLater(1000, session)
    print(paste(&quot;The value of input$n is&quot;, isolate(input$n)))
  })
  output$plot &lt;- renderPlot({
    # Re-execute this reactive expression after 2000 milliseconds
    invalidateLater(2000)
    hist(rnorm(isolate(input$n)))
  })
}

shinyApp(ui, server)

Can someone suggest me workaround for this.

答案1

得分: 1

{shinymanager}的登录界面在一个单独的shiny会话中运行,用户登录后会结束该会话。因此,在登录后,您上面的应用程序会停止。

编辑:

作为session$onSessionEnded()的替代方案,我们可以监听JS unload事件

library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinymanager)

credentials <- data.frame(
  user = c("admin", "shinymanager"), # 必填
  password = c("admin", "12345"), # 必填
  start = c("2022-04-15"), # 可选(所有其他)
  expire = c(NA, "2026-12-31"),
  admin = c(TRUE, TRUE),
  comment = "Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.",
  stringsAsFactors = FALSE
)

ui <- fluidPage(
  tags$script(HTML("$(window).on('unload', function(event) {
                      Shiny.setInputValue(id = 'window_unload', value = true);
                    });")),
  sliderInput("n", "Number of observations", 2, 1000, 500),
  plotOutput("plot")
)

ui <- secure_app(ui)

server <- function(input, output, session) {
  res_auth <- secure_server(
    check_credentials = check_credentials(credentials)
  )

  observeEvent(input$window_unload, {
    print("stopApp()")
    stopApp()
  })

  observe({
    # 在1000毫秒后重新执行此响应式表达式
    invalidateLater(1000, session)
    print(paste("input$n的值是", isolate(input$n)))
  })
  output$plot <- renderPlot({
    # 在2000毫秒后重新执行此响应式表达式
    invalidateLater(2000)
    hist(rnorm(isolate(input$n)))
  })
}

shinyApp(ui, server)

PS: 您可能需要检查[visibilitychange事件][2]是否适用于您的情况。

---

**初始回答:**

因此,我们需要在运行`stopApp`之前检查用户是否已登录:

```R
library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinymanager)

credentials <- data.frame(
  user = c("admin", "shinymanager"), # 必填
  password = c("admin", "12345"), # 必填
  start = c("2022-04-15"), # 可选(所有其他)
  expire = c(NA, "2026-12-31"),
  admin = c(TRUE, TRUE),
  comment = "Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.",
  stringsAsFactors = FALSE
)

ui <- fluidPage(
  sliderInput("n", "Number of observations", 2, 1000, 500),
  plotOutput("plot")
)

ui <- secure_app(ui)

server <- function(input, output, session) {
  res_auth <- secure_server(
    check_credentials = check_credentials(credentials)
  )

  session$onSessionEnded(function() {
    print(paste("Session", session$token, "ended"))
    if(!is.null(isolate({res_auth$user}))){
      stopApp() 
    }
  })

  observe({
    # 在1000毫秒后重新执行此响应式表达式
    invalidateLater(1000, session)
    print(paste("input$n的值是", isolate(input$n)))
  })
  output$plot <- renderPlot({
    # 在2000毫秒后重新执行此响应式表达式
    invalidateLater(2000)
    hist(rnorm(isolate(input$n)))
  })
}

shinyApp(ui, server)
英文:

{shinymanager}'s log-in screen runs in a separate shiny session, which is ended after a user logs in. Therefore your above app stops after log in.

Edit:

As an alternative to session$onSessionEnded() we can listen on the JS unload event:

library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinymanager)
credentials &lt;- data.frame(
user = c(&quot;admin&quot;, &quot;shinymanager&quot;), # mandatory
password = c(&quot;admin&quot;, &quot;12345&quot;), # mandatory
start = c(&quot;2022-04-15&quot;), # optinal (all others)
expire = c(NA, &quot;2026-12-31&quot;),
admin = c(TRUE, TRUE),
comment = &quot;Simple and secure authentification mechanism 
for single ‘Shiny’ applications.&quot;,
stringsAsFactors = FALSE
)
ui &lt;- fluidPage(
tags$script(HTML(&quot;$(window).on(&#39;unload&#39;, function(event) {
Shiny.setInputValue(id = &#39;window_unload&#39;, value = true);
});&quot;)),
sliderInput(&quot;n&quot;, &quot;Number of observations&quot;, 2, 1000, 500),
plotOutput(&quot;plot&quot;)
)
ui &lt;- secure_app(ui)
server &lt;- function(input, output, session) {
res_auth &lt;- secure_server(
check_credentials = check_credentials(credentials)
)
observeEvent(input$window_unload, {
print(&quot;stopApp()&quot;)
stopApp()
})
observe({
# Re-execute this reactive expression after 1000 milliseconds
invalidateLater(1000, session)
print(paste(&quot;The value of input$n is&quot;, isolate(input$n)))
})
output$plot &lt;- renderPlot({
# Re-execute this reactive expression after 2000 milliseconds
invalidateLater(2000)
hist(rnorm(isolate(input$n)))
})
}
shinyApp(ui, server)

PS: you might want to check if the visibilitychange event works in your scenario.


Initial answer:

Accordingly we need to check if a user is logged in before running stopApp:

library(shiny)
library(shinyWidgets)
library(shinythemes)
library(shinymanager)
credentials &lt;- data.frame(
user = c(&quot;admin&quot;, &quot;shinymanager&quot;), # mandatory
password = c(&quot;admin&quot;, &quot;12345&quot;), # mandatory
start = c(&quot;2022-04-15&quot;), # optinal (all others)
expire = c(NA, &quot;2026-12-31&quot;),
admin = c(TRUE, TRUE),
comment = &quot;Simple and secure authentification mechanism 
for single ‘Shiny’ applications.&quot;,
stringsAsFactors = FALSE
)
ui &lt;- fluidPage(
sliderInput(&quot;n&quot;, &quot;Number of observations&quot;, 2, 1000, 500),
plotOutput(&quot;plot&quot;)
)
ui &lt;- secure_app(ui)
server &lt;- function(input, output, session) {
res_auth &lt;- secure_server(
check_credentials = check_credentials(credentials)
)
session$onSessionEnded(function() {
print(paste(&quot;Session&quot;, session$token, &quot;ended&quot;))
if(!is.null(isolate({res_auth$user}))){
stopApp() 
}
})
observe({
# Re-execute this reactive expression after 1000 milliseconds
invalidateLater(1000, session)
print(paste(&quot;The value of input$n is&quot;, isolate(input$n)))
})
output$plot &lt;- renderPlot({
# Re-execute this reactive expression after 2000 milliseconds
invalidateLater(2000)
hist(rnorm(isolate(input$n)))
})
}
shinyApp(ui, server)

huangapple
  • 本文由 发表于 2023年1月6日 14:04:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/75027489.html
匿名

发表评论

匿名网友

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

确定