async def DELETE_Link(request): """HTTP method to delete a link""" log.request(request) app = request.app group_id = request.match_info.get('id') if not group_id: msg = "Missing group id" log.warn(msg) raise HTTPBadRequest(reason=msg) if not isValidUuid(group_id, obj_class="Group"): msg = "Invalid group id: {}".format(group_id) log.warn(msg) raise HTTPBadRequest(reason=msg) link_title = request.match_info.get('title') validateLinkName(link_title) username, pswd = getUserPasswordFromRequest(request) await validateUserPassword(app, username, pswd) domain = getDomainFromRequest(request) if not isValidDomain(domain): msg = "Invalid host value: {}".format(domain) log.warn(msg) raise HTTPBadRequest(reason=msg) await validateAction(app, domain, group_id, username, "delete") req = getDataNodeUrl(app, group_id) req += "/groups/" + group_id + "/links/" + link_title rsp_json = await http_delete(app, req) resp = await jsonResponse(request, rsp_json) log.response(request, resp=resp) return resp
async def DELETE_Link(request): """HTTP DELETE method for group links """ log.request(request) app = request.app params = request.rel_url.query group_id = get_obj_id(request) log.info(f"DELETE link: {group_id}") if not isValidUuid(group_id, obj_class="group"): msg = f"Unexpected group_id: {group_id}" log.warn(msg) raise HTTPBadRequest(reason=msg) link_title = request.match_info.get('title') validateLinkName(link_title) if "bucket" in params: bucket = params["bucket"] else: bucket = None group_json = await get_metadata_obj(app, group_id, bucket=bucket) # TBD: Possible race condition if "links" not in group_json: log.error(f"unexpected group data for id: {group_id}") raise HTTPInternalServerError() links = group_json["links"] if link_title not in links: msg = f"Link name {link_title} not found in group: {group_id}" log.warn(msg) raise HTTPNotFound() del links[link_title] # remove the link from dictionary # update the group lastModified now = time.time() group_json["lastModified"] = now # write back to S3 await save_metadata_obj(app, group_id, group_json, bucket=bucket) hrefs = [] # TBD resp_json = {"href": hrefs} resp = json_response(resp_json) log.response(request, resp=resp) return resp
async def GET_Link(request): """HTTP GET method to return JSON for a link """ log.request(request) app = request.app params = request.rel_url.query group_id = get_obj_id(request) log.info(f"GET link: {group_id}") if not isValidUuid(group_id, obj_class="group"): log.error(f"Unexpected group_id: {group_id}") raise HTTPInternalServerError() link_title = request.match_info.get('title') validateLinkName(link_title) if "bucket" in params: bucket = params["bucket"] else: bucket = None group_json = await get_metadata_obj(app, group_id, bucket=bucket) log.info(f"for id: {group_id} got group json: {group_json}") if "links" not in group_json: log.error(f"unexpected group data for id: {group_id}") raise HTTPInternalServerError() links = group_json["links"] if link_title not in links: log.warn(f"Link name {link_title} not found in group: {group_id}") raise HTTPNotFound() link_json = links[link_title] resp = json_response(link_json) log.response(request, resp=resp) return resp
async def PUT_Link(request): """HTTP method to create a new link""" log.request(request) app = request.app group_id = request.match_info.get('id') if not group_id: msg = "Missing group id" log.warn(msg) raise HTTPBadRequest(reason=msg) if not isValidUuid(group_id, obj_class="Group"): msg = "Invalid group id: {}".format(group_id) log.warn(msg) raise HTTPBadRequest(reason=msg) link_title = request.match_info.get('title') log.info("PUT Link_title: [{}]".format(link_title)) validateLinkName(link_title) username, pswd = getUserPasswordFromRequest(request) # write actions need auth await validateUserPassword(app, username, pswd) if not request.has_body: msg = "PUT Link with no body" log.warn(msg) raise HTTPBadRequest(reason=msg) body = await request.json() link_json = {} if "id" in body: if not isValidUuid(body["id"]): msg = "PUT Link with invalid id in body" log.warn(msg) raise HTTPBadRequest(reason=msg) link_json["id"] = body["id"] link_json["class"] = "H5L_TYPE_HARD" elif "h5path" in body: link_json["h5path"] = body["h5path"] # could be hard or soft link if "h5domain" in body: link_json["h5domain"] = body["h5domain"] link_json["class"] = "H5L_TYPE_EXTERNAL" else: # soft link link_json["class"] = "H5L_TYPE_SOFT" else: msg = "PUT Link with no id or h5path keys" log.warn(msg) raise HTTPBadRequest(reason=msg) domain = getDomainFromRequest(request) if not isValidDomain(domain): msg = "Invalid host value: {}".format(domain) log.warn(msg) raise HTTPBadRequest(reason=msg) await validateAction(app, domain, group_id, username, "create") # for hard links, verify that the referenced id exists and is in this domain if "id" in body: ref_id = body["id"] ref_json = await getObjectJson(app, ref_id) group_json = await getObjectJson(app, group_id) if ref_json["root"] != group_json["root"]: msg = "Hard link must reference an object in the same domain" log.warn(msg) raise HTTPBadRequest(reason=msg) # ready to add link now req = getDataNodeUrl(app, group_id) req += "/groups/" + group_id + "/links/" + link_title log.debug("PUT link - getting group: " + req) put_rsp = await http_put(app, req, data=link_json) log.debug("PUT Link resp: " + str(put_rsp)) hrefs = [] # TBD req_rsp = {"hrefs": hrefs} # link creation successful resp = await jsonResponse(request, req_rsp, status=201) log.response(request, resp=resp) return resp
async def GET_Link(request): """HTTP method to return JSON for a group link""" log.request(request) app = request.app group_id = request.match_info.get('id') if not group_id: msg = "Missing group id" log.warn(msg) raise HTTPBadRequest(reason=msg) if not isValidUuid(group_id, obj_class="Group"): msg = "Invalid group id: {}".format(group_id) log.warn(msg) raise HTTPBadRequest(reason=msg) link_title = request.match_info.get('title') validateLinkName(link_title) username, pswd = getUserPasswordFromRequest(request) if username is None and app['allow_noauth']: username = "******" else: await validateUserPassword(app, username, pswd) domain = getDomainFromRequest(request) if not isValidDomain(domain): msg = "Invalid host value: {}".format(domain) log.warn(msg) raise HTTPBadRequest(reason=msg) await validateAction(app, domain, group_id, username, "read") req = getDataNodeUrl(app, group_id) req += "/groups/" + group_id + "/links/" + link_title log.debug("get LINK: " + req) link_json = await http_get(app, req) log.debug("got link_json: " + str(link_json)) resp_link = {} resp_link["title"] = link_title resp_link["class"] = link_json["class"] if link_json["class"] == "H5L_TYPE_HARD": resp_link["id"] = link_json["id"] resp_link["collection"] = getCollectionForId(link_json["id"]) elif link_json["class"] == "H5L_TYPE_SOFT": resp_link["h5path"] = link_json["h5path"] elif link_json["class"] == "H5L_TYPE_EXTERNAL": resp_link["h5path"] = link_json["h5path"] resp_link["h5domain"] = link_json["h5domain"] else: log.warn("Unexpected link class: {}".format(link_json["class"])) resp_json = {} resp_json["link"] = resp_link resp_json["created"] = link_json["created"] # links don't get modified, so use created timestamp as lastModified resp_json["lastModified"] = link_json["created"] hrefs = [] group_uri = '/groups/' + group_id hrefs.append({ 'rel': 'self', 'href': getHref(request, group_uri + '/links/' + link_title) }) hrefs.append({'rel': 'home', 'href': getHref(request, '/')}) hrefs.append({'rel': 'owner', 'href': getHref(request, group_uri)}) if link_json["class"] == "H5L_TYPE_HARD": target = '/' + resp_link["collection"] + '/' + resp_link["id"] hrefs.append({'rel': 'target', 'href': getHref(request, target)}) resp_json["hrefs"] = hrefs resp = await jsonResponse(request, resp_json) log.response(request, resp=resp) return resp
async def PUT_Link(request): """ Handler creating a new link""" log.request(request) app = request.app params = request.rel_url.query group_id = get_obj_id(request) log.info(f"PUT link: {group_id}") if not isValidUuid(group_id, obj_class="group"): log.error(f"Unexpected group_id: {group_id}") raise HTTPInternalServerError() link_title = request.match_info.get('title') validateLinkName(link_title) log.info(f"link_title: {link_title}") if not request.has_body: msg = "PUT Link with no body" log.warn(msg) raise HTTPBadRequest(reason=msg) body = await request.json() if "class" not in body: msg = "PUT Link with no class key body" log.warn(msg) raise HTTPBadRequest(reason=msg) link_class = body["class"] link_json = {} link_json["class"] = link_class if "id" in body: link_json["id"] = body["id"] if "h5path" in body: link_json["h5path"] = body["h5path"] if "h5domain" in body: link_json["h5domain"] = body["h5domain"] if "bucket" in params: bucket = params["bucket"] elif "bucket" in body: bucket = params["bucket"] else: bucket = None group_json = await get_metadata_obj(app, group_id, bucket=bucket) if "links" not in group_json: log.error(f"unexpected group data for id: {group_id}") raise HTTPInternalServerError() links = group_json["links"] if link_title in links: msg = f"Link name {link_title} already found in group: {group_id}" log.warn(msg) raise HTTPConflict() now = time.time() link_json["created"] = now # add the link links[link_title] = link_json # update the group lastModified group_json["lastModified"] = now # write back to S3, save to metadata cache await save_metadata_obj(app, group_id, group_json, bucket=bucket) resp_json = { } resp = json_response(resp_json, status=201) log.response(request, resp=resp) return resp