Skip to content

Commit c5be1dc

Browse files
committed
auth: add dictionary storage
Allows not to save anything to disk, which is useful overall but especially useful when working with env vars, which could be sensitive so saving their value to disk is undesirable.
1 parent 3940d7b commit c5be1dc

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

pydrive2/auth.py

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from oauth2client.client import AccessTokenRefreshError
1111
from oauth2client.client import OAuth2WebServerFlow
1212
from oauth2client.client import OOB_CALLBACK_URN
13+
from oauth2client.contrib.dictionary_storage import DictionaryStorage
1314
from oauth2client.file import Storage
1415
from oauth2client.tools import ClientRedirectHandler
1516
from oauth2client.tools import ClientRedirectServer
@@ -197,9 +198,9 @@ def __init__(
197198
self.settings = settings or self.DEFAULT_SETTINGS
198199
ValidateSettings(self.settings)
199200

200-
self._storages = self._InitializeStoragesFromSettings()
201-
# Only one (`file`) backend is supported now
202-
self._default_storage = self._storages["file"]
201+
storages, default = self._InitializeStoragesFromSettings()
202+
self._storages = storages
203+
self._default_storage = default
203204

204205
@property
205206
def access_token_expired(self):
@@ -337,7 +338,7 @@ def ServiceAuth(self):
337338
)
338339

339340
def _InitializeStoragesFromSettings(self):
340-
result = {"file": None}
341+
result = {"file": None, "dictionary": None}
341342
backend = self.settings.get("save_credentials_backend")
342343
save_credentials = self.settings.get("save_credentials")
343344
if backend == "file":
@@ -347,11 +348,16 @@ def _InitializeStoragesFromSettings(self):
347348
"Please specify credentials file to read"
348349
)
349350
result[backend] = Storage(credentials_file)
351+
elif backend == "dictionary":
352+
result[backend] = DictionaryStorage(
353+
self.settings["save_credentials_dict"],
354+
self.settings["save_credentials_key"],
355+
)
350356
elif save_credentials:
351357
raise InvalidConfigError(
352358
"Unknown save_credentials_backend: %s" % backend
353359
)
354-
return result
360+
return result, result.get(backend)
355361

356362
def LoadCredentials(self, backend=None):
357363
"""Loads credentials or create empty credentials if it doesn't exist.
@@ -366,6 +372,8 @@ def LoadCredentials(self, backend=None):
366372
raise InvalidConfigError("Please specify credential backend")
367373
if backend == "file":
368374
self.LoadCredentialsFile()
375+
elif backend == "dictionary":
376+
self._LoadCredentialsDictionary()
369377
else:
370378
raise InvalidConfigError("Unknown save_credentials_backend")
371379

@@ -399,6 +407,13 @@ def LoadCredentialsFile(self, credentials_file=None):
399407
if self.credentials:
400408
self.credentials.set_store(self._default_storage)
401409

410+
def _LoadCredentialsDictionary(self):
411+
self._default_storage = self._storages["dictionary"]
412+
self.credentials = self._default_storage.get()
413+
414+
if self.credentials:
415+
self.credentials.set_store(self._default_storage)
416+
402417
def SaveCredentials(self, backend=None):
403418
"""Saves credentials according to specified backend.
404419
@@ -415,6 +430,8 @@ def SaveCredentials(self, backend=None):
415430
raise InvalidConfigError("Please specify credential backend")
416431
if backend == "file":
417432
self.SaveCredentialsFile()
433+
elif backend == "dictionary":
434+
self._SaveCredentialsDictionary()
418435
else:
419436
raise InvalidConfigError("Unknown save_credentials_backend")
420437

@@ -446,6 +463,13 @@ def SaveCredentialsFile(self, credentials_file=None):
446463
"Credentials file cannot be symbolic link"
447464
)
448465

466+
def _SaveCredentialsDictionary(self):
467+
if self.credentials is None:
468+
raise InvalidCredentialsError("No credentials to save")
469+
470+
storage = self._storages["dictionary"]
471+
storage.put(self.credentials)
472+
449473
def LoadClientConfig(self, backend=None):
450474
"""Loads client configuration according to specified backend.
451475

pydrive2/test/test_oauth.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,33 @@ def test_09_SaveLoadCredentialsUsesDefaultStorage(mocker):
125125
assert spy.call_count == 0
126126

127127

128+
def test_10_ServiceAuthFromSavedCredentialsDictionary():
129+
creds_dict = {}
130+
settings = {
131+
"client_config_backend": "service",
132+
"service_config": {
133+
"client_json_file_path": "/tmp/pydrive2/credentials.json",
134+
},
135+
"oauth_scope": ["https://www.googleapis.com/auth/drive"],
136+
"save_credentials": True,
137+
"save_credentials_backend": "dictionary",
138+
"save_credentials_dict": creds_dict,
139+
"save_credentials_key": "creds",
140+
}
141+
ga = GoogleAuth(settings=settings)
142+
ga.ServiceAuth()
143+
assert not ga.access_token_expired
144+
assert creds_dict
145+
first_creds_dict = creds_dict.copy()
146+
# Secondary auth should be made only using the previously saved
147+
# login info
148+
ga = GoogleAuth(settings=settings)
149+
ga.ServiceAuth()
150+
assert not ga.access_token_expired
151+
assert creds_dict == first_creds_dict
152+
time.sleep(1)
153+
154+
128155
def CheckCredentialsFile(credentials, no_file=False):
129156
ga = GoogleAuth(settings_file_path("test_oauth_default.yaml"))
130157
ga.LoadCredentialsFile(credentials)

0 commit comments

Comments
 (0)