Browse code

improve hostname validation and rename 'normalize_hostname'

We prefer the noun 'normalized_hostname' because we are interested
in the return value of the function, not the way in which it alters
the state of the program.

The hostname validation checks as much as it can. This serves its
purpose as a preliminary check to avoid a roundtrip to the Nord API.

Joseph Weston authored on 07/09/2017 02:03:36
Showing 1 changed files
... ...
@@ -40,9 +40,13 @@ async def _get(endpoint):
40 40
     return resp
41 41
 
42 42
 
43
-def _normalize_hostname(hostname):
44
-    if not hostname.endswith('nordvpn.com'):
45
-        return f'{hostname}.nordvpn.com'
43
+def normalized_hostname(hostname):
44
+    """Return the fully qualified domain name of a NordVPN host."""
45
+    host, *domain = hostname.split('.')
46
+    if not domain:
47
+        return f'{host}.nordvpn.com'
48
+    elif tuple(domain) != ('nordvpn', 'com'):
49
+        raise ValueError(f'invalid NordVPN host {hostname}')
46 50
     return hostname
47 51
 
48 52
 
... ...
@@ -68,7 +72,7 @@ async def host_config(host, protocol='tcp'):
68 72
         the trailing '.nordvpn.com'.
69 73
     protocol: str, 'tcp' or 'udp'
70 74
     """
71
-    host = _normalize_hostname(host)
75
+    host = normalized_hostname(host)
72 76
     resp = await _get(f'files/download/{_config_filename(host, protocol)}')
73 77
     return await resp.text()
74 78
 
... ...
@@ -90,7 +94,7 @@ async def host_load(host=None):
90 94
         to percentage load.
91 95
     """
92 96
     if host:
93
-        host = _normalize_hostname(host)
97
+        host = normalized_hostname(host)
94 98
     endpoint = f'server/stats/{host}' if host else 'server/stats'
95 99
     resp = await _get(endpoint)
96 100
     resp = await resp.json()
... ...
@@ -128,3 +132,17 @@ async def dns_servers():
128 132
     """Return a list of ip addresses of NordVPN DNS servers."""
129 133
     resp = await _get('dns/smart')
130 134
     return await resp.json()
135
+
136
+
137
+async def valid_credentials(username, password):
138
+    """Return True if NordVPN accepts the username/password combination.
139
+
140
+    Sometimes connecting to the VPN server gives an authentication error even
141
+    if the correct credentials are given. This function is useful to first verify
142
+    credentials so as to avoid unecessary reconnection attempts.
143
+
144
+    Parameters
145
+    ----------
146
+    username, password : str
147
+    """
148
+    return True