Skip to content

Commit 7be5853

Browse files
Add files via upload
1 parent a194f36 commit 7be5853

11 files changed

+2096
-0
lines changed

CourseScript.Rmd

+1,421
Large diffs are not rendered by default.

PasswordList.csv

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"User ID,Password"
2+
"MyFakeUserID1,pass-word-1234-òàèé"
3+
"MyFakeUserID2,word-pass-абсд-9876"
4+
"MyFakeUserID3,abcd-pass-1234-word"

PasswordsToImport.csv

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
UserName,Email,Password,Description
2+
userUdemy,[email protected],tr0asdf=sses,Password for elearning account
3+
userR,[email protected],pass1234,user R conference password

SecretsApp/server.R

+362
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,362 @@
1+
2+
# (C) 2017 Vladimir Zhbanko
3+
# Udemy Course: "Keep Your Secrets Under Your Control"
4+
5+
library(shiny)
6+
library(DT)
7+
library(openssl)
8+
library(tidyverse)
9+
10+
#=======================================
11+
# CONTENT #
12+
# =======================================
13+
# 1. generatePrivateKey
14+
# 2. storeData
15+
# 3. saveDataGlobal
16+
# 4. decryptData
17+
# 5. joinData
18+
# 6. encryptData
19+
# 7. inputPK
20+
# 8. inputEData
21+
# 9. oneRow
22+
#10. viewData
23+
#11. responses
24+
#12. downloadTable
25+
#13. downloadPrvKey
26+
#14. downloadPubKey
27+
#15. delKey
28+
#16. lineToDelete
29+
#17. eraseLine
30+
#18. importPassw
31+
#19. dataFromImport
32+
#20. dataFromSingleEntry
33+
#21. dataFromDecryption
34+
#22. viewPasswords
35+
# =======================================
36+
# DEFINE GLOBAL FUNCTIONS #
37+
# =======================================
38+
#
39+
#
40+
#--------------------------------------------------------------------
41+
# function that generates private key and write it to the file
42+
generatePrivateKey <- function(keyBits = 2099, keyPath = "private.key", passphrase = "udemy") {
43+
openssl::rsa_keygen(bits = keyBits) %>%
44+
write_pem(path = paste(Sys.Date(), keyPath, sep = ""), password = passphrase)
45+
}
46+
47+
#--------------------------------------------------------------------
48+
# function that save data from DT() to csv file of the temp_folder directory and also check for duplicates
49+
# -- use this function to store data to the file
50+
# -- function also remove duplicate records from table
51+
storeData <- function(data, directoryName, fileName) {
52+
53+
# store only unique records
54+
# non duplicates
55+
nonDuplicate <- data[!duplicated(data), ]
56+
# Write the file to the local system
57+
write.csv(
58+
x = nonDuplicate,
59+
file = file.path(directoryName, fileName),
60+
row.names = FALSE, quote = FALSE, append = TRUE, col.names = FALSE
61+
)
62+
}
63+
64+
#--------------------------------------------------------------------
65+
# function that write data to global directory called "responses"
66+
# -- use this function to append data to the existing table
67+
# -- data will be stored in the global object 'responses'
68+
saveDataGlobal <- function(data) {
69+
70+
if (exists("responses")) { # get data from global environment is it's exist there
71+
responses <<- rbind(responses, data)
72+
} else {
73+
responses <<- data # <<- this saves to the global environment
74+
}
75+
}
76+
77+
#--------------------------------------------------------------------
78+
# function that decrypt information from user
79+
# -- function gets the encrypted file, private key and return obtained result
80+
# -- function write result to the file 'decrypted'
81+
decryptData <- function(fileName, privateKey, passPhrase) {
82+
outputDir <- "temp_folder"
83+
# read file with Encrypted Information (from Computer File System to R Environment)
84+
secret_encrypted <- read_rds(fileName)
85+
86+
# decrypting the list from R Environment
87+
decrypt_envelope(data = secret_encrypted$data,
88+
iv = secret_encrypted$iv,
89+
session = secret_encrypted$session,
90+
key = privateKey,
91+
password = passPhrase) %>%
92+
# getting back original object in a form of the data frame
93+
unserialize() %>%
94+
# write dataframe to the csv file
95+
storeData(outputDir, "decrypted.csv")
96+
97+
# remove secret_encrypted object
98+
rm(secret_encrypted)
99+
}
100+
101+
#--------------------------------------------------------------------
102+
# function that joins and delete available information to encrypt
103+
# three souces of information are available:
104+
# 1. From imported file, 2. from single entry, 3. from decrypted file, 4. previously combined
105+
joinData <- function(){
106+
outputDir <- "temp_folder"
107+
files <- c("imported.csv","singlerow.csv","decrypted.csv")
108+
#join data from all files and delete original files
109+
for (i in 1:3){
110+
if(file.exists(file.path(outputDir, files[i]))){
111+
# store
112+
if(exists("df_joined")){
113+
df_joined <- df_joined %>%
114+
bind_rows(read_csv(file.path(outputDir, files[i])))
115+
} else {
116+
df_joined <- read_csv(file.path(outputDir, files[i]))
117+
}
118+
# delete
119+
file.remove(file.path(outputDir, files[i]))
120+
}
121+
122+
}
123+
# return joined dataframe
124+
saveDataGlobal(df_joined)
125+
return(df_joined)
126+
127+
}
128+
129+
#--------------------------------------------------------------------
130+
# function that encrypt information from user
131+
# -- function uses the data present in the file and encrypt them using private key
132+
# -- funciton writes information to the folder
133+
encryptData <- function(privateKey, passphrase) {
134+
outputDir <- "temp_folder"
135+
# retrieve public key from private one
136+
pubKey <- read_key(file = privateKey, password = passphrase) %>%
137+
# extract element of the list
138+
`[[`("pubkey")
139+
140+
# join data collected by user
141+
joinData() %>%
142+
# serialize the object
143+
serialize(connection = NULL) %>%
144+
# encrypt the object
145+
encrypt_envelope(pubKey) %>%
146+
# write encrypted data to File
147+
write_rds(file.path(outputDir, "PasswordList.Encrypted"))
148+
149+
}
150+
151+
152+
153+
154+
shinyServer(function(input, output, session) {
155+
156+
# =======================================
157+
# DEFINE GLOBAL VARIABLES #
158+
# =======================================
159+
outputDir <- "temp_folder"
160+
161+
#==================================================
162+
# Run once in the event of loading file... with Private Key
163+
observeEvent(input$inputPK, {
164+
# Read file
165+
inFilePK <- input$inputPK
166+
167+
# TDL more secure way is needed (e.g. if wrong file is entered)
168+
if (is.null(inFilePK))
169+
return(NULL)
170+
171+
# # store private key into global environment
172+
# privateKey <- read_key(file = inFilePK$datapath, password = input$passphrase)
173+
174+
})
175+
#==================================================
176+
#==================================================
177+
# Run once in the event of loading file... with Encrypted Data
178+
observeEvent(input$inputEData, {
179+
# Read file EF -> "Encrypted File"
180+
inFileEF <- input$inputEData
181+
182+
# TDL more secure way is needed (e.g. if wrong file is entered)
183+
if (is.null(inFileEF))
184+
return(NULL)
185+
186+
# store encrypted data to the file 'temp_folder/decrypted.csv'
187+
decryptData(fileName = inFileEF$datapath, privateKey = inFilePK$datapath, passPhrase = input$passphrase)
188+
189+
})
190+
#==================================================
191+
192+
193+
194+
195+
# ==========================================
196+
# Objects located in the Tab Add to Encrypt #
197+
# ==========================================
198+
## **-------------- **
199+
# Object DF will contain the results of the password input. Object can be accessed in the code using DF() notation
200+
oneRow <- reactive({
201+
# Data frame
202+
data.frame(UserName = as.character(input$txtInputUser),
203+
Email = as.character(input$txtInputEmail),
204+
Password = as.character(input$txtInputPass),
205+
Description = input$txtInputDesc,
206+
stringsAsFactors = F)
207+
})
208+
## **-------------- **
209+
210+
211+
212+
# function that visualizes the current table results if it's stored in GLobal Environment
213+
viewData <- function() {
214+
if (exists("responses")) {
215+
responses
216+
}
217+
}
218+
219+
# Visualize responses in the interactive tables, refresh when some buttons are pressed...
220+
output$responses <- renderDataTable({
221+
# change in reactive inputs below will refresh data
222+
input$butSaveRow
223+
input$refresh
224+
225+
viewData()
226+
})
227+
## *****-------------- *****
228+
229+
## ******-------------- ******
230+
# show the action button that will enable the data table save to the SQL Database
231+
# refreshData <- eventReactive(input$refresh, {
232+
#
233+
# # code that brings all available decrypted files to very one file
234+
# # this file will be used for visualizing data in the table
235+
# #
236+
# joinData()
237+
#
238+
# })
239+
## ******-------------- ******
240+
241+
## **-------------- **
242+
# output to download file of Decrypted Information (secret)
243+
output$downloadTable <- downloadHandler(
244+
filename = function() {
245+
paste("Data-", Sys.Date(), '.csv', sep='')
246+
},
247+
content = function(file) {
248+
write.csv(df, file)
249+
}
250+
)
251+
## **-------------- **
252+
253+
# ==========================================
254+
# Objects located in the Tab Key Management #
255+
# ==========================================
256+
257+
## **-------------- **
258+
# output to download file with Private Key
259+
output$downloadPrvKey <- downloadHandler(
260+
filename = function() {
261+
paste(Sys.Date(), input$keyname, sep="")
262+
},
263+
content = function(file) {
264+
# generate the key
265+
generatePrivateKey(keyBits = input$keybits, keyPath = input$keyname, passphrase = input$passphrase)
266+
file.copy(paste(Sys.Date(), input$keyname, sep = ""), file)
267+
}
268+
)
269+
## **-------------- **
270+
## **-------------- **
271+
# output to download file with Public Key
272+
output$downloadPubKey <- downloadHandler(
273+
filename = function() {
274+
paste(Sys.Date(), input$keyname, "Pub", sep="")
275+
},
276+
content = function(file) {
277+
# generate the key
278+
k <- read_key(file = paste(Sys.Date(), input$keyname, sep=""), password = input$passphrase)
279+
write_pem(k$pubkey, path = paste(Sys.Date(), input$keyname, "Pub", sep = ""))
280+
file.copy(paste(Sys.Date(), input$keyname, "Pub", sep = ""), file)
281+
}
282+
)
283+
## **-------------- **
284+
## **-------------- **
285+
# Now user must press the button to delete the key from R Environment
286+
observeEvent(input$delKey, {
287+
# user deletes the key once sure that it's saved
288+
file.remove(paste(Sys.Date(), input$keyname, sep = ""))
289+
})
290+
291+
292+
## **-------------- **
293+
294+
## ****-------------- ****
295+
# get value of the input number that indicate which line to delete
296+
lineToDelete <- reactive({ lineToDelete <- input$numLineDelete})
297+
# pressing button will delete single line inside of the response object
298+
observeEvent(input$eraseLine, {
299+
# delete the first element of the table
300+
responses <- responses[-lineToDelete(), ]
301+
})
302+
## ****-------------- ****
303+
304+
## ****** ---------------*******
305+
# Uploading data using the app
306+
observeEvent(input$importPassw, {
307+
pFile <- input$importPassw
308+
if (is.null(pFile))
309+
return()
310+
# TDL: add fail safe (wrong file, etc)
311+
})
312+
## ******---------------********
313+
# this will bring data from imported file from user
314+
dataFromImport <- eventReactive(input$importPassw, {
315+
# return data from imported file on request
316+
req(input$importPassw)
317+
# save to dataframe
318+
df_imported <- read_csv(input$importPassw$datapath)
319+
# store this data persistently... (temporary, further on shall be removed)
320+
storeData(data = df_imported, directoryName = outputDir, fileName = "imported.csv")
321+
# join the data we have already
322+
df_imported <- joinData()
323+
return(df_imported)
324+
})
325+
326+
## *****-------------- *****
327+
# this will bring data stored by user (one line)
328+
dataFromSingleEntry <- eventReactive(input$butSaveRow, {
329+
# save data file to temp directory (temporary, further on shall be removed)
330+
storeData(data = DF(), directoryName = outputDir, fileName = "singlerow.csv")
331+
# join the data we have already
332+
df_single <- joinData()
333+
return(df_single)
334+
})
335+
336+
# ## *****-------------- *****
337+
# # this will bring decrypted data from file
338+
# dataFromDecryption <- eventReactive(input$butSaveRow, {
339+
# # save data file to temp directory (temporary, further on shall be removed)
340+
# saveData(data = DF(), directoryName = outputDir, fileName = "decrypted.csv")
341+
# # join the data we have already
342+
# df_decrypted <- joinData()
343+
# return(df_decrypted)
344+
# })
345+
#
346+
# =================================
347+
# visualize the table that user loads
348+
output$viewPasswords <- renderDataTable({
349+
# data coming from imported files
350+
input$refresh
351+
input$butSaveRow
352+
353+
joinData()
354+
})
355+
356+
## ****-------------- ****
357+
# output the results of the data input as a datatable vector
358+
output$viewOneRow <- renderDataTable({ oneRow() })
359+
## ****-------------- ****
360+
361+
362+
})

0 commit comments

Comments
 (0)