|
13 | 13 | # group handler for service node of hsds cluster |
14 | 14 | # |
15 | 15 |
|
| 16 | +import time |
| 17 | + |
16 | 18 | from aiohttp.web_exceptions import HTTPBadRequest, HTTPForbidden, HTTPNotFound |
17 | 19 | from json import JSONDecodeError |
18 | 20 |
|
|
23 | 25 | from .util.authUtil import validateUserPassword |
24 | 26 | from .util.domainUtil import getDomainFromRequest, isValidDomain |
25 | 27 | from .util.domainUtil import getBucketForDomain, getPathForDomain, verifyRoot |
26 | | -from .util.linkUtil import validateLinkName |
| 28 | +from .util.linkUtil import validateLinkName, getLinkClass |
27 | 29 | from .servicenode_lib import getDomainJson, getObjectJson, validateAction |
28 | 30 | from .servicenode_lib import getObjectIdByPath, getPathForObjectId |
29 | 31 | from .servicenode_lib import createObject, createObjectByPath, deleteObject |
30 | 32 | from . import hsds_logger as log |
| 33 | +from . import config |
31 | 34 |
|
32 | 35 |
|
33 | 36 | async def GET_Group(request): |
@@ -189,6 +192,7 @@ async def POST_Group(request): |
189 | 192 | h5path = None |
190 | 193 | creation_props = None |
191 | 194 | attrs = None |
| 195 | + links = None |
192 | 196 |
|
193 | 197 | if request.has_body: |
194 | 198 | try: |
@@ -236,28 +240,66 @@ async def POST_Group(request): |
236 | 240 | creation_props = body["creationProperties"] |
237 | 241 | if "attributes" in body: |
238 | 242 | attrs = body["attributes"] |
| 243 | + if not isinstance(attrs, dict): |
| 244 | + msg = f"POST_Groups expected dict for for links, but got: {type(links)}" |
| 245 | + log.warn(msg) |
| 246 | + raise HTTPBadRequest(reason=msg) |
239 | 247 | log.debug(f"POST Group attributes: {attrs}") |
| 248 | + if "links" in body: |
| 249 | + links = body["links"] |
| 250 | + if not isinstance(links, dict): |
| 251 | + msg = f"POST_Groups expected dict for for links, but got: {type(links)}" |
| 252 | + log.warn(msg) |
| 253 | + raise HTTPBadRequest(reason=msg) |
| 254 | + # validate the links |
| 255 | + now = time.time() |
| 256 | + |
| 257 | + for title in links: |
| 258 | + try: |
| 259 | + validateLinkName(title) |
| 260 | + link_item = links[title] |
| 261 | + link_class = getLinkClass(link_item) |
| 262 | + if "class" in link_item: |
| 263 | + if link_class != link_item["class"]: |
| 264 | + msg = f"expected link class of: {link_class} but got {link_item}" |
| 265 | + log.warn(msg) |
| 266 | + raise HTTPBadRequest(reason=msg) |
| 267 | + else: |
| 268 | + link_item["class"] = link_class |
| 269 | + getLinkClass(link_item) |
| 270 | + if "created" in link_item: |
| 271 | + created = link_item["created"] |
| 272 | + # allow "pre-dated" attributes if recent enough |
| 273 | + predate_max_time = config.get("predate_max_time", default=10.0) |
| 274 | + if now - created > predate_max_time: |
| 275 | + link_item["created"] = created |
| 276 | + else: |
| 277 | + log.warn("stale created timestamp for link, ignoring") |
| 278 | + if "created" not in link_item: |
| 279 | + link_item["created"] = now |
| 280 | + |
| 281 | + except ValueError: |
| 282 | + raise HTTPBadRequest(reason="invalid link item") |
| 283 | + |
| 284 | + kwargs = {"bucket": bucket} |
| 285 | + if obj_id: |
| 286 | + kwargs["obj_id"] = obj_id |
| 287 | + if creation_props: |
| 288 | + kwargs["creation_props"] = creation_props |
| 289 | + if attrs: |
| 290 | + kwargs["attrs"] = attrs |
| 291 | + if links: |
| 292 | + kwargs["links"] = links |
240 | 293 |
|
241 | 294 | if parent_id: |
242 | | - kwargs = {"bucket": bucket, "parent_id": parent_id, "h5path": h5path} |
243 | | - if obj_id: |
244 | | - kwargs["obj_id"] = obj_id |
245 | | - if creation_props: |
246 | | - kwargs["creation_props"] = creation_props |
247 | | - if attrs: |
248 | | - kwargs["attrs"] = attrs |
| 295 | + kwargs["parent_id"] = parent_id |
| 296 | + kwargs["h5path"] = h5path |
249 | 297 | if implicit: |
250 | 298 | kwargs["implicit"] = True |
251 | 299 | group_json = await createObjectByPath(app, **kwargs) |
252 | 300 | else: |
253 | 301 | # create an anonymous group |
254 | | - kwargs = {"bucket": bucket, "root_id": root_id} |
255 | | - if obj_id: |
256 | | - kwargs["obj_id"] = obj_id |
257 | | - if creation_props: |
258 | | - kwargs["creation_props"] = creation_props |
259 | | - if attrs: |
260 | | - kwargs["attrs"] = attrs |
| 302 | + kwargs["root_id"] = root_id |
261 | 303 | group_json = await createObject(app, **kwargs) |
262 | 304 |
|
263 | 305 | log.debug(f"returning resp: {group_json}") |
|
0 commit comments