/
crunchy-ui.R
142 lines (129 loc) · 4.45 KB
/
crunchy-ui.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# TODO Vignette outline:
# Simple version: use crunchyServer instead of shinyServer, and wrap your UI
# body that you want protected by auth inside of crunchyBody
#
# Options:
# * Specify a different "unauthenticated" page with crunchyPublicBody in your UI,
# after you specify crunchyBody
# * Add authorization requirements so that you require more than just being logged
# into crunch. Either specify an expression in the `authz` arg to crunchyServer,
# or setCrunchyAuthorization() outside of the server function
# * Add a different "unauthorized" page with crunchyUnauthorizedBody in your UI
#' A Shiny UI with Crunch auth
#'
#' When using [crunchyServer()] to wrap your app in Crunch authentication and
#' authorization, you need to wrap your UI body content inside `crunchyBody()`.
#'
#' This is the part that is conditionally rendered if the user is allowed.
#' Any UI elements you want always to show, including `<head>` tags, should go
#' outside this function.
#' @param ... UI elements for your app
#' @return A `uiOutput()` container into which `crunchyServer()` will
#' conditionally render output.
#' @export
#' @seealso [crunchyPublicBody()] [crunchyServer()]
#' @examples
#' \dontrun{
#' shinyUI(fluidPage(
#' tags$head(
#' # This is content that will always be rendered
#' tags$title("My secure app")
#' ),
#' crunchyBody(
#' # This is content that only is rendered if the user is authorized
#' fluidRow(
#' column(6, h1("Column 1")),
#' column(6, h1("Column 2"))
#' )
#' )
#' ))
#' }
crunchyBody <- function (...) {
# This is called inside a UI function. It captures the body content you
# request, stores it for lazy calling inside crunchyServer(), then returns
# the div that crunchyServer() will write into
crunchUIOutput(...)
uiOutput("crunch_body")
}
#' Alternate UIs for unauthenticated and unauthorized users
#'
#' [crunchyServer()] and [crunchyBody()] allow you to protect your app with
#' Crunch authentication and authorization. Add these UI contents to your
#' [shiny::shinyUI()] body to display different content for visitors who are
#' not authenticated with Crunch (`crunchyPublicBody()`) or who are
#' authenticated but not authorized to access your app
#' (`crunchyUnauthorizedBody`).
#' @param ... UI elements for your app, to be conditionally rendered
#' @return An empty string; these functions are called for their side effects of
#' registering the UI elements so that `crunchyServer()` can render them as
#' appropriate.
#' @export
#' @seealso [crunchyBody()]; [setCrunchyAuthorization()] for governing who is
#' authorized to view your app.
#' @examples
#' \dontrun{
#' # This is the example from crunchyBody(), adding these alternate bodies:
#' shinyUI(fluidPage(
#' tags$head(
#' # This is content that will always be rendered
#' tags$title("My secure app")
#' ),
#' crunchyBody(
#' # This is content that only is rendered if the user is authorized
#' fluidRow(
#' column(6, h1("Column 1")),
#' column(6, h1("Column 2"))
#' )
#' ),
#' crunchyPublicBody(
#' # This is shown to visitors who are not logged into Crunch at all
#' h1("Please log into Crunch.")
#' ),
#' crunchyUnauthorizedBody(
#' # This is for Crunch users who don't meet your authorization criteria
#' # Perhaps they don't have access to a particular dataset
#' h1("You don't have access to this app."),
#' tags$div("Contact your_admin@example.com.")
#' )
#' ))
#' }
crunchyPublicBody <- function (...) {
crunchPublicUIOutput(...)
return("")
}
#' @rdname crunchyPublicBody
#' @export
crunchyUnauthorizedBody <- function (...) {
crunchUnauthorizedUIOutput(...)
return("")
}
crunchUIOutput <- function (...) {
ui <- lazyUIOutput(...)
options(crunchy.body=ui)
ui
}
crunchPublicUIOutput <- function (...) {
ui <- lazyUIOutput(...)
options(crunchy.body.public=ui)
ui
}
crunchUnauthorizedUIOutput <- function (...) {
ui <- lazyUIOutput(...)
options(crunchy.body.unauthorized=ui)
ui
}
lazyUIOutput <- function (...) {
function () {
tags$div(...)
}
}
crunchyDefaultPublicUI <- function () {
lazyUIOutput(
tags$h1("You are not authenticated"),
tags$div(
"Try logging in at ",
tags$a(href="https://app.crunch.io/login", "https://app.crunch.io/login"),
"."
)
)
}