def __init__(self): # create API client self.cl = AC() # Send statistics self.cl.setUserAgent("ISPAPICLI", __version__) # init cross OS path reader self.initAppDirectories()
def __init__(self): # check if older versions exist self.__initToolVersions() # create API client self.cl = AC() # Send statistics self.cl.setUserAgent("ISPAPICLI", __version__) # init db self.dbObj = DB()
class Core: def __init__(self): # check if older versions exist self.__initToolVersions() # create API client self.cl = AC() # Send statistics self.cl.setUserAgent("ISPAPICLI", __version__) # init db self.dbObj = DB() def initParser(self, args=None): """ Initialize the parser using the python standard library 'argparse' This step adds all commands to be executed by the end-user Returns: -------- ArgumentParser: parser """ parser = argparse.ArgumentParser(add_help=False) parser.prog = "ispapi" parser.formatter_class = argparse.RawDescriptionHelpFormatter parser.epilog = textwrap.dedent(""" ------------------------------------------------------------ - You must login first to start requesting commands - You can use the command '--help <command>' to know everything about a specific command, - Or visit our documentation on: https://github.com/hexonet/hexonet-api-documentation ------------------------------------------------------------ """) # args: will be the positional args parser.add_argument("args", nargs=argparse.REMAINDER, help="All additional args, e.g. limit=5") # command: is the user command to be executed e.g. QueryDomainList parser.add_argument( "--command", "-c", metavar="<command>", help="Enter a command e.g. -c=CheckDomain or -c CheckDomain", ) # userid: used in login parser.add_argument("--userid", "-u", metavar="<user id>", help="Your login user ID") # password: used in login parser.add_argument("--password", "-p", metavar="<your password>", help="Your login password") # entitiy: either live or ote, used in login parser.add_argument( "--entity", "-e", choices={"live", "ote"}, help="Set entity to either live or ote system e.g. -e=ote", ) # gui: used to start the gui from the terminal parser.add_argument( "--gui", "-g", const="gui", nargs="?", metavar="<>", help="Start graphical application", ) # help: used to show help about how to use the tool, generated by argparse dynamically parser.add_argument( "--help", "-h", const="all", nargs="?", metavar="<command>,<>", help="Show detailed use of a 'command' OR use --help to show help", ) # list: used to list all the commands avaiable parser.add_argument( "--list", "-li", const="list", nargs="?", metavar="<>", help="List all commands' names", ) # logout: used to kill the user session (locally and remotely) parser.add_argument( "--logout", "-l", const="logout", nargs="?", metavar="<>", help="Destroy your current session", ) # update the local user commands. This will call scraper parser.add_argument( "--update", "-up", const="update", nargs="?", metavar="<>", help="Update local command list", ) # version: show the tool version parser.add_argument("--version", "-v", action="version", version=__version__) return parser def parseArgs(self, args): """ This function will check which command is triggered by the user and call a function accordingly Returns ------- Tuple: (string, string) """ # case logout if args["logout"] is not None: result = self.logout() return "logout", result # case gui if args["gui"] is not None: return "gui", "" # case help if args["help"] is not None: if args["help"] == "all": return "help", "" else: command_help = args["help"] help_info = self.getCommandHelp(command_help) return "help_command", help_info # case list of all commands if args["list"] is not None: commands_list = self.getCommandList() return "list", commands_list # case update commands triggered if args["update"]: return "update", "" # case login # check if login credentials provided if None not in (args["userid"], args["password"], args["entity"]): result, msg = self.login(args) return "msg", msg # otherwise it is a command requested # if logged in, and there is a session, then execute a command session_status = self.checkSession(args) if session_status == "valid": if args["command"] is not None: cmd_struct = {} cmd_struct["command"] = args["command"] return "cmd", cmd_struct if args["COMMAND"] is not None: cmd_struct = {} cmd_struct["command"] = args["COMMAND"] return "cmd", cmd_struct # case user trying to log in while his session is valid elif None not in (args["userid"], args["password"], args["entity"]): msg = "You are already logged in, your session is valid." return "msg", msg else: msg = "Command is not recognized!" return "cmd_unknown", msg # initial running elif session_status == "init": msg = "Login first, you can run the command: -u = <your user id> -p = <your password> -e = {ote,live}" return "msg", msg # case sessin expired elif session_status == "expired": msg = """ Session expired. Please login again. Use the command: -u = <your user id> -p = <your password> -e = {ote,live} """ return "msg", msg # case unknown command requested else: msg = "No command found!" return "cmd_unknown", msg def login(self, args, session_status=""): """ This function perform remote login on the server Returns ------- Tuple: ((True | False), msg:string) """ user = args["userid"] password = args["password"] entity = args["entity"] # check which system to use, live of test if entity == "ote": # case ote is set, otherwise by default the system is live self.cl.useOTESystem() self.cl.setCredentials(user, password) r = self.cl.login() if r.isSuccess(): # save login session loginSession = self.cl.getSession() # save session self.__saveLocalSession(loginSession, entity) msg = "Login success. Your session valid for one hour max of idle time" return True, msg else: desc = r.getDescription() code = r.getCode() msg = "Server response: " + str(code) + " " + desc return False, msg def checkSession(self, args=""): """ Check local session. Returns ------- String: 'valid' | 'init' | 'expired' """ # check if there is a session already exist try: # query for login data data = self.dbObj.getLoginInfo() if not data: raise Exception # get login data entity = data[0]["entity"] t_old = data[0]["ts"] session = data[0]["session"] time_format = "%Y-%m-%d %H:%M:%S" t_now = datetime.now().strftime(time_format) t_now_object = datetime.strptime(t_now, time_format) t_old_object = datetime.strptime(t_old, time_format) t_new = t_now_object - timedelta(hours=1) if t_new < t_old_object: result = self.cl.setSession(session) if entity == "ote": self.cl.useOTESystem() return "valid" else: return "expired" # Do something with the session file except Exception: return "init" def logout(self): """ Delete user session. Returns: -------- String: msg """ try: msg = "" # query for login data data = self.dbObj.getLoginInfo() if not data: raise Exception # get login data entity = data[0]["entity"] session = data[0]["session"] if entity == "ote": self.cl.useOTESystem() # delete remote session self.cl.setSession(str(session)) r = self.cl.logout() if r.isSuccess(): flag = True else: flag = False # delete local session self.dbObj.deleteLoginInfo() # return message if flag: msg = "Successfully logged out!" return msg else: msg = "Local session deleted but couldn't delete remote session!" return msg except Exception as e: return "Couldn't delete remote session due to: " + str(e) def request(self, commands): """ Request command from remote server. Returns: ------- Response: response """ response = self.cl.request(commands) return response def getResponse(self, response, mode=""): """ Parse response based on user preference. Returns: -------- List | String """ if mode == "properties": return response.getListHash() elif mode == "list": return response.getListHash() elif mode == "plain": return response.getPlain() else: code = response.getCode() description = response.getDescription() message = "Server response: " + str(code) + " " + description return message def getCommandHelp(self, command_name): """ Get help for a specific command: command_name. Returns: ------- String: <> """ data = self.dbObj.getCommand(command_name) for item in data: try: command_name_lower_case = (item["command"]).lower() if command_name_lower_case == command_name.lower(): command = item["command"] description = item["description"] availability = item["availability"] paramaters = item["paramaters"] basic_info = f""" Command: {command} Description: {description} Availability: {availability} Parameters:""" # dedent, remove spaces basic_info = textwrap.dedent(basic_info).strip() headers = ["Parameter", "Min", "Definition", "Type"] table = [] t = TextWrapper(width=30) for row in paramaters: row_data = [] for key in row: if key == "Definition": row_data.append(t.fill(row[key])) else: row_data.append(row[key]) table.append(row_data) paramaters_table = tabulate(table, headers, tablefmt="fancy_grid") return basic_info + "\n" + paramaters_table except Exception: continue else: return f"Command '{command_name}' not found!" def __saveLocalSession(self, loginSession, entity): """ Saves users session in local file. Returns: -------- Bool: True | False """ try: time_format = "%Y-%m-%d %H:%M:%S" ts = datetime.now().strftime(time_format) data = {} data["session"] = loginSession data["ts"] = ts data["entity"] = entity # insert login if self.dbObj.setLoginInfo(data): return True else: raise Exception except Exception: return False def parseParameters(self, parameters): """ Parse positional arguments, e.g. limit = 5. Returns: -------- Set: params """ params_len = len(parameters) params = {} i = 0 while i < (params_len): if "=" in parameters[i]: key, value = parameters[i].split("=") params[key] = value else: key = parameters[i] i += 1 value = parameters[i] params[key] = value i += 1 # return result return params def getCommandList(self): """ Get all commands from local commands' files Returns: -------- String: return_list """ return_list = "" data = self.dbObj.getAllCommands() for item in data: try: return_list += item["command"] + "\n" except Exception: continue return return_list def getSubUserList(self): """ Get all subusers from local commands' files Returns: -------- String: return_list """ return_list = "" data = self.dbObj.getAllSubusers() for item in data: try: return_list += item["subuser"] + "\n" except Exception: continue return return_list def getMinParameters(self, command_name): """ Get minimum required parameters of the command: command_name Returns: -------- List: returnData """ returnData = [] data = self.dbObj.getCommand(command_name) if data: for item in data: try: command_name_lower_case = (item["command"]).lower() if command_name_lower_case == command_name.lower(): paramaters = item["paramaters"] for row in paramaters: paramater = row["Parameter"] minValue = row["Min"] if minValue == "1" and paramater != "COMMAND": returnData.append(paramater.lower()) except Exception: continue return list(dict.fromkeys(returnData)) def getSubUsers(self): cmd = { "command": "finduser", "pattern": "%", "userdepth": "all", "orderby": "userid", } response = self.request(cmd) listResult = response.getListHash()["LIST"] for item in listResult: subusers = {} subusers["subuser"] = item["USER"] self.dbObj.insertSubuser(item["USER"], subusers) pass def getCurrentVersion(self): return __version__ def __initToolVersions(self): currentVersion = __version__.split(".") currentVersion[2] = str(int(currentVersion[2]) + 1) currentVersion = ".".join(currentVersion) currentToolVersion = "ispapicli-" + currentVersion print(os.listdir()) files = os.listdir() ispapicliVersions = [] for file in files: if file.startswith("ispapicli"): ispapicliVersions.append(file) print(ispapicliVersions, len(ispapicliVersions)) if len(ispapicliVersions) <= 1: return else: for ver in ispapicliVersions: if currentToolVersion != ver: os.remove(ver) print(currentToolVersion, ver, "removed")
def test_apiclientmethods(): cl = AC() rtm.addTemplate( "login200", "[RESPONSE]\r\nPROPERTY[SESSION][0]=h8JLZZHdF2WgWWXlwbKWzEG3XrzoW4y" + "shhvtqyg0LCYiX55QnhgYX9cB0W4mlpbx\r\nDESCRIPTION=Command completed" + " successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.169\r\nEOF\r" + "\n", ) rtm.addTemplate("login500", rtm.generateTemplate("530", "Authentication failed")) rtm.addTemplate( "OK", rtm.generateTemplate("200", "Command completed successfully")) rtm.addTemplate( "listP0", "[RESPONSE]\r\nPROPERTY[TOTAL][0]=2701\r\nPROPERTY[FIRST][0]=0\r\nP" + "ROPERTY[DOMAIN][0]=0-60motorcycletimes.com\r\nPROPERTY[DOMAIN][1]=" + "0-be-s01-0.com\r\nPROPERTY[COUNT][0]=2\r\nPROPERTY[LAST][0]=1\r\nP" + "ROPERTY[LIMIT][0]=2\r\nDESCRIPTION=Command completed successfully" + "\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.023\r\nEOF\r\n", ) rtm.addTemplate( "listP1", "[RESPONSE]\r\nPROPERTY[TOTAL][0]=2701\r\nPROPERTY[FIRST][0]=2\r\nP" + "ROPERTY[DOMAIN][0]=0-qas-ao17-0.org\r\nPROPERTY[DOMAIN][1]=0-sunny" + "da222y.com\r\nPROPERTY[COUNT][0]=2\r\nPROPERTY[LAST][0]=3\r\nPROPE" + "RTY[LIMIT][0]=2\r\nDESCRIPTION=Command completed successfully\r\nC" + "ODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.032\r\nEOF\r\n", ) rtm.addTemplate( "listFP0", "[RESPONSE]\r\nPROPERTY[TOTAL][0]=3\r\nPROPERTY[FIRST][0]=0\r\nPROP" + "ERTY[DOMAIN][0]=0-60motorcycletimes.com\r\nPROPERTY[COUNT][0]=1\r" + "\nPROPERTY[LAST][0]=1\r\nPROPERTY[LIMIT][0]=1\r\nDESCRIPTION=Comma" + "nd completed successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0." + "023\r\nEOF\r\n", ) rtm.addTemplate( "listFP1", "[RESPONSE]\r\nPROPERTY[TOTAL][0]=3\r\nPROPERTY[FIRST][0]=1\r\nPROP" + "ERTY[DOMAIN][0]=0-be-s01-0.com\r\nPROPERTY[COUNT][0]=1\r\nPROPERTY" + "[LAST][0]=2\r\nPROPERTY[LIMIT][0]=1\r\nDESCRIPTION=Command complet" + "ed successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.032\r\nEOF" + "\r\n", ) rtm.addTemplate( "listFP2", "[RESPONSE]\r\nPROPERTY[TOTAL][0]=3\r\nPROPERTY[FIRST][0]=2\r\nPROP" + "ERTY[DOMAIN][0]=0-qas-ao17-0.org\r\nPROPERTY[COUNT][0]=2\r\nPROPER" + "TY[LAST][0]=3\r\nPROPERTY[LIMIT][0]=1\r\nDESCRIPTION=Command compl" + "eted successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.032\r\nE" + "OF\r\n", ) # #.getPOSTData() # test object input with special chars validate = ("s_entity=54cd&s_command=AUTH%3Dgwrgwqg%25" + "%26%5C44t3%2A%0ACOMMAND%3DModifyDomain") enc = cl.getPOSTData({ "COMMAND": "ModifyDomain", "AUTH": "gwrgwqg%&\\44t3*" }) assert enc == validate # test string input enc = cl.getPOSTData("gregergege") assert enc == "s_entity=54cd&s_command=gregergege" # test object input with null value in parameter validate = "s_entity=54cd&s_command=COMMAND%3DModifyDomain" enc = cl.getPOSTData({"COMMAND": "ModifyDomain", "AUTH": None}) assert enc == validate # test secured passwords cl.setCredentials("test.user", "test.passw0rd") enc = cl.getPOSTData( { "COMMAND": "CheckAuthentication", "SUBUSER": "******", "PASSWORD": "******", }, True, ) cl.setCredentials("", "") expected = ( "s_entity=54cd&s_login=test.user&s_pw=***&" + "s_command=COMMAND%3DCheckAuthentication%0APASSWORD%3D%2A%2A%2A%0ASUBUSER%3Dtest.user" ) assert expected == enc # #.enableDebugMode() cl.enableDebugMode() cl.disableDebugMode() # #.getSession() # initial value session = cl.getSession() assert session is None # custom value sessid = "testSessionID12345678" cl.setSession(sessid) session = cl.getSession() assert session is sessid cl.setSession("") # #.getURL() assert cl.getURL() == ISPAPI_CONNECTION_URL_LIVE # #.getUserAgent() pid = "PYTHON-SDK" pyv = platform.python_version() pf = platform.system() arch = platform.architecture()[0] ua = "%s (%s; %s; rv:%s) python/%s" % (pid, pf, arch, cl.getVersion(), pyv) assert cl.getUserAgent() == ua # #.setUserAgent() pid = "WHMCS" rv = "7.7.0" pid2 = "python-sdk" pyv = platform.python_version() pf = platform.system() arch = platform.architecture()[0] ua = "%s (%s; %s; rv:%s) %s/%s python/%s" % ( pid, pf, arch, rv, pid2, cl.getVersion(), pyv, ) cl2 = cl.setUserAgent(pid, rv) assert isinstance(cl2, AC) is True assert cl.getUserAgent() == ua mods = ["reg/2.6.2", "ssl/7.2.2", "dc/8.2.2"] ua = "%s (%s; %s; rv:%s) %s %s/%s python/%s" % ( pid, pf, arch, rv, " ".join(mods), pid2, cl.getVersion(), pyv, ) cl2 = cl.setUserAgent(pid, rv, mods) assert isinstance(cl2, AC) is True assert cl.getUserAgent() == ua # #.setURL() tmp = ISPAPI_CONNECTION_URL_PROXY url = cl.setURL(tmp).getURL() assert url is tmp cl.setURL(ISPAPI_CONNECTION_URL_LIVE) # #.setOTP() # [otp set] cl.setOTP("12345678") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_otp=12345678&s_command=COMMAND%3DStatusAccount" assert tmp == exp # [otp reset] cl.setOTP("") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_command=COMMAND%3DStatusAccount" assert tmp == exp # #.setSession() # [session set] cl.setSession("12345678") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_session=12345678&s_command=COMMAND%3DStatusAccount" assert tmp == exp # [credentials and session set] cl.setRoleCredentials("myaccountid", "myrole", "mypassword") cl.setOTP("12345678") cl.setSession("12345678") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_session=12345678&s_command=COMMAND%3DStatusAccount" assert tmp == exp # [session reset] cl.setSession("") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) assert tmp == "s_entity=54cd&s_command=COMMAND%3DStatusAccount" # #.saveSession/reuseSession sessionobj = {} cl.setSession("12345678").saveSession(sessionobj) cl2 = AC() cl2.reuseSession(sessionobj) tmp = cl2.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_session=12345678&s_command=COMMAND%3DStatusAccount" assert tmp == exp cl.setSession("") # #.setRemoteIPAddress() # [ip set] cl.setRemoteIPAddress("10.10.10.10") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_remoteaddr=10.10.10.10&s_command=COMMAND%3DStatusAccount" assert tmp == exp # [ip reset] cl.setRemoteIPAddress("") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) assert tmp == "s_entity=54cd&s_command=COMMAND%3DStatusAccount" # #.setCredentials() # [credentials set] cl.setCredentials("myaccountid", "mypassword") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_login=myaccountid&s_pw=mypassword&s_command=COMMAND%3DStatusAccount" assert tmp == exp # [session reset] cl.setCredentials("", "") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) assert tmp == "s_entity=54cd&s_command=COMMAND%3DStatusAccount" # #.setRoleCredentials() # [role credentials set] cl.setRoleCredentials("myaccountid", "myroleid", "mypassword") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) exp = "s_entity=54cd&s_login=myaccountid%21myroleid&s_pw=mypassword&s_command=COMMAND%3DStatusAccount" assert tmp == exp # [role credentials reset] cl.setRoleCredentials("", "", "") tmp = cl.getPOSTData({"COMMAND": "StatusAccount"}) assert tmp == "s_entity=54cd&s_command=COMMAND%3DStatusAccount" # #.login() # [login succeeded; no role used] cl.useOTESystem() cl.setCredentials("test.user", "test.passw0rd") cl.setRemoteIPAddress("1.2.3.4") r = cl.login() assert isinstance(r, R) is True assert r.isSuccess() is True, ("{0} {1}").format(r.getCode(), r.getDescription()) rec = r.getRecord(0) assert rec is not None assert rec.getDataByKey("SESSION") is not None # support bulk parameters also as nested array (flattenCommand) r = cl.request({ "COMMAND": "CheckDomains", "DOMAIN": ["example.com", "example.net"] }) assert isinstance(r, R) is True assert r.isSuccess() is True assert r.getCode() is 200 assert r.getDescription() == "Command completed successfully" cmd = r.getCommand() keys = cmd.keys() assert ("DOMAIN0" in keys) is True assert ("DOMAIN1" in keys) is True assert ("DOMAIN" in keys) is False assert cmd["DOMAIN0"] == "example.com" assert cmd["DOMAIN1"] == "example.net" # support autoIDNConvert r = cl.request({ "COMMAND": "CheckDomains", "DOMAIN": ["example.com", "dömäin.example", "example.net"], }) assert isinstance(r, R) is True assert r.isSuccess() is True assert r.getCode() is 200 assert r.getDescription() == "Command completed successfully" cmd = r.getCommand() keys = cmd.keys() assert ("DOMAIN0" in keys) is True assert ("DOMAIN1" in keys) is True assert ("DOMAIN2" in keys) is True assert ("DOMAIN" in keys) is False assert cmd["DOMAIN0"] == "example.com" assert cmd["DOMAIN1"] == "xn--dmin-moa0i.example" assert cmd["DOMAIN2"] == "example.net" # [login succeeded; role used] # cl.useOTESystem() # cl.setRoleCredentials('test.user', 'testrole', 'test.passw0rd') # r = cl.login() # assert isinstance(r, R) # assert r.isSuccess() is True, ("{0} {1}").format(r.getCode(), r.getDescription()) # rec = r.getRecord(0) # assert rec is not None # assert rec.getDataByKey('SESSION') is not None # [login failed; wrong credentials] cl.setCredentials("test.user", "WRONGPASSWORD") r = cl.login() assert isinstance(r, R) assert r.isError() is True # [login failed; http error] tpl = rtm.getTemplate("httperror") old = cl.getURL() cl.setURL("https://iwontsucceedgregegeg343teagr43.com/api/call.cgi") cl.setCredentials("test.user", "WRONGPASSWORD") r = cl.login() assert isinstance(r, R) assert r.isTmpError() is True assert r.getDescription() == tpl.getDescription() cl.setURL(old) # [login succeeded; no session returned] # TODO: need network mock # tpl = R(rtm.getTemplate('OK').getPlain()) # cl.useOTESystem() # cl.setCredentials('test.user', 'test.passw0rd') # r = cl.login() # assert isinstance(r, R) # assert r.isSuccess() is True # rec = r.getRecord(0) # assert rec is Node # #.loginExtended() # [login succeeded; no role used] cl.useOTESystem() cl.setCredentials("test.user", "test.passw0rd") r = cl.loginExtended({"TIMEOUT": 60}) assert isinstance(r, R) is True assert r.isSuccess() is True rec = r.getRecord(0) assert rec is not None assert rec.getDataByKey("SESSION") is not None # #.logout() # [logout succeeded] r = cl.logout() assert isinstance(r, R) assert r.isSuccess() is True # [logout failed; session no longer exists] tpl = R(rtm.getTemplate("login200").getPlain()) cl.enableDebugMode() cl.setSession(tpl.getRecord(0).getDataByKey("SESSION")) r = cl.logout() assert isinstance(r, R) is True assert r.isError() is True # #.request() # [200 < r.statusCode > 299] # TODO need network mock # tpl2 = R(rtm.getTemplate('httperror').getPlain()) # cl.setCredentials('test.user', 'test.passw0rd') # cl.useOTESystem() # r = cl.request({ 'COMMAND': 'GetUserIndex' }) # assert isinstance(r, R) is True # assert r.isTmpError() is True # assert r.getCode() == tpl2.getCode() # assert r.getDescription() == tpl2.getDescription() # [200 < r.statusCode > 299, no debug] # TODO need network mock # tpl2 = R(rtm.getTemplate('httperror').getPlain()) # cl.disableDebugMode() # r = cl.request({ 'COMMAND': 'GetUserIndex' }) # assert isinstance(r, R) # assert r.isTmpError() is True # assert r.getCode() == tpl2.getCode() # assert r.getDescription() == tpl2.getDescription() # .requestNextResponsePage # [no LAST set] cl.setCredentials("test.user", "test.passw0rd") cl.useOTESystem() r = R( rtm.getTemplate("listP0").getPlain(), { "COMMAND": "QueryDomainList", "LIMIT": 2, "FIRST": 0 }, ) nr = cl.requestNextResponsePage(r) assert r.isSuccess() is True assert nr.isSuccess() is True assert r.getRecordsLimitation() == 2 assert nr.getRecordsLimitation() == 2 assert r.getRecordsCount() == 2 assert nr.getRecordsCount() == 2 assert r.getFirstRecordIndex() == 0 assert r.getLastRecordIndex() == 1 assert nr.getFirstRecordIndex() == 2 assert nr.getLastRecordIndex() == 3 # [LAST set] r = R( rtm.getTemplate("listP0").getPlain(), { "COMMAND": "QueryDomainList", "LIMIT": 2, "FIRST": 0, "LAST": 1 }, ) with pytest.raises(Exception, match=r"Parameter LAST in use."): cl.requestNextResponsePage(r) # [no FIRST set] cl.disableDebugMode() r = R( rtm.getTemplate("listP0").getPlain(), { "COMMAND": "QueryDomainList", "LIMIT": 2 }) nr = cl.requestNextResponsePage(r) assert r.isSuccess() is True assert nr.isSuccess() is True assert r.getRecordsLimitation() == 2 assert nr.getRecordsLimitation() == 2 assert r.getRecordsCount() == 2 assert nr.getRecordsCount() == 2 assert r.getFirstRecordIndex() == 0 assert r.getLastRecordIndex() == 1 assert nr.getFirstRecordIndex() == 2 assert nr.getLastRecordIndex() == 3 # #.requestAllResponsePages() # [success case] nr = cl.requestAllResponsePages({ "COMMAND": "QuerySSLCertList", "FIRST": 0, "LIMIT": 100 }) assert len(nr) > 0 # #.setUserView() cl.setUserView("hexotestman.com") r = cl.request({"COMMAND": "GetUserIndex"}) assert isinstance(r, R) is True assert r.isSuccess() is True # #.resetUserView() cl.setUserView("") r = cl.request({"COMMAND": "GetUserIndex"}) assert isinstance(r, R) is True assert r.isSuccess() is True # #.setProxy cl.setProxy("https://127.0.0.1:8080") assert cl.getProxy() == "https://127.0.0.1:8080" cl.setProxy("") # #.setReferer cl.setReferer("https://www.hexonet.net/") assert cl.getReferer() == "https://www.hexonet.net/" cl.setReferer("") # #.useHighPerformanceConnectionSetup cl.useHighPerformanceConnectionSetup() assert cl.getURL() == ISPAPI_CONNECTION_URL_PROXY # #.useDefaultConnectionSetup cl.useDefaultConnectionSetup() assert cl.getURL() == ISPAPI_CONNECTION_URL_LIVE
#!/usr/bin/python # Import the ispapi library from hexonet.apiconnector.apiclient import APIClient as AC # -------- SESSIONLESS COMMUNICATION ----------- # Create a connection using the APIClient class and the appropriate # methods to configure the connection as necessary. # Don't have a HEXONET Account yet? Get one here: # - Live System Account: https://www.hexonet.net/sign-up # - Test/OT&E System Account: https://www.hexonet.net/signup-ote cl = AC() cl.useOTESystem() cl.setCredentials('test.user', 'test.passw0rd') # use the below method in case you have an active # ip filter setting cl.setRemoteIPAddress('1.2.3.4') # Call a command r = cl.request({ 'Command': "QueryDomainList", 'limit': 5 }) # Get the result in the format you want rlist = r.getListHash() rhash = r.getHash() rplain = r.getPlain() # Get the response code and the response description
class Core: def __init__(self): # create API client self.cl = AC() # Send statistics self.cl.setUserAgent("ISPAPICLI", __version__) # init cross OS path reader self.initAppDirectories() def initAppDirectories(self): ''' This function checks whether the apps is running in your editor or in an executable file This is important to correctly associate the path Returns: None ''' if getattr(sys, 'frozen', False): self.absolute_dirpath = os.path.dirname(sys.executable) elif __file__: self.absolute_dirpath = os.path.dirname(__file__) # check if commands exist if not os.path.exists( os.path.join(self.absolute_dirpath, '../commands/')): os.makedirs(os.path.join(self.absolute_dirpath, '../commands/')) # check config directory if not os.path.exists(os.path.join(self.absolute_dirpath, '../config/')): os.makedirs(os.path.join(self.absolute_dirpath, '../config/')) # set path variables self.command_path = os.path.join(self.absolute_dirpath, '../commands/') self.session_path = os.path.join(self.absolute_dirpath, '../config/session.json') return None def initParser(self, args=None): ''' Initialize the parser using the python standard library 'argparse' This step adds all commands to be executed by the end-user Returns: -------- ArgumentParser: parser ''' parser = argparse.ArgumentParser(add_help=False) parser.prog = 'ispapi' parser.formatter_class = argparse.RawDescriptionHelpFormatter parser.epilog = textwrap.dedent(''' ------------------------------------------------------------ - You must login first to start requesting commands - You can use the command '--help <command>' to know everything about a specific command, - Or visit our documentation on: https://github.com/hexonet/hexonet-api-documentation ------------------------------------------------------------ ''') # args: will be the positional args parser.add_argument('args', nargs=argparse.REMAINDER, help='All additional args, e.g. limit=5') # command: is the user command to be executed e.g. QueryDomainList parser.add_argument( '--command', '-c', metavar='<command>', help='Enter a command e.g. -c=CheckDomain or -c CheckDomain') # userid: used in login parser.add_argument('--userid', '-u', metavar='<user id>', help='Your login user ID') # password: used in login parser.add_argument('--password', '-p', metavar='<your password>', help="Your login password") # entitiy: either live or ote, used in login parser.add_argument( '--entity', '-e', choices={'live', 'ote'}, help="Set entity to either live or ote system e.g. -e=ote") # gui: used to start the gui from the terminal parser.add_argument('--gui', '-g', const='gui', nargs='?', metavar='<>', help="Start graphical application") # help: used to show help about how to use the tool, generated by argparse dynamically parser.add_argument( '--help', '-h', const='all', nargs='?', metavar='<command>,<>', help="Show detailed use of a 'command' OR use --help to show help") # list: used to list all the commands avaiable parser.add_argument('--list', '-li', const='list', nargs='?', metavar='<>', help="List all commands' names") # logout: used to kill the user session (locally and remotely) parser.add_argument('--logout', '-l', const='logout', nargs='?', metavar='<>', help="Destroy your current session") # update the local user commands. This will call scraper parser.add_argument('--update', '-up', const='update', nargs='?', metavar='<>', help="Update local command list") # version: show the tool version parser.add_argument('--version', '-v', action='version', version='%(prog)s %(__version__)s') return parser def parseArgs(self, args): ''' This function will check which command is triggered by the user and call a function accordingly Returns ------- Tuple: (string, string) ''' # case logout if args['logout'] is not None: result = self.logout() return 'logout', result # case gui if args['gui'] is not None: return 'gui', '' # case help if args['help'] is not None: if args['help'] == 'all': return 'help', '' else: command_help = args['help'] help_info = self.getCommandHelp(command_help) return 'help_command', help_info # case list of all commands if args['list'] is not None: commands_list = self.getCommandList() return 'list', commands_list # case update commands triggered if args['update']: return 'update', '' # case login # check if login credentials provided if None not in (args['userid'], args['password'], args['entity']): result, msg = self.login(args) return 'msg', msg # otherwise it is a command requested # if logged in, and there is a session, then execute a command session_status = self.checkSession(args) if session_status == 'valid': if args['command'] is not None: cmd_struct = {} cmd_struct['command'] = args['command'] return 'cmd', cmd_struct # case user trying to log in while his session is valid elif None not in (args['userid'], args['password'], args['entity']): msg = 'You are already logged in, your session is valid.' return 'msg', msg else: msg = 'Command is not recognized!' return 'cmd_unknown', msg # initial running elif session_status == 'init': msg = "Login first, you can run the command: -u = <your user id> -p = <your password> -e = {ote,live}" return 'msg', msg # case sessin expired elif session_status == 'expired': msg = """ Session expired. Please login again. Use the command: -u = <your user id> -p = <your password> -e = {ote,live} """ return 'msg', msg # case unknown command requested else: msg = 'No command found!' return 'cmd_unknown', msg def login(self, args, session_status=''): ''' This function perform remote login on the server Returns ------- Tuple: ((True | False), msg:string) ''' user = args['userid'] password = args['password'] entity = args['entity'] # check which system to use, live of test if entity == 'ote': # case ote is set, otherwise by default the system is live self.cl.useOTESystem() self.cl.setCredentials(user, password) r = self.cl.login() if r.isSuccess(): # save login session loginSession = self.cl.getSession() # save session self.__saveLocalSession(loginSession, entity) msg = "Login success. Your session valid for one hour max of idle time" return True, msg else: desc = r.getDescription() code = r.getCode() msg = "Server response: " + str(code) + " " + desc return False, msg def checkSession(self, args=''): ''' Check local session. Returns ------- String: 'valid' | 'init' | 'expired' ''' data = {} # check if there is a session already exist p = self.session_path try: f = open(p, 'r') data = json.load(f) f.close() entity = data['entity'] time_format = "%Y-%m-%d %H:%M:%S" t_now = datetime.now().strftime(time_format) t_now_object = datetime.strptime(t_now, time_format) t_old = data['ts'] t_old_object = datetime.strptime(t_old, time_format) t_new = t_now_object - timedelta(hours=1) if t_new < t_old_object: result = self.cl.setSession(data['session']) if entity == 'ote': self.cl.useOTESystem() return 'valid' else: return 'expired' # Do something with the session file except IOError: return 'init' def logout(self): ''' Delete user session. Returns: -------- String: msg ''' p = self.session_path try: msg = '' f = open(p, 'r') data = json.load(f) f.close() entity = data['entity'] if entity == 'ote': self.cl.useOTESystem() # delete remote session self.cl.setSession(str(data['session'])) r = self.cl.logout() if r.isSuccess(): flag = True else: flag = False # delete local session path = self.session_path if os.path.exists(path): os.remove(path) # delete local session if flag: msg = 'Successfully logged out!' return msg else: msg = "Local session deleted but couldn't delete remote session!" return msg else: msg = 'Session already deleted' return msg except Exception as e: return "Couldn't delete remote session due to: " + str(e) def request(self, commands): ''' Request command from remote server. Returns: ------- Response: response ''' response = self.cl.request(commands) return response def getResponse(self, response, mode=''): ''' Parse response based on user preference. Returns: -------- List | String ''' if mode == 'properties': return response.getListHash() elif mode == 'list': return response.getListHash() elif mode == 'plain': return response.getPlain() else: code = response.getCode() description = response.getDescription() message = "Server response: " + str(code) + " " + description return message def getCommandHelp(self, command_name): ''' Get help for a specific command: command_name. Returns: ------- String: <> ''' command_name = command_name.lower() path = self.command_path data = {} files = os.listdir(path) for file in files: try: file_name, ext = file.split('.') file_name_lower_case = file_name.lower() if file_name_lower_case == command_name: file_path = os.path.join(path, file) f = open(file_path, 'r') data = json.load(f) f.close() command = data['command'] description = data['description'] availability = data['availability'] paramaters = data['paramaters'] basic_info = f''' Command: {command} Description: {description} Availability: {availability} Parameters:''' # dedent, remove spaces basic_info = textwrap.dedent(basic_info).strip() headers = ['Parameter', 'Min', 'Definition', 'Type'] table = [] t = TextWrapper(width=30) for row in paramaters: row_data = [] for key in row: if key == 'Definition': row_data.append(t.fill(row[key])) else: row_data.append(row[key]) table.append(row_data) paramaters_table = tabulate(table, headers, tablefmt="fancy_grid") return basic_info + '\n' + paramaters_table except Exception: continue else: return f"Command '{command_name}' not found!" def __saveLocalSession(self, loginSession, entity): ''' Saves users session in local file. Returns: -------- Bool: True | False ''' try: time_format = "%Y-%m-%d %H:%M:%S" ts = datetime.now().strftime(time_format) data = {} data['session'] = loginSession data['ts'] = ts data['entity'] = entity # write session and current time to local file path = self.session_path f = open(path, 'w') json.dump(data, f) f.close() return True except Exception as e: return False def parseParameters(self, parameters): ''' Parse positional arguments, e.g. limit = 5. Returns: -------- Set: params ''' params_len = len(parameters) params = {} i = 0 while i < (params_len): if '=' in parameters[i]: key, value = parameters[i].split('=') params[key] = value else: key = parameters[i] i += 1 value = parameters[i] params[key] = value i += 1 # return result return params def getCommandList(self): ''' Get all commands from local commands' files Returns: -------- String: return_list ''' path = self.command_path data = {} c_names = os.listdir(path) return_list = '' for name in sorted(c_names): try: file_name, ext = name.split('.') return_list += file_name + '\n' except Exception: continue return return_list def getMinParameters(self, command_name): ''' Get minimum required parameters of the command: command_name Returns: -------- List: returnData ''' command_name = command_name.lower() path = self.command_path returnData = [] files = os.listdir(path) for file in files: try: file_name, ext = file.split('.') file_name_lower_case = file_name.lower() if file_name_lower_case == command_name: file_path = os.path.join(path, file) f = open(file_path, 'r') data = json.load(f) f.close() paramaters = data['paramaters'] for row in paramaters: paramater = row['Parameter'] minValue = row['Min'] if minValue == '1' and paramater != 'COMMAND': returnData.append(paramater.lower()) except Exception: continue return returnData
def test_apiclientmethods(): cl = AC() rtm = RTM.getInstance() rtm.addTemplate( 'login200', '[RESPONSE]\r\nPROPERTY[SESSION][0]=h8JLZZHdF2WgWWXlwbKWzEG3XrzoW4y' + 'shhvtqyg0LCYiX55QnhgYX9cB0W4mlpbx\r\nDESCRIPTION=Command completed' + ' successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.169\r\nEOF\r' + '\n') rtm.addTemplate('login500', rtm.generateTemplate('530', 'Authentication failed')) rtm.addTemplate( 'OK', rtm.generateTemplate('200', 'Command completed successfully')) rtm.addTemplate( 'listP0', '[RESPONSE]\r\nPROPERTY[TOTAL][0]=2701\r\nPROPERTY[FIRST][0]=0\r\nP' + 'ROPERTY[DOMAIN][0]=0-60motorcycletimes.com\r\nPROPERTY[DOMAIN][1]=' + '0-be-s01-0.com\r\nPROPERTY[COUNT][0]=2\r\nPROPERTY[LAST][0]=1\r\nP' + 'ROPERTY[LIMIT][0]=2\r\nDESCRIPTION=Command completed successfully' + '\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.023\r\nEOF\r\n') rtm.addTemplate( 'listP1', '[RESPONSE]\r\nPROPERTY[TOTAL][0]=2701\r\nPROPERTY[FIRST][0]=2\r\nP' + 'ROPERTY[DOMAIN][0]=0-qas-ao17-0.org\r\nPROPERTY[DOMAIN][1]=0-sunny' + 'da222y.com\r\nPROPERTY[COUNT][0]=2\r\nPROPERTY[LAST][0]=3\r\nPROPE' + 'RTY[LIMIT][0]=2\r\nDESCRIPTION=Command completed successfully\r\nC' + 'ODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.032\r\nEOF\r\n') rtm.addTemplate( 'listFP0', '[RESPONSE]\r\nPROPERTY[TOTAL][0]=3\r\nPROPERTY[FIRST][0]=0\r\nPROP' + 'ERTY[DOMAIN][0]=0-60motorcycletimes.com\r\nPROPERTY[COUNT][0]=1\r' + '\nPROPERTY[LAST][0]=1\r\nPROPERTY[LIMIT][0]=1\r\nDESCRIPTION=Comma' + 'nd completed successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.' + '023\r\nEOF\r\n') rtm.addTemplate( 'listFP1', '[RESPONSE]\r\nPROPERTY[TOTAL][0]=3\r\nPROPERTY[FIRST][0]=1\r\nPROP' + 'ERTY[DOMAIN][0]=0-be-s01-0.com\r\nPROPERTY[COUNT][0]=1\r\nPROPERTY' + '[LAST][0]=2\r\nPROPERTY[LIMIT][0]=1\r\nDESCRIPTION=Command complet' + 'ed successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.032\r\nEOF' + '\r\n') rtm.addTemplate( 'listFP2', '[RESPONSE]\r\nPROPERTY[TOTAL][0]=3\r\nPROPERTY[FIRST][0]=2\r\nPROP' + 'ERTY[DOMAIN][0]=0-qas-ao17-0.org\r\nPROPERTY[COUNT][0]=2\r\nPROPER' + 'TY[LAST][0]=3\r\nPROPERTY[LIMIT][0]=1\r\nDESCRIPTION=Command compl' + 'eted successfully\r\nCODE=200\r\nQUEUETIME=0\r\nRUNTIME=0.032\r\nE' + 'OF\r\n') # #.getPOSTData() # test object input with special chars validate = ( 's_entity=54cd&s_command=COMMAND%3DModifyDomain%0AAUTH%3Dgwrgwqg%25' + '%26%5C44t3%2A') enc = cl.getPOSTData({ 'COMMAND': 'ModifyDomain', 'AUTH': 'gwrgwqg%&\\44t3*' }) assert enc == validate # test string input enc = cl.getPOSTData('gregergege') assert enc == 's_entity=54cd&s_command=' # test object input with null value in parameter validate = 's_entity=54cd&s_command=COMMAND%3DModifyDomain' enc = cl.getPOSTData({"COMMAND": 'ModifyDomain', "AUTH": None}) assert enc == validate # #.enableDebugMode() cl.enableDebugMode() cl.disableDebugMode() # #.getSession() # initial value session = cl.getSession() assert session is None # custom value sessid = 'testSessionID12345678' cl.setSession(sessid) session = cl.getSession() assert session is sessid cl.setSession('') # #.getURL() assert cl.getURL() == 'https://coreapi.1api.net/api/call.cgi' # #.setURL() tmp = 'http://coreapi.1api.net/api/call.cgi' url = cl.setURL(tmp).getURL() assert url is tmp cl.setURL('https://coreapi.1api.net/api/call.cgi') # #.setOTP() # [otp set] cl.setOTP('12345678') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = 's_entity=54cd&s_otp=12345678&s_command=COMMAND%3DStatusAccount' assert tmp == exp # [otp reset] cl.setOTP('') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = 's_entity=54cd&s_command=COMMAND%3DStatusAccount' assert tmp == exp # #.setSession() # [session set] cl.setSession('12345678') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = 's_entity=54cd&s_session=12345678&s_command=COMMAND%3DStatusAccount' assert tmp == exp # [credentials and session set] cl.setRoleCredentials('myaccountid', 'myrole', 'mypassword') cl.setOTP('12345678') cl.setSession('12345678') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = 's_entity=54cd&s_session=12345678&s_command=COMMAND%3DStatusAccount' assert tmp == exp # [session reset] cl.setSession('') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) assert tmp == 's_entity=54cd&s_command=COMMAND%3DStatusAccount' # #.saveSession/reuseSession sessionobj = {} cl.setSession('12345678').saveSession(sessionobj) cl2 = AC() cl2.reuseSession(sessionobj) tmp = cl2.getPOSTData({'COMMAND': 'StatusAccount'}) exp = 's_entity=54cd&s_session=12345678&s_command=COMMAND%3DStatusAccount' assert tmp == exp cl.setSession('') # #.setRemoteIPAddress() # [ip set] cl.setRemoteIPAddress('10.10.10.10') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = ( 's_entity=54cd&s_remoteaddr=10.10.10.10&s_command=COMMAND%3DStatusA' + 'ccount') assert tmp == exp # [ip reset] cl.setRemoteIPAddress('') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) assert tmp == 's_entity=54cd&s_command=COMMAND%3DStatusAccount' # #.setCredentials() # [credentials set] cl.setCredentials('myaccountid', 'mypassword') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = ( 's_entity=54cd&s_login=myaccountid&s_pw=mypassword&s_command=COMMAN' + 'D%3DStatusAccount') assert tmp == exp # [session reset] cl.setCredentials('', '') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) assert tmp == 's_entity=54cd&s_command=COMMAND%3DStatusAccount' # #.setRoleCredentials() # [role credentials set] cl.setRoleCredentials('myaccountid', 'myroleid', 'mypassword') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) exp = ( 's_entity=54cd&s_login=myaccountid%21myroleid&s_pw=mypassword&s_com' + 'mand=COMMAND%3DStatusAccount') assert tmp == exp # [role credentials reset] cl.setRoleCredentials('', '', '') tmp = cl.getPOSTData({'COMMAND': 'StatusAccount'}) assert tmp == 's_entity=54cd&s_command=COMMAND%3DStatusAccount' # #.login() # [login succeeded; no role used] cl.useOTESystem() cl.setCredentials('test.user', 'test.passw0rd') cl.setRemoteIPAddress('1.2.3.4') r = cl.login() assert isinstance(r, R) is True assert r.isSuccess() is True, ("{0} {1}").format(r.getCode(), r.getDescription()) rec = r.getRecord(0) assert rec is not None assert rec.getDataByKey('SESSION') is not None # [login succeeded; role used] cl.useOTESystem() cl.setRoleCredentials('test.user', 'testrole', 'test.passw0rd') r = cl.login() assert isinstance(r, R) assert r.isSuccess() is True, ("{0} {1}").format(r.getCode(), r.getDescription()) rec = r.getRecord(0) assert rec is not None assert rec.getDataByKey('SESSION') is not None # [login failed; wrong credentials] cl.setCredentials('test.user', 'WRONGPASSWORD') r = cl.login() assert isinstance(r, R) assert r.isError() is True # [login failed; http error] tpl = rtm.getTemplate('httperror') old = cl.getURL() cl.setURL('https://iwontsucceedgregegeg343teagr43.com/api/call.cgi') cl.setCredentials('test.user', 'WRONGPASSWORD') r = cl.login() assert isinstance(r, R) assert r.isTmpError() is True assert r.getDescription() == tpl.getDescription() cl.setURL(old) # [login succeeded; no session returned] # TODO: need network mock # tpl = R(rtm.getTemplate('OK').getPlain()) # cl.useOTESystem() # cl.setCredentials('test.user', 'test.passw0rd') # r = cl.login() # assert isinstance(r, R) # assert r.isSuccess() is True # rec = r.getRecord(0) # assert rec is Node # #.loginExtended() # [login succeeded; no role used] cl.useOTESystem() cl.setCredentials('test.user', 'test.passw0rd') r = cl.loginExtended({'TIMEOUT': 60}) assert isinstance(r, R) is True assert r.isSuccess() is True rec = r.getRecord(0) assert rec is not None assert rec.getDataByKey('SESSION') is not None # #.logout() # [logout succeeded] r = cl.logout() assert isinstance(r, R) assert r.isSuccess() is True # [logout failed; session no longer exists] tpl = R(rtm.getTemplate('login200').getPlain()) cl.enableDebugMode() cl.setSession(tpl.getRecord(0).getDataByKey('SESSION')) r = cl.logout() assert isinstance(r, R) is True assert r.isError() is True # #.request() # [200 < r.statusCode > 299] # TODO need network mock # tpl2 = R(rtm.getTemplate('httperror').getPlain()) # cl.setCredentials('test.user', 'test.passw0rd') # cl.useOTESystem() # r = cl.request({ 'COMMAND': 'GetUserIndex' }) # assert isinstance(r, R) is True # assert r.isTmpError() is True # assert r.getCode() == tpl2.getCode() # assert r.getDescription() == tpl2.getDescription() # [200 < r.statusCode > 299, no debug] # TODO need network mock # tpl2 = R(rtm.getTemplate('httperror').getPlain()) # cl.disableDebugMode() # r = cl.request({ 'COMMAND': 'GetUserIndex' }) # assert isinstance(r, R) # assert r.isTmpError() is True # assert r.getCode() == tpl2.getCode() # assert r.getDescription() == tpl2.getDescription() # .requestNextResponsePage # [no LAST set] cl.setCredentials('test.user', 'test.passw0rd') cl.useOTESystem() r = R( rtm.getTemplate('listP0').getPlain(), { 'COMMAND': 'QueryDomainList', 'LIMIT': 2, 'FIRST': 0 }) nr = cl.requestNextResponsePage(r) assert r.isSuccess() is True assert nr.isSuccess() is True assert r.getRecordsLimitation() == 2 assert nr.getRecordsLimitation() == 2 assert r.getRecordsCount() == 2 assert nr.getRecordsCount() == 2 assert r.getFirstRecordIndex() == 0 assert r.getLastRecordIndex() == 1 assert nr.getFirstRecordIndex() == 2 assert nr.getLastRecordIndex() == 3 # [LAST set] r = R( rtm.getTemplate('listP0').getPlain(), { 'COMMAND': 'QueryDomainList', 'LIMIT': 2, 'FIRST': 0, 'LAST': 1 }) with pytest.raises(Exception, match=r'Parameter LAST in use.'): cl.requestNextResponsePage(r) # [no FIRST set] cl.disableDebugMode() r = R( rtm.getTemplate('listP0').getPlain(), { 'COMMAND': 'QueryDomainList', 'LIMIT': 2 }) nr = cl.requestNextResponsePage(r) assert r.isSuccess() is True assert nr.isSuccess() is True assert r.getRecordsLimitation() == 2 assert nr.getRecordsLimitation() == 2 assert r.getRecordsCount() == 2 assert nr.getRecordsCount() == 2 assert r.getFirstRecordIndex() == 0 assert r.getLastRecordIndex() == 1 assert nr.getFirstRecordIndex() == 2 assert nr.getLastRecordIndex() == 3 # #.requestAllResponsePages() # [success case] nr = cl.requestAllResponsePages({ 'COMMAND': 'QuerySSLCertList', 'FIRST': 0, 'LIMIT': 100 }) assert len(nr) > 0 # #.setUserView() cl.setUserView('hexotestman.com') r = cl.request({'COMMAND': 'GetUserIndex'}) assert isinstance(r, R) is True assert r.isSuccess() is True # #.resetUserView() cl.setUserView('') r = cl.request({'COMMAND': 'GetUserIndex'}) assert isinstance(r, R) is True assert r.isSuccess() is True
#!/usr/bin/python # Import the ispapi library from hexonet.apiconnector.apiclient import APIClient as AC # -------- SESSIONLESS COMMUNICATION ----------- # Create a connection using the APIClient class and the appropriate # methods to configure the connection as necessary. # Don't have a HEXONET Account yet? Get one here: # - Live System Account: https://www.hexonet.net/sign-up # - Test/OT&E System Account: https://www.hexonet.net/signup-ote print("---- SESSIONLESS COMMUNICATION ----") cl = AC() cl.useOTESystem() cl.setCredentials("test.user", "test.passw0rd") # use the below method in case you have an active # ip filter setting cl.setRemoteIPAddress("1.2.3.4") # Call a command r = cl.request({"Command": "QueryDomainList", "limit": 5}) # Get the result in the format you want rlist = r.getListHash() rhash = r.getHash() rplain = r.getPlain() # or use API methods to access specific data col = r.getColumn("DOMAIN") # get column domain