Skip to content

Commit

Permalink
Merge pull request #198 from CSCfi/feature/replace_objects
Browse files Browse the repository at this point in the history
adjust replace json patch to replace elements in folders
  • Loading branch information
blankdots authored Feb 10, 2021
2 parents 0a509de + 6e6dc4e commit 1b219db
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 76 deletions.
34 changes: 20 additions & 14 deletions metadata_backend/api/handlers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Handle HTTP methods for server."""
import json
import re
import mimetypes
from collections import Counter
from math import ceil
Expand Down Expand Up @@ -366,7 +367,7 @@ async def delete_object(self, req: Request) -> Response:
current_user = req.app["Session"]["user_info"]
check_user = await user_op.check_user_has_doc(collection, current_user, accession_id)
if check_user:
collection = "drafts"
await user_op.remove_objects(current_user, "drafts", [accession_id])
else:
reason = "This object does not seem to belong to anything."
LOG.error(reason)
Expand Down Expand Up @@ -547,19 +548,24 @@ async def patch_folder(self, req: Request) -> Response:
patch_ops = await self._get_data(req)
allowed_paths = ["/name", "/description"]
array_paths = ["/metadataObjects/-", "/drafts/-"]
tags_path = re.compile("^/(metadataObjects|drafts)/[0-9]*/(tags)$")
for op in patch_ops:
if all(i not in op["path"] for i in allowed_paths + array_paths):
reason = f"Request contains '{op['path']}' key that cannot be updated to folders."
LOG.error(reason)
raise web.HTTPBadRequest(reason=reason)
if op["op"] in ["remove", "copy", "test", "move"]:
reason = f"{op['op']} on {op['path']} is not allowed."
LOG.error(reason)
raise web.HTTPUnauthorized(reason=reason)
if op["op"] == "replace" and op["path"] in array_paths:
reason = f"{op['op']} on {op['path']} is not allowed."
LOG.error(reason)
raise web.HTTPUnauthorized(reason=reason)
if tags_path.match(op["path"]):
LOG.info(f"{op['op']} on tags in folder")
pass
else:
if all(i not in op["path"] for i in allowed_paths + array_paths):
reason = f"Request contains '{op['path']}' key that cannot be updated to folders."
LOG.error(reason)
raise web.HTTPBadRequest(reason=reason)
if op["op"] in ["remove", "copy", "test", "move"]:
reason = f"{op['op']} on {op['path']} is not allowed."
LOG.error(reason)
raise web.HTTPUnauthorized(reason=reason)
if op["op"] == "replace" and op["path"] in array_paths:
reason = f"{op['op']} on {op['path']}; replacing all objects is not allowed."
LOG.error(reason)
raise web.HTTPUnauthorized(reason=reason)

check_user = await self._handle_check_ownedby_user(req, "folders", folder_id)
if not check_user:
Expand Down Expand Up @@ -722,7 +728,7 @@ async def delete_user(self, req: Request) -> Response:

for folder_id in user["folders"]:
_folder = await fold_ops.read_folder(folder_id)
if not _folder["published"]:
if "published" in _folder and not _folder["published"]:
for obj in _folder["drafts"] + _folder["metadataObjects"]:
await obj_ops.delete_metadata_object(obj["schema"], obj["accessionId"])
await fold_ops.delete_folder(folder_id)
Expand Down
20 changes: 14 additions & 6 deletions metadata_backend/api/operators.py
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,10 @@ async def check_user_has_doc(self, collection: str, user_id: str, accession_id:
:returns: True if accession_id belongs to user
"""
try:
doc_path = "drafts" if collection.startswith("draft") else "folders"
user_query = {doc_path: {"$elemMatch": {"$eq": accession_id}}, "userId": user_id}
if collection.startswith("draft"):
user_query = {"drafts": {"$elemMatch": {"accessionId": accession_id}}, "userId": user_id}
else:
user_query = {"folders": {"$elemMatch": {"$eq": accession_id}}, "userId": user_id}
user_cursor = self.db_service.query("user", user_query)
user_check = [user async for user in user_cursor]
except (ConnectionFailure, OperationFailure) as error:
Expand Down Expand Up @@ -970,13 +972,19 @@ async def remove_objects(self, user_id: str, collection: str, object_ids: List)
:raises: HTTPBadRequest if db connection fails
returns: None
"""
remove_content: Dict
try:
await self._check_user_exists(user_id)
upd_content = {collection: {"$in": object_ids}}
result = await self.db_service.remove("user", user_id, upd_content)
JSONValidator(result, "users").validate
for obj in object_ids:
if collection == "drafts":
remove_content = {"drafts": {"accessionId": obj}}
else:
remove_content = {"folders": obj}
result = await self.db_service.remove("user", user_id, remove_content)
LOG.info(f"result {result}")
JSONValidator(result, "users").validate
except (ConnectionFailure, OperationFailure) as error:
reason = f"Error happened while getting user: {error}"
reason = f"Error happened while removing objects from user: {error}"
LOG.error(reason)
raise web.HTTPBadRequest(reason=reason)

Expand Down
4 changes: 2 additions & 2 deletions metadata_backend/helpers/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,9 +258,9 @@ def jsonpatch_mongo(identifier: Dict, json_patch: List[Dict[str, Any]]) -> List:
)
)
else:
queries.append(UpdateOne(identifier, {"$set": {op["path"][1:]: op["value"]}}))
queries.append(UpdateOne(identifier, {"$set": {op["path"][1:].replace("/", "."): op["value"]}}))
elif op["op"] == "replace":
path = op["path"][1:-2] if op["path"].endswith("/-") else op["path"][1:]
path = op["path"][1:-2] if op["path"].endswith("/-") else op["path"][1:].replace("/", ".")
queries.append(UpdateOne(identifier, {"$set": {path: op["value"]}}))

return queries
Loading

0 comments on commit 1b219db

Please sign in to comment.