Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: a way to not load the UI until after logging in #5

Open
daattali opened this issue Dec 18, 2020 · 4 comments
Open
Labels
feature New feature

Comments

@daattali
Copy link

daattali commented Dec 18, 2020

I'm not sure how, or if it's possible, but the current way of requiring all content to use either f$req_sign_in() or reqSignin() seems like it would get tedious and very verbose very fast. It would be good to have bypass that, like how RStudio's authentication and {auth0} really don't load the UI until it's safe to do so

@bjungbogati
Copy link

I agree with @daatalli, authentication in UI would be great.

Is there any workround for this problem @JohnCoene.

@JohnCoene
Copy link
Owner

Yes indeed, it does get tedious.

It could be done but it's quite a bit of work.

There are two ways I can think of doing this: by hijacking the app object as returned by shinyApp to, instead of returning the UI as response, return the login screen (when GET /).

Then either upon login load the shiny UI via websocket (can't return another response), or from the UI screen exectute a POST to another handler (e.g.: /login) which would return the UI.

The first is likely to cause issues with the rendering of some things as the UI is not meant to be loaded like that (e.g.: dependencies), the second is rather convoluted as it feels like we're logging people in twice.

There might be an easier way but I'm not seeing it.

Currently, using modules it's possible to reduce the use req_sign_in somewhat.

  observeEvent(f$req_sign_in(), {
    callModule(module_name_server, "module_name")
  })

@JohnCoene JohnCoene added the feature New feature label Oct 24, 2021
@chris31415926535
Copy link

Here's a potential workaround: build your ui() as usual, but wrap it in a call to shiny::renderUI() with a single f$req_sign_in().

The toy example below works for me: the text "Logged in!" doesn't show up in the html (as inspected using Chrome's dev panel) until you log in. I haven't tested it with a full app, but it worked okay with some buttons and other inputs and outputs.

Here's a screenshot showing the empty div "logged_in_ui" using this method:

image

Using firebase::reqSignIn() seems to just hide elements, so they can be found in the html. Here's the same ui wrapped in reqSignIn(): the text is there, just made invisible with the css style = display: none; .

image

This is a very minimal example, so maybe there are disadvantages in more complex cases--@JohnCoene, are there any obvious reasons this is a bad idea?

ui_secure <- fluidPage(
  useFirebase(), # import dependencies
  firebaseUIContainer(),
  
  shiny::uiOutput("logged_in_ui")
)

ui_secret <- shiny::fluidPage(
  h4("Logged in!")
)

server <- function(input, output){
  
  f <- FirebaseUI$
    new()$ # instantiate
    set_providers( # define providers
      email = TRUE,
      google = TRUE
    )$
    launch() # launch
  
  output$logged_in_ui <- shiny::renderUI({
    f$req_sign_in()
    ui_secret
  })
}

shiny::shinyApp(ui = ui_secure, server = server)

I'm posting here since there's been more discussion, but it's mostly a duplicate of this issue.

@durraniu
Copy link

@chris31415926535 Thank you for the solution above. I am trying to extend it with using a modal dialog. It works nicely for sign in but when signed out, It does not show the firebaseUI again. I'll appreciate any advice.

library(shiny)
library(firebase)
library(bslib)

# Firebase project configuration ------------------------------------------

firebase::firebase_config(api_key = "API_KEY",
                          project_id = "PROJECT_ID",
                          app_id = "APP_ID",
                          overwrite = TRUE)



# define signin
signin <- modalDialog(
  title = "Welcome. Please Sign in.",
  # useFirebase(),
  firebaseUIContainer(),
  footer = NULL
)


ui_dashboard <- page_navbar(

  title = "title",
  sidebar = sidebar("Sidebar"),
  nav_panel("P1", "Page 1 content"),
  nav_panel("P2", "Page 2 content"),
  nav_panel("P3", "Page 3 content"),
  nav_panel("P4", "Page 4 content"),

  ## Space between sections and sign out button
  nav_spacer(),
  ## Sign out button
  nav_item(
    uiOutput("sign_out_button")
  )
)


ui <- page_fillable(
  useFirebase(),
  shiny::uiOutput("logged_in_ui", fill = TRUE)
)

server <- function(input, output) {
  showModal(signin)

  f <- FirebaseUI$new()$set_providers(
    email = TRUE,
    google = TRUE)$launch()

  observe({
    f$req_sign_in()
    removeModal()
  })

  output$sign_out_button <- shiny::renderUI({
    f$req_sign_in()
    actionButton("signout", "Sign out")
  })


  observeEvent(input$signout, {
    f$sign_out()

    # Show the modal dialog
    showModal(signin)
  })

  output$logged_in_ui <- shiny::renderUI({
    f$req_sign_in()
    ui_dashboard
  })
}

shinyApp(ui, server)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New feature
Projects
None yet
Development

No branches or pull requests

5 participants