├── .gitignore ├── .Rbuildignore ├── tests ├── testthat.R └── testthat │ ├── test-pathRemapping.R │ ├── test-userAuth.R │ └── test-dataTransfer.R ├── man ├── path_check.Rd ├── classConversion.Rd ├── fileConversion.Rd ├── resetPassword.Rd ├── createUser.Rd ├── auth.Rd ├── put.Rd ├── patch.Rd ├── delete.Rd ├── upload.Rd ├── dataBackup.Rd └── download.Rd ├── .gitattributes ├── .travis.yml ├── NAMESPACE ├── DESCRIPTION ├── LICENSE.txt ├── README.md └── R └── index.R /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | LICENCE 5 | inst/doc 6 | -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^\.travis\.yml$ 4 | ^LICENSE.txt 5 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library("testthat") 2 | library("fireData") 3 | 4 | test_check("fireData") 5 | -------------------------------------------------------------------------------- /tests/testthat/test-pathRemapping.R: -------------------------------------------------------------------------------- 1 | library("testthat") 2 | library("fireData") 3 | 4 | test_that("Test path remapping", { 5 | path = "abc./d}e" 6 | expect_warning(path_check("abc./d}e")) 7 | }) 8 | 9 | test_that("Test class to binary conversion", { 10 | conversion = fireData:::classConversion(mtcars) 11 | expect_equal(nchar(conversion$base64Set), 1646) 12 | }) 13 | -------------------------------------------------------------------------------- /man/path_check.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{path_check} 4 | \alias{path_check} 5 | \title{Path key replacement function:} 6 | \usage{ 7 | path_check(path) 8 | } 9 | \arguments{ 10 | \item{path}{is the db path {string}} 11 | } 12 | \value{ 13 | the approved and cleaned path_string 14 | } 15 | \description{ 16 | replaces all disallowed path symbols with a "-" 17 | } 18 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: r 2 | r: 3 | - release 4 | cache: packages 5 | sudo: false 6 | 7 | warnings_are_errors: false 8 | 9 | r_packages: 10 | - covr 11 | - httr 12 | - jsonlite 13 | - curl 14 | - testthat 15 | 16 | after_success: 17 | 18 | - Rscript \ 19 | --default-packages='httr,curl,testthat,jsonlite' \ 20 | -e 'library(covr); covr::codecov(token="065e3977-f8e1-4ce8-b984-6c1b8de579e6")' 21 | 22 | notifications: 23 | email: 24 | on_failure: robin@kohze.com 25 | -------------------------------------------------------------------------------- /man/classConversion.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{classConversion} 4 | \alias{classConversion} 5 | \title{Internal class to binary conversion:} 6 | \usage{ 7 | classConversion(x) 8 | } 9 | \arguments{ 10 | \item{x}{is the S4 class object} 11 | } 12 | \value{ 13 | returns base64 encoded binary value of class object 14 | } 15 | \description{ 16 | The internal conversion is needed to conserve all class information 17 | } 18 | -------------------------------------------------------------------------------- /man/fileConversion.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{fileConversion} 4 | \alias{fileConversion} 5 | \title{Data conversion function} 6 | \usage{ 7 | fileConversion(x) 8 | } 9 | \arguments{ 10 | \item{x}{the input file.} 11 | } 12 | \value{ 13 | returns optionally reformatted data. 14 | } 15 | \description{ 16 | The internal data conversion function to bring data in the right json format. In case the uploaded file is a s4 class object, the object is converted to a binary s4 object. 17 | } 18 | -------------------------------------------------------------------------------- /man/resetPassword.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{resetPassword} 4 | \alias{resetPassword} 5 | \title{Password resett function:} 6 | \usage{ 7 | resetPassword(projectAPI, email) 8 | } 9 | \arguments{ 10 | \item{projectAPI}{The Firebase Project API {string}} 11 | 12 | \item{email}{The user email {string}} 13 | } 14 | \value{ 15 | Success or warning message. 16 | } 17 | \description{ 18 | Resets the user password and sends an email to the user account. 19 | } 20 | \examples{ 21 | \dontrun{ 22 | resetPassword(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "useYourOwn@email.com") 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(auth) 4 | export(anonymous_login) 5 | export(createUser) 6 | export(dataBackup) 7 | export(delete_storage) 8 | export(deploy_rmarkdown) 9 | export(delete) 10 | export(download) 11 | export(get_dynamic_link) 12 | export(get_storage) 13 | export(get_url) 14 | export(google_devstorage_read_only) 15 | export(google_devstorage_read_write) 16 | export(google_firestore) 17 | export(google_login) 18 | export(list_storage) 19 | export(o_auth_login) 20 | export(patch) 21 | export(path_check) 22 | export(put) 23 | export(resetPassword) 24 | export(shiny_auth_server) 25 | export(upload) 26 | export(upload_folder) 27 | export(upload_storage) 28 | export(upload) -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: fireData 2 | Title: Connecting R to Google Firebase 3 | Version: 1.16 4 | Authors@R: person("Robin", "Kohze", email = "Robin@Kohze.com", role = c("aut", "cre")) 5 | Description: Provides API access to common features of the Google Firebase realtime database. 6 | Usecases of firebase are creating user logins with persistent data storage for mobile apps, shiny applications 7 | or IOT applications. See the fireData github repository for more information. 8 | Depends: R (>= 3.3.3) 9 | License: MIT + file LICENCE 10 | URL: https://github.com/Kohze/fireData 11 | BugReports: https://github.com/Kohze/fireData/issues 12 | Encoding: UTF-8 13 | LazyData: true 14 | RoxygenNote: 6.1.0 15 | Imports: 16 | httr (>= 1.2.1), 17 | jsonlite (>= 1.4), 18 | curl (>= 2.3) 19 | Suggests: 20 | testthat (>= 1.0), 21 | covr (>= 2.2.2) 22 | -------------------------------------------------------------------------------- /man/createUser.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{createUser} 4 | \alias{createUser} 5 | \title{Firebase user creation function} 6 | \usage{ 7 | createUser(projectAPI, email = "prompt", password = "prompt") 8 | } 9 | \arguments{ 10 | \item{projectAPI}{The Firebase Project API {string}} 11 | 12 | \item{email}{The user email {string}} 13 | 14 | \item{password}{The user password {string}} 15 | } 16 | \value{ 17 | Registers a new user and returns the status. 18 | } 19 | \description{ 20 | Creates a new firebase user account. All user accounts can accessed at the firebase.com project console. One of the advantages of firebase accounts in R is the ability to access a website and analyse the data of the website with the very same login. 21 | } 22 | \examples{ 23 | \dontrun{ 24 | createUser(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "your@email.com", password = "12341234" ) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /man/auth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{auth} 4 | \alias{auth} 5 | \title{The user authentication function:} 6 | \usage{ 7 | auth(projectAPI, email = "prompt", password = "prompt") 8 | } 9 | \arguments{ 10 | \item{projectAPI}{The Firebase Project API {string}} 11 | 12 | \item{email}{The user email {string}} 13 | 14 | \item{password}{The user password {string}} 15 | } 16 | \value{ 17 | Returns the content of the firebase API request, such as the state of registration, idToken, and validity of the user password. 18 | } 19 | \description{ 20 | fireData::auth checks the validity of a login and returns the temporary JWT user token. FireData_auth can be used to store individual user data in specified directories that are only accessible to that specific user. 21 | } 22 | \examples{ 23 | \dontrun{ 24 | auth(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "robin@kohze.com", password = "12341234") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /man/put.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{put} 4 | \alias{put} 5 | \title{The firebase data put function:} 6 | \usage{ 7 | put(x, projectURL, directory = "main", token = "none") 8 | } 9 | \arguments{ 10 | \item{x}{A list, data.frame or data.table {object}} 11 | 12 | \item{projectURL}{The Firebase project URL {string}} 13 | 14 | \item{directory}{The optimal Firebase subdirectory {string}} 15 | 16 | \item{token}{The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string}} 17 | } 18 | \value{ 19 | returns http request answer. 20 | } 21 | \description{ 22 | The function allows to update data objects, such as variables, lists and data.frames 23 | } 24 | \examples{ 25 | \dontrun{ 26 | patch(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 27 | } 28 | } 29 | \author{ 30 | Kevin McGinley 31 | } 32 | -------------------------------------------------------------------------------- /man/patch.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{patch} 4 | \alias{patch} 5 | \title{The firebase data patch function:} 6 | \usage{ 7 | patch(x, projectURL, directory = "main", token = "none") 8 | } 9 | \arguments{ 10 | \item{x}{A list, data.frame or data.table {object}} 11 | 12 | \item{projectURL}{The Firebase project URL {string}} 13 | 14 | \item{directory}{The optimal Firebase subdirectory {string}} 15 | 16 | \item{token}{The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string}} 17 | } 18 | \value{ 19 | returns http request answer. 20 | } 21 | \description{ 22 | The function allows to update data objects, such as variables, lists and data.frames 23 | } 24 | \examples{ 25 | \dontrun{ 26 | patch(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 27 | } 28 | } 29 | \author{ 30 | Kevin McGinley 31 | } 32 | -------------------------------------------------------------------------------- /man/delete.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{delete} 4 | \alias{delete} 5 | \title{The firebase data delete function:} 6 | \usage{ 7 | delete(x, projectURL, directory = "main", token = "none") 8 | } 9 | \arguments{ 10 | \item{x}{A list, data.frame or data.table {object}} 11 | 12 | \item{projectURL}{The Firebase project URL {string}} 13 | 14 | \item{directory}{The optimal Firebase subdirectory {string}} 15 | 16 | \item{token}{The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string}} 17 | } 18 | \value{ 19 | returns http request answer. 20 | } 21 | \description{ 22 | The function allows to delete data objects, such as variables, lists and data.frames 23 | } 24 | \examples{ 25 | \dontrun{ 26 | delete(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 27 | } 28 | } 29 | \author{ 30 | Kevin McGinley 31 | } 32 | -------------------------------------------------------------------------------- /man/upload.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{upload} 4 | \alias{upload} 5 | \title{The firebase data upload function:} 6 | \usage{ 7 | upload(x, projectURL, directory = "main", token = "none") 8 | } 9 | \arguments{ 10 | \item{x}{A data.frame or data.table {object}} 11 | 12 | \item{projectURL}{The Firebase project URL {string}} 13 | 14 | \item{directory}{The optimal Firebase subdirectory {string}} 15 | 16 | \item{token}{The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string}} 17 | } 18 | \value{ 19 | returns http request answer which includes the random key. 20 | } 21 | \description{ 22 | The function allows to upload data objects, such as variables,lists and data.frames 23 | } 24 | \examples{ 25 | \dontrun{ 26 | upload(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 27 | } 28 | } 29 | \author{ 30 | Robin Kohze 31 | } 32 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Robin Kohze 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /tests/testthat/test-userAuth.R: -------------------------------------------------------------------------------- 1 | library("testthat") 2 | library("fireData") 3 | 4 | projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc" 5 | 6 | test_that("Test the firebase user authentication", { 7 | email = "robin@kohze.com" 8 | password = 12341234 9 | response = auth(projectAPI = projectAPI, email = email, password = password) 10 | expect_identical(response$email, "robin@kohze.com") 11 | }) 12 | 13 | test_that("Test the email reset", { 14 | email = "wrong@email.com" 15 | expect_warning(resetPassword(projectAPI = projectAPI, email = email)) 16 | }) 17 | 18 | test_that("Test passwort reset functionality", { 19 | email = paste0("testMail", as.numeric(format(Sys.time(), "%OS3")) * 1000, "@googleMail.com") 20 | createUser(projectAPI = projectAPI, email = email, password = "12341234" ) 21 | expect_equal(resetPassword(projectAPI = projectAPI, email = email), paste0("Password reset email was send to ", email)) 22 | } 23 | ) 24 | 25 | test_that("Test for user creation", { 26 | expect_true("email" %in% names(createUser(projectAPI = projectAPI, email = paste0("testMail", as.numeric(format(Sys.time(), "%OS3")) * 1000, "@googleMail.com"), password = "12341234" ))) 27 | }) 28 | 29 | 30 | -------------------------------------------------------------------------------- /man/dataBackup.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{dataBackup} 4 | \alias{dataBackup} 5 | \title{The firebase database backup function:} 6 | \usage{ 7 | dataBackup(projectURL, secretKey = "prompt", fileName) 8 | } 9 | \arguments{ 10 | \item{projectURL}{The Firebase Project Url {string}} 11 | 12 | \item{secretKey}{The firebase secret key, which can be found in the Config/ Service Accounts/ Database secrets firebase page. {string}} 13 | 14 | \item{fileName}{The output file name. Can be any string with .json format {string}} 15 | } 16 | \value{ 17 | Returns either a warning or the backup file name. 18 | } 19 | \description{ 20 | The backup functionality allows to download the whole database into a .json file (which can later be uploaded in the firebase console to do a restore of the DB). Generally this function may allow to save costs by not relying on the Firebase automatic backup function that is only available with the Firebase Blaze premium payment contract. 21 | } 22 | \examples{ 23 | \dontrun{ 24 | dataBackup(projectURL = "https://firedata-efa5a.firebaseio.com", secretKey = "2bYA6k72wKna90MqPGa6yuMG7jAysoDJZwJqYXsm", "test.json") 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /man/download.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/index.R 3 | \name{download} 4 | \alias{download} 5 | \title{Data conversion function} 6 | \usage{ 7 | download(projectURL, fileName, secretKey = "none", token = "none", 8 | isClass = FALSE) 9 | } 10 | \arguments{ 11 | \item{projectURL}{The firebase database url. {string}} 12 | 13 | \item{fileName}{The filename or subdirectory. {string}} 14 | 15 | \item{secretKey}{The optional database secret key for admin access. {string}} 16 | 17 | \item{token}{The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string}} 18 | 19 | \item{isClass}{In case a s4 class object is downloaded, fireData expects a isClass=TRUE} 20 | } 21 | \value{ 22 | returns optionally reformatted data. 23 | } 24 | \description{ 25 | The internal data conversion function to bring data in the right json format. In case the uploaded file is a s4 class object, the object is converted to a binary s4 object. 26 | } 27 | \examples{ 28 | \dontrun{ 29 | download(projectURL = "https://firedata-b0e54.firebaseio.com/", fileName = "main/-KxwWNTVdplXFRZwGMkH") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /tests/testthat/test-dataTransfer.R: -------------------------------------------------------------------------------- 1 | library("testthat") 2 | library("fireData") 3 | 4 | test_that("Test the Firebase upload functionality / normal objects", { 5 | response = fireData::upload(mtcars,"https://firedata-efa5a.firebaseio.com",directory = "test") 6 | expect_equal(nchar(response), 25) 7 | }) 8 | 9 | test_that("Test the Firebase upload functionality / s4 classes", { 10 | setClass("testClass", slots = list(name = "character")) 11 | testClassObject = new("testClass", name = "testName") 12 | response = fireData::upload(testClassObject,"https://firedata-efa5a.firebaseio.com",directory = "test") 13 | expect_equal(nchar(response), 25) 14 | }) 15 | 16 | test_that("Test the Firebase download functionality", { 17 | response = fireData::download("https://firedata-efa5a.firebaseio.com/directory","-KnsrqkNIDOFa993pcI9") 18 | expect_true(is.data.frame(response)) 19 | }) 20 | 21 | test_that("Test the Firebase download functionality / with secret key", { 22 | response = fireData::download("https://firedata-efa5a.firebaseio.com/directory","-KnsrqkNIDOFa993pcI9", secretKey = "2bYA6k72wKna90MqPGa6yuMG7jAysoDJZwJqYXsm") 23 | expect_true(is.data.frame(response)) 24 | }) 25 | 26 | test_that("Test the firebase backup functionality", { 27 | response = dataBackup(projectURL = "https://firedata-efa5a.firebaseio.com", 28 | secretKey = "2bYA6k72wKna90MqPGa6yuMG7jAysoDJZwJqYXsm", 29 | "test.json") 30 | expect_equal(nchar(response), 27) 31 | file.remove("test.json") 32 | }) 33 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![fireData](http://frapbot.kohze.com/fireData/topImage6.jpg) 2 | 3 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/Kohze/fireData/master/LICENSE.txt) 4 | [![Build Status](https://travis-ci.org/Kohze/fireData.svg?branch=master)](https://travis-ci.org/Kohze/fireData) 5 | [![codecov](https://codecov.io/gh/Kohze/fireData/branch/master/graph/badge.svg)](https://codecov.io/gh/Kohze/fireData) 6 | 7 | 8 | **Project Title:** FireData: Connecting R to Google Firebase 9 | 10 | --- 11 | 12 | FireData integrates R Datascience with the abilities and possibilities of the Google Firebase Framework. 13 | 14 | Firebase makes it possible to exchange in real-time information in the Cloud and thereby opening the R language to IoT hardware/data processing. Other than that it is also immensely useful for shiny application to integrate Social Authentications and persistent data & uploads. 15 | 16 | This package was created within the framework of Google Summer of Code 2017 and 2018. 17 | 18 | ![fireData](http://frapbot.kohze.com/fireData/setup2.jpg) 19 | 20 | **Database Setup:** 21 | - visit https://firebase.google.com/ 22 | - login and enter the "console" 23 | - add new project 24 | - find the API keys at the "overview" page clicking on add firebase to web-app 25 | - certain functions requires OAuth 2.0 access which needed client_id and client_secret, these can be found from the [google developer console](https://console.developers.google.com/apis/credentials) 26 | 27 | **R Package Setup:** 28 | 29 | ``` 30 | if (!require("devtools")) install.packages("devtools") 31 | devtools::install_github("Kohze/fireData") 32 | 33 | library(fireData) 34 | ``` 35 | 36 | ![examples](http://frapbot.kohze.com/fireData/examples2.jpg) 37 | 38 | **Authentification** 39 | 40 | - using anonymous login 41 | 42 | ```r 43 | token <- anonymous_login(project_api = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc") 44 | 45 | token$idToken 46 | ``` 47 | 48 | **General Functions:** 49 | 50 | - uploading a data.frame: 51 | 52 | ```upload(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main")``` 53 | 54 | - patching a data.frame: 55 | 56 | ```patch(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main/-KxwWNTVdplXFRZwGMkH")``` 57 | 58 | - putting a data.frame: 59 | 60 | ```put(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main/-KxwWNTVdplXFRZwGMkH")``` 61 | 62 | - download a data.frame: 63 | 64 | ```download(projectURL = "https://firedata-b0e54.firebaseio.com/", fileName = "main/-KxwWNTVdplXFRZwGMkH")``` 65 | 66 | - register a new user 67 | 68 | ```createUser(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "your@email.com", password = "12341234" )``` 69 | 70 | - create token for authenticated requests (can be used for the token argument of upload/download) 71 | 72 | ```auth(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "robin@kohze.com", password = "12341234")``` 73 | 74 | - reset user password 75 | 76 | ```resetPassword(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "useYourOwn@email.com")``` 77 | 78 | - backup the database and save as .json 79 | 80 | ```dataBackup(projectURL = "https://firedata-efa5a.firebaseio.com", secretKey = "2bYA6k72wKna90MqPGa6yuMG7jAysoDJZwJqYXsm", "test.json")``` 81 | 82 | 83 | 84 | 85 | 86 | ![fireData](http://frapbot.kohze.com/fireData/related2.jpg) 87 | 88 | fireData is already integrated into a several projects. 89 | 90 | - SpatialMaps: A spatial proteomics platform that utilizes firebase as cross platform database. 91 | 92 | - Cryptotrade-hq bot: A simple data collector (with shiny) that uses firebase for secure storage of API keys. 93 | 94 | 95 | ![fireData](http://frapbot.kohze.com/fireData/development2.jpg) 96 | 97 | We are currently planning to add the new Cloud Firebase database and enhance the integration into R web applications. 98 | 99 | --- 100 | 101 | **Aknowledgements:** 102 | 103 | I hereby want to thank my GSOC mentors L. Pedraza, S. Schmidt for their project support and especially L. Gatto for his insights and experience to make this package a reality. 104 | -------------------------------------------------------------------------------- /R/index.R: -------------------------------------------------------------------------------- 1 | #' @title The firebase data delete function: 2 | #' @author Kevin McGinley 3 | #' @description The function allows to delete data objects, such as variables, lists and data.frames 4 | #' @param x A list, data.frame or data.table {object} 5 | #' @param projectURL The Firebase project URL {string} 6 | #' @param directory The optimal Firebase subdirectory {string} 7 | #' @param token The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string} 8 | #' @return returns http request answer. 9 | #' @export 10 | #' @examples 11 | #' \dontrun{ 12 | #' delete(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 13 | #' } 14 | delete <- function(x, projectURL, directory = "main", token = "none"){ 15 | output = fileConversion(x) 16 | if (token == "none") { 17 | Response = httr::DELETE(paste0(projectURL,"/",directory,".json"), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 18 | } else { 19 | Response = httr::DELETE(paste0(projectURL,"/",directory,".json?auth=",token), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 20 | } 21 | return(paste0(directory,"/",httr::content(Response)$name)) 22 | } 23 | 24 | #' @title The firebase data patch function: 25 | #' @author Kevin McGinley 26 | #' @description The function allows to update data objects, such as variables, lists and data.frames 27 | #' @param x A list, data.frame or data.table {object} 28 | #' @param projectURL The Firebase project URL {string} 29 | #' @param directory The optimal Firebase subdirectory {string} 30 | #' @param token The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string} 31 | #' @return returns http request answer. 32 | #' @export 33 | #' @examples 34 | #' \dontrun{ 35 | #' patch(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 36 | #' } 37 | patch <- function(x, projectURL, directory = "main", token = "none"){ 38 | output = fileConversion(x) 39 | if (token == "none") { 40 | Response = httr::PATCH(paste0(projectURL,"/",directory,".json"), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 41 | } else { 42 | Response = httr::PATCH(paste0(projectURL,"/",directory,".json?auth=",token), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 43 | } 44 | return(paste0(directory,"/",httr::content(Response)$name)) 45 | } 46 | 47 | #' @title The firebase data put function: 48 | #' @author Kevin McGinley 49 | #' @description The function allows to update data objects, such as variables, lists and data.frames 50 | #' @param x A list, data.frame or data.table {object} 51 | #' @param projectURL The Firebase project URL {string} 52 | #' @param directory The optimal Firebase subdirectory {string} 53 | #' @param token The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string} 54 | #' @return returns http request answer. 55 | #' @export 56 | #' @examples 57 | #' \dontrun{ 58 | #' patch(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 59 | #' } 60 | put <- function(x, projectURL, directory = "main", token = "none"){ 61 | output = fileConversion(x) 62 | if (token == "none") { 63 | Response = httr::PUT(paste0(projectURL,"/",directory,".json"), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 64 | } else { 65 | Response = httr::PUT(paste0(projectURL,"/",directory,".json?auth=",token), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 66 | } 67 | return(paste0(directory,"/",httr::content(Response)$name)) 68 | } 69 | 70 | #' @title The firebase data upload function: 71 | #' @author Robin Kohze 72 | #' @description The function allows to upload data objects, such as variables,lists and data.frames 73 | #' @param x A data.frame or data.table {object} 74 | #' @param projectURL The Firebase project URL {string} 75 | #' @param directory The optimal Firebase subdirectory {string} 76 | #' @param token The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string} 77 | #' @return returns http request answer which includes the random key. 78 | #' @export 79 | #' @examples 80 | #' \dontrun{ 81 | #' upload(x = mtcars, projectURL = "https://firedata-b0e54.firebaseio.com/", directory = "main") 82 | #' } 83 | upload <- function(x, projectURL, directory = "main", token = "none"){ 84 | output = fileConversion(x) 85 | if (token == "none") { 86 | Response = httr::POST(paste0(projectURL,"/",directory,".json"), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 87 | } else { 88 | Response = httr::POST(paste0(projectURL,"/",directory,".json?auth=",token), body = jsonlite::toJSON(output, auto_unbox = TRUE)) 89 | } 90 | return(paste0(directory,"/",httr::content(Response)$name)) 91 | } 92 | 93 | #' @title Data conversion function 94 | #' @description The internal data conversion function to bring data in the right json format. In case the uploaded file is a s4 class object, the object is converted to a binary s4 object. 95 | #' @param x the input file. 96 | #' @return returns optionally reformatted data. 97 | fileConversion <- function(x){ 98 | if (isS4(x)) { 99 | output = classConversion(x) 100 | } else { 101 | output = x 102 | } 103 | } 104 | 105 | #' @title Data conversion function 106 | #' @description The internal data conversion function to bring data in the right json format. In case the uploaded file is a s4 class object, the object is converted to a binary s4 object. 107 | #' @param projectURL The firebase database url. {string} 108 | #' @param fileName The filename or subdirectory. {string} 109 | #' @param secretKey The optional database secret key for admin access. {string} 110 | #' @param token The user access token that can be retrieved with the auth() function. Required when if the database rules specify the need for user authentications. {string} 111 | #' @param isClass In case a s4 class object is downloaded, fireData expects a isClass=TRUE 112 | #' @return returns optionally reformatted data. 113 | #' @export 114 | #' @examples 115 | #' \dontrun{ 116 | #' download(projectURL = "https://firedata-b0e54.firebaseio.com/", fileName = "main/-KxwWNTVdplXFRZwGMkH") 117 | #' } 118 | download <- function(projectURL, fileName, secretKey = "none", token = "none", isClass = FALSE) { 119 | 120 | if (secretKey == "none" && token == "none") { 121 | urlPath = paste0(projectURL,"/",fileName,".json") 122 | } else if (token != "none") { 123 | urlPath = paste0(projectURL,"/",fileName,".json?auth=",token) 124 | } else { 125 | urlPath = paste0(projectURL,"/",fileName,".json?auth=",secretKey) 126 | } 127 | 128 | data = httr::GET(urlPath) 129 | 130 | if (is.null(jsonlite::fromJSON(httr::content(data,"text")))) warning("No data found at database location.") 131 | if (isClass) { 132 | retrievedData = httr::content(data,"text") 133 | tempPath = tempfile() 134 | writeBin(jsonlite::base64_dec(jsonlite::fromJSON(retrievedData)), tempPath) 135 | return(readRDS(tempPath)) 136 | } else { 137 | return(jsonlite::fromJSON(httr::content(data,"text"))) 138 | } 139 | } 140 | 141 | #' @title The firebase database backup function: 142 | #' @param projectURL The Firebase Project Url {string} 143 | #' @param secretKey The firebase secret key, which can be found in the Config/ Service Accounts/ Database secrets firebase page. {string} 144 | #' @param fileName The output file name. Can be any string with .json format {string} 145 | #' @description The backup functionality allows to download the whole database into a .json file (which can later be uploaded in the firebase console to do a restore of the DB). Generally this function may allow to save costs by not relying on the Firebase automatic backup function that is only available with the Firebase Blaze premium payment contract. 146 | #' @return Returns either a warning or the backup file name. 147 | #' @export 148 | #' @examples 149 | #' \dontrun{ 150 | #' dataBackup(projectURL = "https://firedata-efa5a.firebaseio.com", secretKey = "2bYA6k72wKna90MqPGa6yuMG7jAysoDJZwJqYXsm", "test.json") 151 | #' } 152 | 153 | dataBackup <- function(projectURL, secretKey="prompt", fileName){ 154 | if (secretKey == "prompt") { 155 | secretKey <- readline(prompt = "secretKey: ") 156 | print(paste0("Connecting to", project_api, ":")) 157 | } 158 | print("Fetching Data") 159 | urlPath = paste0(projectURL,"/.json?auth=",secretKey) 160 | curl::curl_download(url = urlPath, 161 | destfile = fileName, 162 | quiet = FALSE) 163 | print(paste0("Backup created in ", fileName)) 164 | } 165 | 166 | #' @title The user authentication function: 167 | #' @description fireData::auth checks the validity of a login and returns the temporary JWT user token. FireData_auth can be used to store individual user data in specified directories that are only accessible to that specific user. 168 | #' @param projectAPI The Firebase Project API {string} 169 | #' @param email The user email {string} 170 | #' @param password The user password {string} 171 | #' @return Returns the content of the firebase API request, such as the state of registration, idToken, and validity of the user password. 172 | #' @export 173 | #' @examples 174 | #' \dontrun{ 175 | #' auth(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "robin@kohze.com", password = "12341234") 176 | #' } 177 | auth <- function(projectAPI, email="prompt", password="prompt"){ 178 | if (password == "prompt" && email == "prompt") { 179 | email <- readline(prompt = "Email: ") 180 | password <- readline(prompt = "Password: ") 181 | print(paste0("Connecting to ", projectAPI, ":")) 182 | } 183 | AuthUrl = paste0("https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=", projectAPI) 184 | userData = httr::POST(url = AuthUrl, body = list("email" = email, "password" = password, "returnSecureToken" = "True"), encode = "json") 185 | return(httr::content(userData)) 186 | } 187 | 188 | #' @title The anonymous login function: 189 | #' @author Paul Spende 190 | #' @description fireData::anonymous_login signs in a user anonymously. 191 | #' @param project_api The Firebase Project API {string} 192 | #' @return Returns the content of the firebase API request, such as the idToken, the refreshToken, and the localId. 193 | #' @export 194 | #' @examples 195 | #' \dontrun{ 196 | #' anonymous_login(project_api = AIzaSyAYX_RxenP08jWpHExzsZIaO3CXeZhUSW8) 197 | #' } 198 | anonymous_login <- function(project_api) { 199 | anonymous_login_url <- paste0("https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=", project_api) 200 | anonymous_login_data <- httr::POST(url = anonymous_login_url, body = list("returnSecureToken" = "True"), encode = "json") 201 | return(httr::content(anonymous_login_data)) 202 | } 203 | 204 | #' @title The OAuth login function: 205 | #' @author Paul Spende 206 | #' @description fireData::o_auth_login signs in a user with OAuth credentials. 207 | #' @param project_api The Firebase Project API {string} 208 | #' @param request_uri The URI to which the IDP redirects the user back. {string} 209 | #' @param post_body Contains the OAuth credential (an ID token or access token) and provider ID which issues the credential. {string} 210 | #' @param return_idp_credential Whether to force the return of the OAuth credential on the following errors: FEDERATED_USER_ID_ALREADY_LINKED and EMAIL_EXISTS. {boolean} 211 | #' @return Returns the content of the firebase API request, such as the idToken, the refreshToken, and the localId. 212 | #' @export 213 | #' @examples 214 | #' \dontrun{ 215 | #' TODO: 216 | #' } 217 | o_auth_login <- function(project_api, request_uri, post_body, return_idp_credential){ 218 | o_auth_login_url <- paste0("https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyAssertion?key=", project_api) 219 | o_auth_login_data <- httr::POST(url = o_auth_login_url, body = list("requestUri" = request_uri, "postBody" = post_body, "returnSecureToken" = "True", "returnIdpCredential" = return_idp_credential), encode = "json") 220 | httr::content(o_auth_login_data) 221 | } 222 | 223 | #' @title The OAuth login function for google: 224 | #' @author Paul Spende 225 | #' @description fireData::google_login signs in a user with OAuth credentials. 226 | #' @param project_api The Firebase Project API {string} 227 | #' @param request_uri The URI to which the IDP redirects the user back. {string} 228 | #' @param redirect_uri The URI to be redirected after the authentification. {string} 229 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 230 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 231 | #' @param return_idp_credential Whether to force the return of the OAuth credential on the following errors: FEDERATED_USER_ID_ALREADY_LINKED and EMAIL_EXISTS. {boolean} 232 | #' @param cache Cache the tokens in the .httr-oauth file or not. {boolean} 233 | #' @return Returns the content of the firebase API request, such as the idToken, the refreshToken, and the localId. 234 | #' @export 235 | #' @examples 236 | #' \dontrun{ 237 | #' TODO: 238 | #' } 239 | google_login <- function(project_api, web_client_id = "prompt", web_client_secret = "prompt", request_uri, redirect_uri = httr::oauth_callback(), return_idp_credential=TRUE, cache = FALSE){ 240 | if (web_client_id == "prompt" && web_client_secret == "prompt") { 241 | web_client_id <- readline(prompt = "Web Client ID: ") 242 | web_client_secret <- readline(prompt = "Web Client Secret: ") 243 | print(paste0("Connecting to", project_api, ":")) 244 | } 245 | 246 | myapp <- httr::oauth_app("google", 247 | key = web_client_id, 248 | secret = web_client_secret, 249 | redirect_uri = redirect_uri) 250 | 251 | google_token <- httr::oauth2.0_token(httr::oauth_endpoints("google"), myapp, 252 | scope = "https://www.googleapis.com/auth/userinfo.profile", 253 | cache = cache) 254 | 255 | pbody <- paste0("id_token=", google_token$credentials$id_token, "&providerId=google.com") 256 | 257 | o_auth_login(project_api = project_api, request_uri = request_uri, post_body = pbody, return_idp_credential = return_idp_credential) 258 | } 259 | 260 | #' @title The OAuth function to get read/write access to the storage: 261 | #' @author Paul Spende 262 | #' @description fireData::google_devstorage_read_write retrieves a token with read/write access to the storage. 263 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 264 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 265 | #' @return Returns the token data. 266 | #' @export 267 | #' @examples 268 | #' \dontrun{ 269 | #' TODO: 270 | #' } 271 | google_devstorage_read_write <- function(web_client_id = "prompt", web_client_secret = "prompt") { 272 | if (web_client_id == "prompt" && web_client_secret == "prompt") { 273 | web_client_id <- readline(prompt = "Web Client ID: ") 274 | web_client_secret <- readline(prompt = "Web Client Secret: ") 275 | } 276 | 277 | myapp <- httr::oauth_app("google", 278 | key = web_client_id, 279 | secret = web_client_secret) 280 | 281 | httr::oauth2.0_token(httr::oauth_endpoints("google"), myapp, 282 | scope = "https://www.googleapis.com/auth/devstorage.read_write") 283 | } 284 | 285 | #' @title The OAuth function to get read access to the storage: 286 | #' @author Paul Spende 287 | #' @description fireData::google_devstorage_read_only retrieves a token with read access to the storage. 288 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 289 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 290 | #' @return Returns the token data. 291 | #' @export 292 | #' @examples 293 | #' \dontrun{ 294 | #' TODO: 295 | #' } 296 | google_devstorage_read_only <- function(web_client_id = "prompt", web_client_secret = "prompt") { 297 | if (web_client_id == "prompt" && web_client_secret == "prompt") { 298 | web_client_id <- readline(prompt = "Web Client ID: ") 299 | web_client_secret <- readline(prompt = "Web Client Secret: ") 300 | } 301 | 302 | myapp <- httr::oauth_app("google", 303 | key = web_client_id, 304 | secret = web_client_secret) 305 | 306 | httr::oauth2.0_token(httr::oauth_endpoints("google"), myapp, 307 | scope = "https://www.googleapis.com/auth/devstorage.read_only") 308 | } 309 | 310 | #' @title The OAuth function to get access to the cloud firestore: 311 | #' @author Paul Spende 312 | #' @description fireData::google_firestore retrieves a token with read access to the cloud firestore 313 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 314 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 315 | #' @param cache Cache the tokens in the .httr-oauth file or not. {boolean} 316 | #' @return Returns the token data. 317 | #' @export 318 | #' @examples 319 | #' \dontrun{ 320 | #' TODO: 321 | #' } 322 | google_firestore <- function(web_client_id = "prompt", web_client_secret = "prompt", cache = FALSE) { 323 | if (web_client_id == "prompt" && web_client_secret == "prompt") { 324 | web_client_id <- readline(prompt = "Web Client ID: ") 325 | web_client_secret <- readline(prompt = "Web Client Secret: ") 326 | } 327 | 328 | myapp <- httr::oauth_app("google", 329 | key = web_client_id, 330 | secret = web_client_secret) 331 | 332 | httr::oauth2.0_token(httr::oauth_endpoints("google"), myapp, 333 | scope = "https://www.googleapis.com/auth/datastore https://www.googleapis.com/auth/cloud-platform", 334 | cache = cache) 335 | } 336 | 337 | #' @title Firebase user creation function 338 | #' @param projectAPI The Firebase Project API {string} 339 | #' @param email The user email {string} 340 | #' @param password The user password {string} 341 | #' @description Creates a new firebase user account. All user accounts can accessed at the firebase.com project console. One of the advantages of firebase accounts in R is the ability to access a website and analyse the data of the website with the very same login. 342 | #' @return Registers a new user and returns the status. 343 | #' @export 344 | #' @examples 345 | #' \dontrun{ 346 | #' createUser(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "your@email.com", password = "12341234" ) 347 | #' } 348 | createUser <- function(projectAPI, email="prompt", password="prompt"){ 349 | if (password == "prompt" && email == "prompt") { 350 | email <- readline(prompt = "Email: ") 351 | password <- readline(prompt = "Password: ") 352 | print(paste0("Connecting to", project_api, ":")) 353 | } 354 | AuthUrl = paste0("https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=", projectAPI) 355 | userData = httr::POST(url = AuthUrl, body = list("email" = email, "password" = password), encode = "json") 356 | httr::content(userData) 357 | } 358 | 359 | #' @title Password resett function: 360 | #' @param projectAPI The Firebase Project API {string} 361 | #' @param email The user email {string} 362 | #' @description Resets the user password and sends an email to the user account. 363 | #' @return Success or warning message. 364 | #' @export 365 | #' @examples 366 | #' \dontrun{ 367 | #' resetPassword(projectAPI = "AIzaSyAjZLO9-CRV3gObpwdFz-k8AiTOxHSBmdc", email = "useYourOwn@email.com") 368 | #' } 369 | resetPassword <- function(projectAPI, email){ 370 | AuthUrl = paste0("https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode?key=", projectAPI) 371 | userData = httr::POST(url = AuthUrl, body = list("email" = email, "requestType" = "PASSWORD_RESET"), encode = "json") 372 | if ("error" %in% names(httr::content(userData))) { 373 | warning(paste0("User email ", email, " was not found in the database")) 374 | } else { 375 | print(paste0("Password reset email was send to ", email)) 376 | } 377 | } 378 | 379 | #' @title The upload function for firebase storage: 380 | #' @author Paul Spende 381 | #' @description fireData::upload_storage uploads a file to the firebase storage. 382 | #' @param bucket_name The name of your storage bucket. {string} 383 | #' @param object_name The name you want to give your file in the storage. {string} 384 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 385 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 386 | #' @param file_path The path of the file you want to upload, leave this empty to create a folder. {string} 387 | #' @param predefined_acl The predefined set of access controls. (authenticatedRead, bucketOwnerFullControl, bucketOwnerRead, private, projectPrivate, publicRead) {string} 388 | #' @return Returns the storage object informations. 389 | #' @export 390 | #' @examples 391 | #' \dontrun{ 392 | #' TODO: 393 | #' } 394 | upload_storage <- 395 | function(bucket_name, 396 | object_name, 397 | web_client_id = "prompt", 398 | web_client_secret = "prompt", 399 | file_path = NULL, 400 | predefined_acl = "publicRead") { 401 | google_token <- 402 | google_devstorage_read_write(web_client_id, web_client_secret) 403 | 404 | upload_url <- 405 | paste0( 406 | 'https://www.googleapis.com/upload/storage/v1/b/', 407 | bucket_name, 408 | '/o?uploadType=media&name=', 409 | object_name, 410 | '&predefinedAcl=', 411 | predefined_acl 412 | ) 413 | 414 | headers <- c("Authorization" = paste("Bearer", google_token$credentials$access_token)) 415 | 416 | if (is.null(file_path)) { 417 | response <- httr::POST(url = upload_url, 418 | add_headers( 419 | headers 420 | )) 421 | } else { 422 | response <- httr::POST( 423 | url = upload_url, 424 | body = upload_file(file_path), 425 | add_headers( 426 | headers 427 | ) 428 | ) 429 | } 430 | 431 | data <- httr::content(response) 432 | data['url'] <- paste('https://storage.cloud.google.com', bucket_name, object_name, sep = '/') 433 | 434 | data 435 | } 436 | 437 | #' @title The delete function for firebase storage: 438 | #' @author Paul Spende 439 | #' @description fireData::delete_storage deletes the file in the firebase storage bucket. 440 | #' @param bucket_name The name of your storage bucket. {string} 441 | #' @param object_name The name of the file that you want to delete from the bucket. {string} 442 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 443 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 444 | #' @return Returns NULL when successful. 445 | #' @export 446 | #' @examples 447 | #' \dontrun{ 448 | #' TODO: 449 | #' } 450 | delete_storage <- function(bucket_name, object_name, web_client_id = "prompt", web_client_secret = "prompt"){ 451 | google_token <- google_devstorage_read_write(web_client_id, web_client_secret) 452 | 453 | upload_url <- paste0('https://www.googleapis.com/storage/v1/b/', bucket_name, 454 | '/o/', object_name) 455 | 456 | response <- httr::DELETE(url = upload_url, 457 | add_headers("Authorization" = paste("Bearer", google_token$credentials$access_token))) 458 | 459 | httr::content(response) 460 | } 461 | 462 | #' @title The list function for firebase storage: 463 | #' @author Paul Spende 464 | #' @description fireData::list_storage lists all files in the firebase storage bucket. 465 | #' @param bucket_name The name of your storage bucket. {string} 466 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 467 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 468 | #' @return Returns the storage object informations for all files in the bucket. 469 | #' @export 470 | #' @examples 471 | #' \dontrun{ 472 | #' TODO: 473 | #' } 474 | list_storage <- function(bucket_name, web_client_id = "prompt", web_client_secret = "prompt"){ 475 | google_token <- google_devstorage_read_only(web_client_id, web_client_secret) 476 | 477 | upload_url <- paste0('https://www.googleapis.com/storage/v1/b/', bucket_name, '/o') 478 | 479 | response <- httr::GET(url = upload_url, 480 | add_headers("Authorization" = paste("Bearer", google_token$credentials$access_token))) 481 | 482 | httr::content(response) 483 | } 484 | 485 | #' @title The get function for firebase storage: 486 | #' @author Paul Spende 487 | #' @description fireData::get_storage lists all files in the firebase storage bucket. 488 | #' @param bucket_name The name of your storage bucket. {string} 489 | #' @param object_name The name of the file that you want to get from the bucket. {string} 490 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 491 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 492 | #' @return Returns the storage object ressource for the file in the bucket. 493 | #' @export 494 | #' @examples 495 | #' \dontrun{ 496 | #' TODO: 497 | #' } 498 | get_storage <- function(bucket_name, object_name, web_client_id = "prompt", web_client_secret = "prompt"){ 499 | google_token <- google_devstorage_read_only(web_client_id, web_client_secret) 500 | 501 | upload_url <- paste0('https://www.googleapis.com/storage/v1/b/', bucket_name, 502 | '/o/', object_name) 503 | 504 | response <- httr::GET(url = upload_url, 505 | add_headers("Authorization" = paste("Bearer", google_token$credentials$access_token))) 506 | 507 | httr::content(response) 508 | } 509 | 510 | #' @title The get the url for an object in storage (e.g. an htmk file): 511 | #' @author Paul Spende 512 | #' @description fireData::get_url outputs the url to access the object in storage. 513 | #' @param bucket_name The name of your storage bucket. {string} 514 | #' @param object_name The name of the file that you want to get from the bucket. {string} 515 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 516 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 517 | #' @return Returns the url for the storage object. 518 | #' @export 519 | #' @examples 520 | #' \dontrun{ 521 | #' TODO: 522 | #' } 523 | get_url <- function(bucket_name, object_name, web_client_id = "prompt", web_client_secret = "prompt"){ 524 | object_ressources <- get_storage(bucket_name, object_name, web_client_id, web_client_secret) 525 | 526 | paste0( 527 | "https://firebasestorage.googleapis.com/v0/b/", 528 | bucket_name, 529 | "/o/", 530 | object_name, 531 | "?alt=media&token=", 532 | object_ressources$metadata$firebaseStorageDownloadTokens 533 | ) 534 | } 535 | 536 | #' @title This function uploads a local folder to the storage bucket:: 537 | #' @author Paul Spende 538 | #' @description fireData::upload_folder uploads all files in the folder to the firebase storage bucket. 539 | #' @param bucket_name The name of your storage bucket. {string} 540 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 541 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 542 | #' @param folder_path The path to the folder on the local machine. {string} 543 | #' @return Returns list of storage object ressources of all the files uploaded in the bucket. 544 | #' @export 545 | #' @examples 546 | #' \dontrun{ 547 | #' TODO: 548 | #' } 549 | upload_folder <- function(bucket_name, web_client_id = "prompt", web_client_secret = "prompt", folder_path) { 550 | files <- list.files(path = folder_path, full.names = FALSE, recursive = TRUE) 551 | 552 | google_token <- google_devstorage_read_write(web_client_id, web_client_secret) 553 | 554 | responses <- list() 555 | 556 | for (file in files) { 557 | object_name <- paste0(folder_path, "/", file) 558 | 559 | print(object_name) 560 | 561 | upload_url <- paste0('https://www.googleapis.com/upload/storage/v1/b/', bucket_name, 562 | '/o?uploadType=media&name=', file) 563 | 564 | response <- httr::POST(url = upload_url, 565 | body = upload_file(paste0(folder_path, "/", file)), 566 | add_headers("Authorization" = paste("Bearer", google_token$credentials$access_token))) 567 | 568 | responses <- append(responses, httr::content(response)) 569 | } 570 | 571 | responses 572 | } 573 | 574 | #' @title This function complies a rmarkdown file to html and uploads it to the storage bucket:: 575 | #' @author Paul Spende 576 | #' @description fireData::deploy_rmarkdown deploys rmarkdown file to the firebase storage bucket. 577 | #' @param rmarkdown_path The path to the rmarkdown files. {string} 578 | #' @param bucket_name The name of your storage bucket. {string} 579 | #' @param object_name The name of the file that you want to get from the bucket. {string} 580 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 581 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 582 | #' @return Returns list of storage object ressources of all the files uploaded in the bucket. 583 | #' @export 584 | #' @examples 585 | #' \dontrun{ 586 | #' TODO: 587 | #' } 588 | deploy_rmarkdown <- function(rmarkdown_path, bucket_name, object_name, web_client_id = "prompt", web_client_secret = "prompt") { 589 | html_file <- rmarkdown::render(input = rmarkdown_path, output_format = "html_document") 590 | 591 | upload_storage( 592 | bucket_name = bucket_name, 593 | web_client_id = web_client_id, 594 | web_client_secret = web_client_secret, 595 | object_name = object_name, 596 | file_path = html_file 597 | ) 598 | } 599 | 600 | #' @title This function creates short dynamic links:: 601 | #' @author Paul Spende 602 | #' @description fireData::get_dynamic_link creates a short link for a longer one. 603 | #' @return Returns json object with short url and further information. 604 | #' @param project_api The Firebase Project API {string} 605 | #' @param domain The Firebase dynamic link domain {string} 606 | #' @param link The URL you want to shorten {string} 607 | #' @param short Flag to generate a short url (TRUE) or an unguessable url (FALSE). {boolean} 608 | #' @param social_title The title of the link preview. {string} 609 | #' @param social_description The description of the link preview. {string} 610 | #' @param social_image_link The URL to the image shown in the preview of the link. {string} 611 | #' @export 612 | #' @examples 613 | #' \dontrun{ 614 | #' TODO: 615 | #' } 616 | get_dynamic_link <- 617 | function(project_api, 618 | domain, 619 | link, 620 | short = TRUE, 621 | social_title = "", 622 | social_description = "", 623 | social_image_link = "") { 624 | option <- ifelse(short, "SHORT", "UNGUESSABLE") 625 | url <- 626 | paste0('https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=', 627 | project_api) 628 | response <- 629 | httr::POST( 630 | url = url, 631 | body = list( 632 | "dynamicLinkInfo" = list( 633 | "dynamicLinkDomain" = domain, 634 | "link" = link, 635 | "socialMetaTagInfo" = list( 636 | "socialTitle" = social_title, 637 | "socialDescription" = social_description, 638 | "socialImageLink" = social_image_link 639 | ) 640 | ), 641 | "suffix" = list("option" = option) 642 | ), 643 | encode = "json" 644 | ) 645 | httr::content(response) 646 | } 647 | 648 | #' @title This function creates a login overlay for a shiny application:: 649 | #' @author Paul Spende 650 | #' @description fireData::shiny_auth creates a short link for a longer one. 651 | #' @return Returns a functional login overlay. 652 | #' @param user A flag if user is logged in or not. E.g. USER <- reactiveValues(Logged = FALSE) {reactiveValues} 653 | #' @param input The input to the shiny server. (shinyServer(function(input, output) ...) {input} 654 | #' @param output The output to the shiny server. (shinyServer(function(input, output) ...) {input} 655 | #' @param credentials If the email and password login should be available. {boolean} 656 | #' @param goauth If google OAuth login should be available. {boolean} 657 | #' @param anonymous If the anonymous login should be available. {boolean} 658 | #' @param project_api The Firebase Project API {string} 659 | #' @param web_client_id The Web Client ID of your Google OAuth in your Firebase. {string} 660 | #' @param web_client_secret The Web Client Secret of your Google OAuth in your Firebase. {string} 661 | #' @param request_uri The URI to which the IDP redirects the user back. {string} 662 | #' @export 663 | #' @examples 664 | #' \dontrun{ 665 | #' TODO: 666 | #' } 667 | shiny_auth_server <- 668 | function(user, 669 | input, 670 | output, 671 | credentials = TRUE, 672 | goauth = TRUE, 673 | anonymous = TRUE, 674 | project_api = NULL, 675 | web_client_id= NULL, 676 | web_client_secret = NULL, 677 | request_uri = NULL) { 678 | 679 | if(anonymous) { 680 | observeEvent(input$.anonymous, { 681 | token <- 682 | anonymous_login(project_api = project_api) 683 | if (exists("idToken", where = token)) { 684 | user$Logged <- TRUE 685 | } else { 686 | show("message") 687 | output$message = renderText("Invalid user name or password") 688 | shinyjs::delay(2000, hide("message", anim = TRUE, animType = "fade")) 689 | } 690 | }) 691 | insertUI( 692 | selector = "#login", 693 | where = "afterBegin", 694 | ui = div(actionButton(".anonymous", "Anonymous login"), style = 695 | "text-align: center;") 696 | ) 697 | } 698 | 699 | if(goauth) { 700 | observeEvent(input$.goauth, { 701 | token <- 702 | google_login( 703 | project_api = project_api, 704 | web_client_id = web_client_id, 705 | web_client_secret = web_client_secret, 706 | request_uri = request_uri 707 | ) 708 | if (exists("oauthIdToken", where = token)) { 709 | user$Logged <- TRUE 710 | } else { 711 | show("message") 712 | output$message = renderText("Invalid user name or password") 713 | shinyjs::delay(1500, hide("message", anim = TRUE, animType = "fade")) 714 | } 715 | }) 716 | insertUI( 717 | selector = "#login", 718 | where = "afterBegin", 719 | ui = div(actionButton(".goauth", "Google login"), style = 720 | "text-align: center;") 721 | ) 722 | } 723 | 724 | if(credentials) { 725 | observeEvent(input$.login, { 726 | token <- 727 | auth( 728 | projectAPI = project_api, 729 | email = input$.username, 730 | password = input$.password 731 | ) 732 | if (exists("idToken", where = token)) { 733 | user$Logged <- TRUE 734 | } else { 735 | show("message") 736 | output$message = renderText("Invalid user name or password") 737 | shinyjs::delay(2000, hide("message", anim = TRUE, animType = "fade")) 738 | } 739 | }) 740 | insertUI( 741 | selector = "#login", 742 | where = "afterBegin", 743 | ui = tagList( 744 | textInput(".username", "Username:"), 745 | passwordInput(".password", "Password:"), 746 | div(actionButton(".login", "Login"), style = 747 | "text-align: center;") 748 | ) 749 | ) 750 | } 751 | 752 | fluidRow(column( 753 | width = 4, 754 | offset = 4, 755 | wellPanel( 756 | id = "login" 757 | ), 758 | textOutput("message") 759 | )) 760 | } 761 | 762 | #' @title Internal class to binary conversion: 763 | #' @param x is the S4 class object 764 | #' @description The internal conversion is needed to conserve all class information 765 | #' @return returns base64 encoded binary value of class object 766 | classConversion <- function(x){ 767 | #convert object to base64 768 | tempPath = tempfile() 769 | saveRDS(x, file = tempPath) 770 | binarySet = readBin(tempPath, what = "raw", n = 50000000) 771 | base64Set = jsonlite::base64_enc(binarySet) 772 | #adding key by assigning to data.frame 773 | pRolocList = list("base64Set" = base64Set) 774 | return(pRolocList) 775 | } 776 | 777 | #' @title Path key replacement function: 778 | #' @description replaces all disallowed path symbols with a "-" 779 | #' @param path is the db path {string} 780 | #' @return the approved and cleaned path_string 781 | #' @export 782 | path_check <- function(path){ 783 | path_replaced = gsub("\\$","-", path) 784 | path_replaced = gsub("\\#","-", path_replaced) 785 | path_replaced = gsub("\\]","-", path_replaced) 786 | path_replaced = gsub("\\[","-", path_replaced) 787 | path_replaced = gsub("\\/","-", path_replaced) 788 | path_replaced = gsub("\\.","-", path_replaced) 789 | if (path_replaced != path) warning(paste0("path changed to ", path_replaced)) 790 | return(path) 791 | } 792 | --------------------------------------------------------------------------------