def json(self): if not self.data: raise APIBadRequest("No POST data was sent to load json from.") try: return json.loads(self.data) except json.JSONDecodeError as e: raise APIBadRequest( "Could not load json from the POST data ({})".format(e))
def post(self, entity): """Starts following a user, defined by the post data""" try: post_data = json.loads(request.data) except json.JSONDecodeError as e: raise APIBadRequest(str(e)) if not post_data: raise APIBadRequest("No POST data.") follower = follow.start_following(entity, post_data) return jsonify(follower.to_json())
def delete(self, follower_id): """Deletes a following relationship.""" try: follow.stop_following(g.entity, follower_id) return make_response(), 200 except ValidationError: raise APIBadRequest("The given follower id was invalid")
def delete(self, entity, schema): """Delete a profile type.""" if schema == CoreProfile.__schema__: raise APIBadRequest('Cannot delete the core profile.') profile = entity.profiles.get_or_404(schema=schema) profile.delete() return '', 200
def put(self, entity, follower_id): """Updates a following relationship.""" try: post_data = json.loads(request.data) except json.JSONDecodeError as e: raise APIBadRequest(str(e)) follower = follow.update_follower(entity, follower_id, post_data) return jsonify(follower.to_json())
def post(self): """Create a new profile of the specified type. This is specific to pytentd, and is similar to PUT /profile/<schema>. TODO: Document this! TODO: This doesn't appear to be covered by any tests """ if not 'schema' in request.json: raise APIBadRequest("A profile schema is required.") return jsonify(Profile(entity=g.entity, **request.json).save())
def discover_entity(identity): """Find an entity from the given identity - Fetch the identity, giving us a list of profiles - Fetch a profile, giving us the entity's canonical identity url and api endpoints TODO: Move this into a generic tent module? """ # TODO: Parse html for links # https://tent.io/docs/server-protocol#server-discovery try: response = requests.head(identity) except requests.ConnectionError as ex: raise APIBadRequest("Could not discover entity ({})".format(ex)) # TODO: 404 is probably the wrong error code if not 'Link' in response.headers: raise APIBadRequest("Entity has no 'Link' header") link = response.headers['Link'] # TODO: deal with multiple headers # https://tent.io/docs/server-protocol#http-codelinkcode-header url = re.search('^<(.+)>; rel="https://tent.io/rels/profile"$', link).group(1) # https://tent.io/docs/server-protocol#completing-the-discovery-process # TODO: Accept: application/vnd.tent.v0+json try: profile = requests.get(url).json() if CoreProfile.__schema__ not in profile: raise APIException("Entity has no core profile.") except requests.ConnectionError as ex: raise APIException("Could not fetch entity profile ({})".format(ex)) return profile
def put(self, entity, schema): """Update a profile type.""" profile = entity.profiles.get_or_404(schema=schema) try: update_data = json.loads(request.data) except json.JSONDecodeError as e: raise APIBadRequest(str(e)) if 'identity' in update_data: profile.identity = update_data['identity'] if 'servers' in update_data: profile.servers = update_data['servers'] profile.save() return jsonify(profile.to_json()), 200
def put(self, entity, post_id): post = entity.posts.get_or_404(id=post_id) try: post_data = json.loads(request.data) except json.JSONDecodeError as e: raise APIBadRequest(str(e)) # TODO: Posts have more attributes than this if 'content' in post_data: post.content = post_data['content'] if 'schema' in post_data: post.schema = post_data['schema'] # TODO: Versioning. post.save() return jsonify(post.to_json()), 200
def post(self, entity): try: data = json.loads(request.data) except json.JSONDecodeError as e: raise APIBadRequest(str(e)) new_post = Post() new_post.entity = entity new_post.schema = data['schema'] new_post.content = data['content'] new_post.save() for to_notify in entity.followers: notification_link = follow.get_notification_link(to_notify) requests.post(notification_link, data=jsonify(new_post.to_json())) #TODO Handle failled notifications somehow return jsonify(new_post.to_json()), 200