def post(self): """ This function creates new rebind subdomain from json looking something like this: { "ip_props": { "1":{ # <= Order in which domains will be resolved "ip": "88.23.99.110", # <= ip to resolve "repeat": 3 # <= how many times } "2":{ "ip": "169.254.169.254", "repeat": "4ever" # <= forever can be supplied to never stop resolving this domain } }, "name": "rbnd_test" # <= name (useful in web ui) } And half of the code just checks if input is correct if someone reading this has an idea how to do it more efficently please contribute """ parser = reqparse.RequestParser() parser.add_argument('ip_props', help='This field cannot be blank wtf', required=True, location="json") parser.add_argument('name', help='This field cannot be blank wtf', required=True, location="json") req_data = parser.parse_args() """ req_data['ip_props'] is a json in string so I need to load it :D """ data = json.loads(req_data['ip_props'].replace('\'', '"')) """ Validate input against base_schema """ req_data['ip_props'] = data base_schema = { "type": "object", "properties": { "ip_props": { "type": "object" }, "name": { "type": "string", "maxLength": 120 } } } try: validate(instance=req_data, schema=base_schema) except jsonschema.exceptions.ValidationError: return { 'message': 'Something went wrong, the supplied input doesn\'t seem to be valid' }, 500 """ Check if - Less than 32 IPs are supplied - Some retard can't count """ if not len(data.keys()) < 32: return {'message': 'Something went wrong, max IPs: 32'}, 500 elif not checkKeys(data.keys()): return { 'message': f"Something went wrong, the str(numbers) go like this: ['1','2','3','4',...] and not {[x for x in data.keys()]}" }, 500 """ Iterate through every ip_prop and do some checks - details are in comments below """ for i in data.keys(): """ This schema checks if - repeat is "4ever" or integer greater or equal to 1 - ip and type is compatibile with one of A,AAAA and CNAME """ prop_schema = { "type": "object", "properties": { "repeat": { "anyOf": [{ "type": "integer", "minimum": 1 }, { "type": "string", "pattern": "^4ever$" }] }, "ip": { "type": "string", "anyOf": [{ "format": "ipv4" }, { "format": "ipv6" }, { "format": "idn-hostname" }] }, "type": { "type": "string", "anyOf": [{ "pattern": "^A$" }, { "pattern": "^AAAA$" }, { "pattern": "^CNAME$" }] } } } try: validate(instance=data[i], schema=prop_schema) except jsonschema.exceptions.ValidationError: return { 'message': f'Something went wrong, the supplied input doesn\'t seem to be valid in [`ip_props`][{int(i)-1}]' }, 500 """ Check if supplied record type matches ip So 127.0.0.1 can't be CNAME And google.com can't be answer for A :D """ record_funcs = {"CNAME": checkDomain, "A": ipv4, "AAAA": ipv6} if not record_funcs[data[i]['type']](data[i]['ip']): return { 'message': f"data[{int(i)-1}]['ip'] has to be in {data[{int(i)-1}]['type']} format" }, 500 """ Then put the data together Generate new uuid4 Put it in database and redis Then return the whole domain """ # rbnd_json does not need name parameter - it's meant to be stored in redis and in props column in database rbnd_json = {'ip_props': data, 'ip_to_resolve': '1', 'turn': -1} uuid = uuid4().hex if DnsModel.find_by_uuid(uuid): """ Just in case something bad happens """ return { 'message': 'An error occured, please try again (REALLY TRY AGAIN, server generated uuid that exists, I didn\'t know it was possible :d) If you get this error please send it to me on twitter @marek_geleta You can follow me too' }, 500 new_uuid = DnsModel(username=get_jwt_identity(), uuid=uuid, props=json.dumps(rbnd_json), name=req_data['name']) try: new_uuid.save_to_db() setJson(uuid, rbnd_json) return {"subdomain": f"{uuid}.{DOMAIN}"} except: return {'message': 'Something went wrong'}, 500
def post(self): """ This function creates new rebind subdomain from json looking something like this: { "ip_props": { "1":{ # <= Order in which domains will be resolved "ip": "88.23.99.110", # <= ip to resolve "repeat": 3 # <= how many times } "2":{ "ip": "169.254.169.254", "repeat": "4ever" # <= forever can be supplied to never stop resolving this domain } }, "name": "rbnd_test" # <= name (useful in web ui) } And half of the code just checks if input is correct if someone reading this has an idea how to do it more efficently please contribute """ parser = reqparse.RequestParser() parser.add_argument('ip_props', help='This field cannot be blank wtf', required=True, location="json") parser.add_argument('name', help='This field cannot be blank wtf', required=True, location="json") req_data = parser.parse_args() """ req_data['ip_props'] is a json in string so I need to load it :D """ data = json.loads(req_data['ip_props'].replace('\'', '"')) """ Check if - Less than 32 IPs are supplied - Some retard can't count - Name is not longer than 64 """ if not len(data.keys()) < 32: return {'message': 'Something went wrong, max IPs: 32'}, 500 elif not checkKeys(data.keys()): return { 'message': f"Something went wrong, the str(numbers) go like this: ['1','2','3','4',...] and not {[x for x in data.keys()]}" }, 500 elif len(req_data['name']) > 64: return {'message': 'Something went wrong, max name len: 64'}, 500 """ Iterate through every ip_prop and check """ for i in data.keys(): """ If repeat - Is "4ever" or positive integer - Is not 0 - kind of makes no sense to repeat it 0 times """ if (data[i]['repeat'] != '4ever' and type(data[i]['repeat']) != int ) or abs(data[i]['repeat']) != data[i]['repeat']: repeat = data[i]['repeat'] return { 'message': f'Something went wrong, `repeat` field can only hold positive integers or string `4ever` (in [`ip_props`][{i}][`repeat`])' }, 500 elif data[i]['repeat'] == 0: return { 'message': f'How am I supposed to repeat it 0 times??? [`ip_props`][{i}][`repeat`]' }, 500 """ If ip - Is in IPV4 format and if it's not a subnet because the IP function is a bit weird and idk what to use :D """ try: if IP(data[i]['ip']).version() == 4 and IP( data[i]['ip']).strNormal(0) == str(IP(data[i]['ip'])): data[i]['ip'] = IP(data[i]['ip']).strNormal(0) else: return {'message': 'IP has to be in IPV4 format'}, 500 except: return { 'message': f'An error occured, check [`ip_props`][{i}][`ip`] ' }, 500 """ Then put the data together Generate new uuid4 Put it in database and redis Then return the whole domain """ rbnd_json = {'ip_props': data, 'ip_to_resolve': '1', 'turn': -1} uuid = uuid4().hex if DnsModel.find_by_uuid(uuid): """ Just in case something bad happens """ return { 'message': 'An error occured, please try again (REALLY TRY AGAIN, server generated uuid that exists, I didn\'t know it was possible :d) If you get this error please send it to me on twitter @marek_geleta You can follow me too' }, 500 new_uuid = DnsModel(username=get_jwt_identity(), uuid=uuid, props=json.dumps(rbnd_json), name=req_data['name']) try: new_uuid.save_to_db() setJson(uuid, rbnd_json) return {"subdomain": f"{uuid}.{DOMAIN}"} except: return {'message': 'Something went wrong'}, 500