Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Use the credentials package #422

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Imports:
Depends:
R (>= 3.1)
Suggests:
getPass
askpass
Type: Package
LazyData: true
Biarch: true
Expand Down
80 changes: 41 additions & 39 deletions R/credential.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## git2r, R bindings to the libgit2 library.
## Copyright (C) 2013 - 2019 The git2r contributors
## Copyright (C) 2013 - 2020 The git2r contributors
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License, version 2,
Expand Down Expand Up @@ -46,8 +46,8 @@
##' push(repo, credentials = cred)
##' }
cred_env <- function(username = NULL, password = NULL) {
structure(list(username = username, password = password),
class = "cred_env")
structure(list(username = username, password = password),
class = "cred_env")
}

##' Create a new personal access token credential object
Expand Down Expand Up @@ -81,15 +81,15 @@ cred_env <- function(username = NULL, password = NULL) {
##' push(repo, credentials = cred)
##' }
cred_token <- function(token = "GITHUB_PAT") {
structure(list(token = token), class = "cred_token")
structure(list(token = token), class = "cred_token")
}

##' Create a new plain-text username and password credential object
##'
##' @family git credential functions
##' @param username The username of the credential
##' @param password The password of the credential. If getPass is installed
##' and the only input is username, \code{getPass::getPass()} will be
##' @param password The password of the credential. If askpass is installed
##' and the only input is username, \code{askpass::askpass()} will be
##' called to allow for interactive and obfuscated interactive
##' input of the password.
##' @return A list of class \code{cred_user_pass} with entries:
Expand All @@ -108,17 +108,16 @@ cred_token <- function(token = "GITHUB_PAT") {
##' cred_user_pass("Random Developer", "SecretPassword")
##' }
cred_user_pass <- function(username = NULL, password = NULL) {

if (!is.null(username)) {
if (is.null(password)) {
if (requireNamespace("getPass", quietly = TRUE)) {
password <- getPass::getPass()
}
if (!is.null(username)) {
if (is.null(password)) {
if (requireNamespace("askpass", quietly = TRUE)) {
password <- askpass::askpass()
}
}
}
}

structure(list(username = username, password = password),
class = "cred_user_pass")
structure(list(username = username, password = password),
class = "cred_user_pass")
}

##' Create a new passphrase-protected ssh key credential object
Expand All @@ -129,8 +128,8 @@ cred_user_pass <- function(username = NULL, password = NULL) {
##' @param privatekey The path to the private key of the
##' credential. Default is \code{ssh_path("id_rsa")}
##' @param passphrase The passphrase of the credential. Default is
##' \code{character(0)}. If getPass is installed and private key
##' is passphrase protected \code{getPass::getPass()} will be
##' \code{character(0)}. If askpass is installed and private key
##' is passphrase protected \code{askpass::askpass()} will be
##' called to allow for interactive and obfuscated interactive
##' input of the passphrase.
##' @return A list of class \code{cred_ssh_key} with entries:
Expand All @@ -157,31 +156,33 @@ cred_user_pass <- function(username = NULL, password = NULL) {
cred_ssh_key <- function(publickey = ssh_path("id_rsa.pub"),
privatekey = ssh_path("id_rsa"),
passphrase = character(0)) {
publickey <- normalizePath(publickey, mustWork = TRUE)
privatekey <- normalizePath(privatekey, mustWork = TRUE)
publickey <- normalizePath(publickey, mustWork = TRUE)
privatekey <- normalizePath(privatekey, mustWork = TRUE)

if (length(passphrase) == 0) {
if (ssh_key_needs_passphrase(privatekey)) {
if (requireNamespace("getPass", quietly = TRUE)) {
passphrase <- getPass::getPass()
}
if (length(passphrase) == 0) {
if (ssh_key_needs_passphrase(privatekey)) {
if (requireNamespace("askpass", quietly = TRUE)) {
passphrase <- askpass::askpass()
}
}
}
}

structure(list(publickey = publickey,
privatekey = privatekey,
passphrase = passphrase),
class = "cred_ssh_key")
structure(list(publickey = publickey,
privatekey = privatekey,
passphrase = passphrase),
class = "cred_ssh_key")
}

##' Check if private key is passphrase protected
##' @param privatekey The path to the private key of the
##' credential. Default is \code{ssh_path("id_rsa")}
##' @noRd
ssh_key_needs_passphrase <- function(privatekey = ssh_path("id_rsa")) {
private_content <- readLines(privatekey, n = 3)
contains_encrypted <- grepl("encrypted", private_content, ignore.case = TRUE)
any(contains_encrypted)
private_content <- readLines(privatekey, n = 3)
contains_encrypted <- grepl("encrypted",
private_content,
ignore.case = TRUE)
any(contains_encrypted)
}

##' Compose usual path to ssh keys
Expand All @@ -207,15 +208,16 @@ ssh_key_needs_passphrase <- function(privatekey = ssh_path("id_rsa")) {
##' ssh_path()
##' ssh_path("is_rsa.pub")
ssh_path <- function(file = "") {
file.path(home_dir(), ".ssh", file)
file.path(home_dir(), ".ssh", file)
}

# Return the user's home directory regardless of operating system
home_dir <- function() {
if (.Platform$OS.type == "windows") {
home <- Sys.getenv("USERPROFILE")
} else {
home <- path.expand("~")
}
return(home)
if (.Platform$OS.type == "windows") {
home <- Sys.getenv("USERPROFILE")
} else {
home <- path.expand("~")
}

home
}
4 changes: 2 additions & 2 deletions man/cred_ssh_key.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions man/cred_user_pass.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.