|
|
|
@ -12,18 +12,43 @@ import ( |
|
|
|
|
"google.golang.org/api/drive/v3" |
|
|
|
|
"google.golang.org/api/googleapi" |
|
|
|
|
"google.golang.org/api/option" |
|
|
|
|
"io/ioutil" |
|
|
|
|
"log" |
|
|
|
|
"os" |
|
|
|
|
"path/filepath" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
type TokenCache struct { |
|
|
|
|
CredentialPath string |
|
|
|
|
CredentialScopes []string |
|
|
|
|
ConfigPath string |
|
|
|
|
TokenPath string |
|
|
|
|
configLoaded bool |
|
|
|
|
CredentialData *google.Credentials |
|
|
|
|
ConfigData oauth2.Config |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *TokenCache) Credentials() (*google.Credentials, error) { |
|
|
|
|
if c.CredentialData != nil { |
|
|
|
|
f, err := os.Open(c.CredentialPath) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("could not open credentials: %v", err) |
|
|
|
|
} |
|
|
|
|
defer func() { _ = f.Close() }() |
|
|
|
|
data, err := ioutil.ReadAll(f) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("could not read credentials: %v", err) |
|
|
|
|
} |
|
|
|
|
c.CredentialData, err = google.CredentialsFromJSON(context.Background(), data, c.CredentialScopes...) |
|
|
|
|
err = json.NewDecoder(f).Decode(&c.ConfigData) |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, fmt.Errorf("could not decode config: %v", err) |
|
|
|
|
} |
|
|
|
|
c.configLoaded = true |
|
|
|
|
} |
|
|
|
|
return c.CredentialData, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *TokenCache) Config() (*oauth2.Config, error) { |
|
|
|
|
if !c.configLoaded { |
|
|
|
|
f, err := os.Open(c.ConfigPath) |
|
|
|
@ -40,11 +65,29 @@ func (c *TokenCache) Config() (*oauth2.Config, error) { |
|
|
|
|
return &c.ConfigData, nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Retrieves a token and saves the token.
|
|
|
|
|
func (c *TokenCache) CredentialToken() (*oauth2.Token, error) { |
|
|
|
|
log.Printf("Getting token from credentials file %s", c.CredentialPath) |
|
|
|
|
creds, err := c.Credentials() |
|
|
|
|
if err != nil { |
|
|
|
|
return nil, err |
|
|
|
|
} |
|
|
|
|
return creds.TokenSource.Token() |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func (c *TokenCache) Token() (*oauth2.Token, error) { |
|
|
|
|
if c.CredentialPath != "" { |
|
|
|
|
return c.CredentialToken() |
|
|
|
|
} else { |
|
|
|
|
return c.StandardToken() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Retrieves a token and saves the token.
|
|
|
|
|
func (c *TokenCache) StandardToken() (*oauth2.Token, error) { |
|
|
|
|
// The file token.json stores the user's access and refresh tokens, and is
|
|
|
|
|
// created automatically when the authorization flow completes for the first
|
|
|
|
|
// time.
|
|
|
|
|
log.Printf("Getting token from secret file %s with cache in %s", c.ConfigPath, c.TokenPath) |
|
|
|
|
tok, err := c.CachedToken() |
|
|
|
|
if err == nil && tok.Valid() { |
|
|
|
|
return tok, nil |
|
|
|
@ -142,6 +185,7 @@ func (c *TokenCache) SaveToken(token *oauth2.Token) error { |
|
|
|
|
|
|
|
|
|
func main() { |
|
|
|
|
tokenCacheSource := TokenCache{ |
|
|
|
|
CredentialScopes: []string{drive.DriveScope}, |
|
|
|
|
ConfigData: oauth2.Config{ |
|
|
|
|
Endpoint: google.Endpoint, |
|
|
|
|
RedirectURL: "urn:ietf:wg:oauth:2.0:oob", |
|
|
|
@ -149,15 +193,20 @@ func main() { |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
flag.StringVar( |
|
|
|
|
&tokenCacheSource.ConfigPath, |
|
|
|
|
"secrets", |
|
|
|
|
"./secrets.json", |
|
|
|
|
"The path to the json file containing the client ID and secret.") |
|
|
|
|
&tokenCacheSource.CredentialPath, |
|
|
|
|
"credentials", |
|
|
|
|
"", |
|
|
|
|
"If set, overrides secrets.json and token.json. The path where the credentials file should be read from.") |
|
|
|
|
flag.StringVar( |
|
|
|
|
&tokenCacheSource.TokenPath, |
|
|
|
|
"token", |
|
|
|
|
"./token.json", |
|
|
|
|
"The path where the cached token should be stored and read from.") |
|
|
|
|
flag.StringVar( |
|
|
|
|
&tokenCacheSource.ConfigPath, |
|
|
|
|
"secrets", |
|
|
|
|
"./secrets.json", |
|
|
|
|
"The path to the json file containing the client ID and secret.") |
|
|
|
|
fileId := flag.String( |
|
|
|
|
"file-id", |
|
|
|
|
"", |
|
|
|
|