synapse 2.223.0__py311-none-any.whl → 2.225.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 (135) hide show
  1. synapse/axon.py +10 -5
  2. synapse/common.py +2 -2
  3. synapse/cortex.py +52 -3
  4. synapse/datamodel.py +1 -1
  5. synapse/lib/cell.py +1 -1
  6. synapse/lib/const.py +4 -0
  7. synapse/lib/layer.py +6 -6
  8. synapse/lib/multislabseqn.py +36 -1
  9. synapse/lib/nexus.py +67 -8
  10. synapse/lib/queue.py +4 -1
  11. synapse/lib/rstorm.py +2 -2
  12. synapse/lib/schemas.py +13 -1
  13. synapse/lib/slabseqn.py +28 -0
  14. synapse/lib/storm.py +40 -2
  15. synapse/lib/stormhttp.py +7 -1
  16. synapse/lib/stormlib/imap.py +12 -4
  17. synapse/lib/stormlib/task.py +0 -1
  18. synapse/lib/stormtypes.py +19 -1
  19. synapse/lib/version.py +2 -2
  20. synapse/models/inet.py +29 -0
  21. synapse/models/media.py +4 -0
  22. synapse/models/proj.py +3 -0
  23. synapse/models/risk.py +9 -0
  24. synapse/models/syn.py +8 -0
  25. synapse/tests/test_common.py +4 -0
  26. synapse/tests/test_cortex.py +53 -2
  27. synapse/tests/test_lib_agenda.py +1 -1
  28. synapse/tests/test_lib_cell.py +1 -1
  29. synapse/tests/test_lib_certdir.py +1 -1
  30. synapse/tests/test_lib_httpapi.py +1 -1
  31. synapse/tests/test_lib_layer.py +1 -1
  32. synapse/tests/test_lib_multislabseqn.py +22 -0
  33. synapse/tests/test_lib_nexus.py +42 -1
  34. synapse/tests/test_lib_slabseqn.py +30 -1
  35. synapse/tests/test_lib_storm.py +156 -1
  36. synapse/tests/test_lib_stormhttp.py +16 -0
  37. synapse/tests/test_lib_stormlib_imap.py +14 -0
  38. synapse/tests/test_lib_stormlib_oauth.py +1 -1
  39. synapse/tests/test_lib_stormsvc.py +1 -1
  40. synapse/tests/test_lib_stormtypes.py +12 -0
  41. synapse/tests/test_lib_trigger.py +1 -1
  42. synapse/tests/test_model_inet.py +29 -0
  43. synapse/tests/test_model_media.py +4 -1
  44. synapse/tests/test_model_proj.py +3 -1
  45. synapse/tests/test_model_risk.py +12 -0
  46. synapse/tests/test_model_syn.py +54 -2
  47. synapse/tests/{test_tools_axon2axon.py → test_tools_axon_copy.py} +4 -4
  48. synapse/tests/{test_tools_pullfile.py → test_tools_axon_get.py} +4 -4
  49. synapse/tests/{test_tools_pushfile.py → test_tools_axon_put.py} +7 -7
  50. synapse/tests/{test_tools_csvtool.py → test_tools_cortex_csv.py} +12 -3
  51. synapse/tests/{test_tools_feed.py → test_tools_cortex_feed.py} +2 -2
  52. synapse/tests/{test_tools_apikey.py → test_tools_service_apikey.py} +1 -4
  53. synapse/tests/{test_tools_backup.py → test_tools_service_backup.py} +5 -5
  54. synapse/tests/{test_tools_demote.py → test_tools_service_demote.py} +1 -1
  55. synapse/tests/{test_tools_healthcheck.py → test_tools_service_healthcheck.py} +1 -1
  56. synapse/tests/{test_tools_livebackup.py → test_tools_service_livebackup.py} +1 -1
  57. synapse/tests/{test_tools_modrole.py → test_tools_service_modrole.py} +1 -1
  58. synapse/tests/{test_tools_moduser.py → test_tools_service_moduser.py} +1 -1
  59. synapse/tests/{test_tools_promote.py → test_tools_service_promote.py} +1 -1
  60. synapse/tests/{test_tools_reload.py → test_tools_service_reload.py} +1 -1
  61. synapse/tests/{test_tools_shutdown.py → test_tools_service_shutdown.py} +1 -1
  62. synapse/tests/{test_tools_snapshot.py → test_tools_service_snapshot.py} +1 -1
  63. synapse/tests/{test_tools_storm.py → test_tools_storm_cli.py} +1 -1
  64. synapse/tests/{test_tools_pkgs_gendocs.py → test_tools_storm_pkg_doc.py} +12 -3
  65. synapse/tests/{test_tools_genpkg.py → test_tools_storm_pkg_gen.py} +1 -1
  66. synapse/tests/{test_tools_autodoc.py → test_tools_utils_autodoc.py} +1 -1
  67. synapse/tests/test_tools_utils_changelog.py +454 -0
  68. synapse/tests/{test_tools_easycert.py → test_tools_utils_easycert.py} +48 -46
  69. synapse/tests/{test_tools_guid.py → test_tools_utils_guid.py} +3 -3
  70. synapse/tests/{test_tools_json2mpk.py → test_tools_utils_json2mpk.py} +3 -3
  71. synapse/tests/{test_tools_rstorm.py → test_tools_utils_rstorm.py} +6 -1
  72. synapse/tests/utils.py +3 -1
  73. synapse/tools/apikey.py +4 -83
  74. synapse/tools/autodoc.py +3 -1031
  75. synapse/tools/axon/copy.py +44 -0
  76. synapse/tools/axon/get.py +64 -0
  77. synapse/tools/axon/put.py +122 -0
  78. synapse/tools/axon2axon.py +3 -36
  79. synapse/tools/backup.py +6 -176
  80. synapse/tools/changelog.py +3 -1098
  81. synapse/tools/cortex/csv.py +236 -0
  82. synapse/tools/cortex/feed.py +151 -0
  83. synapse/tools/csvtool.py +3 -227
  84. synapse/tools/demote.py +4 -40
  85. synapse/tools/docker/validate.py +3 -3
  86. synapse/tools/easycert.py +4 -129
  87. synapse/tools/feed.py +3 -140
  88. synapse/tools/genpkg.py +3 -307
  89. synapse/tools/guid.py +7 -6
  90. synapse/tools/healthcheck.py +3 -101
  91. synapse/tools/json2mpk.py +6 -38
  92. synapse/tools/livebackup.py +4 -27
  93. synapse/tools/modrole.py +3 -108
  94. synapse/tools/moduser.py +3 -179
  95. synapse/tools/pkgs/gendocs.py +3 -164
  96. synapse/tools/promote.py +4 -41
  97. synapse/tools/pullfile.py +3 -56
  98. synapse/tools/pushfile.py +3 -114
  99. synapse/tools/reload.py +4 -61
  100. synapse/tools/rstorm.py +3 -26
  101. synapse/tools/service/__init__.py +0 -0
  102. synapse/tools/service/apikey.py +90 -0
  103. synapse/tools/service/backup.py +181 -0
  104. synapse/tools/service/demote.py +47 -0
  105. synapse/tools/service/healthcheck.py +109 -0
  106. synapse/tools/service/livebackup.py +34 -0
  107. synapse/tools/service/modrole.py +116 -0
  108. synapse/tools/service/moduser.py +184 -0
  109. synapse/tools/service/promote.py +48 -0
  110. synapse/tools/service/reload.py +68 -0
  111. synapse/tools/service/shutdown.py +51 -0
  112. synapse/tools/service/snapshot.py +64 -0
  113. synapse/tools/shutdown.py +5 -45
  114. synapse/tools/snapshot.py +4 -57
  115. synapse/tools/storm/__init__.py +0 -0
  116. synapse/tools/storm/__main__.py +5 -0
  117. synapse/tools/{storm.py → storm/_cli.py} +0 -3
  118. synapse/tools/storm/pkg/__init__.py +0 -0
  119. synapse/tools/{pkgs/pandoc_filter.py → storm/pkg/_pandoc_filter.py} +1 -1
  120. synapse/tools/storm/pkg/doc.py +176 -0
  121. synapse/tools/storm/pkg/gen.py +315 -0
  122. synapse/tools/utils/__init__.py +0 -0
  123. synapse/tools/utils/autodoc.py +1040 -0
  124. synapse/tools/utils/changelog.py +1124 -0
  125. synapse/tools/utils/easycert.py +136 -0
  126. synapse/tools/utils/guid.py +11 -0
  127. synapse/tools/utils/json2mpk.py +46 -0
  128. synapse/tools/utils/rstorm.py +35 -0
  129. {synapse-2.223.0.dist-info → synapse-2.225.0.dist-info}/METADATA +1 -1
  130. {synapse-2.223.0.dist-info → synapse-2.225.0.dist-info}/RECORD +134 -105
  131. synapse/tests/test_tools_changelog.py +0 -196
  132. /synapse/tests/{test_tools_axon.py → test_tools_axon_dump_load.py} +0 -0
  133. {synapse-2.223.0.dist-info → synapse-2.225.0.dist-info}/WHEEL +0 -0
  134. {synapse-2.223.0.dist-info → synapse-2.225.0.dist-info}/licenses/LICENSE +0 -0
  135. {synapse-2.223.0.dist-info → synapse-2.225.0.dist-info}/top_level.txt +0 -0
@@ -21,7 +21,7 @@ import synapse.lib.stormtypes as s_stormtypes
21
21
  import synapse.tests.utils as s_t_utils
22
22
  from synapse.tests.utils import alist
23
23
 
24
- import synapse.tools.backup as s_tools_backup
24
+ import synapse.tools.service.backup as s_tools_backup
25
25
 
26
26
  class StormTest(s_t_utils.SynTest):
27
27
 
@@ -4627,6 +4627,161 @@ class StormTest(s_t_utils.SynTest):
4627
4627
  self.stormIsInPrint('$lib.bytes.hashset`` has been deprecated and will be removed in version v3.0.0', msgs)
4628
4628
  self.stormIsInPrint('Use the corresponding ``$lib.axon`` function.', msgs)
4629
4629
 
4630
+ async def test_storm_cmd_deprecations(self):
4631
+
4632
+ async with self.getTestCore() as core:
4633
+
4634
+ deprpkg = {
4635
+ 'name': 'testdepr',
4636
+ 'version': '0.0.1',
4637
+ 'synapse_version': '>=2.8.0,<3.0.0',
4638
+ 'commands': (
4639
+ {
4640
+ 'name': 'deprmesg',
4641
+ 'descr': 'deprecated command',
4642
+ 'deprecated': {'eolvers': 'v3.0.0', 'mesg': 'Please use something else.'},
4643
+ 'storm': '[ inet:ipv4=1.2.3.4 ]',
4644
+ },
4645
+ {
4646
+ 'name': 'deprnomesg',
4647
+ 'descr': 'deprecated command',
4648
+ 'deprecated': {'eoldate': '2099-01-01'},
4649
+ 'storm': '[ inet:ipv4=1.2.3.4 ]',
4650
+ },
4651
+ {
4652
+ 'name': 'deprargs',
4653
+ 'descr': 'deprecated command',
4654
+ 'storm': '[ inet:ipv4=1.2.3.4 ]',
4655
+ 'cmdargs': (
4656
+ ('--start-time', {
4657
+ 'type': 'time',
4658
+ 'deprecated': {'eolvers': 'v3.0.0', 'mesg': 'Use --period instead.'},
4659
+ }),
4660
+ ('--end-time', {
4661
+ 'type': 'time',
4662
+ 'deprecated': {'eolvers': 'v3.0.0'},
4663
+ }),
4664
+ ('--period', {
4665
+ 'type': 'time',
4666
+ }),
4667
+ ),
4668
+ },
4669
+ ),
4670
+ }
4671
+
4672
+ self.none(await core.addStormPkg(deprpkg))
4673
+
4674
+ # Deprecation message shows up in command help
4675
+ deprmesg = '"deprmesg" is deprecated: Please use something else.'
4676
+ msgs = await core.stormlist('deprmesg -h')
4677
+ self.stormIsInPrint(f'Deprecated: {deprmesg}', msgs)
4678
+ self.stormHasNoWarnErr(msgs)
4679
+
4680
+ # Deprecation message shows up in command execution as warning
4681
+ msgs = await core.stormlist('deprmesg')
4682
+ self.stormIsInWarn(deprmesg, msgs)
4683
+
4684
+ # Deprecation message shows up in command help (with no message specified)
4685
+ deprmesg = '"deprnomesg" is deprecated and will be removed on 2099-01-01.'
4686
+ msgs = await core.stormlist('deprnomesg -h')
4687
+ self.stormIsInPrint(f'Deprecated: {deprmesg}', msgs)
4688
+ self.stormHasNoWarnErr(msgs)
4689
+
4690
+ # Deprecation message shows up in command execution as warning (with no message specified)
4691
+ msgs = await core.stormlist('deprnomesg')
4692
+ self.stormIsInWarn(deprmesg, msgs)
4693
+
4694
+ # Deprecation message shows up in help for command args
4695
+ msgs = await core.stormlist('deprargs -h')
4696
+ self.stormIsInPrint(' Deprecated: "--start-time" is deprecated: Use --period instead.', msgs)
4697
+ self.stormIsInPrint(' Deprecated: "--end-time" is deprecated and will be removed in v3.0.0.', msgs)
4698
+ self.stormHasNoWarnErr(msgs)
4699
+
4700
+ # Deprecation message doesn't show up in command execution when not using deprecated args
4701
+ msgs = await core.stormlist('deprargs')
4702
+ self.stormHasNoWarnErr(msgs)
4703
+
4704
+ # Deprecation message shows up in command execution as warning
4705
+ msgs = await core.stormlist('deprargs --start-time now')
4706
+ self.stormIsInWarn('"--start-time" is deprecated: Use --period instead.', msgs)
4707
+ self.stormNotInWarn('"--end-time" is deprecated and will be removed in v3.0.0.', msgs)
4708
+
4709
+ msgs = await core.stormlist('deprargs --end-time now')
4710
+ self.stormNotInWarn('"--start-time" is deprecated: Use --period instead.', msgs)
4711
+ self.stormIsInWarn('"--end-time" is deprecated and will be removed in v3.0.0.', msgs)
4712
+
4713
+ msgs = await core.stormlist('deprargs --start-time now --end-time now')
4714
+ self.stormIsInWarn('"--start-time" is deprecated: Use --period instead.', msgs)
4715
+ self.stormIsInWarn('"--end-time" is deprecated and will be removed in v3.0.0.', msgs)
4716
+
4717
+ # Deprecation message only appears once per runtime
4718
+ msgs = await core.stormlist('[ inet:ipv4=10.0.0.0/28 ] | deprmesg')
4719
+ self.stormIsInWarn('"deprmesg" is deprecated: Please use something else.', msgs)
4720
+ self.len(1, [m for m in msgs if m[0] == 'warn'])
4721
+
4722
+ msgs = await core.stormlist('[ inet:ipv4=10.0.0.0/28 ] | deprargs --start-time now --end-time now')
4723
+ self.stormIsInWarn('"--start-time" is deprecated: Use --period instead.', msgs)
4724
+ self.stormIsInWarn('"--end-time" is deprecated and will be removed in v3.0.0.', msgs)
4725
+ self.len(2, [m for m in msgs if m[0] == 'warn'])
4726
+
4727
+ async def test_storm_cmd_cmdconf(self):
4728
+ pkgdef = {
4729
+ 'name': 'testpkg',
4730
+ 'version': '1.0.0',
4731
+ 'commands': [
4732
+ {
4733
+ 'name': 'getcmdconf',
4734
+ 'cmdconf': {
4735
+ 'valu': 0,
4736
+ 'sub': {
4737
+ 'valu': 0,
4738
+ },
4739
+ },
4740
+ 'storm': '''
4741
+ $lib.print(`VALU: {$cmdconf.valu}.`)
4742
+ $lib.print(`SUBVALU: {$cmdconf.sub.valu}.`)
4743
+ $cmdconf.valu = ($cmdconf.valu + 1)
4744
+ $cmdconf.sub.valu = ($cmdconf.sub.valu + 1)
4745
+ ''',
4746
+ },
4747
+ ],
4748
+ }
4749
+
4750
+ async with self.getTestCore() as core:
4751
+ await core.addStormPkg(pkgdef)
4752
+
4753
+ msgs = await core.stormlist('getcmdconf')
4754
+ self.stormHasNoWarnErr(msgs)
4755
+ self.stormIsInPrint('VALU: 0.', msgs)
4756
+ self.stormIsInPrint('SUBVALU: 0.', msgs)
4757
+
4758
+ msgs = await core.stormlist('getcmdconf | getcmdconf')
4759
+ self.stormHasNoWarnErr(msgs)
4760
+ msgs = [k for k in msgs if k[0] == 'print']
4761
+ self.len(4, msgs)
4762
+ self.sorteq(
4763
+ ['VALU: 0.', 'VALU: 0.', 'SUBVALU: 0.', 'SUBVALU: 0.'],
4764
+ [msg[1].get('mesg') for msg in msgs]
4765
+ )
4766
+
4767
+ msgs = await core.stormlist('for $i in $lib.range(16) {[test:int=$i]} | getcmdconf')
4768
+ self.stormHasNoWarnErr(msgs)
4769
+
4770
+ self.stormIsInPrint('VALU: 0.', msgs)
4771
+ self.stormIsInPrint('VALU: 1.', msgs)
4772
+ self.stormIsInPrint('VALU: 15.', msgs)
4773
+ self.stormNotInPrint('VALU: 16.', msgs)
4774
+
4775
+ self.stormIsInPrint('SUBVALU: 0.', msgs)
4776
+ self.stormIsInPrint('SUBVALU: 1.', msgs)
4777
+ self.stormIsInPrint('SUBVALU: 15.', msgs)
4778
+ self.stormNotInPrint('SUBVALU: 16.', msgs)
4779
+
4780
+ msgs = await core.stormlist('getcmdconf')
4781
+ self.stormHasNoWarnErr(msgs)
4782
+ self.stormIsInPrint('VALU: 0.', msgs)
4783
+ self.stormIsInPrint('SUBVALU: 0.', msgs)
4784
+
4630
4785
  async def test_liftby_edge(self):
4631
4786
  async with self.getTestCore() as core:
4632
4787
 
@@ -47,6 +47,11 @@ class HttpBadJson(s_httpapi.Handler):
47
47
  async def get(self):
48
48
  self.write(b'{"foo": "bar\x80"}')
49
49
 
50
+ class HttpGiantHeader(s_httpapi.Handler):
51
+ async def get(self):
52
+ self.set_header('Giant', 'x' * 64_000)
53
+ self.write('test')
54
+
50
55
  class StormHttpTest(s_test.SynTest):
51
56
 
52
57
  async def test_storm_http_get(self):
@@ -60,6 +65,7 @@ class StormHttpTest(s_test.SynTest):
60
65
  core.addHttpApi('/api/v0/test', s_test.HttpReflector, {'cell': core})
61
66
  core.addHttpApi('/api/v0/notjson', HttpNotJson, {'cell': core})
62
67
  core.addHttpApi('/api/v0/badjson', HttpBadJson, {'cell': core})
68
+ core.addHttpApi('/api/v0/giantheader', HttpGiantHeader, {'cell': core})
63
69
  url = f'https://root:root@127.0.0.1:{port}/api/v0/test'
64
70
  status_url = f'https://127.0.0.1:{port}/api/v1/status'
65
71
  opts = {'vars': {'url': url, 'port': port, 'status_url': status_url}}
@@ -273,6 +279,16 @@ class StormHttpTest(s_test.SynTest):
273
279
  self.isinstance(resp, tuple)
274
280
  self.len(0, resp)
275
281
 
282
+ gianturl = f'https://root:root@127.0.0.1:{port}/api/v0/giantheader'
283
+ giantopts = {'vars': {'url': gianturl}}
284
+ q = '''
285
+ $resp = $lib.inet.http.get($url, ssl_verify=$lib.false)
286
+ return ( $resp )
287
+ '''
288
+ resp = await core.callStorm(q, opts=giantopts)
289
+ self.eq(resp['body'], b'test')
290
+ self.len(64_000, resp['headers'].get('Giant'))
291
+
276
292
  async def test_storm_http_inject_ca(self):
277
293
 
278
294
  with self.getTestDir() as dirn:
@@ -445,6 +445,8 @@ class ImapTest(s_test.SynTest):
445
445
 
446
446
  while not link.isfini:
447
447
  mesg = await link.rx()
448
+ if mesg is None:
449
+ break
448
450
 
449
451
  # Receive commands from client
450
452
  command = mesg.get('command')
@@ -854,6 +856,8 @@ class ImapTest(s_test.SynTest):
854
856
  self.stormIsInErr('Cannot process EXPUNGE command.', mesgs)
855
857
 
856
858
  imap = await s_link.connect('127.0.0.1', port, linkcls=s_imap.IMAPClient)
859
+ core.onfini(imap)
860
+
857
861
  await imap.login('user01@vertex.link', 'spaces lol')
858
862
  await imap.select('INBOX')
859
863
  self.eq(
@@ -868,6 +872,8 @@ class ImapTest(s_test.SynTest):
868
872
 
869
873
  # Normal response
870
874
  imap = await s_link.connect('127.0.0.1', port, linkcls=s_imap.IMAPClient)
875
+ core.onfini(imap)
876
+
871
877
  await imap.login(user, 'pass00')
872
878
  await imap.select('INBOX')
873
879
  ret = await imap.uid_fetch('1', '(RFC822 BODY[HEADER])')
@@ -884,6 +890,8 @@ class ImapTest(s_test.SynTest):
884
890
 
885
891
  # Normal response
886
892
  imap = await s_link.connect('127.0.0.1', port, linkcls=s_imap.IMAPClient)
893
+ core.onfini(imap)
894
+
887
895
  await imap.login(user, 'pass00')
888
896
  self.eq(
889
897
  await imap.logout(),
@@ -897,6 +905,8 @@ class ImapTest(s_test.SynTest):
897
905
 
898
906
  with mock.patch.object(IMAPServer, 'logout', logout_no):
899
907
  imap = await s_link.connect('127.0.0.1', port, linkcls=s_imap.IMAPClient)
908
+ core.onfini(imap)
909
+
900
910
  await imap.login(user, 'pass00')
901
911
  self.eq(
902
912
  await imap.logout(),
@@ -910,6 +920,8 @@ class ImapTest(s_test.SynTest):
910
920
 
911
921
  with mock.patch.object(IMAPServer, 'logout', logout_nobye):
912
922
  imap = await s_link.connect('127.0.0.1', port, linkcls=s_imap.IMAPClient)
923
+ core.onfini(imap)
924
+
913
925
  await imap.login(user, 'pass00')
914
926
  self.eq(
915
927
  await imap.logout(),
@@ -932,6 +944,8 @@ class ImapTest(s_test.SynTest):
932
944
 
933
945
  # Check command validation
934
946
  imap = await s_link.connect('127.0.0.1', port, linkcls=s_imap.IMAPClient)
947
+ core.onfini(imap)
948
+
935
949
  with self.raises(s_exc.ImapError) as exc:
936
950
  tag = imap._genTag()
937
951
  await imap._command(tag, 'NEWP')
@@ -11,7 +11,7 @@ import synapse.lib.coro as s_coro
11
11
  import synapse.lib.oauth as s_oauth
12
12
  import synapse.lib.httpapi as s_httpapi
13
13
  import synapse.tests.utils as s_test
14
- import synapse.tools.backup as s_backup
14
+ import synapse.tools.service.backup as s_backup
15
15
 
16
16
  logger = logging.getLogger(__name__)
17
17
 
@@ -9,7 +9,7 @@ import synapse.lib.cell as s_cell
9
9
  import synapse.lib.share as s_share
10
10
  import synapse.lib.stormsvc as s_stormsvc
11
11
 
12
- import synapse.tools.backup as s_tools_backup
12
+ import synapse.tools.service.backup as s_tools_backup
13
13
 
14
14
  old_pkg = {
15
15
  'name': 'old',
@@ -3297,6 +3297,18 @@ class StormTypesTest(s_test.SynTest):
3297
3297
  self.false(mesgs[0])
3298
3298
  self.isin('Ambiguous time', mesgs[1]['errinfo']['mesg'])
3299
3299
 
3300
+ valu = await core.callStorm('return($lib.time.format($lib.cast(time, 20251002), $lib.time.formats.iso8601))')
3301
+ self.eq(valu, '2025-10-02T00:00:00Z')
3302
+
3303
+ valu = await core.callStorm('return($lib.time.format($lib.cast(time, 20251002), $lib.time.formats.iso8601us))')
3304
+ self.eq(valu, '2025-10-02T00:00:00.000000Z')
3305
+
3306
+ valu = await core.callStorm('return($lib.time.format($lib.cast(time, 20251002), $lib.time.formats.rfc2822))')
3307
+ self.eq(valu, '02 Oct 2025 00:00:00 UT')
3308
+
3309
+ valu = await core.callStorm('return($lib.time.format($lib.cast(time, 20251002), $lib.time.formats.synapse))')
3310
+ self.eq(valu, '2025/10/02 00:00:00.000000')
3311
+
3300
3312
  async def test_storm_lib_time_ticker(self):
3301
3313
 
3302
3314
  async with self.getTestCore() as core:
@@ -4,7 +4,7 @@ import synapse.common as s_common
4
4
 
5
5
  import synapse.telepath as s_telepath
6
6
  import synapse.tests.utils as s_t_utils
7
- import synapse.tools.backup as s_tools_backup
7
+ import synapse.tools.service.backup as s_tools_backup
8
8
 
9
9
  class TrigTest(s_t_utils.SynTest):
10
10
 
@@ -2991,10 +2991,17 @@ class InetModelTest(s_t_utils.SynTest):
2991
2991
 
2992
2992
  q = '''
2993
2993
  [ inet:service:platform=(slack,)
2994
+ :id=foo
2994
2995
  :url="https://slack.com"
2995
2996
  :urls=(https://slacker.com,)
2997
+ :zones=(slack.com, slacker.com)
2996
2998
  :name=Slack
2997
2999
  :names=("slack chat",)
3000
+ :parent={[ inet:service:platform=({"name": "salesforce"}) ]}
3001
+ :status=available
3002
+ :period=(2022, 2023)
3003
+ :creator={[ inet:service:account=({"id": "bar"}) ]}
3004
+ :remover={[ inet:service:account=({"id": "baz"}) ]}
2998
3005
  :provider={ ou:org:name=$provname }
2999
3006
  :provider:name=$provname
3000
3007
  ]
@@ -3002,20 +3009,36 @@ class InetModelTest(s_t_utils.SynTest):
3002
3009
  nodes = await core.nodes(q, opts=opts)
3003
3010
  self.len(1, nodes)
3004
3011
  self.eq(nodes[0].ndef, ('inet:service:platform', s_common.guid(('slack',))))
3012
+ self.eq('foo', nodes[0].get('id'))
3005
3013
  self.eq(nodes[0].get('url'), 'https://slack.com')
3006
3014
  self.eq(nodes[0].get('urls'), ('https://slacker.com',))
3015
+ self.eq(nodes[0].get('zones'), ('slack.com', 'slacker.com'))
3007
3016
  self.eq(nodes[0].get('name'), 'slack')
3008
3017
  self.eq(nodes[0].get('names'), ('slack chat',))
3018
+ self.eq(nodes[0].repr('status'), 'available')
3019
+ self.eq(nodes[0].repr('period'), ('2022/01/01 00:00:00.000', '2023/01/01 00:00:00.000'))
3009
3020
  self.eq(nodes[0].get('provider'), provider.ndef[1])
3010
3021
  self.eq(nodes[0].get('provider:name'), provname.lower())
3011
3022
  platform = nodes[0]
3012
3023
 
3024
+ nodes = await core.nodes('inet:service:platform=(slack,) :parent -> *')
3025
+ self.eq(['salesforce'], [n.get('name') for n in nodes])
3026
+
3027
+ nodes = await core.nodes('inet:service:platform=(slack,) :creator -> *')
3028
+ self.eq(['bar'], [n.get('id') for n in nodes])
3029
+
3030
+ nodes = await core.nodes('inet:service:platform=(slack,) :remover -> *')
3031
+ self.eq(['baz'], [n.get('id') for n in nodes])
3032
+
3013
3033
  nodes = await core.nodes('[ inet:service:platform=({"name": "slack chat"}) ]')
3014
3034
  self.eq(nodes[0].ndef, platform.ndef)
3015
3035
 
3016
3036
  nodes = await core.nodes('[ inet:service:platform=({"url": "https://slacker.com"}) ]')
3017
3037
  self.eq(nodes[0].ndef, platform.ndef)
3018
3038
 
3039
+ nodes = await core.nodes('[ inet:service:platform=({"zone": "slacker.com"}) ]')
3040
+ self.eq(nodes[0].ndef, platform.ndef)
3041
+
3019
3042
  q = '''
3020
3043
  [ inet:service:instance=(vertex, slack)
3021
3044
  :id='T2XK1223Y'
@@ -3045,6 +3068,7 @@ class InetModelTest(s_t_utils.SynTest):
3045
3068
  (inet:service:account=(blackout, account, vertex, slack)
3046
3069
  :id=U7RN51U1J
3047
3070
  :user=blackout
3071
+ :users=(zeblackout, blackoutalt, zeblackout)
3048
3072
  :url=https://vertex.link/users/blackout
3049
3073
  :email=blackout@vertex.link
3050
3074
  :profile={ gen.ps.contact.email vertex.employee blackout@vertex.link }
@@ -3076,6 +3100,7 @@ class InetModelTest(s_t_utils.SynTest):
3076
3100
  self.eq(accounts[0].ndef, ('inet:service:account', s_common.guid(('blackout', 'account', 'vertex', 'slack'))))
3077
3101
  self.eq(accounts[0].get('id'), 'U7RN51U1J')
3078
3102
  self.eq(accounts[0].get('user'), 'blackout')
3103
+ self.eq(accounts[0].get('users'), ('blackoutalt', 'zeblackout'))
3079
3104
  self.eq(accounts[0].get('url'), 'https://vertex.link/users/blackout')
3080
3105
  self.eq(accounts[0].get('email'), 'blackout@vertex.link')
3081
3106
  self.eq(accounts[0].get('profile'), blckprof.ndef[1])
@@ -3089,6 +3114,10 @@ class InetModelTest(s_t_utils.SynTest):
3089
3114
 
3090
3115
  self.len(1, await core.nodes('inet:service:account:email=visi@vertex.link :parent -> inet:service:account'))
3091
3116
 
3117
+ nodes = await core.nodes('[ inet:service:account=({"user": "blackoutalt"}) ]')
3118
+ self.len(1, nodes)
3119
+ self.eq(accounts[0].ndef, nodes[0].ndef)
3120
+
3092
3121
  q = '''
3093
3122
  [ inet:service:group=(developers, group, vertex, slack)
3094
3123
  :id=X1234
@@ -22,6 +22,7 @@ class MediaModelTest(s_t_utils.SynTest):
22
22
  'file': file0,
23
23
  'title': 'Synapse is awesome! ',
24
24
  'summary': 'I forget ',
25
+ 'body': 'It is Awesome ',
25
26
  'published': 0,
26
27
  'updated': 0,
27
28
  'org': 'verteX',
@@ -34,7 +35,7 @@ class MediaModelTest(s_t_utils.SynTest):
34
35
 
35
36
  q = '''[(media:news=$valu
36
37
  :url=$p.url :file=$p.file :title=$p.title
37
- :summary=$p.summary :published=$p.published :updated=$p.updated
38
+ :summary=$p.summary :body=$p.body :published=$p.published :updated=$p.updated
38
39
  :org=$p.org :authors=$p.authors
39
40
  :publisher=$p.publisher :publisher:name=$p."publisher:name"
40
41
  :rss:feed=$p."rss:feed" :topics=$p.topics
@@ -49,6 +50,8 @@ class MediaModelTest(s_t_utils.SynTest):
49
50
  self.eq(node.get('url:fqdn'), 'vertex.link')
50
51
  self.eq(node.get('file'), 'sha256:' + file0)
51
52
  self.eq(node.get('title'), 'synapse is awesome! ')
53
+ self.eq(node.get('summary'), 'I forget ')
54
+ self.eq(node.get('body'), 'It is Awesome ')
52
55
  self.eq(node.get('published'), 0)
53
56
  self.eq(node.get('updated'), 0)
54
57
  self.eq(node.get('publisher'), publisher)
@@ -1,4 +1,5 @@
1
1
  import synapse.exc as s_exc
2
+ import synapse.common as s_common
2
3
  import synapse.tests.utils as s_test
3
4
 
4
5
  class ProjModelTest(s_test.SynTest):
@@ -256,13 +257,14 @@ class ProjModelTest(s_test.SynTest):
256
257
  self.eq('highest', nodes[0].repr('priority'))
257
258
  self.eq(proj, nodes[0].get('project'))
258
259
 
259
- nodes = await core.nodes('proj:comment')
260
+ nodes = await core.nodes('proj:comment [ :ext:creator={[ps:contact=(visi,) :name=visi ]} ]')
260
261
  self.len(1, nodes)
261
262
  self.nn(nodes[0].get('created'))
262
263
  self.nn(nodes[0].get('updated'))
263
264
  self.eq(tick, nodes[0].get('ticket'))
264
265
  self.eq('hithere', nodes[0].get('text'))
265
266
  self.eq(visi.iden, nodes[0].get('creator'))
267
+ self.eq(s_common.guid(('visi',)), nodes[0].get('ext:creator'))
266
268
 
267
269
  self.eq('foo', await core.callStorm('return($lib.projects.get($proj).name)', opts=opts))
268
270
  self.eq('bar', await core.callStorm('return($lib.projects.get($proj).epics.get($epic).name)', opts=opts))
@@ -3,6 +3,7 @@ import logging
3
3
  import synapse.exc as s_exc
4
4
  import synapse.common as s_common
5
5
  import synapse.lib.chop as s_chop
6
+ import synapse.lib.time as s_time
6
7
  import synapse.tests.utils as s_t_utils
7
8
 
8
9
  logger = logging.getLogger(__name__)
@@ -325,6 +326,15 @@ class RiskModelTest(s_t_utils.SynTest):
325
326
  self.len(1, await core.nodes('risk:alert :service:platform -> inet:service:platform'))
326
327
  self.len(1, await core.nodes('risk:alert :service:instance -> inet:service:instance'))
327
328
 
329
+ opts = {'vars': {'ndef': nodes[0].ndef[1]}}
330
+ nodes = await core.nodes('risk:alert=$ndef [ :updated=20251003 ]', opts=opts)
331
+ self.len(1, nodes)
332
+ self.eq(s_time.parse('20251003'), nodes[0].get('updated'))
333
+
334
+ self.len(1, await core.nodes('[ risk:alert=({"name": "bazfaz"}) +(about)> {[ file:bytes=* :name=alert.txt]} ]'))
335
+ self.len(1, fnode := await core.nodes('risk:alert=({"name": "bazfaz"}) -(about)> file:bytes'))
336
+ self.eq(fnode[0].get('name'), 'alert.txt')
337
+
328
338
  nodes = await core.nodes('''[
329
339
  risk:compromise=*
330
340
  :vector=*
@@ -591,6 +601,7 @@ class RiskModelTest(s_t_utils.SynTest):
591
601
  risk:mitigation=*
592
602
  :vuln=*
593
603
  :name=" FooBar "
604
+ :id=" IDa123 "
594
605
  :type=foo.bar
595
606
  :desc=BazFaz
596
607
  :hardware=*
@@ -603,6 +614,7 @@ class RiskModelTest(s_t_utils.SynTest):
603
614
  self.eq('BazFaz', nodes[0].props['desc'])
604
615
  self.eq('vertex', nodes[0].get('reporter:name'))
605
616
  self.eq('foo.bar.', nodes[0].get('type'))
617
+ self.eq('IDa123', nodes[0].get('id'))
606
618
  self.nn(nodes[0].get('reporter'))
607
619
  self.len(1, await core.nodes('risk:mitigation -> risk:vuln'))
608
620
  self.len(1, await core.nodes('risk:mitigation -> it:prod:softver'))
@@ -1,8 +1,9 @@
1
1
  import synapse.exc as s_exc
2
2
  import synapse.common as s_common
3
3
  import synapse.cortex as s_cortex
4
- import synapse.datamodel as s_datamodel
5
4
 
5
+ import synapse.lib.time as s_time
6
+ import synapse.lib.version as s_version
6
7
  import synapse.lib.stormsvc as s_stormsvc
7
8
 
8
9
  import synapse.tests.utils as s_t_utils
@@ -42,6 +43,21 @@ class TestService(s_stormsvc.StormSvc):
42
43
  },
43
44
  'storm': '',
44
45
  },
46
+ {
47
+ 'name': 'deprvers',
48
+ 'storm': '',
49
+ 'deprecated': {'eolvers': 'v3.0.0'},
50
+ },
51
+ {
52
+ 'name': 'deprdate',
53
+ 'storm': '',
54
+ 'deprecated': {'eoldate': '2099-01-01'},
55
+ },
56
+ {
57
+ 'name': 'deprmesg',
58
+ 'storm': '',
59
+ 'deprecated': {'eoldate': '2099-01-01', 'mesg': 'Please use ``ohhai``.'},
60
+ },
45
61
  )
46
62
  },
47
63
  )
@@ -683,7 +699,7 @@ class SynModelTest(s_t_utils.SynTest):
683
699
 
684
700
  # check that runt nodes for new commands are created
685
701
  nodes = await core.nodes('syn:cmd +:package')
686
- self.len(2, nodes)
702
+ self.len(5, nodes)
687
703
 
688
704
  self.eq(nodes[0].ndef, ('syn:cmd', 'foobar'))
689
705
  self.eq(nodes[0].get('doc'), 'foobar is a great service')
@@ -692,6 +708,7 @@ class SynModelTest(s_t_utils.SynTest):
692
708
  self.eq(nodes[0].get('nodedata'), (('foo', 'inet:ipv4'), ('bar', 'inet:fqdn')))
693
709
  self.eq(nodes[0].get('package'), 'foo')
694
710
  self.eq(nodes[0].get('svciden'), iden)
711
+ self.none(nodes[0].get('deprecated'))
695
712
 
696
713
  self.eq(nodes[1].ndef, ('syn:cmd', 'ohhai'))
697
714
  self.eq(nodes[1].get('doc'), 'No description')
@@ -700,6 +717,41 @@ class SynModelTest(s_t_utils.SynTest):
700
717
  self.none(nodes[1].get('nodedata'))
701
718
  self.eq(nodes[1].get('package'), 'foo')
702
719
  self.eq(nodes[1].get('svciden'), iden)
720
+ self.none(nodes[1].get('deprecated'))
721
+
722
+ self.eq(nodes[2].ndef, ('syn:cmd', 'deprvers'))
723
+ self.true(nodes[2].get('deprecated'))
724
+ self.eq(nodes[2].get('deprecated:version'), s_version.packVersion(3, 0, 0))
725
+ self.none(nodes[2].get('deprecated:date'))
726
+ self.none(nodes[2].get('deprecated:mesg'))
727
+
728
+ self.eq(nodes[3].ndef, ('syn:cmd', 'deprdate'))
729
+ self.true(nodes[3].get('deprecated'))
730
+ self.none(nodes[3].get('deprecated:version'))
731
+ self.eq(nodes[3].get('deprecated:date'), s_time.parse('2099-01-01'))
732
+ self.none(nodes[3].get('deprecated:mesg'))
733
+
734
+ self.eq(nodes[4].ndef, ('syn:cmd', 'deprmesg'))
735
+ self.true(nodes[4].get('deprecated'))
736
+ self.none(nodes[4].get('deprecated:version'))
737
+ self.eq(nodes[4].get('deprecated:date'), s_time.parse('2099-01-01'))
738
+ self.eq(nodes[4].get('deprecated:mesg'), 'Please use ``ohhai``.')
739
+
740
+ nodes = await core.nodes('syn:cmd:deprecated')
741
+ self.len(5, nodes)
742
+ self.sorteq(['deprvers', 'deprdate', 'deprmesg', 'ps.list', 'ps.kill'], [k.ndef[1] for k in nodes])
743
+
744
+ nodes = await core.nodes('syn:cmd:deprecated:version')
745
+ self.len(3, nodes)
746
+ self.sorteq(['deprvers', 'ps.list', 'ps.kill'], [k.ndef[1] for k in nodes])
747
+
748
+ nodes = await core.nodes('syn:cmd:deprecated:date')
749
+ self.len(2, nodes)
750
+ self.sorteq(['deprdate', 'deprmesg'], [k.ndef[1] for k in nodes])
751
+
752
+ nodes = await core.nodes('syn:cmd:deprecated:mesg')
753
+ self.len(3, nodes)
754
+ self.sorteq(['deprmesg', 'ps.list', 'ps.kill'], [k.ndef[1] for k in nodes])
703
755
 
704
756
  # Pivot from cmds to their forms
705
757
  nodes = await core.nodes('syn:cmd=foobar -> *')
@@ -1,5 +1,5 @@
1
1
  import synapse.tests.utils as s_test
2
- import synapse.tools.axon2axon as s_axon2axon
2
+ import synapse.tools.axon.copy as s_copy
3
3
 
4
4
  class Axon2AxonTest(s_test.SynTest):
5
5
 
@@ -15,7 +15,7 @@ class Axon2AxonTest(s_test.SynTest):
15
15
  (size, sha256) = await srcaxon.put(b'visi')
16
16
 
17
17
  outp = self.getTestOutp()
18
- await s_axon2axon.main([srcurl, dsturl], outp=outp)
18
+ await s_copy.main([srcurl, dsturl], outp=outp)
19
19
  self.true(await dstaxon.has(sha256))
20
20
  outp.expect('Starting transfer at offset: 0')
21
21
  outp.expect('[ 0] - e45bbb7e03acacf4d1cca4c16af1ec0c51d777d10e53ed3155bd3d8deb398f3f (4)')
@@ -23,11 +23,11 @@ class Axon2AxonTest(s_test.SynTest):
23
23
  (size, sha256) = await srcaxon.put(b'vertex')
24
24
 
25
25
  outp = self.getTestOutp()
26
- await s_axon2axon.main([srcurl, dsturl, '--offset', '1'], outp=outp)
26
+ await s_copy.main([srcurl, dsturl, '--offset', '1'], outp=outp)
27
27
  self.true(await dstaxon.has(sha256))
28
28
  outp.expect('Starting transfer at offset: 1')
29
29
  outp.expect('[ 1] - e1b683e26a3aad218df6aa63afe9cf57fdb5dfaf5eb20cddac14305d67f48a02 (6)')
30
30
 
31
31
  outp = self.getTestOutp()
32
- self.eq(1, await s_axon2axon.main([], outp=outp))
32
+ self.eq(1, await s_copy.main([], outp=outp))
33
33
  outp.expect('arguments are required:')
@@ -5,7 +5,7 @@ import pathlib
5
5
  from unittest import mock
6
6
 
7
7
  import synapse.tests.utils as s_t_utils
8
- import synapse.tools.pullfile as s_pullfile
8
+ import synapse.tools.axon.get as s_get
9
9
 
10
10
  class TestPullFile(s_t_utils.SynTest):
11
11
 
@@ -30,13 +30,13 @@ class TestPullFile(s_t_utils.SynTest):
30
30
  with self.getTestDir() as wdir:
31
31
 
32
32
  outp = self.getTestOutp()
33
- self.eq(0, await s_pullfile.main(['-a', axonurl,
33
+ self.eq(0, await s_get.main(['-a', axonurl,
34
34
  '-o', wdir,
35
35
  '-l', testhash,
36
36
  '-l', nonehash], outp))
37
37
  oldcwd = os.getcwd()
38
38
  os.chdir(wdir)
39
- self.eq(0, await s_pullfile.main(['-a', axonurl,
39
+ self.eq(0, await s_get.main(['-a', axonurl,
40
40
  '-l', visihash], outp))
41
41
 
42
42
  os.chdir(oldcwd)
@@ -52,6 +52,6 @@ class TestPullFile(s_t_utils.SynTest):
52
52
  self.true(outp.expect(f'Fetching {visihash} to file'))
53
53
 
54
54
  with mock.patch('synapse.axon.Axon.get', self._getFail):
55
- self.eq(0, await s_pullfile.main(['-a', axonurl,
55
+ self.eq(0, await s_get.main(['-a', axonurl,
56
56
  '-l', visihash], outp))
57
57
  self.isin('Error: Hit Exception', str(outp))