synapse 2.219.0__py311-none-any.whl → 2.221.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 (55) hide show
  1. synapse/data/__init__.py +4 -0
  2. synapse/data/lark/__init__.py +0 -0
  3. synapse/data/lark/imap.lark +8 -0
  4. synapse/exc.py +2 -0
  5. synapse/lib/json.py +6 -5
  6. synapse/lib/layer.py +134 -0
  7. synapse/lib/link.py +49 -50
  8. synapse/lib/parser.py +3 -5
  9. synapse/lib/rstorm.py +65 -2
  10. synapse/lib/snap.py +21 -13
  11. synapse/lib/storm.py +1 -0
  12. synapse/lib/stormhttp.py +10 -10
  13. synapse/lib/stormlib/aha.py +3 -3
  14. synapse/lib/stormlib/auth.py +11 -11
  15. synapse/lib/stormlib/cell.py +1 -1
  16. synapse/lib/stormlib/cortex.py +9 -9
  17. synapse/lib/stormlib/env.py +4 -5
  18. synapse/lib/stormlib/ethereum.py +1 -1
  19. synapse/lib/stormlib/gen.py +3 -3
  20. synapse/lib/stormlib/hex.py +2 -2
  21. synapse/lib/stormlib/imap.py +478 -37
  22. synapse/lib/stormlib/infosec.py +2 -2
  23. synapse/lib/stormlib/iters.py +2 -2
  24. synapse/lib/stormlib/model.py +5 -5
  25. synapse/lib/stormlib/notifications.py +1 -1
  26. synapse/lib/stormlib/oauth.py +2 -2
  27. synapse/lib/stormlib/project.py +3 -3
  28. synapse/lib/stormlib/scrape.py +2 -1
  29. synapse/lib/stormlib/smtp.py +3 -3
  30. synapse/lib/stormlib/stats.py +2 -2
  31. synapse/lib/stormlib/stix.py +2 -2
  32. synapse/lib/stormlib/utils.py +19 -0
  33. synapse/lib/stormlib/vault.py +1 -1
  34. synapse/lib/stormlib/xml.py +2 -2
  35. synapse/lib/stormlib/yaml.py +1 -1
  36. synapse/lib/stormtypes.py +203 -60
  37. synapse/lib/version.py +2 -2
  38. synapse/tests/test_lib_grammar.py +2 -4
  39. synapse/tests/test_lib_json.py +29 -0
  40. synapse/tests/test_lib_layer.py +86 -67
  41. synapse/tests/test_lib_rstorm.py +132 -0
  42. synapse/tests/test_lib_storm.py +11 -1
  43. synapse/tests/test_lib_stormlib_env.py +3 -1
  44. synapse/tests/test_lib_stormlib_imap.py +1307 -230
  45. synapse/tests/test_lib_stormlib_utils.py +10 -0
  46. synapse/tests/test_lib_stormtypes.py +583 -2
  47. synapse/tools/aha/list.py +9 -9
  48. synapse/tools/aha/provision/service.py +2 -2
  49. synapse/utils/stormcov/plugin.py +2 -5
  50. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/METADATA +1 -2
  51. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/RECORD +55 -53
  52. /synapse/{lib → data/lark}/storm.lark +0 -0
  53. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/WHEEL +0 -0
  54. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/licenses/LICENSE +0 -0
  55. {synapse-2.219.0.dist-info → synapse-2.221.0.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,18 @@
1
1
  import synapse.exc as s_exc
2
+ import synapse.common as s_common
3
+
2
4
  import synapse.tests.utils as s_test
3
5
 
4
6
  class UtilsTest(s_test.SynTest):
5
7
 
8
+ async def test_lib_stormlib_utils_buid(self):
9
+ async with self.getTestCore() as core:
10
+ obj = ('meta:source', '0123456789abcdef0123456789abcdef')
11
+ self.eq(
12
+ await core.callStorm('return($lib.utils.buid($obj))', opts={'vars': {'obj': obj}}),
13
+ s_common.buid(obj)
14
+ )
15
+
6
16
  async def test_lib_stormlib_utils_todo(self):
7
17
 
8
18
  async with self.getTestCore() as core:
@@ -17,6 +17,7 @@ import synapse.axon as s_axon
17
17
  import synapse.common as s_common
18
18
 
19
19
  import synapse.lib.json as s_json
20
+ import synapse.lib.node as s_node
20
21
  import synapse.lib.time as s_time
21
22
  import synapse.lib.storm as s_storm
22
23
  import synapse.lib.hashset as s_hashset
@@ -884,13 +885,32 @@ class StormTypesTest(s_test.SynTest):
884
885
  self.eq(2, await core.callStorm('return($lib.len($lib.layer.get().getStorNodes()))', opts=opts))
885
886
 
886
887
  await core.nodes('[ media:news=c0dc5dc1f7c3d27b725ef3015422f8e2 +(refs)> { inet:ipv4=1.2.3.4 } ]')
888
+ expN1 = [('refs', '20153b758f9d5eaaa38e4f4a65c36da797c3e59e549620fa7c4895e1a920991f')]
889
+ expN2 = [('refs', 'ddf7f87c0164d760e8e1e5cd2cae2fee96868a3cf184f6dab9154e31ad689528')]
890
+
887
891
  edges = await core.callStorm('''
888
892
  $edges = ([])
889
893
  media:news=c0dc5dc1f7c3d27b725ef3015422f8e2
890
894
  for $i in $lib.layer.get().getEdgesByN1($node.iden()) { $edges.append($i) }
891
895
  fini { return($edges) }
892
896
  ''')
893
- self.eq([('refs', '20153b758f9d5eaaa38e4f4a65c36da797c3e59e549620fa7c4895e1a920991f')], edges)
897
+ self.eq(expN1, edges)
898
+
899
+ edges = await core.callStorm('''
900
+ $edges = ([])
901
+ media:news=c0dc5dc1f7c3d27b725ef3015422f8e2
902
+ for $i in $lib.layer.get().getEdgesByN1($node.iden(), verb=refs) { $edges.append($i) }
903
+ fini { return($edges) }
904
+ ''')
905
+ self.eq(expN1, edges)
906
+
907
+ edges = await core.callStorm('''
908
+ $edges = ([])
909
+ media:news=c0dc5dc1f7c3d27b725ef3015422f8e2
910
+ for $i in $lib.layer.get().getEdgesByN1($node.iden(), verb=newp) { $edges.append($i) }
911
+ fini { return($edges) }
912
+ ''')
913
+ self.eq([], edges)
894
914
 
895
915
  edges = await core.callStorm('''
896
916
  $edges = ([])
@@ -898,7 +918,37 @@ class StormTypesTest(s_test.SynTest):
898
918
  for $i in $lib.layer.get().getEdgesByN2($node.iden()) { $edges.append($i) }
899
919
  fini { return($edges) }
900
920
  ''')
901
- self.eq([('refs', 'ddf7f87c0164d760e8e1e5cd2cae2fee96868a3cf184f6dab9154e31ad689528')], edges)
921
+ self.eq(expN2, edges)
922
+
923
+ edges = await core.callStorm('''
924
+ $edges = ([])
925
+ inet:ipv4=1.2.3.4
926
+ for $i in $lib.layer.get().getEdgesByN2($node.iden(), verb=refs) { $edges.append($i) }
927
+ fini { return($edges) }
928
+ ''')
929
+ self.eq(expN2, edges)
930
+
931
+ edges = await core.callStorm('''
932
+ $edges = ([])
933
+ inet:ipv4=1.2.3.4
934
+ for $i in $lib.layer.get().getEdgesByN2($node.iden(), verb=newp) { $edges.append($i) }
935
+ fini { return($edges) }
936
+ ''')
937
+ self.eq([], edges)
938
+
939
+ ret = await core.callStorm('''
940
+ $n1 = { media:news=c0dc5dc1f7c3d27b725ef3015422f8e2 return($node.iden()) }
941
+ $n2 = { inet:ipv4=1.2.3.4 return($node.iden()) }
942
+ return($lib.layer.get().hasEdge($n1, refs, $n2))
943
+ ''')
944
+ self.true(ret)
945
+
946
+ ret = await core.callStorm('''
947
+ $n1 = { media:news=c0dc5dc1f7c3d27b725ef3015422f8e2 return($node.iden()) }
948
+ $n2 = { inet:ipv4=1.2.3.4 return($node.iden()) }
949
+ return($lib.layer.get().hasEdge($n1, newp, $n2))
950
+ ''')
951
+ self.false(ret)
902
952
 
903
953
  edges = await core.callStorm('''
904
954
  $edges = ([])
@@ -1538,6 +1588,38 @@ class StormTypesTest(s_test.SynTest):
1538
1588
  with self.raises(s_exc.BadJsonText):
1539
1589
  await core.callStorm(q, opts={'vars': {'buf': b'lol{newp,', 'encoding': None}})
1540
1590
 
1591
+ async def test_storm_lib_bytes_xor(self):
1592
+ async with self.getTestCore() as core:
1593
+ encval = await core.callStorm("return(('foobar').encode().xor(asdf))")
1594
+ self.eq(encval, b'\x07\x1c\x0b\x04\x00\x01')
1595
+
1596
+ decval = await core.callStorm("return($foo.xor(asdf).decode())", opts={'vars': {'foo': encval}})
1597
+ self.eq(decval, 'foobar')
1598
+
1599
+ encval = await core.callStorm("return(('foofoo').encode().xor(v))")
1600
+ self.eq(encval, b'\x10\x19\x19\x10\x19\x19')
1601
+
1602
+ encval = await core.callStorm("$key=$lib.base64.decode('AA==') return(('foofoo').encode().xor($key))")
1603
+ self.eq(encval, b'foofoo')
1604
+
1605
+ encval = await core.callStorm("$key=$lib.base64.decode('/w==') return(('foofoo').encode().xor($key))")
1606
+ self.eq(encval, b'\x99\x90\x90\x99\x90\x90')
1607
+
1608
+ encval = await core.callStorm("$key=$lib.base64.decode('/w==') return(('foofoo').encode().xor($key).xor($key))")
1609
+ self.eq(encval, b'foofoo')
1610
+
1611
+ encval = await core.callStorm("return(('v').encode().xor(foo))")
1612
+ self.eq(encval, b'\x10')
1613
+
1614
+ encval = await core.callStorm("return(('').encode().xor(foo))")
1615
+ self.eq(encval, b'')
1616
+
1617
+ with self.raises(s_exc.BadArg):
1618
+ await core.callStorm("return(('foobar').encode().xor(''))")
1619
+
1620
+ with self.raises(s_exc.BadArg):
1621
+ await core.callStorm("return(('foobar').encode().xor((123)))")
1622
+
1541
1623
  async def test_storm_lib_list(self):
1542
1624
  async with self.getTestCore() as core:
1543
1625
  # Base List object behavior
@@ -1735,6 +1817,435 @@ class StormTypesTest(s_test.SynTest):
1735
1817
  await visi.addRule((True, ('layer', 'read')), gateiden=layriden)
1736
1818
  await core.callStorm('return($lib.layer.get($layriden).getStorNode($iden))', opts=opts)
1737
1819
 
1820
+ async def test_storm_layer_getstornodesbyprop(self):
1821
+ async with self.getTestCore() as core:
1822
+ nodes = await core.nodes('[ test:str=foobar :hehe=foobaz ]')
1823
+ self.len(1, nodes)
1824
+
1825
+ buid00 = nodes[0].iden()
1826
+ sode00 = {
1827
+ 'form': 'test:str',
1828
+ 'props': {
1829
+ '.created': (nodes[0].get('.created'), 21),
1830
+ 'hehe': ('foobaz', 1)
1831
+ },
1832
+ 'valu': ('foobar', 1),
1833
+ }
1834
+ expval00 = (buid00, sode00)
1835
+
1836
+ nodes = await core.nodes('[ test:str=boobar :hehe=boobaz ]')
1837
+ self.len(1, nodes)
1838
+
1839
+ buid01 = nodes[0].iden()
1840
+ sode01 = {
1841
+ 'form': 'test:str',
1842
+ 'props': {
1843
+ '.created': (nodes[0].get('.created'), 21),
1844
+ 'hehe': ('boobaz', 1)
1845
+ },
1846
+ 'valu': ('boobar', 1),
1847
+ }
1848
+ expval01 = (buid01, sode01)
1849
+
1850
+ # just prop
1851
+ q = '''
1852
+ $sodes = ([])
1853
+ for ($buid, $sode) in $lib.layer.get().getStorNodesByProp(test:str:hehe) {
1854
+ $sodes.append(($buid, $sode))
1855
+ }
1856
+ return($sodes)
1857
+ '''
1858
+ sodes = await core.callStorm(q)
1859
+ self.len(2, sodes)
1860
+ self.sorteq(sodes, (expval00, expval01))
1861
+
1862
+ # prop with propvalu
1863
+ q = '''
1864
+ $sodes = ([])
1865
+ for ($buid, $sode) in $lib.layer.get().getStorNodesByProp(test:str:hehe, propvalu=foobaz) {
1866
+ $sodes.append(($buid, $sode))
1867
+ }
1868
+ return($sodes)
1869
+ '''
1870
+ sodes = await core.callStorm(q)
1871
+ self.len(1, sodes)
1872
+ self.eq(sodes[0], expval00)
1873
+
1874
+ # just form
1875
+ q = '''
1876
+ $sodes = ([])
1877
+ for ($buid, $sode) in $lib.layer.get().getStorNodesByProp(test:str) {
1878
+ $sodes.append(($buid, $sode))
1879
+ }
1880
+ return($sodes)
1881
+ '''
1882
+ sodes = await core.callStorm(q)
1883
+ self.len(2, sodes)
1884
+ self.sorteq(sodes, (expval00, expval01))
1885
+
1886
+ # form with valu
1887
+ q = '''
1888
+ $sodes = ([])
1889
+ for ($buid, $sode) in $lib.layer.get().getStorNodesByProp(test:str, propvalu=boobar) {
1890
+ $sodes.append(($buid, $sode))
1891
+ }
1892
+ return($sodes)
1893
+ '''
1894
+ sodes = await core.callStorm(q)
1895
+ self.len(1, sodes)
1896
+ self.eq(sodes[0], expval01)
1897
+
1898
+ # Non-existent prop
1899
+ msgs = await core.stormlist('for $item in $lib.layer.get().getStorNodesByProp(test:str:_custom) {}')
1900
+ self.stormIsInErr('The property test:str:_custom does not exist.', msgs)
1901
+
1902
+ async def test_storm_layer_setstornodeprop(self):
1903
+ async with self.getTestCore() as core:
1904
+
1905
+ nodes = await core.nodes('[ test:str=foo :hehe=bar ]')
1906
+ self.len(1, nodes)
1907
+ self.eq(nodes[0].repr(), 'foo')
1908
+ self.eq(nodes[0].get('hehe'), 'bar')
1909
+
1910
+ msgs = await core.stormlist('test:str $lib.layer.get().setStorNodeProp($node.iden(), test:str:hehe, baz)')
1911
+ self.stormHasNoWarnErr(msgs)
1912
+
1913
+ nodes = await core.nodes('test:str')
1914
+ self.len(1, nodes)
1915
+ self.eq(nodes[0].repr(), 'foo')
1916
+ self.eq(nodes[0].get('hehe'), 'baz')
1917
+
1918
+ # no test:str:newp prop
1919
+ q = '''
1920
+ [ test:str=foobar00 ]
1921
+ $lib.layer.get().setStorNodeProp($node.iden(), test:str:newp, bar00)
1922
+ '''
1923
+ msgs = await core.stormlist(q)
1924
+ self.stormIsInErr('No property named test:str:newp.', msgs)
1925
+
1926
+ # Bad type
1927
+ msgs = await core.stormlist('[ test:str=foobar01 ] $lib.layer.get().setStorNodeProp($node.iden(), test:str:tick, newp)')
1928
+ self.stormIsInErr('Unknown time format for newp', msgs)
1929
+
1930
+ # insufficient perms
1931
+ lowuser = await core.auth.addUser('lowuser')
1932
+ await lowuser.addRule((True, ('node', 'add', 'test:str')))
1933
+
1934
+ q = '''
1935
+ [ test:str=foobar02 ]
1936
+ $lib.layer.get().setStorNodeProp($node.iden(), test:str:hehe, baz02)
1937
+ '''
1938
+ msgs = await core.stormlist(q, opts={'user': lowuser.iden})
1939
+ self.stormIsInErr('setStorNodeProp() requires admin privileges.', msgs)
1940
+
1941
+ # readonly layer
1942
+ layer = core.view.layers[0]
1943
+ await layer.setLayerInfo('readonly', True)
1944
+ msgs = await core.stormlist('test:str $lib.layer.get().setStorNodeProp($node.iden(), test:str:hehe, baz)')
1945
+ self.stormIsInErr(f'Layer {layer.iden} is read only!', msgs)
1946
+
1947
+ async def test_storm_layer_delstornode(self):
1948
+ async with self.getTestCore() as core:
1949
+ await core.addTagProp('score00', ('int', {}), {})
1950
+ await core.addTagProp('score01', ('int', {}), {})
1951
+ q = '''
1952
+ [ test:str=foo
1953
+ :hehe=bar
1954
+ +#foo
1955
+ +#foo.bar=now
1956
+ +#foo.baz:score00=10
1957
+ +#foo.baz:score01=20
1958
+
1959
+ <(seen)+ {[ meta:source=* :name=seen]}
1960
+ +(refs)> {[ meta:source=* :name=refs]}
1961
+ ]
1962
+
1963
+ $node.data.set(foo, foo)
1964
+ $node.data.set(bar, bar)
1965
+ $node.data.set(baz, baz)
1966
+ '''
1967
+ nodes = await core.nodes(q)
1968
+ self.len(1, nodes)
1969
+ opts = {'vars': {'iden': nodes[0].iden()}}
1970
+ created = nodes[0].get('.created')
1971
+ foobar = nodes[0].get('#foo.bar')
1972
+
1973
+ sode = await core.callStorm('return($lib.layer.get().getStorNode($iden))', opts=opts)
1974
+ self.eq(sode, {
1975
+ 'form': 'test:str',
1976
+ 'props': {'.created': (created, 21), 'hehe': ('bar', 1)},
1977
+ 'tagprops': {
1978
+ 'foo.baz': {
1979
+ 'score00': (10, 9),
1980
+ 'score01': (20, 9)
1981
+ }
1982
+ },
1983
+ 'tags': {
1984
+ 'foo': (None, None),
1985
+ 'foo.bar': foobar,
1986
+ 'foo.baz': (None, None)
1987
+ },
1988
+ 'valu': ('foo', 1)
1989
+ })
1990
+
1991
+ msgs = await core.stormlist('$lib.layer.get().delStorNode($iden)', opts=opts)
1992
+ self.stormHasNoWarnErr(msgs)
1993
+
1994
+ sode = await core.callStorm('return($lib.layer.get().getStorNode($iden))', opts=opts)
1995
+ self.eq(sode, {})
1996
+
1997
+ q = '''
1998
+ $data = ([])
1999
+ for $item in $lib.layer.get().getNodeData($iden) {
2000
+ $data.append($item)
2001
+ }
2002
+ return($data)
2003
+ '''
2004
+ nodedata = await core.callStorm(q, opts=opts)
2005
+ self.len(0, nodedata)
2006
+
2007
+ q = '''
2008
+ $edges = ([])
2009
+ for $edge in $lib.layer.get().getEdgesByN1($iden) {
2010
+ $edges.append($edge)
2011
+ }
2012
+ for $edge in $lib.layer.get().getEdgesByN2($iden) {
2013
+ $edges.append($edge)
2014
+ }
2015
+ return($edges)
2016
+ '''
2017
+ edges = await core.callStorm(q, opts=opts)
2018
+ self.len(0, edges)
2019
+
2020
+ self.false(await core.callStorm('return($lib.layer.get().delStorNode($iden))', opts=opts))
2021
+
2022
+ # insufficient perms
2023
+ lowuser = await core.auth.addUser('lowuser')
2024
+ await lowuser.addRule((True, ('node', 'add', 'test:str')))
2025
+
2026
+ q = '''
2027
+ [ test:str=foobar02 ]
2028
+ $lib.layer.get().delStorNode($node.iden())
2029
+ '''
2030
+ msgs = await core.stormlist(q, opts={'user': lowuser.iden})
2031
+ self.stormIsInErr('delStorNode() requires admin privileges.', msgs)
2032
+
2033
+ # Readonly layer
2034
+ nodes = await core.nodes('[ test:str=foobar ]')
2035
+ self.len(1, nodes)
2036
+ self.eq(nodes[0].repr(), 'foobar')
2037
+ layer = core.view.layers[0]
2038
+ await layer.setLayerInfo('readonly', True)
2039
+ msgs = await core.stormlist('test:str $lib.layer.get().delStorNode($node.iden())')
2040
+ self.stormIsInErr(f'Layer {layer.iden} is read only!', msgs)
2041
+
2042
+ async def test_storm_layer_delstornodeprop(self):
2043
+ async with self.getTestCore() as core:
2044
+ nodes = await core.nodes('[ test:str=foo :hehe=bar ]')
2045
+ self.len(1, nodes)
2046
+ self.eq(nodes[0].repr(), 'foo')
2047
+ self.eq(nodes[0].get('hehe'), 'bar')
2048
+
2049
+ msgs = await core.stormlist('test:str $lib.layer.get().delStorNodeProp($node.iden(), test:str:hehe)')
2050
+ self.stormHasNoWarnErr(msgs)
2051
+
2052
+ nodes = await core.nodes('test:str')
2053
+ self.len(1, nodes)
2054
+ self.eq(nodes[0].repr(), 'foo')
2055
+ self.none(nodes[0].get('hehe'))
2056
+
2057
+ # no test:str:newp prop
2058
+ q = '''
2059
+ [ test:str=foobar00 ]
2060
+ $lib.layer.get().delStorNodeProp($node.iden(), test:str:newp)
2061
+ '''
2062
+ msgs = await core.stormlist(q)
2063
+ self.stormIsInErr('No property named test:str:newp.', msgs)
2064
+
2065
+ # insufficient perms
2066
+ lowuser = await core.auth.addUser('lowuser')
2067
+ await lowuser.addRule((True, ('node', 'add', 'test:str')))
2068
+
2069
+ q = '''
2070
+ [ test:str=foobar02 ]
2071
+ $lib.layer.get().delStorNodeProp($node.iden(), test:str:hehe)
2072
+ '''
2073
+ msgs = await core.stormlist(q, opts={'user': lowuser.iden})
2074
+ self.stormIsInErr('delStorNodeProp() requires admin privileges.', msgs)
2075
+
2076
+ # Readonly layer
2077
+ layer = core.view.layers[0]
2078
+ await layer.setLayerInfo('readonly', True)
2079
+ msgs = await core.stormlist('test:str $lib.layer.get().delStorNodeProp($node.iden(), test:str:hehe)')
2080
+ self.stormIsInErr(f'Layer {layer.iden} is read only!', msgs)
2081
+
2082
+ async def test_storm_layer_delnodedata(self):
2083
+ async with self.getTestCore() as core:
2084
+ q = '''
2085
+ $_ = { [test:str=foo] $node.data.set(foo, woot) }
2086
+ $_ = { [test:str=bar] $node.data.set(bar00, woot00) $node.data.set(bar01, woot01)}
2087
+ $_ = { [test:str=baz] $node.data.set(baz, woot) }
2088
+ '''
2089
+ msgs = await core.stormlist(q)
2090
+ self.stormHasNoWarnErr(msgs)
2091
+
2092
+ nodes = await core.nodes('test:str=foo')
2093
+ self.len(1, nodes)
2094
+ self.eq(nodes[0].repr(), 'foo')
2095
+ self.eq(await s_test.alist(nodes[0].iterData()), [('foo', 'woot')])
2096
+
2097
+ # Delete specific nodedata key
2098
+ msgs = await core.stormlist('test:str $lib.layer.get().delNodeData($node, foo)')
2099
+ self.stormHasNoWarnErr(msgs)
2100
+
2101
+ nodes = await core.nodes('test:str=foo')
2102
+ self.len(1, nodes)
2103
+ self.len(0, await s_test.alist(nodes[0].iterData()))
2104
+
2105
+ nodes = await core.nodes('test:str=bar')
2106
+ self.len(1, nodes)
2107
+ self.eq(nodes[0].repr(), 'bar')
2108
+ self.eq(await s_test.alist(nodes[0].iterData()), [('bar00', 'woot00'), ('bar01', 'woot01')])
2109
+
2110
+ # Delete all nodedata
2111
+ msgs = await core.stormlist('test:str=bar $lib.layer.get().delNodeData($node)')
2112
+ self.stormHasNoWarnErr(msgs)
2113
+
2114
+ nodes = await core.nodes('test:str=bar')
2115
+ self.len(1, nodes)
2116
+ self.len(0, await s_test.alist(nodes[0].iterData()))
2117
+
2118
+ # No edits to make
2119
+ self.false(await core.callStorm('test:str=bar return($lib.layer.get().delNodeData($node))'))
2120
+
2121
+ # insufficient perms
2122
+ lowuser = await core.auth.addUser('lowuser')
2123
+ await lowuser.addRule((True, ('node', 'add', 'test:str')))
2124
+
2125
+ q = '''
2126
+ test:str
2127
+ $lib.layer.get().delNodeData($node)
2128
+ '''
2129
+ msgs = await core.stormlist(q, opts={'user': lowuser.iden})
2130
+ self.stormIsInErr('delNodeData() requires admin privileges.', msgs)
2131
+
2132
+ # Readonly layer
2133
+ layer = core.view.layers[0]
2134
+ await layer.setLayerInfo('readonly', True)
2135
+ msgs = await core.stormlist('test:str=baz $lib.layer.get().delNodeData($node)')
2136
+ self.stormIsInErr(f'Layer {layer.iden} is read only!', msgs)
2137
+
2138
+ async def test_storm_layer_delnodeedge(self):
2139
+ async with self.getTestCore() as core:
2140
+ q = '''
2141
+ $seen00 = { [ meta:source=* :name=delnodeedge00 ] }
2142
+ $seen01 = { [ meta:source=* :name=delnodeedge01 ] }
2143
+ $refs = { [ it:dev:str=foobar ] }
2144
+ $_ = { [test:str=foo <(seen)+ $seen00 <(seen)+ $seen01]}
2145
+ $_ = { [test:str=bar <(seen)+ $seen00 +(refs)> $refs] }
2146
+ $_ = { [test:str=baz] }
2147
+ $_ = { [test:str=woot <(seen)+ $seen00 +(refs)> $refs] }
2148
+ '''
2149
+ msgs = await core.stormlist(q)
2150
+ self.stormHasNoWarnErr(msgs)
2151
+
2152
+ nodes = await core.nodes('meta:source:name=delnodeedge00')
2153
+ self.len(1, nodes)
2154
+ seen00 = nodes[0]
2155
+
2156
+ nodes = await core.nodes('meta:source:name=delnodeedge01')
2157
+ self.len(1, nodes)
2158
+ seen01 = nodes[0]
2159
+
2160
+ nodes = await core.nodes('it:dev:str=foobar')
2161
+ self.len(1, nodes)
2162
+ refs = nodes[0]
2163
+
2164
+ # Delete n2 edge
2165
+ nodes = await core.nodes('test:str=foo')
2166
+ self.len(1, nodes)
2167
+ self.len(0, await s_test.alist(nodes[0].iterEdgesN1()))
2168
+ self.sorteq(await s_test.alist(nodes[0].iterEdgesN2()), [('seen', seen00.iden()), ('seen', seen01.iden())])
2169
+
2170
+ q = '''
2171
+ $seen00 = { meta:source:name=delnodeedge00 }
2172
+ test:str=foo
2173
+ $lib.layer.get().delEdge($seen00, seen, $node)
2174
+ '''
2175
+ msgs = await core.stormlist(q)
2176
+ self.stormHasNoWarnErr(msgs)
2177
+
2178
+ nodes = await core.nodes('test:str=foo')
2179
+ self.len(1, nodes)
2180
+ self.len(0, await s_test.alist(nodes[0].iterEdgesN1()))
2181
+ self.eq(await s_test.alist(nodes[0].iterEdgesN2()), [('seen', seen01.iden())])
2182
+
2183
+ # Delete n1 edge
2184
+ nodes = await core.nodes('test:str=bar')
2185
+ self.len(1, nodes)
2186
+ self.sorteq(await s_test.alist(nodes[0].iterEdgesN1()), [('refs', refs.iden())])
2187
+ self.sorteq(await s_test.alist(nodes[0].iterEdgesN2()), [('seen', seen00.iden())])
2188
+
2189
+ q = '''
2190
+ $refs = { it:dev:str=foobar }
2191
+ test:str=bar
2192
+ $lib.layer.get().delEdge($node, refs, $refs)
2193
+ '''
2194
+ msgs = await core.stormlist(q)
2195
+ self.stormHasNoWarnErr(msgs)
2196
+
2197
+ nodes = await core.nodes('test:str=bar')
2198
+ self.len(1, nodes)
2199
+ self.len(0, await s_test.alist(nodes[0].iterEdgesN1()))
2200
+ self.eq(await s_test.alist(nodes[0].iterEdgesN2()), [('seen', seen00.iden())])
2201
+
2202
+ # No edits to make
2203
+ nodes = await core.nodes('test:str=baz')
2204
+ self.len(1, nodes)
2205
+ self.len(0, await s_test.alist(nodes[0].iterEdgesN1()))
2206
+ self.len(0, await s_test.alist(nodes[0].iterEdgesN2()))
2207
+
2208
+ q = '''
2209
+ $refs = { it:dev:str=foobar }
2210
+ test:str=baz
2211
+ $lib.layer.get().delEdge($node, refs, $refs)
2212
+ '''
2213
+ msgs = await core.stormlist(q)
2214
+ self.stormHasNoWarnErr(msgs)
2215
+
2216
+ # insufficient perms
2217
+ lowuser = await core.auth.addUser('lowuser')
2218
+ await lowuser.addRule((True, ('node', 'add', 'test:str')))
2219
+
2220
+ nodes = await core.nodes('test:str=woot')
2221
+ self.len(1, nodes)
2222
+ self.len(1, await s_test.alist(nodes[0].iterEdgesN1()))
2223
+ self.len(1, await s_test.alist(nodes[0].iterEdgesN2()))
2224
+
2225
+ q = '''
2226
+ $seen = { meta:source:name=delnodeedge00 }
2227
+ test:str=woot
2228
+ $lib.layer.get().delEdge($seen, seen, $node)
2229
+ '''
2230
+ msgs = await core.stormlist(q, opts={'user': lowuser.iden})
2231
+ self.stormIsInErr('delEdge() requires admin privileges.', msgs)
2232
+
2233
+ nodes = await core.nodes('test:str=woot')
2234
+ self.len(1, nodes)
2235
+ self.len(1, await s_test.alist(nodes[0].iterEdgesN1()))
2236
+ self.len(1, await s_test.alist(nodes[0].iterEdgesN2()))
2237
+
2238
+ # Readonly layer
2239
+ layer = core.view.layers[0]
2240
+ await layer.setLayerInfo('readonly', True)
2241
+ msgs = await core.stormlist(q)
2242
+ self.stormIsInErr(f'Layer {layer.iden} is read only!', msgs)
2243
+
2244
+ nodes = await core.nodes('test:str=woot')
2245
+ self.len(1, nodes)
2246
+ self.len(1, await s_test.alist(nodes[0].iterEdgesN1()))
2247
+ self.len(1, await s_test.alist(nodes[0].iterEdgesN2()))
2248
+
1738
2249
  async def test_storm_lib_fire(self):
1739
2250
  async with self.getTestCore() as core:
1740
2251
  text = '$lib.fire(foo:bar, baz=faz)'
@@ -5639,6 +6150,76 @@ class StormTypesTest(s_test.SynTest):
5639
6150
  q = '$tally = $lib.stats.tally() $tally.inc(foo) $tally.inc(foo) return($tally)'
5640
6151
  self.eq({'foo': 2}, await core.callStorm(q))
5641
6152
 
6153
+ async def test_stormtypes_tobuid(self):
6154
+ async with self.getTestCore() as core:
6155
+
6156
+ buid = s_common.buid()
6157
+ sode = (
6158
+ buid,
6159
+ {
6160
+ 'ndef': ('it:dev:str', 'foobar'),
6161
+ }
6162
+ )
6163
+
6164
+ async with await core.snap() as snap:
6165
+ node = s_node.Node(snap, sode)
6166
+ snode = s_stormtypes.Node(node)
6167
+
6168
+ self.eq(await s_stormtypes.tobuid(node), buid)
6169
+ self.eq(await s_stormtypes.tobuid(snode), buid)
6170
+
6171
+ self.eq(await s_stormtypes.tobuid(buid.hex()), buid)
6172
+ self.eq(await s_stormtypes.tobuid(buid), buid)
6173
+
6174
+ with self.raises(s_exc.BadCast) as exc:
6175
+ await s_stormtypes.tobuid('newp')
6176
+ self.eq(exc.exception.get('mesg'), 'Invalid buid string: newp')
6177
+
6178
+ with self.raises(s_exc.BadCast) as exc:
6179
+ await s_stormtypes.tobuid([])
6180
+ self.eq(exc.exception.get('mesg'), 'Invalid buid valu: ()')
6181
+
6182
+ with self.raises(s_exc.BadCast) as exc:
6183
+ await s_stormtypes.tobuid(b'newp')
6184
+ self.eq(exc.exception.get('mesg'), "Invalid buid valu: b'newp'")
6185
+
6186
+ async def test_stormtypes_tobuidhex(self):
6187
+ async with self.getTestCore() as core:
6188
+
6189
+ self.none(await s_stormtypes.tobuidhex(None, noneok=True))
6190
+
6191
+ buid = s_common.buid()
6192
+ buidhex = s_common.ehex(buid)
6193
+ sode = (
6194
+ buid,
6195
+ {
6196
+ 'ndef': ('it:dev:str', 'foobar'),
6197
+ }
6198
+ )
6199
+
6200
+ async with await core.snap() as snap:
6201
+ node = s_node.Node(snap, sode)
6202
+ snode = s_stormtypes.Node(node)
6203
+
6204
+ self.eq(await s_stormtypes.tobuidhex(node), buidhex)
6205
+ self.eq(await s_stormtypes.tobuidhex(snode), buidhex)
6206
+
6207
+ self.eq(await s_stormtypes.tobuidhex(buidhex), buidhex)
6208
+ self.eq(await s_stormtypes.tobuidhex(buid), buidhex)
6209
+
6210
+ with self.raises(s_exc.BadCast) as exc:
6211
+ await s_stormtypes.tobuidhex('newp')
6212
+ self.eq(exc.exception.get('mesg'), 'Invalid buid string: newp')
6213
+
6214
+ with self.raises(s_exc.BadCast) as exc:
6215
+ await s_stormtypes.tobuidhex([])
6216
+ self.eq(exc.exception.get('mesg'), 'Invalid buid valu: ()')
6217
+
6218
+ newp = b'newp'
6219
+ with self.raises(s_exc.BadCast) as exc:
6220
+ await s_stormtypes.tobuidhex(newp)
6221
+ self.eq(exc.exception.get('mesg'), "Invalid buid valu: b'newp'")
6222
+
5642
6223
  async def test_print_warn(self):
5643
6224
  async with self.getTestCore() as core:
5644
6225
  q = '$lib.print(hello)'
synapse/tools/aha/list.py CHANGED
@@ -7,14 +7,17 @@ import synapse.lib.version as s_version
7
7
 
8
8
  reqver = '>=2.11.0,<3.0.0'
9
9
 
10
+ descr = 'List AHA services.'
11
+
10
12
  async def main(argv, outp=s_output.stdout):
11
13
 
12
- if len(argv) not in (1, 2):
13
- outp.printf('usage: python -m synapse.tools.aha.list <url> [network name]')
14
- return 1
14
+ pars = s_cmd.Parser(prog='synapse.tools.aha.list', outp=outp, description=descr)
15
+ pars.add_argument('url', help='The telepath URL to connect to the AHA service.')
16
+ pars.add_argument('network', nargs='?', default=None, help='The AHA network name.')
17
+ opts = pars.parse_args(argv)
15
18
 
16
19
  async with s_telepath.withTeleEnv():
17
- async with await s_telepath.openurl(argv[0]) as prox:
20
+ async with await s_telepath.openurl(opts.url) as prox:
18
21
  try:
19
22
  s_version.reqVersion(prox._getSynVers(), reqver)
20
23
  except s_exc.BadVersion as e: # pragma: no cover
@@ -23,13 +26,10 @@ async def main(argv, outp=s_output.stdout):
23
26
  return 1
24
27
  classes = prox._getClasses()
25
28
  if 'synapse.lib.aha.AhaApi' not in classes:
26
- outp.printf(f'Service at {argv[0]} is not an Aha server')
29
+ outp.printf(f'Service at {opts.url} is not an Aha server')
27
30
  return 1
28
31
 
29
- try:
30
- network = argv[1]
31
- except IndexError:
32
- network = None
32
+ network = opts.network
33
33
 
34
34
  mesg = f"{'Service':<20s} {'network':<30s} {'leader':<6} {'online':<6} {'scheme':<6} {'host':<20} {'port':<5} connection opts"
35
35
  outp.printf(mesg)