Skip to content

Commit

Permalink
Auth is working for github, google, and calendly!
Browse files Browse the repository at this point in the history
  • Loading branch information
cansavvy committed Nov 8, 2023
1 parent 701df11 commit 8808647
Show file tree
Hide file tree
Showing 15 changed files with 128 additions and 165 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
^renv\.lock$
^.*\.Rproj$
^\.Rproj\.user$
^\.httr-oauth$
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
.RData
.Ruserdata
.DS_Store
.secrets/*
.secrets/*
.httr-oauth
9 changes: 8 additions & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Package: metricminer2
Package: metricminer
Type: Package
Title: What the Package Does (Title Case)
Version: 0.1.0
Expand All @@ -7,5 +7,12 @@ Maintainer: The package maintainer <[email protected]>
Description: More about what it does (maybe more than one line)
Use four spaces when indenting paragraphs within the Description.
License: What license is it under?
BugReports: https://github.com/datatrail-jhu/rgoogleclassroom/issues
Imports:
attempt,
curl,
httr,
jsonlite
Encoding: UTF-8
RoxygenNote: 7.2.3
LazyData: true
100 changes: 72 additions & 28 deletions R/auth.R
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@

# TODO: Need to figure out a storage system for each app's token


.onAttach <- function(libname, pkgname) {
packageStartupMessage("Use authorize() function to begin give the package the proper credentials to run. ")
supported_endpoints <- function() {
list(
"calendly" = "https://auth.calendly.com/oauth/token",
"github" = httr::oauth_endpoints("github"),
"google" = httr::oauth_endpoints("google")
)
}


############### The creds handlers ###############
.Env <- new.env(parent = emptyenv())
.Env$Token <- NULL

.Env$metricminer_tokens <- list(
"calendly" = NULL,
"github" = NULL,
"google" = NULL
)

# Set token to environment
set_token <- function(value) {
.Env$Token <- value
return(value)
set_token <- function(token, app_name) {
.Env$metricminer_tokens[[app_name]] <- token
return(token)
}

# Get token from environment
get_token <- function() {
.Env$Token
get_token <- function(app_name) {
.Env$metricminer_tokens[app_name]
}

################################################################################
#' Authorize R package to access endpoints
#' @description This is a function to authorize the R package to access APIs interactively.
#' @param token an output from \code{\link{oauth2.0_token}} to set as the authentication token.
Expand All @@ -33,10 +41,22 @@ get_token <- function() {
#'
#' authorize()
#' }
authorize <- function(endpoint = NULL,
authorize <- function(app_name = NULL,
token = NULL,
cache = FALSE,
...) {

if (is.null(app_name)) {
# Ask the user what app they would like to authorize
endpoint_index <- menu(names(supported_endpoints()), title = "Which app would you like to authorize?")

# Extract info from supported endpoints list
endpoint <- supported_endpoints()[endpoint_index]

# Set app name based on selection
app_name <- names(endpoint)
}

if (!cache) {
cache_it <- menu(c("Yes store credentials as .httr-oauth file", "No do not store credentials, I will re-run this authorize() in my next R session"))
if (cache_it == 1) {
Expand All @@ -45,19 +65,34 @@ authorize <- function(endpoint = NULL,
} else {
cache_it <- 1
}
if (is.null(token)) {

# scopes_list <- find_scopes(endpoint)
if (app_name == "calendly") {
browseURL("https://calendly.com/integrations/api_webhooks")
message("On the opened page, click 'Generate Token'. Choose a name, then click 'Create Token'.")
token <- readline(prompt = "Paste token here and press enter. ")
}

if (app_name == "google") {
browseURL("https://github.com/settings/tokens/new?description=metricminer&scopes=repo,read:packages,read:org")
message("On the opened page, scroll down and click 'Generate Token'.")
token <- readline(prompt = "Paste token here and press enter.")
}

token <- oauth2.0_token(
endpoint = app_set_up()$endpoint,
app = app_set_up()$app,
if (is.null(token)) {
if (app_name == "google") {
scopes_list <- unlist(find_scopes(app_name))
} else {
scopes_list <- NULL
}
token <- httr::oauth2.0_token(
endpoint = app_set_up(app_name)$endpoint,
app = app_set_up(app_name)$app,
cache = cache_it == 1,
scope = scopes_list,
...
)
}
set_token(token)
set_token(token = token, app_name = app_name)
return(invisible(token))
}

Expand All @@ -80,7 +115,7 @@ authorize <- function(endpoint = NULL,
#' )
#' }
#'
auth_from_secret <- function(endpoint, access_token, refresh_token) {
auth_from_secret <- function(app_name, access_token, refresh_token) {
credentials <- list(
access_token = access_token,
expires_in = 3599L,
Expand All @@ -90,8 +125,8 @@ auth_from_secret <- function(endpoint, access_token, refresh_token) {
)

token <- httr::oauth2.0_token(
endpoint = app_set_up()$endpoint,
app = app_set_up()$app,
endpoint = app_set_up(endpoint)$endpoint,
app = app_set_up(endpoint)$app,
scope = scopes,
credentials = credentials
)
Expand All @@ -100,21 +135,30 @@ auth_from_secret <- function(endpoint, access_token, refresh_token) {
return(invisible(token))
}

#' App Set Up
#' @description This is a function that sets up the app. It's generally called by another function
#' @importFrom utils menu installed.packages
#' @importFrom httr oauth_app oauth_endpoints oauth2.0_token
#'
# This sets up the app creds no matter which way authorization is called
app_set_up <- function(endpoint) {
app_set_up <- function(app_name) {

supported <- names(supported_endpoints())

if (!(app_name %in% supported)) stop("That is not a supported app or endpoint")

decrypted <- openssl::aes_cbc_decrypt(
readRDS(encrypt_creds_path(endpoint)),
key = readRDS(key_encrypt_creds_path(endpoint))
readRDS(encrypt_creds_path(app_name)),
key = readRDS(key_encrypt_creds_path())
)

app <- oauth_app(
app <- httr::oauth_app(
appname = "metricminer",
key = unserialize(decrypted)$client_id,
secret = unserialize(decrypted)$client_secret
)
endpoint <- oauth_endpoints(endpoint)

return(list(app = app, endpoint = endpoint))
endpoint_url <- httr::oauth_endpoints(app_name)

return(list(app = app, endpoint = endpoint_url))
}
47 changes: 1 addition & 46 deletions R/google-analytics.R
Original file line number Diff line number Diff line change
@@ -1,46 +1 @@
remotes::install_github("MarkEdmondson1234/googleAnalyticsR")

library(tidyverse)
library(here)
library(googleAnalyticsR)
library(jsonlite)

ga_auth()
account_df <- ga_accounts()

account_df$id

## View account_list and pick the viewId you want to extract data from.
ga_id <- account_df$id[2]

ga_webproperty_list(ga_id)

## simple query to test connection, get 10 rows
google_analytics(ga_id,
date_range = c("2021-01-01", lubridate::today()),
metrics = "sessions",
dimensions = "date",
max = 10
)


# Ideally these Property IDs would get pulled from the API using the package,
# but I can't figure out how to get them to show up. See the README.md for this
# repo for more information.

here("app", "data", "ga-properties.json") |>
read_json() |>
pluck("properties") |>
bind_rows() |>
select(name, displayName) |>
mutate(name = gsub("properties/", "", name)) |>
rename(ID = name, Property = displayName) |>
select(Property, ID) |>
mutate(GA = map(ID, ga_data,
metrics = c("activeUsers", "sessions"),
dimensions = c("date", "pagePath", "pageTitle"),
date_range = c("2022-01-01", as.character(Sys.Date())),
limit = -1
)) %>%
unnest(GA) %>%
write_csv(here("app", "data", "ga.csv"))
# Extracting data from Google Analytics
63 changes: 24 additions & 39 deletions R/google-forms.R
Original file line number Diff line number Diff line change
@@ -1,46 +1,31 @@
remotes::install_github("MarkEdmondson1234/googleAnalyticsR")
# Extracting data from Google Forms

library(tidyverse)
library(here)
library(googleAnalyticsR)
library(jsonlite)

ga_auth()
account_df <- ga_accounts()
get_drive_file_list <- function(drive_id) {
# Get endpoint url
url <- get_endpoint("googledrive.endpoint")

account_df$id
# Get auth token
token <- get_token("google")
config <- httr::config(token = token)

## View account_list and pick the viewId you want to extract data from.
ga_id <- account_df$id[2]
# Wrapping body parameters in a requests list
body_params <- list(
corpora = "drive",
driveId = drive_id,
includeItemsFromAllDrives = "true",
supportsAllDrives = "true"
)

ga_webproperty_list(ga_id)
# Get list of topics
result <- httr::GET(url, config = config, body = body_params, accept_json())

## simple query to test connection, get 10 rows
google_analytics(ga_id,
date_range = c("2021-01-01", lubridate::today()),
metrics = "sessions",
dimensions = "date",
max = 10
)
if (httr::status_code(result) != 200) {
httr::stop_for_status(result)
}


# Ideally these Property IDs would get pulled from the API using the package,
# but I can't figure out how to get them to show up. See the README.md for this
# repo for more information.

here("app", "data", "ga-properties.json") |>
read_json() |>
pluck("properties") |>
bind_rows() |>
select(name, displayName) |>
mutate(name = gsub("properties/", "", name)) |>
rename(ID = name, Property = displayName) |>
select(Property, ID) |>
mutate(GA = map(ID, ga_data,
metrics = c("activeUsers", "sessions"),
dimensions = c("date", "pagePath", "pageTitle"),
date_range = c("2022-01-01", as.character(Sys.Date())),
limit = -1
)) %>%
unnest(GA) %>%
write_csv(here("app", "data", "ga.csv"))
# Process and return results
result_content <- content(result, "text")
result_list <- fromJSON(result_content)
return(result_list)
}
1 change: 1 addition & 0 deletions R/googlesheets.R
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Extracting data from Google Sheets
55 changes: 13 additions & 42 deletions R/scopes.R
Original file line number Diff line number Diff line change
@@ -1,49 +1,20 @@
# Scopes


find_scopes <- function(endpoint) {


find_scopes <- function(app_name) {
### Declare all the scopes
forms_scopes_list <- c(
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/drive.metadata.readonly",
"https://www.googleapis.com/auth/forms.body",
"https://www.googleapis.com/auth/forms.body.readonly",
"https://www.googleapis.com/auth/forms.responses.readonly"
scopes <- list(
google = c(
"https://www.googleapis.com/auth/drive",
"https://www.googleapis.com/auth/drive.file",
"https://www.googleapis.com/auth/drive.readonly",
"https://www.googleapis.com/auth/drive.metadata.readonly",
"https://www.googleapis.com/auth/forms.body",
"https://www.googleapis.com/auth/forms.body.readonly",
"https://www.googleapis.com/auth/forms.responses.readonly"
),
github = c("repo")
)

base_classroom_uri <- "https://www.googleapis.com/auth/classroom."

classroom_scopes_list <- paste0(
base_classroom_uri,
c(
"courses",
"courses.readonly",
"topics",
"topics.readonly",
"profile.emails",
"profile.photos",
"rosters",
"rosters.readonly",
"announcements",
"announcements.readonly",
"course-work.readonly",
"student-submissions.students.readonly",
"student-submissions.me.readonly",
"coursework.me",
"courseworkmaterials",
"coursework.students",
"courseworkmaterials",
"coursework.students.readonly",
"coursework.me.readonly",
"addons.student",
"push-notifications",
"addons.teacher",
"rosters",
"profile.emails"
)
)
return(scopes[app_name])
}
Loading

0 comments on commit 8808647

Please sign in to comment.