synapse 2.220.0__py311-none-any.whl → 2.222.0__py311-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of synapse might be problematic. Click here for more details.

Files changed (52) hide show
  1. synapse/cortex.py +34 -14
  2. synapse/data/lark/storm.lark +9 -6
  3. synapse/lib/ast.py +8 -2
  4. synapse/lib/layer.py +149 -8
  5. synapse/lib/parser.py +1 -0
  6. synapse/lib/rstorm.py +83 -2
  7. synapse/lib/schemas.py +4 -0
  8. synapse/lib/snap.py +21 -13
  9. synapse/lib/stormhttp.py +10 -10
  10. synapse/lib/stormlib/aha.py +3 -3
  11. synapse/lib/stormlib/auth.py +11 -11
  12. synapse/lib/stormlib/cell.py +1 -1
  13. synapse/lib/stormlib/cortex.py +10 -10
  14. synapse/lib/stormlib/env.py +4 -5
  15. synapse/lib/stormlib/ethereum.py +1 -1
  16. synapse/lib/stormlib/gen.py +3 -3
  17. synapse/lib/stormlib/hex.py +2 -2
  18. synapse/lib/stormlib/imap.py +2 -2
  19. synapse/lib/stormlib/infosec.py +2 -2
  20. synapse/lib/stormlib/iters.py +2 -2
  21. synapse/lib/stormlib/model.py +5 -5
  22. synapse/lib/stormlib/notifications.py +1 -1
  23. synapse/lib/stormlib/oauth.py +2 -2
  24. synapse/lib/stormlib/project.py +3 -3
  25. synapse/lib/stormlib/scrape.py +2 -1
  26. synapse/lib/stormlib/smtp.py +3 -3
  27. synapse/lib/stormlib/stats.py +2 -2
  28. synapse/lib/stormlib/stix.py +2 -2
  29. synapse/lib/stormlib/utils.py +19 -0
  30. synapse/lib/stormlib/vault.py +1 -1
  31. synapse/lib/stormlib/xml.py +2 -2
  32. synapse/lib/stormlib/yaml.py +1 -1
  33. synapse/lib/stormtypes.py +182 -64
  34. synapse/lib/version.py +2 -2
  35. synapse/models/orgs.py +3 -0
  36. synapse/tests/test_lib_grammar.py +4 -4
  37. synapse/tests/test_lib_layer.py +86 -67
  38. synapse/tests/test_lib_rstorm.py +180 -0
  39. synapse/tests/test_lib_storm.py +80 -1
  40. synapse/tests/test_lib_stormlib_auth.py +84 -0
  41. synapse/tests/test_lib_stormlib_cortex.py +1 -0
  42. synapse/tests/test_lib_stormlib_env.py +3 -1
  43. synapse/tests/test_lib_stormlib_utils.py +10 -0
  44. synapse/tests/test_lib_stormtypes.py +576 -2
  45. synapse/tests/test_model_orgs.py +6 -1
  46. synapse/tools/aha/list.py +9 -9
  47. synapse/tools/aha/provision/service.py +2 -2
  48. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/METADATA +1 -1
  49. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/RECORD +52 -52
  50. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/WHEEL +0 -0
  51. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/licenses/LICENSE +0 -0
  52. {synapse-2.220.0.dist-info → synapse-2.222.0.dist-info}/top_level.txt +0 -0
synapse/lib/stormtypes.py CHANGED
@@ -312,6 +312,18 @@ class StormTypesRegistry:
312
312
  locl = getattr(obj, funcname, None)
313
313
  assert locl is not None, f'bad _funcname=[{funcname}] for {obj} {info.get("name")}'
314
314
  args = rtype.get('args', ())
315
+ for idx, arg in enumerate(args):
316
+ argname = arg.get('name')
317
+ assert argname is not None, f'Argument at index {idx} has no name'
318
+ argtype = arg.get('type')
319
+ assert argtype is not None, f'The type for argument {argname} of function {funcname} is unknown'
320
+ if isinstance(argtype, (list, tuple)):
321
+ for atyp in argtype:
322
+ if atyp not in self.known_types and atyp not in self.undefined_types:
323
+ raise s_exc.NoSuchType(mesg=f'The argument type {atyp} for arg {argname} of function {obj.__name__}.{funcname} is unknown.', type=argtype)
324
+ else:
325
+ if argtype not in self.known_types and argtype not in self.undefined_types:
326
+ raise s_exc.NoSuchType(mesg=f'The argument type {argtype} for arg {argname} of function {obj.__name__}.{funcname} is unknown.', type=argtype)
315
327
  callsig = getCallSig(locl)
316
328
  # Assert the callsigs match
317
329
  callsig_args = [str(v).split('=')[0] for v in callsig.parameters.values()]
@@ -1454,7 +1466,7 @@ class LibBase(Lib):
1454
1466
  {'name': 'valu', 'type': 'any', 'desc': 'The value to normalize.', },
1455
1467
  ),
1456
1468
  'returns': {'type': 'list',
1457
- 'desc': 'A list of (<bool>, <prim>) for status and normalized value.', }}},
1469
+ 'desc': 'A list of (<boolean>, <prim>) for status and normalized value.', }}},
1458
1470
  {'name': 'repr', 'desc': '''
1459
1471
  Attempt to convert a system mode value to a display mode string.
1460
1472
 
@@ -1583,8 +1595,16 @@ class LibBase(Lib):
1583
1595
 
1584
1596
  if not asroot:
1585
1597
  permtext = ' or '.join(('.'.join(p) for p in rootperms))
1586
- mesg = f'Module ({name}) requires permission: {permtext}'
1587
- raise s_exc.AuthDeny(mesg=mesg, user=self.runt.user.iden, username=self.runt.user.name)
1598
+
1599
+ match mdef.get('asroot:ondeny:import', 'deny'):
1600
+ case 'allow':
1601
+ pass
1602
+ case 'warn':
1603
+ mesg = f'Module ({name}) permissions will not be elevated. Missing permission: {permtext}.'
1604
+ await self.runt.warnonce(mesg, log=False)
1605
+ case _:
1606
+ mesg = f'Module ({name}) requires permission: {permtext}'
1607
+ raise s_exc.AuthDeny(mesg=mesg, user=self.runt.user.iden, username=self.runt.user.name)
1588
1608
 
1589
1609
  else:
1590
1610
  perm = ('storm', 'asroot', 'mod') + tuple(name.split('.'))
@@ -2159,7 +2179,7 @@ class LibAxon(Lib):
2159
2179
  'desc': 'Set to False to disable SSL/TLS certificate verification.', 'default': True},
2160
2180
  {'name': 'timeout', 'type': 'int', 'desc': 'Timeout for the download operation.',
2161
2181
  'default': None},
2162
- {'name': 'proxy', 'type': ['bool', 'str'],
2182
+ {'name': 'proxy', 'type': ['boolean', 'str'],
2163
2183
  'desc': 'Configure proxy usage. See $lib.axon help for additional details.', 'default': True},
2164
2184
  {'name': 'ssl_opts', 'type': 'dict',
2165
2185
  'desc': 'Optional SSL/TLS options. See $lib.axon help for additional details.',
@@ -2182,7 +2202,7 @@ class LibAxon(Lib):
2182
2202
  'desc': 'Set to False to disable SSL/TLS certificate verification.', 'default': True},
2183
2203
  {'name': 'timeout', 'type': 'int', 'desc': 'Timeout for the download operation.',
2184
2204
  'default': None},
2185
- {'name': 'proxy', 'type': ['bool', 'str'],
2205
+ {'name': 'proxy', 'type': ['boolean', 'str'],
2186
2206
  'desc': 'Configure proxy usage. See $lib.axon help for additional details.', 'default': True},
2187
2207
  {'name': 'ssl_opts', 'type': 'dict',
2188
2208
  'desc': 'Optional SSL/TLS options. See $lib.axon help for additional details.',
@@ -2212,7 +2232,7 @@ class LibAxon(Lib):
2212
2232
  ''',
2213
2233
  'type': {'type': 'function', '_funcname': 'del_',
2214
2234
  'args': (
2215
- {'name': 'sha256', 'type': 'hash:sha256',
2235
+ {'name': 'sha256', 'type': 'str',
2216
2236
  'desc': 'The sha256 of the bytes to remove from the Axon.'},
2217
2237
  ),
2218
2238
  'returns': {'type': 'boolean', 'desc': 'True if the bytes were found and removed.'}}},
@@ -7178,11 +7198,11 @@ class Layer(Prim):
7178
7198
  'type': {'type': 'function', '_funcname': 'getStorNodesByProp',
7179
7199
  'args': (
7180
7200
  {'name': 'propname', 'type': 'str', 'desc': 'The full property name to lift by.'},
7181
- {'name': 'propvalu', 'type': 'obj', 'desc': 'The value for the property.', 'default': None},
7201
+ {'name': 'propvalu', 'type': 'prim', 'desc': 'The value for the property.', 'default': None},
7182
7202
  {'name': 'propcmpr', 'type': 'str', 'desc': 'The comparison operation to use on the value.',
7183
7203
  'default': '='},
7184
7204
  ),
7185
- 'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Tuple of buid, sode values.', }}},
7205
+ 'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Tuple of node iden, sode values.', }}},
7186
7206
  {'name': 'setStorNodeProp',
7187
7207
  'desc': 'Set a property on a node in this layer.',
7188
7208
  'type': {'type': 'function', '_funcname': 'setStorNodeProp',
@@ -7192,6 +7212,13 @@ class Layer(Prim):
7192
7212
  {'name': 'valu', 'type': 'any', 'desc': 'The value to set.'},
7193
7213
  ),
7194
7214
  'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7215
+ {'name': 'delStorNode',
7216
+ 'desc': 'Delete a storage node, node data, and associated edges from a node in this layer.',
7217
+ 'type': {'type': 'function', '_funcname': 'delStorNode',
7218
+ 'args': (
7219
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
7220
+ ),
7221
+ 'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7195
7222
  {'name': 'delStorNodeProp',
7196
7223
  'desc': 'Delete a property from a node in this layer.',
7197
7224
  'type': {'type': 'function', '_funcname': 'delStorNodeProp',
@@ -7200,6 +7227,23 @@ class Layer(Prim):
7200
7227
  {'name': 'prop', 'type': 'str', 'desc': 'The property name to delete.'},
7201
7228
  ),
7202
7229
  'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7230
+ {'name': 'delNodeData',
7231
+ 'desc': 'Delete node data from a node in this layer.',
7232
+ 'type': {'type': 'function', '_funcname': 'delNodeData',
7233
+ 'args': (
7234
+ {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
7235
+ {'name': 'name', 'type': 'str', 'default': None, 'desc': 'The node data key to delete.'},
7236
+ ),
7237
+ 'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7238
+ {'name': 'delEdge',
7239
+ 'desc': 'Delete edges from a node in this layer.',
7240
+ 'type': {'type': 'function', '_funcname': 'delEdge',
7241
+ 'args': (
7242
+ {'name': 'nodeid1', 'type': 'str', 'desc': 'The hex string of the N1 node iden.'},
7243
+ {'name': 'verb', 'type': 'str', 'desc': 'The edge verb to delete.'},
7244
+ {'name': 'nodeid2', 'type': 'str', 'desc': 'The hex string of the N2 node iden.'},
7245
+ ),
7246
+ 'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
7203
7247
  {'name': 'getMirrorStatus', 'desc': '''
7204
7248
  Return a dictionary of the mirror synchronization status for the layer.
7205
7249
  ''',
@@ -7254,7 +7298,7 @@ class Layer(Prim):
7254
7298
  'type': {'type': 'function', '_funcname': 'liftByProp',
7255
7299
  'args': (
7256
7300
  {'name': 'propname', 'type': 'str', 'desc': 'The full property name to lift by.'},
7257
- {'name': 'propvalu', 'type': 'obj', 'desc': 'The value for the property.', 'default': None},
7301
+ {'name': 'propvalu', 'type': 'any', 'desc': 'The value for the property.', 'default': None},
7258
7302
  {'name': 'propcmpr', 'type': 'str', 'desc': 'The comparison operation to use on the value.', 'default': '='},
7259
7303
  ),
7260
7304
  'returns': {'name': 'Yields', 'type': 'node',
@@ -7296,6 +7340,16 @@ class Layer(Prim):
7296
7340
  'returns': {'name': 'Yields', 'type': 'node',
7297
7341
  'desc': 'Yields nodes.', }}},
7298
7342
 
7343
+ {'name': 'hasEdge', 'desc': 'Check if a light edge between two nodes exists in the layer.',
7344
+ 'type': {'type': 'function', '_funcname': 'hasEdge',
7345
+ 'args': (
7346
+ {'name': 'nodeid1', 'type': 'str', 'desc': 'The hex string of the N1 node iden.'},
7347
+ {'name': 'verb', 'type': 'str', 'desc': 'The edge verb.'},
7348
+ {'name': 'nodeid2', 'type': 'str', 'desc': 'The hex string of the N2 node iden.'},
7349
+ ),
7350
+ 'returns': {'type': 'boolean',
7351
+ 'desc': 'True if the edge exists in the layer, False if it does not.', }}},
7352
+
7299
7353
  {'name': 'getEdges', 'desc': '''
7300
7354
  Yield (n1iden, verb, n2iden) tuples for any light edges in the layer.
7301
7355
 
@@ -7326,6 +7380,7 @@ class Layer(Prim):
7326
7380
  'type': {'type': 'function', '_funcname': 'getEdgesByN1',
7327
7381
  'args': (
7328
7382
  {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
7383
+ {'name': 'verb', 'type': 'str', 'desc': 'An optional edge verb to filter by.', 'default': None},
7329
7384
  ),
7330
7385
  'returns': {'name': 'Yields', 'type': 'list',
7331
7386
  'desc': 'Yields (<verb>, <n2iden>) tuples', }}},
@@ -7343,6 +7398,7 @@ class Layer(Prim):
7343
7398
  'type': {'type': 'function', '_funcname': 'getEdgesByN2',
7344
7399
  'args': (
7345
7400
  {'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
7401
+ {'name': 'verb', 'type': 'str', 'desc': 'An optional edge verb to filter by.', 'default': None},
7346
7402
  ),
7347
7403
  'returns': {'name': 'Yields', 'type': 'list',
7348
7404
  'desc': 'Yields (<verb>, <n1iden>) tuples', }}},
@@ -7405,6 +7461,7 @@ class Layer(Prim):
7405
7461
  'delPush': self._delPush,
7406
7462
  'addPull': self._addPull,
7407
7463
  'delPull': self._delPull,
7464
+ 'hasEdge': self.hasEdge,
7408
7465
  'getEdges': self.getEdges,
7409
7466
  'liftByTag': self.liftByTag,
7410
7467
  'liftByProp': self.liftByProp,
@@ -7424,7 +7481,10 @@ class Layer(Prim):
7424
7481
  'getNodeData': self.getNodeData,
7425
7482
  'getMirrorStatus': self.getMirrorStatus,
7426
7483
  'setStorNodeProp': self.setStorNodeProp,
7484
+ 'delStorNode': self.delStorNode,
7427
7485
  'delStorNodeProp': self.delStorNodeProp,
7486
+ 'delNodeData': self.delNodeData,
7487
+ 'delEdge': self.delEdge,
7428
7488
  }
7429
7489
 
7430
7490
  @stormfunc(readonly=True)
@@ -7442,8 +7502,7 @@ class Layer(Prim):
7442
7502
  async for _, buid, sode in layr.liftByTag(tagname, form=formname):
7443
7503
  yield await self.runt.snap._joinStorNode(buid, {iden: sode})
7444
7504
 
7445
- @stormfunc(readonly=True)
7446
- async def liftByProp(self, propname, propvalu=None, propcmpr='='):
7505
+ async def _liftByProp(self, propname, propvalu=None, propcmpr='='):
7447
7506
 
7448
7507
  propname = await tostr(propname)
7449
7508
  propvalu = await toprim(propvalu)
@@ -7471,12 +7530,18 @@ class Layer(Prim):
7471
7530
 
7472
7531
  if propvalu is None:
7473
7532
  async for _, buid, sode in layr.liftByProp(liftform, liftprop):
7474
- yield await self.runt.snap._joinStorNode(buid, {iden: sode})
7533
+ yield buid, sode
7475
7534
  return
7476
7535
 
7477
7536
  norm, info = prop.type.norm(propvalu)
7478
7537
  cmprvals = prop.type.getStorCmprs(propcmpr, norm)
7479
7538
  async for _, buid, sode in layr.liftByPropValu(liftform, liftprop, cmprvals):
7539
+ yield buid, sode
7540
+
7541
+ @stormfunc(readonly=True)
7542
+ async def liftByProp(self, propname, propvalu=None, propcmpr='='):
7543
+ iden = self.valu.get('iden')
7544
+ async for buid, sode in self._liftByProp(propname, propvalu=propvalu, propcmpr=propcmpr):
7480
7545
  yield await self.runt.snap._joinStorNode(buid, {iden: sode})
7481
7546
 
7482
7547
  @stormfunc(readonly=True)
@@ -7499,24 +7564,56 @@ class Layer(Prim):
7499
7564
  return await layr.getMirrorStatus()
7500
7565
 
7501
7566
  async def setStorNodeProp(self, nodeid, prop, valu):
7502
- iden = self.valu.get('iden')
7503
- layr = self.runt.snap.core.getLayer(iden)
7504
- buid = s_common.uhex(await tostr(nodeid))
7567
+ buid = await tobuid(nodeid)
7505
7568
  prop = await tostr(prop)
7506
7569
  valu = await tostor(valu)
7570
+
7571
+ iden = self.valu.get('iden')
7572
+ layr = self.runt.snap.core.getLayer(iden)
7507
7573
  self.runt.reqAdmin(mesg='setStorNodeProp() requires admin privileges.')
7508
7574
  meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7509
7575
  return await layr.setStorNodeProp(buid, prop, valu, meta=meta)
7510
7576
 
7511
- async def delStorNodeProp(self, nodeid, prop):
7577
+ async def delStorNode(self, nodeid):
7578
+ buid = await tobuid(nodeid)
7579
+
7512
7580
  iden = self.valu.get('iden')
7513
7581
  layr = self.runt.snap.core.getLayer(iden)
7514
- buid = s_common.uhex(await tostr(nodeid))
7582
+ self.runt.reqAdmin(mesg='delStorNode() requires admin privileges.')
7583
+ meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7584
+ return await layr.delStorNode(buid, meta=meta)
7585
+
7586
+ async def delStorNodeProp(self, nodeid, prop):
7587
+ buid = await tobuid(nodeid)
7515
7588
  prop = await tostr(prop)
7589
+
7590
+ iden = self.valu.get('iden')
7591
+ layr = self.runt.snap.core.getLayer(iden)
7516
7592
  self.runt.reqAdmin(mesg='delStorNodeProp() requires admin privileges.')
7517
7593
  meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7518
7594
  return await layr.delStorNodeProp(buid, prop, meta=meta)
7519
7595
 
7596
+ async def delNodeData(self, nodeid, name=None):
7597
+ buid = await tobuid(nodeid)
7598
+ name = await tostr(name, noneok=True)
7599
+
7600
+ iden = self.valu.get('iden')
7601
+ layr = self.runt.snap.core.getLayer(iden)
7602
+ self.runt.reqAdmin(mesg='delNodeData() requires admin privileges.')
7603
+ meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7604
+ return await layr.delNodeData(buid, meta=meta, name=name)
7605
+
7606
+ async def delEdge(self, nodeid1, verb, nodeid2):
7607
+ n1buid = await tobuid(nodeid1)
7608
+ verb = await tostr(verb)
7609
+ n2buid = await tobuid(nodeid2)
7610
+
7611
+ iden = self.valu.get('iden')
7612
+ layr = self.runt.snap.core.getLayer(iden)
7613
+ self.runt.reqAdmin(mesg='delEdge() requires admin privileges.')
7614
+ meta = {'time': s_common.now(), 'user': self.runt.user.iden}
7615
+ return await layr.delEdge(n1buid, verb, n2buid, meta=meta)
7616
+
7520
7617
  async def _addPull(self, url, offs=0, queue_size=s_const.layer_pdef_qsize, chunk_size=s_const.layer_pdef_csize):
7521
7618
  url = await tostr(url)
7522
7619
  offs = await toint(offs)
@@ -7748,7 +7845,8 @@ class Layer(Prim):
7748
7845
 
7749
7846
  layr = self.runt.snap.core.reqLayer(self.valu.get('iden'))
7750
7847
 
7751
- self.runt.confirm(('layer', 'edits', 'read'), gateiden=layr.iden)
7848
+ if not self.runt.allowed(('layer', 'edits', 'read'), gateiden=layr.iden):
7849
+ self.runt.confirm(('layer', 'read'), gateiden=layr.iden)
7752
7850
 
7753
7851
  if reverse:
7754
7852
  wait = False
@@ -7772,11 +7870,11 @@ class Layer(Prim):
7772
7870
 
7773
7871
  @stormfunc(readonly=True)
7774
7872
  async def getStorNode(self, nodeid):
7775
- nodeid = await tostr(nodeid)
7873
+ nodeid = await tobuid(nodeid)
7776
7874
  layriden = self.valu.get('iden')
7777
7875
  await self.runt.reqUserCanReadLayer(layriden)
7778
7876
  layr = self.runt.snap.core.getLayer(layriden)
7779
- return await layr.getStorNode(s_common.uhex(nodeid))
7877
+ return await layr.getStorNode(nodeid)
7780
7878
 
7781
7879
  @stormfunc(readonly=True)
7782
7880
  async def getStorNodes(self):
@@ -7801,25 +7899,18 @@ class Layer(Prim):
7801
7899
 
7802
7900
  @stormfunc(readonly=True)
7803
7901
  async def getStorNodesByProp(self, propname, propvalu=None, propcmpr='='):
7804
- propname = await tostr(propname)
7805
- propvalu = await tostor(propvalu)
7806
- propcmpr = await tostr(propcmpr)
7902
+ async for buid, sode in self._liftByProp(propname, propvalu=propvalu, propcmpr=propcmpr):
7903
+ yield s_common.ehex(buid), sode
7807
7904
 
7905
+ @stormfunc(readonly=True)
7906
+ async def hasEdge(self, nodeid1, verb, nodeid2):
7907
+ nodeid1 = await tobuid(nodeid1)
7908
+ verb = await tostr(verb)
7909
+ nodeid2 = await tobuid(nodeid2)
7808
7910
  layriden = self.valu.get('iden')
7809
7911
  await self.runt.reqUserCanReadLayer(layriden)
7810
7912
  layr = self.runt.snap.core.getLayer(layriden)
7811
-
7812
- prop = self.runt.snap.core.model.reqProp(propname)
7813
-
7814
- if propvalu is not None:
7815
- norm, info = prop.type.norm(propvalu)
7816
- cmprvals = prop.type.getStorCmprs(propcmpr, norm)
7817
- async for _, buid, sode in layr.liftByPropValu(prop.form.name, prop.name, cmprvals):
7818
- yield (s_common.ehex(buid), sode)
7819
- return
7820
-
7821
- async for _, buid, sode in layr.liftByProp(prop.form.name, prop.name):
7822
- yield (s_common.ehex(buid), sode)
7913
+ return await layr.hasNodeEdge(nodeid1, verb, nodeid2)
7823
7914
 
7824
7915
  @stormfunc(readonly=True)
7825
7916
  async def getEdges(self):
@@ -7830,30 +7921,32 @@ class Layer(Prim):
7830
7921
  yield item
7831
7922
 
7832
7923
  @stormfunc(readonly=True)
7833
- async def getEdgesByN1(self, nodeid):
7834
- nodeid = await tostr(nodeid)
7924
+ async def getEdgesByN1(self, nodeid, verb=None):
7925
+ nodeid = await tobuid(nodeid)
7926
+ verb = await tostr(verb, noneok=True)
7835
7927
  layriden = self.valu.get('iden')
7836
7928
  await self.runt.reqUserCanReadLayer(layriden)
7837
7929
  layr = self.runt.snap.core.getLayer(layriden)
7838
- async for item in layr.iterNodeEdgesN1(s_common.uhex(nodeid)):
7930
+ async for item in layr.iterNodeEdgesN1(nodeid, verb=verb):
7839
7931
  yield item
7840
7932
 
7841
7933
  @stormfunc(readonly=True)
7842
- async def getEdgesByN2(self, nodeid):
7843
- nodeid = await tostr(nodeid)
7934
+ async def getEdgesByN2(self, nodeid, verb=None):
7935
+ nodeid = await tobuid(nodeid)
7936
+ verb = await tostr(verb, noneok=True)
7844
7937
  layriden = self.valu.get('iden')
7845
7938
  await self.runt.reqUserCanReadLayer(layriden)
7846
7939
  layr = self.runt.snap.core.getLayer(layriden)
7847
- async for item in layr.iterNodeEdgesN2(s_common.uhex(nodeid)):
7940
+ async for item in layr.iterNodeEdgesN2(nodeid, verb=verb):
7848
7941
  yield item
7849
7942
 
7850
7943
  @stormfunc(readonly=True)
7851
7944
  async def getNodeData(self, nodeid):
7852
- nodeid = await tostr(nodeid)
7945
+ nodeid = await tobuid(nodeid)
7853
7946
  layriden = self.valu.get('iden')
7854
7947
  await self.runt.reqUserCanReadLayer(layriden)
7855
7948
  layr = self.runt.snap.core.getLayer(layriden)
7856
- async for item in layr.iterNodeData(s_common.uhex(nodeid)):
7949
+ async for item in layr.iterNodeData(nodeid):
7857
7950
  yield item
7858
7951
 
7859
7952
  @stormfunc(readonly=True)
@@ -9154,39 +9247,39 @@ class LibJsonStor(Lib):
9154
9247
  {'name': 'get', 'desc': 'Return a stored JSON object or object property.',
9155
9248
  'type': {'type': 'function', '_funcname': 'get',
9156
9249
  'args': (
9157
- {'name': 'path', 'type': 'str|list', 'desc': 'A path string or list of path parts.'},
9158
- {'name': 'prop', 'type': 'str|list', 'desc': 'A property name or list of name parts.', 'default': None},
9250
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'A path string or list of path parts.'},
9251
+ {'name': 'prop', 'type': ['str', 'list'], 'desc': 'A property name or list of name parts.', 'default': None},
9159
9252
  ),
9160
9253
  'returns': {'type': 'prim', 'desc': 'The previously stored value or ``(null)``.'}}},
9161
9254
 
9162
9255
  {'name': 'set', 'desc': 'Set a JSON object or object property.',
9163
9256
  'type': {'type': 'function', '_funcname': 'set',
9164
9257
  'args': (
9165
- {'name': 'path', 'type': 'str|list', 'desc': 'A path string or list of path elements.'},
9258
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'A path string or list of path elements.'},
9166
9259
  {'name': 'valu', 'type': 'prim', 'desc': 'The value to set as the JSON object or object property.'},
9167
- {'name': 'prop', 'type': 'str|list', 'desc': 'A property name or list of name parts.', 'default': None},
9260
+ {'name': 'prop', 'type': ['str', 'list'], 'desc': 'A property name or list of name parts.', 'default': None},
9168
9261
  ),
9169
9262
  'returns': {'type': 'boolean', 'desc': 'True if the set operation was successful.'}}},
9170
9263
 
9171
9264
  {'name': 'del', 'desc': 'Delete a stored JSON object or object.',
9172
9265
  'type': {'type': 'function', '_funcname': '_del',
9173
9266
  'args': (
9174
- {'name': 'path', 'type': 'str|list', 'desc': 'A path string or list of path parts.'},
9175
- {'name': 'prop', 'type': 'str|list', 'desc': 'A property name or list of name parts.', 'default': None},
9267
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'A path string or list of path parts.'},
9268
+ {'name': 'prop', 'type': ['str', 'list'], 'desc': 'A property name or list of name parts.', 'default': None},
9176
9269
  ),
9177
9270
  'returns': {'type': 'boolean', 'desc': 'True if the del operation was successful.'}}},
9178
9271
 
9179
9272
  {'name': 'iter', 'desc': 'Yield (<path>, <valu>) tuples for the JSON objects.',
9180
9273
  'type': {'type': 'function', '_funcname': 'iter',
9181
9274
  'args': (
9182
- {'name': 'path', 'type': 'str|list', 'desc': 'A path string or list of path parts.', 'default': None},
9275
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'A path string or list of path parts.', 'default': None},
9183
9276
  ),
9184
9277
  'returns': {'name': 'Yields', 'type': 'list', 'desc': '(<path>, <item>) tuples.'}}},
9185
9278
  {'name': 'cacheget',
9186
9279
  'desc': 'Retrieve data stored with cacheset() if it was stored more recently than the asof argument.',
9187
9280
  'type': {'type': 'function', '_funcname': 'cacheget',
9188
9281
  'args': (
9189
- {'name': 'path', 'type': 'str|list', 'desc': 'The base path to use for the cache key.', },
9282
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'The base path to use for the cache key.', },
9190
9283
  {'name': 'key', 'type': 'prim', 'desc': 'The value to use for the GUID cache key.', },
9191
9284
  {'name': 'asof', 'type': 'time', 'default': 'now', 'desc': 'The max cache age.'},
9192
9285
  {'name': 'envl', 'type': 'boolean', 'default': False, 'desc': 'Return the full cache envelope.'},
@@ -9196,7 +9289,7 @@ class LibJsonStor(Lib):
9196
9289
  'desc': 'Set cache data with an envelope that tracks time for cacheget() use.',
9197
9290
  'type': {'type': 'function', '_funcname': 'cacheset',
9198
9291
  'args': (
9199
- {'name': 'path', 'type': 'str|list', 'desc': 'The base path to use for the cache key.', },
9292
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'The base path to use for the cache key.', },
9200
9293
  {'name': 'key', 'type': 'prim', 'desc': 'The value to use for the GUID cache key.', },
9201
9294
  {'name': 'valu', 'type': 'prim', 'desc': 'The data to store.', },
9202
9295
  ),
@@ -9205,7 +9298,7 @@ class LibJsonStor(Lib):
9205
9298
  'desc': 'Remove cached data set with cacheset.',
9206
9299
  'type': {'type': 'function', '_funcname': 'cachedel',
9207
9300
  'args': (
9208
- {'name': 'path', 'type': 'str|list', 'desc': 'The base path to use for the cache key.', },
9301
+ {'name': 'path', 'type': ['str', 'list'], 'desc': 'The base path to use for the cache key.', },
9209
9302
  {'name': 'key', 'type': 'prim', 'desc': 'The value to use for the GUID cache key.', },
9210
9303
  ),
9211
9304
  'returns': {'type': 'boolean', 'desc': 'True if the del operation was successful.'}}},
@@ -9434,7 +9527,7 @@ class LibCron(Lib):
9434
9527
  {'name': 'prefix', 'type': 'str',
9435
9528
  'desc': 'A prefix to match in order to identify a cron job to modify. '
9436
9529
  'Only a single matching prefix will be modified.', },
9437
- {'name': 'query', 'type': ['str', 'query'],
9530
+ {'name': 'query', 'type': ['str', 'storm:query'],
9438
9531
  'desc': 'The new Storm query for the Cron Job.', }
9439
9532
  ),
9440
9533
  'returns': {'type': 'str', 'desc': 'The iden of the CronJob which was modified.'}}},
@@ -10274,24 +10367,44 @@ async def torepr(valu, usestr=False):
10274
10367
  return str(valu)
10275
10368
  return repr(valu)
10276
10369
 
10277
- async def tobuidhex(valu, noneok=False):
10278
-
10279
- if noneok and valu is None:
10280
- return None
10370
+ async def tobuid(valu):
10281
10371
 
10282
10372
  if isinstance(valu, Node):
10283
- return valu.valu.iden()
10373
+ return valu.valu.buid
10284
10374
 
10285
10375
  if isinstance(valu, s_node.Node):
10286
- return valu.iden()
10376
+ return valu.buid
10377
+
10378
+ valu = await toprim(valu)
10379
+
10380
+ if isinstance(valu, str):
10381
+ if not s_common.isbuidhex(valu):
10382
+ mesg = f'Invalid buid string: {valu}'
10383
+ raise s_exc.BadCast(mesg=mesg)
10384
+
10385
+ return s_common.uhex(valu)
10386
+
10387
+ if not isinstance(valu, bytes):
10388
+ mesg = f'Invalid buid valu: {valu}'
10389
+ raise s_exc.BadCast(mesg=mesg)
10287
10390
 
10288
- valu = await tostr(valu)
10289
- if not s_common.isbuidhex(valu):
10290
- mesg = f'Invalid buid string: {valu}'
10391
+ if len(valu) != 32:
10392
+ mesg = f'Invalid buid valu: {valu}'
10291
10393
  raise s_exc.BadCast(mesg=mesg)
10292
10394
 
10293
10395
  return valu
10294
10396
 
10397
+ async def tobuidhex(valu, noneok=False):
10398
+
10399
+ if noneok and valu is None:
10400
+ return None
10401
+
10402
+ if isinstance(valu, str) and s_common.isbuidhex(valu):
10403
+ return valu
10404
+
10405
+ buid = await tobuid(valu)
10406
+ return s_common.ehex(buid)
10407
+
10295
10408
  async def totype(valu, basetypes=False) -> str:
10296
10409
  '''
10297
10410
  Convert a value to its Storm type string.
@@ -10335,5 +10448,10 @@ async def totype(valu, basetypes=False) -> str:
10335
10448
  async def typeerr(name, reqt):
10336
10449
  if not isinstance(name, reqt):
10337
10450
  styp = await totype(name, basetypes=True)
10338
- mesg = f"Expected value of type '{reqt}', got '{styp}' with value {name}."
10451
+
10452
+ reqtname = str(reqt)
10453
+ if (clsname := getattr(reqt, '__name__')):
10454
+ reqtname = clsname
10455
+
10456
+ mesg = f"Expected value of type '{reqtname}', got '{styp}' with value {name}."
10339
10457
  return s_exc.StormRuntimeError(mesg=mesg, name=name, type=styp)
synapse/lib/version.py CHANGED
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
223
223
  ##############################################################################
224
224
  # The following are touched during the release process by bumpversion.
225
225
  # Do not modify these directly.
226
- version = (2, 220, 0)
226
+ version = (2, 222, 0)
227
227
  verstring = '.'.join([str(x) for x in version])
228
- commit = '913156d6c195af916a32860341f285954cb4e882'
228
+ commit = '1ab0342cfb8272e9f9a629f1755b0e33b78b78b3'
synapse/models/orgs.py CHANGED
@@ -729,6 +729,9 @@ class OuModule(s_module.CoreModule):
729
729
 
730
730
  ('ext:id', ('str', {'strip': True}), {
731
731
  'doc': 'An external identifier for the technique.'}),
732
+
733
+ ('parent', ('ou:technique', {}), {
734
+ 'doc': 'The parent technique for the technique.'}),
732
735
  )),
733
736
  ('ou:technique:taxonomy', {}, ()),
734
737
  ('ou:orgtype', {}, ()),
@@ -1267,7 +1267,7 @@ _ParseResults = [
1267
1267
  'Query: [EditTagPropDel: [TagProp: [TagName: [Const: baz, Const: faz], Const: lol]]]',
1268
1268
  'Query: [EditTagPropSet: [TagProp: [TagName: [Const: baz, Const: faz], Const: lol], Const: =, Const: 20]]',
1269
1269
  'Query: [LiftTagProp: [TagProp: [TagName: [Const: tag], Const: somegeoloctypebecauseihatelife], Const: near=, List: [VarValue: [Const: lat], VarValue: [Const: long]]]]',
1270
- 'Query: [LiftPropBy: [VarValue: [Const: foo], Const: near=, Const: 20]]',
1270
+ 'Query: [LiftPropBy: [DerefProps: [VarValue: [Const: foo]], Const: near=, Const: 20]]',
1271
1271
  'Query: [EditNodeAdd: [FormName: [Const: test:str], Const: =, VarDeref: [VarDeref: [VarDeref: [VarDeref: [VarDeref: [VarValue: [Const: foo], Const: woot], Const: var], VarValue: [Const: bar]], Const: mar], VarValue: [Const: car]]]]',
1272
1272
  'Query: [LiftPropBy: [Const: test:str, Const: =, VarDeref: [VarDeref: [VarValue: [Const: foo], VarValue: [Const: space key]], Const: subkey]]]',
1273
1273
  'Query: [ForLoop: [Const: iterkey, VarDeref: [VarDeref: [VarValue: [Const: foo], VarValue: [Const: bar key]], VarValue: [Const: biz key]], SubQuery: [Query: [LiftPropBy: [Const: inet:ipv4, Const: =, VarDeref: [VarDeref: [VarDeref: [VarValue: [Const: foo], VarValue: [Const: bar key]], VarValue: [Const: biz key]], VarValue: [Const: iterkey]]]]]]]',
@@ -1337,11 +1337,11 @@ _ParseResults = [
1337
1337
  'Query: [VarEvalOper: [FuncCall: [VarDeref: [VarValue: [Const: lib], Const: print], CallArgs: [DollarExpr: [FuncCall: [VarDeref: [DollarExpr: [RelPropValue: [Const: prop]], Const: upper], CallArgs: [], CallKwargs: []]]], CallKwargs: []]]]',
1338
1338
  'Query: [VarEvalOper: [FuncCall: [VarDeref: [VarValue: [Const: lib], Const: print], CallArgs: [VarDeref: [DollarExpr: [ExprDict: [Const: unicode, Const: 1]], DollarExpr: [RelPropValue: [Const: prop]]]], CallKwargs: []]]]',
1339
1339
  'Query: [VarEvalOper: [FuncCall: [VarDeref: [VarValue: [Const: lib], Const: print], CallArgs: [DollarExpr: [ExprNode: [VarDeref: [DollarExpr: [ExprDict: [Const: unicode, Const: 1]], DollarExpr: [RelPropValue: [Const: prop]]], Const: +, DollarExpr: [Const: 2]]]], CallKwargs: []]]]',
1340
- 'Query: [LiftFormTag: [VarValue: [Const: form], TagName: [VarValue: [Const: tag]]]]',
1341
- 'Query: [LiftFormTagProp: [FormTagProp: [VarValue: [Const: form], TagName: [VarValue: [Const: tag]], VarValue: [Const: prop]]]]',
1340
+ 'Query: [LiftFormTag: [DerefProps: [VarValue: [Const: form]], TagName: [VarValue: [Const: tag]]]]',
1341
+ 'Query: [LiftFormTagProp: [FormTagProp: [DerefProps: [VarValue: [Const: form]], TagName: [VarValue: [Const: tag]], VarValue: [Const: prop]]]]',
1342
1342
  'Query: [LiftProp: [Const: inet:ipv4]]',
1343
1343
  'Query: [LiftPropBy: [Const: inet:ipv4, Const: =, Const: 1.2.3.4]]',
1344
- 'Query: [LiftPropBy: [VarValue: [Const: form], Const: =, VarValue: [Const: valu]]]',
1344
+ 'Query: [LiftPropBy: [DerefProps: [VarValue: [Const: form]], Const: =, VarValue: [Const: valu]]]',
1345
1345
  'Query: [LiftPropBy: [Const: test:str, Const: =, Const: foobar], FormPivot: [Const: inet:dns*], isjoin=False]',
1346
1346
  'Query: [LiftPropBy: [Const: test:str, Const: =, Const: foobar], FormPivot: [Const: inet:dns:*], isjoin=False]',
1347
1347
  'Query: [LiftPropBy: [Const: test:str, Const: =, Const: foobar], FormPivot: [List: [Const: meta:source, Const: inet:dns:a]], isjoin=False]',