diff --git a/web/pgadmin/browser/server_groups/servers/__init__.py b/web/pgadmin/browser/server_groups/servers/__init__.py index 78200b69e..05f29f8fc 100644 --- a/web/pgadmin/browser/server_groups/servers/__init__.py +++ b/web/pgadmin/browser/server_groups/servers/__init__.py @@ -19,7 +19,6 @@ from pgadmin.utils.ajax import make_json_response, bad_request, forbidden, \ make_response as ajax_response, internal_server_error, unauthorized, gone from pgadmin.utils.crypto import encrypt, decrypt, pqencryptpassword from pgadmin.utils.menu import MenuItem -from pgadmin.utils.ip import is_valid_ipaddress from pgadmin.tools.sqleditor.utils.query_history import QueryHistory import config @@ -30,6 +29,7 @@ from pgadmin.utils.master_password import get_crypt_key from pgadmin.utils.exception import CryptKeyMissing from pgadmin.tools.schema_diff.node_registry import SchemaDiffRegistry from psycopg2 import Error as psycopg2_Error, OperationalError +from pgadmin.browser.server_groups.servers.utils import is_valid_ipaddress def has_any(data, keys): @@ -523,8 +523,8 @@ class ServerNode(PGChildNodeView): if 'db_res' in data: data['db_res'] = ','.join(data['db_res']) - if 'hostaddr' in data and data['hostaddr'] and data['hostaddr'] != '' \ - and not is_valid_ipaddress(data['hostaddr']): + hostaddr = data.get('hostaddr') + if hostaddr and not is_valid_ipaddress(hostaddr): return make_json_response( success=0, status=400, @@ -755,8 +755,8 @@ class ServerNode(PGChildNodeView): ).format(arg) ) - if 'hostaddr' in data and data['hostaddr'] and data['hostaddr'] != '' \ - and not is_valid_ipaddress(data['hostaddr']): + hostaddr = data.get('hostaddr') + if hostaddr and not is_valid_ipaddress(data['hostaddr']): return make_json_response( success=0, status=400, @@ -774,7 +774,7 @@ class ServerNode(PGChildNodeView): servergroup_id=data.get('gid', gid), name=data.get('name'), host=data.get('host', None), - hostaddr=data.get('hostaddr', None), + hostaddr=hostaddr, port=data.get('port'), maintenance_db=data.get('db', None), username=data.get('username'), diff --git a/web/pgadmin/browser/server_groups/servers/tests/test_is_valid_address.py b/web/pgadmin/browser/server_groups/servers/tests/test_is_valid_address.py new file mode 100644 index 000000000..05dc6da9e --- /dev/null +++ b/web/pgadmin/browser/server_groups/servers/tests/test_is_valid_address.py @@ -0,0 +1,40 @@ +########################################################################## +# +# pgAdmin 4 - PostgreSQL Tools +# +# Copyright (C) 2013 - 2020, The pgAdmin Development Team +# This software is released under the PostgreSQL Licence +# +########################################################################## + +from pgadmin.utils.route import BaseTestGenerator +from .. import utils + + +class IsValidAddressTestCase(BaseTestGenerator): + scenarios = [ + ('TestCase for Valid Ipv4 Address', { + 'address': '192.168.0.1', + 'respdata': True + }), + ('TestCase for Valid Ipv6 Address', { + 'address': '2001:db8::', + 'respdata': True + }), + ('TestCase for Invalid Ip Address', { + 'address': 'toto', + 'respdata': False + }), + ] + + @classmethod + def setUpClass(cls): + pass + + def runTest(self): + self.assertEquals(utils.is_valid_ipaddress(self.address), + self.respdata) + + @classmethod + def tearDownClass(cls): + pass diff --git a/web/pgadmin/browser/server_groups/servers/utils.py b/web/pgadmin/browser/server_groups/servers/utils.py index a76c33788..59fa30ce7 100644 --- a/web/pgadmin/browser/server_groups/servers/utils.py +++ b/web/pgadmin/browser/server_groups/servers/utils.py @@ -8,11 +8,20 @@ ########################################################################## """Server helper utilities""" +from ipaddress import ip_address + from pgadmin.utils.crypto import encrypt, decrypt import config from pgadmin.model import db, Server +def is_valid_ipaddress(address): + try: + return bool(ip_address(address)) + except ValueError: + return False + + def parse_priv_from_db(db_privileges): """ Common utility function to parse privileges retrieved from database. diff --git a/web/pgadmin/utils/ip.py b/web/pgadmin/utils/ip.py deleted file mode 100644 index 7d969f360..000000000 --- a/web/pgadmin/utils/ip.py +++ /dev/null @@ -1,61 +0,0 @@ -########################################################################## -# -# pgAdmin 4 - PostgreSQL Tools -# -# Copyright (C) 2013 - 2020, The pgAdmin Development Team -# This software is released under the PostgreSQL Licence -# -######################################################################### - -"""This File Provides ipv4 and ipv6 address check.""" - -import re - -IPV4SEG = r'(?:25[0-5]|(?:2[0-4]|1{0,1}[0-9]){0,1}[0-9])' -IPV4ADDR = r'(?:(?:' + IPV4SEG + r'\.){3,3}' + IPV4SEG + r')' -IPV6SEG = r'(?:(?:[0-9a-fA-F]){1,4})' -IPV6GROUPS = ( - # 1:2:3:4:5:6:7:8 - r'(?:' + IPV6SEG + r':){7,7}' + IPV6SEG, - # 1:: 1:2:3:4:5:6:7:: - r'(?:' + IPV6SEG + r':){1,7}:', - # 1::8 1:2:3:4:5:6::8 1:2:3:4:5:6::8 - r'(?:' + IPV6SEG + r':){1,6}:' + IPV6SEG, - # 1::7:8 1:2:3:4:5::7:8 1:2:3:4:5::8 - r'(?:' + IPV6SEG + r':){1,5}(?::' + IPV6SEG + r'){1,2}', - # 1::6:7:8 1:2:3:4::6:7:8 1:2:3:4::8 - r'(?:' + IPV6SEG + r':){1,4}(?::' + IPV6SEG + r'){1,3}', - # 1::5:6:7:8 1:2:3::5:6:7:8 1:2:3::8 - r'(?:' + IPV6SEG + r':){1,3}(?::' + IPV6SEG + r'){1,4}', - # 1::4:5:6:7:8 1:2::4:5:6:7:8 1:2::8 - r'(?:' + IPV6SEG + r':){1,2}(?::' + IPV6SEG + r'){1,5}', - # 1::3:4:5:6:7:8 1::3:4:5:6:7:8 1::8 - IPV6SEG + r':(?:(?::' + IPV6SEG + r'){1,6})', - # ::2:3:4:5:6:7:8 ::2:3:4:5:6:7:8 ::8 :: - r':(?:(?::' + IPV6SEG + r'){1,7}|:)', - # fe80::7:8%eth0 fe80::7:8%1 (link-local IPv6 addresses with zone index) - r'fe80:(?::' + IPV6SEG + r'){0,4}%[0-9a-zA-Z]{1,}', - # ::255.255.255.255 ::ffff:255.255.255.255 ::ffff:0:255.255.255.255 - # (IPv4-mapped IPv6 addresses and IPv4-translated addresses) - r'::(?:ffff(?::0{1,4}){0,1}:){0,1}[^\s:]' + IPV4ADDR, - # 2001:db8:3:4::192.0.2.33 64:ff9b::192.0.2.33 - # (IPv4-Embedded IPv6 Address) - r'(?:' + IPV6SEG + r':){1,4}:[^\s:]' + IPV4ADDR, -) -# Reverse rows for greedy match -IPV6ADDR = '|'.join(['(?:{})'.format(g) for g in IPV6GROUPS[::-1]]) - -ip6re = re.compile(IPV6ADDR) -ip4re = re.compile(IPV4ADDR) - - -def is_valid_ip4address(addr): - return ip4re.match(addr) - - -def is_valid_ip6address(addr): - return ip6re.match(addr) - - -def is_valid_ipaddress(addr): - return ip4re.match(addr) or is_valid_ip6address(addr)