Serkan
Serkan

Reputation: 1945

How to Secure a tow-file ShinyApp using Shinymanager?

I have a two-file shinyapp-layout with ui.R and server.R, which I want to secure with shinymanager.

Following the instructions works fine when following the guide here. However, this only works for single-layouts where ui.R and server.R are combined into one.

A similar question has been posted here. But this does not solve my question, as the solution is similar to that of the Github-solution(First link).

Reproducible code is given below:

The contents of ui.R

#
# This is the user-interface definition of a Shiny web application. You can
# run the application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(shinymanager)
# Define UI for application that draws a histogram
ui <- secure_app(
    shinyUI(fluidPage(
        
        # Application title
        titlePanel("Old Faithful Geyser Data"),
        
        # Sidebar with a slider input for number of bins
        sidebarLayout(
            sidebarPanel(
                sliderInput("bins",
                            "Number of bins:",
                            min = 1,
                            max = 50,
                            value = 30)
            ),
            
            # Show a plot of the generated distribution
            mainPanel(
                plotOutput("distPlot")
            )
        )
    ))
)

The contents of server.R

#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(shinymanager)


# Define server logic required to draw a histogram
credentials <- data.frame(
    user = c("shiny", "shinymanager"), # mandatory
    password = c("azerty", "12345"), # mandatory
    start = c("2019-04-15"), # optinal (all others)
    expire = c(NA, "2019-12-31"),
    admin = c(FALSE, TRUE),
    comment = "Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.",
    stringsAsFactors = FALSE
)



server <- shinyServer(function(input, output) {
    
    # call the server part
    # check_credentials returns a function to authenticate users
    res_auth <- secure_server(
        check_credentials = check_credentials(credentials)
    )
    
    output$auth_output <- renderPrint({
        reactiveValuesToList(res_auth)
    })
    
    
    output$distPlot <- renderPlot({

        # generate bins based on input$bins from ui.R
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)

        # draw the histogram with the specified number of bins
        hist(x, breaks = bins, col = 'darkgray', border = 'white')

    })

})

If I combine the files into one file, say, app.R, everything works as intended,

#
# This is the server logic of a Shiny web application. You can run the
# application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(shinymanager)


# Define server logic required to draw a histogram
credentials <- data.frame(
    user = c("shiny", "shinymanager"), # mandatory
    password = c("azerty", "12345"), # mandatory
    start = c("2019-04-15"), # optinal (all others)
    expire = c(NA, "2019-12-31"),
    admin = c(FALSE, TRUE),
    comment = "Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.",
    stringsAsFactors = FALSE
)



server <- shinyServer(function(input, output) {
    
    # call the server part
    # check_credentials returns a function to authenticate users
    res_auth <- secure_server(
        check_credentials = check_credentials(credentials)
    )
    
    output$auth_output <- renderPrint({
        reactiveValuesToList(res_auth)
    })
    
    
    output$distPlot <- renderPlot({
        
        # generate bins based on input$bins from ui.R
        x    <- faithful[, 2]
        bins <- seq(min(x), max(x), length.out = input$bins + 1)
        
        # draw the histogram with the specified number of bins
        hist(x, breaks = bins, col = 'darkgray', border = 'white')
        
    })
    
})

#
# This is the user-interface definition of a Shiny web application. You can
# run the application by clicking 'Run App' above.
#
# Find out more about building applications with Shiny here:
#
#    http://shiny.rstudio.com/
#

library(shiny)
library(shinymanager)
# Define UI for application that draws a histogram
ui <- secure_app(
    shinyUI(fluidPage(
        
        # Application title
        titlePanel("Old Faithful Geyser Data"),
        
        # Sidebar with a slider input for number of bins
        sidebarLayout(
            sidebarPanel(
                sliderInput("bins",
                            "Number of bins:",
                            min = 1,
                            max = 50,
                            value = 30)
            ),
            
            # Show a plot of the generated distribution
            mainPanel(
                plotOutput("distPlot")
            )
        )
    ))
)


shinyApp(ui,server)

This is the exact same code, except for the addition of shinyApp(ui,server).

Upvotes: 0

Views: 765

Answers (1)

Serkan
Serkan

Reputation: 1945

If anyone is looking for an answer to this, it was - awkwardly- simple. Assume that you have one script pr ui.R and server.R, such that the server-logic is given as,

Here the server-logic is saved as tab.R

output$content1 <- renderUI({
    "Tab 1 content"
})

output$content2 <- renderUI({
    "Tab 2 content"
})

And the ui contents is saved as tab.R aswell,

tabPanel(
    "Tab 1",
    uiOutput("content1")
)

tabPanel(
    "Tab 2",
    uiOutput("content2")
)

Then collecting everything in app.R, with the following contents will secure the app;

library(shiny)
library(shinymanager)

# See https://datastorm-open.github.io/shinymanager/ and https://github.com/daattali/advanced-shiny/blob/master/split-code/app.R

credentials <- data.frame(
    user = c("shiny", "shinymanager"), # mandatory
    password = c("azerty", "12345"), # mandatory
    start = c("2019-04-15"), # optinal (all others)
    expire = c(NA, "2019-12-31"),
    admin = c(FALSE, TRUE),
    comment = "Simple and secure authentification mechanism 
  for single ‘Shiny’ applications.",
    stringsAsFactors = FALSE
)



ui <- navbarPage(
   
     title = "Securing App across multiple files",
    
    # include the UI for each tab
    source(file.path("ui", "tab.R"),  local = TRUE)$value
)


ui <- secure_app(ui)


server <- function(input, output, session) {
    
    # call the server part
    # check_credentials returns a function to authenticate users
    res_auth <- secure_server(
        check_credentials = check_credentials(credentials)
    )
    
    output$auth_output <- renderPrint({
        reactiveValuesToList(res_auth)
    })
    
    # Include the logic (server) for each tab
    source(file.path("server", "tab.R"),  local = TRUE)$value

}

shinyApp(ui = ui, server = server)

See here and here for more information.

Upvotes: 1

Related Questions