-
Notifications
You must be signed in to change notification settings - Fork 5
Create R script to replicate App outputs (#467) #789
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
base: main
Are you sure you want to change the base?
Changes from all commits
6f54851
867957d
84207ca
27a933f
8fe876d
3b8a051
76ebe77
b214e70
3e6ee2c
07bc425
0dedfca
68ef670
cf2d74b
2a898fc
3a2f51d
09eb170
4f49a86
bc3fb4d
bc10724
81667bb
c825d48
9c0d993
fe89909
28e44f1
87a25c8
0cf7275
16bf164
198cd9e
9555215
a844516
bd22e67
8d7925b
930a02f
eab4308
163654b
af86697
94596fe
e9122bb
3cbbd23
afc3cd6
521e856
25ebaa6
06a3860
37e5009
1aea3b8
d518136
ecef742
5ae7cf7
df923f6
4f10ab8
2f7fd28
6972895
862e2aa
e288422
d89b4aa
da94426
0e224d3
19cdcde
f36af9a
8e29485
c35f58d
75e5fe0
6871759
2a68562
c69e9bc
a516839
e2e2819
dcf98c8
3a44f36
5efa505
80e05ad
110595e
17594ab
e9254c4
3b0a9e4
1ebfeaf
0f4acac
28a2841
e150b75
613ece8
a845355
70fd838
05f2c98
1c3921b
9f02bfc
c34b7bb
377ed97
f19fc1a
d140074
1aa17fe
b5ef41d
1b78da1
a332b90
af3fd7c
7144766
ef71957
47c2b2f
1fb2b2a
892d4d8
b80a389
5b60c53
cb35e83
20c47d4
3370ca7
086f66e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,191 @@ | ||||||
| #' Generate a session script code in R that can replicate the App outputs | ||||||
| #' | ||||||
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| #' @param template_path Path to the R script template (e.g., script_template.R) | ||||||
| #' @param session The session object containing userData, etc. | ||||||
| #' @param output_path Path to write the resulting script file (e.g., "output_script.R") | ||||||
| #' @return The output_path (invisibly) | ||||||
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| #' @export | ||||||
| get_session_code <- function(template_path, session, output_path) { | ||||||
| # Helper to get value from session$userData by path (e.g., 'settings$method') | ||||||
| get_session_value <- function(path) { | ||||||
| parts <- strsplit(path, "\\$")[[1]] | ||||||
| obj <- session$userData | ||||||
| for (p in parts) { | ||||||
| if (inherits(obj[[p]], "reactive")) { | ||||||
| obj <- obj[[p]]() | ||||||
| } else { | ||||||
| obj <- obj[[p]] | ||||||
| } | ||||||
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| if (is.null(obj)) { | ||||||
| return(NULL) | ||||||
| } | ||||||
| } | ||||||
| obj | ||||||
| } | ||||||
| # Read template | ||||||
| script <- readLines(template_path, warn = FALSE) %>% | ||||||
| paste(collapse = "\n") | ||||||
|
|
||||||
| # Find all session$userData$... | ||||||
| pattern <- "session\\$userData(\\$[a-zA-Z0-9_]+(\\(\\))?(\\$[a-zA-Z0-9_]+)*)" | ||||||
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
| pattern <- "session\\$userData(\\$[a-zA-Z0-9_]+(\\(\\))?(\\$[a-zA-Z0-9_]+)*)" | |
| pattern <- "session\\$userData(\\$[a-zA-Z0-9_]+(\\$[a-zA-Z0-9_]+)*)" |
Copilot
AI
Dec 5, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error message could be more helpful by including the actual template path that was attempted. This would help users debug path issues. Consider:
stop(
"Template at '", template_path, "' has no placeholders (session$userData...) to substitute. ",
"This may be due to an incorrect file path, a missing template, ",
"or a modified template without placeholders."
)| "Template has no placeholders (session$userData...) to substitute.", | |
| "Template at '", template_path, "' has no placeholders (session$userData...) to substitute. ", |
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
Gero1999 marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Dec 30, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_session_code writes a runnable R script by interpolating values from session$userData, but clean_deparse.character and .deparse_vector embed raw string contents into the generated code without escaping quotes, backslashes, or newlines. An attacker who controls any session$userData string used in the template (for example via uploaded data, mapping names, or text inputs) can craft a value like "abc"); system("whoami"); # so that the exported session_code.R contains and executes arbitrary R commands when run. To mitigate this, ensure that all character data and list/data.frame names are safely encoded for R string literals (e.g., via robust escaping or dput-style serialization) before being inserted into the script, or treat the export as pure data rather than executable code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: I believe this whole file should be in
inst/shinysince it is only related and usable from within the application and it handles app-specific entities, like the session object.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a good point, but for automation purposes it can also be interesting for some programming-users to use this function with a settings file and then perhaps just change the input rather than go through the App
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, but currently the function needs the session object, so you have to go through the app anyway? I would agree if the function also accepted a settings file and had a more generic name, but currently it does not.
At the very least, if we want to implement it this way right now and then add the functionality of parsing a settings file instead of session object, we should have
# TODOcomments with link or number of appropriate issue to rely that intent.