def children_get_delete(child_id): if request.method == 'GET': verify_content_type(request) payload = verify_jwt(request) child_key = client.key('children', int(child_id)) single_child = client.get(key=child_key) # If child does not exist, else return child information if single_child == None: return json.dumps({"Error": "No child with this child_id exists."}), 404, {'Content-Type':'application/json'} # If jwt is not user for child, return error if single_child['user_id'] != payload['sub']: return json.dumps({'Error': 'You do not have authorization to view this child.'}), 401, {'Content-Type':'application/json'} single_child['id'] = child_id return json.dumps(single_child), 200, {'Content-Type':'application/json'} elif request.method == 'DELETE': verify_content_type(request) payload = verify_jwt(request) child_key = client.key('children', int(child_id)) single_child = client.get(key=child_key) # If child does not exist, else return child information if single_child == None: return json.dumps({"Error": "No child with this child_id exists."}), 404, {'Content-Type':'application/json'} # If jwt is not user for child, return error if single_child['user_id'] != payload['sub']: return json.dumps({'Error': 'You do not have authorization to view this child.'}), 401, {'Content-Type':'application/json'} # If child exists, remove child information from milestones for element in single_child['milestones_assigned']: milestone_key = client.key('milestones', int(element['id'])) single_milestone = client.get(key=milestone_key) single_milestone['children_id_assigned'].remove(int(child_id)) client.put(single_milestone) # Remove child from user list in users entity query = client.query(kind='users') query.add_filter('user_id', '=', payload['sub']) single_user = list(query.fetch())[0] # Make sure user exists if single_user == None: return jsonify({"Error": "No user with this user_id exists."}), 404, {'Content-Type':'application/json'} single_user['children'].remove({ 'child_id': int(child_id), 'self': request.base_url } ) client.put(single_user) client.delete(child_key) return {}, 204, {'Content-Type':'application/json'}
def get_childs_from_milestone(child_id): if request.method == 'GET': verify_content_type(request) payload = verify_jwt(request) child_key = client.key('children', int(child_id)) single_child = client.get(key=child_key) # If no milestone with id if not single_child: return json.dumps({'Error': 'No child with this child_id exists.'}), 404, {'Content-Type':'application/json'} # If jwt is not user for child, return error if single_child['user_id'] != payload['sub']: return json.dumps({'Error': 'You do not have authorization to view this child.'}), 401, {'Content-Type':'application/json'} results = [] # Get all milestones information assigned to child for milestone in single_child['milestones_assigned']: milestone_key = client.key('milestones', int(milestone['id'])) single_milestone = client.get(key=milestone_key) single_milestone['id'] = milestone['id'] results.append(single_milestone) return json.dumps(results), 200, {'Content-Type':'application/json'}
def userid_icebergs_valid(user_id): if request.method == "GET": if "application/json" not in request.accept_mimetypes: # Failure 406 Not Acceptable return status_fail(406, ERR.WRONG_MEDIA_REQUESTED) # Display Icebergs with pagination user = verify_jwt() query = client.query(kind=ICEBERGS) query.add_filter("founder", "=", user_id) if user == "Error": # Return public Icebergs only query.add_filter("public", "=", True) # Set limit, offset, and iterator q_limit = int(request.args.get("limit", 5)) q_offset = int(request.args.get("offset", 0)) iterator = query.fetch(limit=q_limit, offset=q_offset) results = list(next(iterator.pages)) if iterator.next_page_token: next_offset = q_offset + q_limit next_url = (request.base_url + "?limit=" + str(q_limit) + "&offset=" + str(next_offset)) else: next_url = None for i in results: i["id"] = i.id i["self"] = request.url_root + "icebergs/" + str(i.id) output = {"icebergs": results} if next_url: output["next"] = next_url return status_success(200, output=json.dumps(output), page=next_url) # Success 200 OK return status_success(200, output=json.dumps(output)) else: # Failure 405 Method Not Allowed userid_icebergs_invalid()
def get(self): """ takes the jwt and decodes it returning the payload """ auth_token = request.headers.get('Authorization') if not auth_token: return {'error': 'no token'} # strip out the Bearer part of the token. auth_token = str(auth_token).replace('Bearer ', '') try: payload = verify_jwt(auth_token) return { 'token': auth_token, 'payload': payload, } except (jwt.ExpiredSignatureError, jwt.InvalidTokenError) as e: app.logger.exception(e) return { 'error': f"{type(e).__name__}:{str(e)}", 'payload': jwt.decode(auth_token.encode(), verify=False) }
def children_add_remove_milestone(milestone_id, child_id): if request.method == 'PUT': verify_content_type(request) payload = verify_jwt(request) milestone_key = client.key('milestones', int(milestone_id)) single_milestone = client.get(key=milestone_key) child_key = client.key('children', int(child_id)) single_child = client.get(key=child_key) # Check if milestone or child do not exist if not single_milestone or not single_child: return json.dumps({'Error': 'The specified milestone and/or child does not exist.'}), 404, {'Content-Type':'application/json'} # If the milestone is already assigned to a child for element in single_child['milestones_assigned']: if single_milestone.key.id == element['id']: return json.dumps({'Error': 'This milestone is already assigned to the child.'}), 403, {'Content-Type':'application/json'} # Add milestone information to child and add to database single_child['milestones_assigned'].append({ 'id': int(milestone_id), 'self': single_milestone['self'] }) client.put(single_child) single_milestone['children_id_assigned'].append(int(child_id)) client.put(single_milestone) return {}, 204, {'Content-Type':'application/json'} elif request.method == 'DELETE': verify_content_type(request) payload = verify_jwt(request) milestone_key = client.key('milestones', int(milestone_id)) single_milestone = client.get(key=milestone_key) child_key = client.key('children', int(child_id)) single_child = client.get(key=child_key) # Check if milestone or child does not exist if not single_milestone or not single_child: return json.dumps({'Error': 'The specified milestone and/or child does not exist.'}), 404, {'Content-Type':'application/json'} # If jwt is not user for child, return error if single_child['user_id'] != payload['sub']: return json.dumps({'Error': 'You do not have authorization to view this child.'}), 401, {'Content-Type':'application/json'} # If the milestone is not assigned to this child if int(child_id) not in single_milestone['children_id_assigned']: return json.dumps({'Error': 'No milestone with this milestone_id is assigned to the child with this child_id.'}), 404, {'Content-Type': 'application/json'} # Delete milestone from child single_child['milestones_assigned'].remove({ 'id': int(milestone_id), 'self': single_milestone['self'] }) client.put(single_child) # Remove children assigned single_milestone['children_id_assigned'].remove(int(child_id)) client.put(single_milestone) return {}, 204, {'Content-Type':'application/json'}
def children_get_post(): if request.method == 'GET': verify_content_type(request) payload = verify_jwt(request) if not payload: return json.dumps([]), 200, {'Content-Type':'application/json'} query = client.query(kind='children') # Setting pagination q_limit = 5 q_offset = int(request.args.get('offset', '0')) l_iterator = query.fetch(limit = q_limit, offset = q_offset) # Get pages variable and list of children pages = l_iterator.pages all_children = list(next(pages)) # If more children are on next page set next_url, else no more pages if l_iterator.next_page_token: next_offset = q_offset + q_limit next_url = request.base_url + "?offset=" + str(next_offset) else: next_url = None # Set id for each milestone\ all_children = [e for e in all_children if e['user_id'] == payload['sub']] for e in all_children: e["id"] = e.key.id # Format children appropriately all_children_formatted = { "children": all_children } # Set next_url if is not None if next_url: all_children_formatted['next'] = next_url return json.dumps(all_children_formatted), 200, {'Content-Type':'application/json'} elif request.method == 'POST': verify_content_type(request) payload = verify_jwt(request) body = request.get_json() child_required_headers = ['first_name', 'gender', 'birthday'] if not set(child_required_headers).issubset(body.keys()): return json.dumps({'Error': 'The request object is missing at least one of the required attributes.'}), 400, {'Content-Type':'application/json'} # Set up entity and add to client new_child = datastore.Entity(key=client.key('children')) new_child.update({ 'first_name': body['first_name'], 'gender': body['gender'], 'birthday': body['birthday'], 'user_id': payload['sub'], 'milestones_assigned': [] }) client.put(new_child) # Update with self url and return with id new_child.update({ 'self': request.base_url + '/' + str(new_child.key.id) }) client.put(new_child) new_child['id'] = new_child.key.id # Add child to user account in entity query = client.query(kind='users') query.add_filter('user_id', '=', payload['sub']) single_user = list(query.fetch())[0] # Make sure user exists if single_user == None: return jsonify({"Error": "No user with this user_id exists."}), 404, {'Content-Type':'application/json'} single_user['children'].append({ 'child_id': new_child.key.id, 'self': request.base_url + '/' + str(new_child.key.id) }) client.put(single_user) return json.dumps(new_child), 201, {'Content-Type':'application/json'} else: return json.dumps({'Error': 'This API does not support this operation.'}), 405, {'Content-Type': 'application/json'}
def icebergid_animals_animalid_valid(iceberg_id, animal_id): iceberg_key = client.key(ICEBERGS, int(iceberg_id)) animal_key = client.key(ANIMALS, int(animal_id)) iceberg = client.get(key=iceberg_key) animal = client.get(key=animal_key) # Check if Iceberg and Animal exist if iceberg is None: if animal is None: return status_fail(404, ERR.NEITHER_EXISTS) return status_fail(404, ERR.NO_ICEBERG) if animal is None: return status_fail(404, ERR.NO_ANIMAL) # Verify user user = verify_jwt() if user == "Error": return status_fail(401, ERR.UNAUTHORIZED) # Put an Animal on an Iceberg if request.method == "PUT": # Check media type if "application/json" not in request.content_type: # Failure 415 Unsupported Media Type return status_fail(415, ERR.WRONG_MEDIA_RECEIVED) if animal["home"] is None: animal.update({"home": str(iceberg.id)}) else: return status_fail(400, ERR.ANIMAL_ASSIGNED) # Add Animal to Iceberg if iceberg["inhabitants"] is None: iceberg["inhabitants"] = [str(animal.id)] else: iceberg["inhabitants"].append(str(animal.id)) client.put(iceberg) client.put(animal) # Success 303 See Other output = iceberg_output(iceberg, client) return status_success(303, output=json.dumps(output), location=output["self"]) # Remove an Animal from an Iceberg elif request.method == "DELETE": if iceberg["inhabitants"] is None: return status_fail(404, ERR.NO_ANIMAL_HERE) if "inhabitants" in iceberg.keys(): if str(animal_id) in iceberg["inhabitants"]: iceberg["inhabitants"].remove(str(animal_id)) if len(iceberg["inhabitants"]) == 0: iceberg["inhabitants"] = None animal["home"] = None client.put(iceberg) client.put(animal) else: return status_fail(404, ERR.NO_ANIMAL_HERE) # Success 204 No Content return status_success(204) else: # Failure 405 Method Not Allowed icebergid_animals_animalid_invalid()
def icebergs_valid(): # Create an Iceberg if request.method == "POST": # Verify user user = verify_jwt() if user == "Error": return status_fail(401, ERR.UNAUTHORIZED) # Check media type if "application/json" not in request.content_type: # Failure 415 Unsupported Media Type return status_fail(415, ERR.WRONG_MEDIA_RECEIVED) if "application/json" not in request.accept_mimetypes: # Failure 406 Not Acceptable return status_fail(406, ERR.WRONG_MEDIA_REQUESTED) # Check if request is missing any of the required attributes content = request.get_json() if ("name" not in content.keys() or "area" not in content.keys() or "shape" not in content.keys() or "public" not in content.keys()): # Failure 400 Bad Request return status_fail(400, ERR.MISSING_ATTRIBUTE) # Validate request if not valid_alphanum(content["name"], 50): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_NAME) if not valid_int(content["area"], 8000): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_AREA) if not valid_shape(content["shape"]): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_SHAPE) if not valid_public(content["public"]): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_PUBLIC) # Ensure that the name of an Iceberg is unique across all Icebergs query = client.query(kind=ICEBERGS) results = list(query.fetch()) for i in results: if i["name"] == content["name"]: # Failure 403 Forbidden return status_fail(403, ERR.NAME_EXISTS) # Update Iceberg iceberg = datastore.Entity(key=client.key(ICEBERGS)) iceberg.update({ "name": content["name"], "area": content["area"], "shape": content["shape"], "inhabitants": None, "public": content["public"], "founder": user }) client.put(iceberg) # Success 201 Created output = iceberg_output(iceberg, client) return status_success(201, output=json.dumps(output), location=output["self"]) # List all Icebergs elif request.method == "GET": if "application/json" not in request.accept_mimetypes: # Failure 406 Not Acceptable return status_fail(406, ERR.WRONG_MEDIA_REQUESTED) # Display Icebergs with pagination query = client.query(kind=ICEBERGS) user = verify_jwt() if user == "Error": # Return all public Icebergs query = query.add_filter("public", '=', True) else: # Return all Icebergs whose founder matches the user query = query.add_filter("founder", '=', user) # Set limit, offset, and iterator q_limit = int(request.args.get("limit", 5)) q_offset = int(request.args.get("offset", 0)) iterator = query.fetch(limit=q_limit, offset=q_offset) results = list(next(iterator.pages)) if iterator.next_page_token: next_offset = q_offset + q_limit next_url = (request.base_url + "?limit=" + str(q_limit) + "&offset=" + str(next_offset)) else: next_url = None for i in results: i["id"] = i.id i["self"] = request.url_root + "icebergs/" + str(i.id) output = {"icebergs": results} if next_url: output["next"] = next_url return status_success(200, output=json.dumps(output), page=next_url) # Success 200 OK return status_success(200, output=json.dumps(output)) else: # Failure 405 Method Not Allowed icebergs_invalid()
def icebergid_valid(iceberg_id): iceberg_key = client.key(ICEBERGS, int(iceberg_id)) iceberg = client.get(key=iceberg_key) # No Iceberg with this iceberg_id exists if iceberg is None: # Failure 404 Not Found return status_fail(404, ERR.NO_ICEBERG) # Verify user user = verify_jwt() if user == "Error": return status_fail(401, ERR.UNAUTHORIZED) # Get an Iceberg if request.method == "GET": if iceberg["founder"] != user and iceberg["public"] is False: return status_fail(403, ERR.NO_PERMISSION) if "application/json" in request.accept_mimetypes: # Success 200 OK output = iceberg_output(iceberg, client) return status_success(200, output=json.dumps(output)) elif "text/html" in request.accept_mimetypes: # Success 200 OK output = iceberg_output(iceberg, client) conversion = json2html.convert(json=json.dumps(output)) return status_success(200, output=conversion, mime="text/html") else: # Failure 406 Not Acceptable return status_fail(406, ERR.WRONG_MEDIA_REQUESTED) # Edit an Iceberg elif request.method == "PUT": if iceberg["founder"] != user: return status_fail(403, ERR.NO_PERMISSION) # Check media type if "application/json" not in request.content_type: # Failure 415 Unsupported Media Type return status_fail(415, ERR.WRONG_MEDIA_RECEIVED) if "application/json" not in request.accept_mimetypes: # Failure 406 Not Acceptable return status_fail(406, ERR.WRONG_MEDIA_REQUESTED) # Check if request is missing any of the required attributes content = request.get_json() if ("name" not in content.keys() or "area" not in content.keys() or "shape" not in content.keys() or "public" not in content.keys()): # Failure 400 Bad Request return status_fail(400, ERR.MISSING_ATTRIBUTE) # Validate request if not valid_alphanum(content["name"], 50): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_NAME) if not valid_int(content["area"], 8000): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_AREA) if not valid_shape(content["shape"]): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_SHAPE) if not valid_public(content["public"]): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_PUBLIC) # Ensure that the name of an Iceberg is unique across all Icebergs query = client.query(kind=ICEBERGS) results = list(query.fetch()) for i in results: if i["name"] == content["name"]: # Failure 403 Forbidden return status_fail(403, ERR.NAME_EXISTS) # Update Iceberg iceberg.update({ "name": content["name"], "area": content["area"], "shape": content["shape"], "public": content["public"] }) client.put(iceberg) # Success 303 See Other output = iceberg_output(iceberg, client) return status_success(303, output=json.dumps(output), location=output["self"]) # Edit an Iceberg elif request.method == "PATCH": if iceberg["founder"] != user: return status_fail(403, ERR.NO_PERMISSION) # Check media type if "application/json" not in request.content_type: # Failure 415 Unsupported Media Type return status_fail(415, ERR.WRONG_MEDIA_RECEIVED) if "application/json" not in request.accept_mimetypes: # Failure 406 Not Acceptable return status_fail(406, ERR.WRONG_MEDIA_REQUESTED) # Check if request contains any of the object attributes content = request.get_json() if "name" in content.keys(): # Validate name if not valid_alphanum(content["name"], 50): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_NAME) # Ensure that the name of an Iceberg is unique across all Icebergs query = client.query(kind=ICEBERGS) results = list(query.fetch()) for i in results: if i["name"] == content["name"]: # Failure 403 Forbidden return status_fail(403, ERR.NAME_EXISTS) iceberg.update({"name": content["name"]}) if "area" in content.keys(): # Validate area if not valid_int(content["area"], 8000): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_AREA) iceberg.update({"area": content["area"]}) if "shape" in content.keys(): # Validate shape if not valid_shape(content["shape"]): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_SHAPE) iceberg.update({"shape": content["shape"]}) if "public" in content.keys(): # Validate public if not valid_public(content["public"]): # Failure 400 Bad Request return status_fail(400, ERR.INVALID_PUBLIC) iceberg.update({"public": content["public"]}) client.put(iceberg) # Success 303 See Other output = iceberg_output(iceberg, client) return status_success(303, output=json.dumps(output), location=output["self"]) # Delete an Iceberg elif request.method == "DELETE": # JWT is valid but iceberg_id is founded by someone else if iceberg["founder"] != user: return status_fail(403, ERR.NO_PERMISSION) # Remove Animals from Iceberg if applicable query = client.query(kind=ANIMALS) results = list(query.fetch()) for a in results: if a["home"] == iceberg_id: a.update({"home": None}) client.put(a) # Success 204 No Content client.delete(iceberg_key) return status_success(204) else: # Failure 405 Method Not Allowed icebergid_invalid()