Rshiny: Как я могу вызвать мою функцию аутентификации JS, чтобы приложение Rshiny могло использовать результат? - PullRequest
0 голосов
/ 14 июля 2020

Итак, у меня есть приложение Rshiny, настроенное на publi sh на сервере, но нам нужен токен аутентификации API, чтобы гарантировать, что данный пользователь имеет доступ. Процесс аутентификации обрабатывается в тегах JS вне приложения, в то время как фактический процесс Rshiny хранится в iFrame на странице.

У меня есть сценарий js, сохраненный извне в подкаталоге www /, упакованном с приложением. Сценарий JS запрашивает значение в localStorage для определения идентификатора пользователя и пингует проверку API с этим токеном для определения доступа. Похоже на это (выборка - это настраиваемая функция, которая запрашивает локальное хранилище для установки значения аутентификации).

/**
 * This Fn ! using to vaidate the user login access
 * @param none
 */
(function validateUserLoginInfo() {
    console.log("Sending user acess");
    var url = `https://authentication-url.com/isAuthy `;
    fetch(url, { method: 'GET' }, function (response) {
        if (response) {
            // user validation is Successfully done
            // $("#userValidated").val("Yes");
        } else {
            //invalid user access/login failure
            //Shiny.setInputValue("userValidated","No")
            // $("#userValidated").val("No");
        }
    });
})(); // => self executing Fn !

То, что я, по сути, пытаюсь сделать, - это запустить эту JS функцию, так что успех дает ввод, переданный в среду сервера Rshiny, например input $ isUserValidated, поэтому я могу маршрутизировать процессы приложения и предупреждать экземпляр о том, что у пользователя нет доступа. Я настроил его так, что текст страницы «Добро пожаловать» изменяется на основе этого проверочного ответа, а фактические вкладки с анализом впоследствии скрываются от экземпляра.

В вызовах if (response) else в функции JS закомментированные строки - это попытки передать ответ серверной среде, но они не сработали. И я считаю, что способ, которым я вызываю эту функцию из приложения, работает, но я не уверен, действительно ли работает функция validateUserLoginInfo.

Так что я могу разбить свою путаницу на два шага

  1. После получения скрипта через tags$head(tags$script(type="text/javascript", src = "www/authenticateUser.js")) или includeScript('www/authenticateUser.js') как я могу запустить фактическую функцию validateUserLoginInfo() с сервера r? Или он уже запускается автоматически при загрузке приложения?

  2. После вызова validateUserLoginInfo(), как я могу передать ответ от этого вызова, чтобы сервер R мог его использовать?

Вот, надеюсь, простое приложение, которое улавливает то, что я ищу. Функцию AuthenticateUser. js можно рассматривать как функцию, которая возвращает просто «Да» или «Нет», и я просто пытаюсь получить доступ к этому ответу с сервера R.

ui <- fluidPage(
  includeScript('www/authenticateUser.js')
  textOutput('authed'),
)
server <- function(input,output,session){
  output$authed <- renderText({
    # No clue which one of these works; none have worked for me so far
    response <- input$userValidated
    response2 <- validateUserLoginInfo()
    response3 <- shinyjs::js$validateUserLoginInfo()
    return(c(response,response2,response3))
  })
}

Я искал ответы повсюду и, похоже, не нашел ничего, что помогло бы мне достичь sh здесь. Отправка предупреждений или событий onClick из JS <-> Shiny, похоже, является тем, что большинство людей используют JS для Rshiny. Так что любая помощь приветствуется. Спасибо.

1 Ответ

0 голосов
/ 15 июля 2020

На сервере Shiny попробуйте заключить вывод renderText в observeEvent, который запускается при изменении значения userValidated.

server <- function(input, output, session) {
  observeEvent(input$userValidated, {
    output$auth <- renderText({
       input$userValidated
    })
  }, ignoreNULL = TRUE)
}

В функции js validateuserLoginInfo, используйте response.ok, чтобы оценить статус запроса и соответственно установить значение userValidated.

Я не уверен, какую информацию вам нужно отправить с запросом, поэтому вот пример, демонстрирующий концепции . В этом примере я написал короткий запрос, который проверяет, являются ли RStudio и RStudi действительными пользователями GitHub (второй URL-адрес не будет использоваться при использовании в запросе).

library(shiny)

# js
js <- '
// validate user (this will run on page load)
(function validateUserLoginInfo() {
    console.log("Sending user acess");

    // set url (using github API as a generic example; test each url)
    //var url = "https://api.github.com/users/rstudio" // this will pass
    var url = "https://api.github.com/users/rstudi" // this will fail

    // create a new request
    fetch(url, {method: "GET"})
    .then((response) => {
        if (response.ok) {
            return response.json();
        } else {
            throw new Error(response.status);
        }
    })
    .then((result) => {

        // set shiny input as true
        Shiny.setInputValue("userValidated", JSON.stringify(true));

    }).catch((error) => {

        // set input as false + log error
        Shiny.setInputValue("userValidated", JSON.stringify(false));
        console.log(error);
    });

})();
'

# ui
ui <- fluidPage(
  textOutput("authed"),
  tags$script(HTML(js))
)

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

    # run when change
    observeEvent(input$userValidated, {
        response <- jsonlite::fromJSON(input$userValidated)
        output$authed <- renderPrint({
            response
        })
    }, ignoreNULL = TRUE)
}

# app
shinyApp(ui, server)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...