mirror of
https://github.com/samsonjs/vdirsyncer.git
synced 2026-04-05 10:45:51 +00:00
Add tests for get_password
This commit is contained in:
parent
d5fe537196
commit
7321da0f02
2 changed files with 130 additions and 39 deletions
|
|
@ -7,6 +7,7 @@
|
|||
:license: MIT, see LICENSE for more details.
|
||||
'''
|
||||
|
||||
import pytest
|
||||
import vdirsyncer.utils as utils
|
||||
|
||||
|
||||
|
|
@ -26,3 +27,67 @@ def test_parse_options():
|
|||
'bam': 123,
|
||||
'asd': False
|
||||
}
|
||||
|
||||
|
||||
def test_get_password_from_netrc(monkeypatch):
|
||||
username = 'foouser'
|
||||
password = 'foopass'
|
||||
resource = 'http://example.com/path/to/whatever/'
|
||||
hostname = 'example.com'
|
||||
|
||||
calls = []
|
||||
|
||||
def authenticators(self, hostname):
|
||||
calls.append(hostname)
|
||||
return username, 'bogus', password
|
||||
|
||||
import netrc
|
||||
|
||||
monkeypatch.setattr(netrc.netrc, 'authenticators', authenticators)
|
||||
|
||||
_password = utils.get_password(username, resource)
|
||||
assert _password == password
|
||||
assert calls == [hostname]
|
||||
|
||||
|
||||
@pytest.mark.parametrize('resources_to_test', range(1, 8))
|
||||
def test_get_password_from_system_keyring(monkeypatch, resources_to_test):
|
||||
username = 'foouser'
|
||||
password = 'foopass'
|
||||
resource = 'http://example.com/path/to/whatever/'
|
||||
hostname = 'example.com'
|
||||
|
||||
class KeyringMock(object):
|
||||
def __init__(self):
|
||||
p = utils.password_key_prefix
|
||||
self.resources = [
|
||||
p + 'http://example.com/path/to/whatever/',
|
||||
p + 'http://example.com/path/to/whatever',
|
||||
p + 'http://example.com/path/to/',
|
||||
p + 'http://example.com/path/to',
|
||||
p + 'http://example.com/path/',
|
||||
p + 'http://example.com/path',
|
||||
p + 'http://example.com/',
|
||||
][:resources_to_test]
|
||||
|
||||
def get_password(self, resource, _username):
|
||||
assert _username == username
|
||||
assert resource == self.resources.pop(0)
|
||||
if not self.resources:
|
||||
return password
|
||||
|
||||
import sys
|
||||
monkeypatch.setitem(sys.modules, 'keyring', KeyringMock())
|
||||
|
||||
import netrc
|
||||
netrc_calls = []
|
||||
|
||||
def authenticators(self, h):
|
||||
netrc_calls.append(h)
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(netrc.netrc, 'authenticators', authenticators)
|
||||
|
||||
_password = utils.get_password(username, resource)
|
||||
assert _password == password
|
||||
assert netrc_calls == [hostname]
|
||||
|
|
|
|||
|
|
@ -8,9 +8,11 @@
|
|||
'''
|
||||
|
||||
import os
|
||||
|
||||
import vdirsyncer.log
|
||||
|
||||
password_key_prefix = 'vdirsyncer:'
|
||||
|
||||
|
||||
def expand_path(p):
|
||||
p = os.path.expanduser(p)
|
||||
p = os.path.abspath(p)
|
||||
|
|
@ -65,54 +67,78 @@ def get_password(username, resource):
|
|||
|
||||
"""
|
||||
import getpass
|
||||
from netrc import netrc
|
||||
try:
|
||||
from urlparse import urlsplit
|
||||
from urlparse import urlsplit, urlunsplit
|
||||
except ImportError:
|
||||
from urllib.parse import urlsplit
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
sync_logger = vdirsyncer.log.get('sync')
|
||||
|
||||
# XXX is it save to asume that a password is always the same for
|
||||
# any given (hostname, username) combination?
|
||||
hostname = urlsplit(resource).hostname
|
||||
|
||||
# netrc
|
||||
try:
|
||||
auths = netrc().authenticators(hostname)
|
||||
# auths = (user, password)
|
||||
except IOError:
|
||||
pass
|
||||
else:
|
||||
if auths is not None:
|
||||
sync_logger.debug("Read password for user {0} on {1} in .netrc".format(
|
||||
auths[0], hostname))
|
||||
return auths[1]
|
||||
|
||||
# keyring
|
||||
try:
|
||||
import keyring
|
||||
except ImportError:
|
||||
keyring, password = None, None
|
||||
else:
|
||||
password = keyring.get_password(
|
||||
'vdirsyncer:' + hostname, username)
|
||||
keyring = None
|
||||
|
||||
logger = vdirsyncer.log.get('sync')
|
||||
hostname = urlsplit(resource).hostname
|
||||
|
||||
def _netrc():
|
||||
'''.netrc'''
|
||||
from netrc import netrc
|
||||
try:
|
||||
netrc_user, account, password = \
|
||||
netrc().authenticators(hostname) or (None, None, None)
|
||||
if netrc_user == username:
|
||||
return password
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
def _keyring():
|
||||
'''system keyring'''
|
||||
if keyring is None:
|
||||
return None
|
||||
|
||||
key = resource
|
||||
password = None
|
||||
|
||||
while True:
|
||||
password = keyring.get_password(password_key_prefix + key, username)
|
||||
if password is not None:
|
||||
return password
|
||||
|
||||
parsed = urlsplit(key)
|
||||
path = parsed.path
|
||||
if path.endswith('/'):
|
||||
path = path.rstrip('/')
|
||||
else:
|
||||
path = path.rsplit('/', 1)[0] + '/'
|
||||
|
||||
new_key = urlunsplit((
|
||||
parsed.scheme,
|
||||
parsed.netloc,
|
||||
path,
|
||||
parsed.query,
|
||||
parsed.fragment
|
||||
))
|
||||
if new_key == key:
|
||||
return None
|
||||
key = new_key
|
||||
|
||||
for func in (_netrc, _keyring):
|
||||
password = func()
|
||||
if password is not None:
|
||||
sync_logger.debug("Got password for user {0}@{1} from keyring".format(
|
||||
username, hostname))
|
||||
logger.debug('Got password for {} from {}'
|
||||
.format(username, func.__doc__))
|
||||
return password
|
||||
|
||||
if password is None:
|
||||
prompt = 'Server password {0}@{1}: '.format(username, hostname)
|
||||
password = getpass.getpass(prompt=prompt)
|
||||
prompt = ('Server password for {} at the resource {}: '
|
||||
.format(username, resource))
|
||||
password = getpass.getpass(prompt=prompt)
|
||||
|
||||
if keyring:
|
||||
answer = 'x'
|
||||
while answer.lower() not in ['', 'y', 'n']:
|
||||
if keyring is not None:
|
||||
answer = None
|
||||
while answer not in ['', 'y', 'n']:
|
||||
prompt = 'Save this password in the keyring? [y/N] '
|
||||
answer = raw_input(prompt)
|
||||
if answer.lower() == 'y':
|
||||
keyring.set_password(
|
||||
'vdirsyncer:' + hostname, username, password)
|
||||
answer = raw_input(prompt).lower()
|
||||
if answer == 'y':
|
||||
keyring.set_password(password_key_prefix + resource, username, password)
|
||||
|
||||
return password
|
||||
|
|
|
|||
Loading…
Reference in a new issue