synapse 2.220.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 (42) hide show
  1. synapse/lib/layer.py +134 -0
  2. synapse/lib/rstorm.py +65 -2
  3. synapse/lib/snap.py +21 -13
  4. synapse/lib/stormhttp.py +10 -10
  5. synapse/lib/stormlib/aha.py +3 -3
  6. synapse/lib/stormlib/auth.py +11 -11
  7. synapse/lib/stormlib/cell.py +1 -1
  8. synapse/lib/stormlib/cortex.py +9 -9
  9. synapse/lib/stormlib/env.py +4 -5
  10. synapse/lib/stormlib/ethereum.py +1 -1
  11. synapse/lib/stormlib/gen.py +3 -3
  12. synapse/lib/stormlib/hex.py +2 -2
  13. synapse/lib/stormlib/imap.py +2 -2
  14. synapse/lib/stormlib/infosec.py +2 -2
  15. synapse/lib/stormlib/iters.py +2 -2
  16. synapse/lib/stormlib/model.py +5 -5
  17. synapse/lib/stormlib/notifications.py +1 -1
  18. synapse/lib/stormlib/oauth.py +2 -2
  19. synapse/lib/stormlib/project.py +3 -3
  20. synapse/lib/stormlib/scrape.py +2 -1
  21. synapse/lib/stormlib/smtp.py +3 -3
  22. synapse/lib/stormlib/stats.py +2 -2
  23. synapse/lib/stormlib/stix.py +2 -2
  24. synapse/lib/stormlib/utils.py +19 -0
  25. synapse/lib/stormlib/vault.py +1 -1
  26. synapse/lib/stormlib/xml.py +2 -2
  27. synapse/lib/stormlib/yaml.py +1 -1
  28. synapse/lib/stormtypes.py +164 -60
  29. synapse/lib/version.py +2 -2
  30. synapse/tests/test_lib_layer.py +86 -67
  31. synapse/tests/test_lib_rstorm.py +132 -0
  32. synapse/tests/test_lib_storm.py +6 -0
  33. synapse/tests/test_lib_stormlib_env.py +3 -1
  34. synapse/tests/test_lib_stormlib_utils.py +10 -0
  35. synapse/tests/test_lib_stormtypes.py +551 -2
  36. synapse/tools/aha/list.py +9 -9
  37. synapse/tools/aha/provision/service.py +2 -2
  38. {synapse-2.220.0.dist-info → synapse-2.221.0.dist-info}/METADATA +1 -1
  39. {synapse-2.220.0.dist-info → synapse-2.221.0.dist-info}/RECORD +42 -42
  40. {synapse-2.220.0.dist-info → synapse-2.221.0.dist-info}/WHEEL +0 -0
  41. {synapse-2.220.0.dist-info → synapse-2.221.0.dist-info}/licenses/LICENSE +0 -0
  42. {synapse-2.220.0.dist-info → synapse-2.221.0.dist-info}/top_level.txt +0 -0
@@ -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 = ([])
@@ -1767,6 +1817,435 @@ class StormTypesTest(s_test.SynTest):
1767
1817
  await visi.addRule((True, ('layer', 'read')), gateiden=layriden)
1768
1818
  await core.callStorm('return($lib.layer.get($layriden).getStorNode($iden))', opts=opts)
1769
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
+
1770
2249
  async def test_storm_lib_fire(self):
1771
2250
  async with self.getTestCore() as core:
1772
2251
  text = '$lib.fire(foo:bar, baz=faz)'
@@ -5671,6 +6150,76 @@ class StormTypesTest(s_test.SynTest):
5671
6150
  q = '$tally = $lib.stats.tally() $tally.inc(foo) $tally.inc(foo) return($tally)'
5672
6151
  self.eq({'foo': 2}, await core.callStorm(q))
5673
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
+
5674
6223
  async def test_print_warn(self):
5675
6224
  async with self.getTestCore() as core:
5676
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)
@@ -10,10 +10,10 @@ A tool to prepare provisioning entries in the AHA server.
10
10
 
11
11
  Examples:
12
12
 
13
- # provision a new serivce named 00.axon from within the AHA container.
13
+ # provision a new service named 00.axon from within the AHA container.
14
14
  python -m synapse.tools.aha.provision.service 00.axon
15
15
 
16
- # provision a new serivce named 01.cortex as a mirror from within the AHA container.
16
+ # provision a new service named 01.cortex as a mirror from within the AHA container.
17
17
  python -m synapse.tools.aha.provision.service 01.cortex --mirror 00.cortex
18
18
 
19
19
  '''
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: synapse
3
- Version: 2.220.0
3
+ Version: 2.221.0
4
4
  Summary: Synapse Intelligence Analysis Framework
5
5
  Author-email: The Vertex Project LLC <root@vertex.link>
6
6
  License-Expression: Apache-2.0