Skip to content

Commit 8bfd0d4

Browse files
committed
Implement gs4_scopes()
Closes #291
1 parent a9102de commit 8bfd0d4

File tree

10 files changed

+193
-17
lines changed

10 files changed

+193
-17
lines changed

NAMESPACE

+1
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ export(gs4_has_token)
9797
export(gs4_oauth_app)
9898
export(gs4_oauth_client)
9999
export(gs4_random)
100+
export(gs4_scopes)
100101
export(gs4_token)
101102
export(gs4_user)
102103
export(local_gs4_quiet)

NEWS.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# googlesheets4 (development version)
22

3+
* `gs4_scopes()` is a new function to access scopes relevant to the Sheets and
4+
Drive APIs. When called without arguments, `gs4_scopes()` returns a named
5+
vector of scopes, where the names are the associated short aliases.
6+
`gs4_scopes()` can also be called with a character vector; any element that's
7+
recognized as a short alias is replaced with the associated full scope (#291).
8+
39
# googlesheets4 1.1.0
410

511
## Syncing up with gargle

R/gs4_auth.R

+60-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,21 @@ gargle_lookup_table <- list(
2020
#' @eval gargle:::PREFIX_auth_details(gargle_lookup_table)
2121
#' @eval gargle:::PREFIX_auth_params()
2222
#'
23+
#' @param scopes One or more API scopes. Each scope can be specified in full or,
24+
#' for Sheets API-specific scopes, in an abbreviated form that is recognized by
25+
#' [gs4_scopes()]:
26+
#' * "spreadsheets" = "https://www.googleapis.com/auth/spreadsheets"
27+
#' (the default)
28+
#' * "spreadsheets.readonly" =
29+
#' "https://www.googleapis.com/auth/spreadsheets.readonly"
30+
#' * "drive" = "https://www.googleapis.com/auth/drive"
31+
#' * "drive.readonly" = "https://www.googleapis.com/auth/drive.readonly"
32+
#' * "drive.file" = "https://www.googleapis.com/auth/drive.file"
33+
#'
34+
#' See
35+
#' <https://developers.google.com/identity/protocols/oauth2/scopes#sheets> for
36+
#' details on the permissions for each scope.
37+
#'
2338
#' @family auth functions
2439
#' @export
2540
#'
@@ -36,19 +51,19 @@ gargle_lookup_table <- list(
3651
#' gs4_auth(email = NA)
3752
#'
3853
#' # use a 'read only' scope, so it's impossible to edit or delete Sheets
39-
#' gs4_auth(
40-
#' scopes = "https://www.googleapis.com/auth/spreadsheets.readonly"
54+
#' gs4_auth(scopes = "spreadsheets.readonly")
4155
#' )
4256
#'
4357
#' # use a service account token
4458
#' gs4_auth(path = "foofy-83ee9e7c9c48.json")
4559
gs4_auth <- function(email = gargle::gargle_oauth_email(),
4660
path = NULL,
47-
scopes = "https://www.googleapis.com/auth/spreadsheets",
61+
scopes = "spreadsheets",
4862
cache = gargle::gargle_oauth_cache(),
4963
use_oob = gargle::gargle_oob_default(),
5064
token = NULL) {
5165
gargle::check_is_service_account(path, hint = "gs4_auth_configure")
66+
scopes <- gs4_scopes(scopes)
5267

5368
# I have called `gs4_auth(token = drive_token())` multiple times now,
5469
# without attaching googledrive. Expose this error noisily, before it gets
@@ -259,6 +274,48 @@ check_gs4_email_is_drive_email <- function() {
259274
}
260275
}
261276

277+
#' Produce scopes specific to the Sheets API
278+
#'
279+
#' When called with no arguments, `gs4_scopes()` returns a named character
280+
#' vector of scopes associated with the Sheets API. If `gs4_scopes(scopes =)` is
281+
#' given, an abbreviated entry such as `"sheets.readonly"` is expanded to a full
282+
#' scope (`"https://www.googleapis.com/auth/sheets.readonly"` in this case).
283+
#' Unrecognized scopes are passed through unchanged.
284+
#'
285+
#' @inheritParams gs4_auth
286+
#'
287+
#' @seealso
288+
#' <https://developers.google.com/identity/protocols/oauth2/scopes#sheets> for
289+
#' details on the permissions for each scope.
290+
#' @returns A character vector of scopes.
291+
#' @family auth functions
292+
#' @export
293+
#' @examples
294+
#' gs4_scopes("spreadsheets")
295+
#' gs4_scopes("spreadsheets.readonly")
296+
#' gs4_scopes("drive")
297+
#' gs4_scopes()
298+
gs4_scopes <- function(scopes = NULL) {
299+
if (is.null(scopes)) {
300+
sheets_scopes
301+
} else {
302+
resolve_scopes(user_scopes = scopes, package_scopes = sheets_scopes)
303+
}
304+
}
305+
306+
sheets_scopes <- c(
307+
spreadsheets = "https://www.googleapis.com/auth/spreadsheets",
308+
spreadsheets.readonly = "https://www.googleapis.com/auth/spreadsheets.readonly",
309+
drive = "https://www.googleapis.com/auth/drive",
310+
drive.readonly = "https://www.googleapis.com/auth/drive.readonly",
311+
drive.file = "https://www.googleapis.com/auth/drive.file"
312+
)
313+
314+
resolve_scopes <- function(user_scopes, package_scopes) {
315+
m <- match(user_scopes, names(package_scopes))
316+
ifelse(is.na(m), user_scopes, package_scopes[m])
317+
}
318+
262319
# unexported helpers that are nice for internal use ----
263320
gs4_auth_internal <- function(account = c("docs", "testing"),
264321
scopes = NULL,

man/gs4_auth.Rd

+19-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/gs4_auth_configure.Rd

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/gs4_deauth.Rd

+2-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/gs4_scopes.Rd

+52
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkgdown/_pkgdown.yml

+1
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ reference:
108108
- gs4_deauth
109109
- gs4_user
110110
- gs4_auth_configure
111+
- gs4_scopes
111112
- googlesheets4-configuration
112113
- title: "Programming around the Sheets API"
113114
desc: >

tests/testthat/_snaps/gs4_auth.md

+16
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,19 @@
2424
The `app` argument of `gs4_auth_configure()` is deprecated as of googlesheets4 1.1.0.
2525
i Please use the `client` argument instead.
2626

27+
# gs4_scopes() reveals Sheets scopes
28+
29+
Code
30+
gs4_scopes()
31+
Output
32+
spreadsheets
33+
"https://www.googleapis.com/auth/spreadsheets"
34+
spreadsheets.readonly
35+
"https://www.googleapis.com/auth/spreadsheets.readonly"
36+
drive
37+
"https://www.googleapis.com/auth/drive"
38+
drive.readonly
39+
"https://www.googleapis.com/auth/drive.readonly"
40+
drive.file
41+
"https://www.googleapis.com/auth/drive.file"
42+

tests/testthat/test-gs4_auth.R

+34
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,37 @@ test_that("gs4_auth_configure(app =) is deprecated in favor of client", {
5757
expect_equal(gs4_oauth_client()$id, "abc.apps.googleusercontent.com")
5858
})
5959

60+
# gs4_scopes() ----
61+
test_that("gs4_scopes() reveals Sheets scopes", {
62+
expect_snapshot(gs4_scopes())
63+
})
64+
65+
test_that("gs4_scopes() substitutes actual scope for short form", {
66+
expect_equal(
67+
gs4_scopes(c(
68+
"spreadsheets",
69+
"drive",
70+
"drive.readonly"
71+
)),
72+
c(
73+
"https://www.googleapis.com/auth/spreadsheets",
74+
"https://www.googleapis.com/auth/drive",
75+
"https://www.googleapis.com/auth/drive.readonly"
76+
)
77+
)
78+
})
79+
80+
test_that("gs4_scopes() passes unrecognized scopes through", {
81+
expect_equal(
82+
gs4_scopes(c(
83+
"email",
84+
"spreadsheets.readonly",
85+
"https://www.googleapis.com/auth/cloud-platform"
86+
)),
87+
c(
88+
"email",
89+
"https://www.googleapis.com/auth/spreadsheets.readonly",
90+
"https://www.googleapis.com/auth/cloud-platform"
91+
)
92+
)
93+
})

0 commit comments

Comments
 (0)