synapse 2.190.0__py311-none-any.whl → 2.192.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.
- synapse/axon.py +54 -23
- synapse/common.py +9 -0
- synapse/cortex.py +3 -2
- synapse/datamodel.py +8 -1
- synapse/lib/ast.py +6 -2
- synapse/lib/cell.py +55 -7
- synapse/lib/msgpack.py +10 -3
- synapse/lib/nexus.py +2 -1
- synapse/lib/stormhttp.py +32 -35
- synapse/lib/stormlib/model.py +37 -0
- synapse/lib/stormtypes.py +102 -20
- synapse/lib/version.py +2 -2
- synapse/models/auth.py +2 -1
- synapse/models/base.py +20 -0
- synapse/models/crypto.py +5 -2
- synapse/models/economic.py +45 -11
- synapse/models/inet.py +78 -21
- synapse/models/person.py +11 -4
- synapse/models/risk.py +6 -0
- synapse/models/syn.py +22 -12
- synapse/models/telco.py +3 -1
- synapse/tests/test_axon.py +10 -0
- synapse/tests/test_cortex.py +60 -17
- synapse/tests/test_lib_agenda.py +1 -6
- synapse/tests/test_lib_ast.py +6 -0
- synapse/tests/test_lib_cell.py +63 -4
- synapse/tests/test_lib_httpapi.py +11 -6
- synapse/tests/test_lib_lmdbslab.py +1 -4
- synapse/tests/test_lib_stormhttp.py +57 -12
- synapse/tests/test_lib_stormlib_cortex.py +1 -3
- synapse/tests/test_lib_stormlib_log.py +1 -6
- synapse/tests/test_lib_stormlib_model.py +28 -0
- synapse/tests/test_lib_stormtypes.py +1 -2
- synapse/tests/test_lib_trigger.py +2 -3
- synapse/tests/test_model_base.py +12 -2
- synapse/tests/test_model_inet.py +23 -0
- synapse/tests/test_model_person.py +2 -0
- synapse/tests/test_model_risk.py +5 -0
- synapse/tests/test_model_syn.py +198 -0
- synapse/tests/test_servers_univ.py +0 -12
- synapse/tests/test_tools_apikey.py +227 -0
- synapse/tests/test_utils.py +23 -4
- synapse/tests/utils.py +39 -5
- synapse/tools/apikey.py +93 -0
- {synapse-2.190.0.dist-info → synapse-2.192.0.dist-info}/METADATA +4 -4
- {synapse-2.190.0.dist-info → synapse-2.192.0.dist-info}/RECORD +49 -47
- {synapse-2.190.0.dist-info → synapse-2.192.0.dist-info}/LICENSE +0 -0
- {synapse-2.190.0.dist-info → synapse-2.192.0.dist-info}/WHEEL +0 -0
- {synapse-2.190.0.dist-info → synapse-2.192.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_model_syn.py
CHANGED
|
@@ -362,6 +362,93 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
362
362
|
nodes = await core.nodes('syn:tagprop')
|
|
363
363
|
self.len(0, nodes)
|
|
364
364
|
|
|
365
|
+
async with self.getTestCore() as core:
|
|
366
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
367
|
+
|
|
368
|
+
numforms = len(core.model.forms)
|
|
369
|
+
|
|
370
|
+
q = '''
|
|
371
|
+
init {
|
|
372
|
+
$forms = ()
|
|
373
|
+
$count = (0)
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
syn:form
|
|
377
|
+
|
|
378
|
+
$forms.append(({'name': $node.repr(), 'doc': :doc }))
|
|
379
|
+
|
|
380
|
+
$count = ($count + 1)
|
|
381
|
+
|
|
382
|
+
if ($count = (2)) {
|
|
383
|
+
$info = ({"doc": "test taxonomy", "interfaces": ["meta:taxonomy"]})
|
|
384
|
+
$lib.model.ext.addForm(_test:taxonomy, taxonomy, ({}), $info)
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
spin |
|
|
388
|
+
|
|
389
|
+
fini { return($forms) }
|
|
390
|
+
'''
|
|
391
|
+
|
|
392
|
+
forms = await core.callStorm(q)
|
|
393
|
+
self.len(numforms, forms)
|
|
394
|
+
self.len(numforms + 1, core.model.forms)
|
|
395
|
+
|
|
396
|
+
numtypes = len(core.model.types)
|
|
397
|
+
q = '''
|
|
398
|
+
init {
|
|
399
|
+
$types = ()
|
|
400
|
+
$count = (0)
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
syn:type
|
|
404
|
+
|
|
405
|
+
$types.append(({'name': $node.repr(), 'doc': :doc }))
|
|
406
|
+
|
|
407
|
+
$count = ($count + 1)
|
|
408
|
+
|
|
409
|
+
if ($count = (2)) {
|
|
410
|
+
$typeopts = ({"lower": true, "onespace": true})
|
|
411
|
+
$typeinfo = ({"doc": "A test type doc."})
|
|
412
|
+
$lib.model.ext.addType(_test:type, str, $typeopts, $typeinfo)
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
spin |
|
|
416
|
+
|
|
417
|
+
fini { return($types) }
|
|
418
|
+
'''
|
|
419
|
+
|
|
420
|
+
types = await core.callStorm(q)
|
|
421
|
+
self.len(numtypes, types)
|
|
422
|
+
self.len(numtypes + 1, core.model.types)
|
|
423
|
+
|
|
424
|
+
q = '''
|
|
425
|
+
init {
|
|
426
|
+
$tagprops = ()
|
|
427
|
+
$count = (0)
|
|
428
|
+
$lib.model.ext.addTagProp(cypher, (str, ({})), ({}))
|
|
429
|
+
$lib.model.ext.addTagProp(trinity, (str, ({})), ({}))
|
|
430
|
+
$lib.model.ext.addTagProp(morpheus, (str, ({})), ({}))
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
syn:tagprop
|
|
434
|
+
|
|
435
|
+
$tagprops.append(({'name': $node.repr(), 'doc': :doc }))
|
|
436
|
+
|
|
437
|
+
$count = ($count + 1)
|
|
438
|
+
|
|
439
|
+
if ($count = (2)) {
|
|
440
|
+
$lib.model.ext.addTagProp(neo, (str, ({})), ({}))
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
spin |
|
|
444
|
+
|
|
445
|
+
fini { return($tagprops) }
|
|
446
|
+
'''
|
|
447
|
+
|
|
448
|
+
tagprops = await core.callStorm(q)
|
|
449
|
+
self.len(3, tagprops)
|
|
450
|
+
self.len(4, core.model.tagprops)
|
|
451
|
+
|
|
365
452
|
async def test_syn_trigger_runts(self):
|
|
366
453
|
async with self.getTestCore() as core:
|
|
367
454
|
nodes = await core.nodes('syn:trigger')
|
|
@@ -465,6 +552,42 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
465
552
|
pode = nodes[0].pack()
|
|
466
553
|
self.eq(pode[0][1], iden)
|
|
467
554
|
|
|
555
|
+
async with self.getTestCore() as core:
|
|
556
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
557
|
+
|
|
558
|
+
tdef = {'cond': 'node:add', 'form': 'it:dev:str', 'storm': '[inet:user=1] | testcmd'}
|
|
559
|
+
await core.view.addTrigger(tdef)
|
|
560
|
+
|
|
561
|
+
tdef = {'cond': 'node:add', 'form': 'it:dev:str', 'storm': '[inet:user=2] | testcmd'}
|
|
562
|
+
await core.view.addTrigger(tdef)
|
|
563
|
+
|
|
564
|
+
q = '''
|
|
565
|
+
init {
|
|
566
|
+
$trigs = ()
|
|
567
|
+
$count = (0)
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
syn:trigger
|
|
571
|
+
|
|
572
|
+
$trigs.append(({'name': $node.repr(), 'doc': :doc }))
|
|
573
|
+
|
|
574
|
+
$count = ($count + 1)
|
|
575
|
+
|
|
576
|
+
if ($count = (2)) {
|
|
577
|
+
$lib.trigger.add($tdef)
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
spin |
|
|
581
|
+
|
|
582
|
+
fini { return($trigs) }
|
|
583
|
+
'''
|
|
584
|
+
|
|
585
|
+
tdef = {'cond': 'node:add', 'form': 'it:dev:str', 'storm': '[inet:user=3] | testcmd'}
|
|
586
|
+
opts = {'vars': {'tdef': tdef}}
|
|
587
|
+
triggers = await core.callStorm(q, opts=opts)
|
|
588
|
+
self.len(2, triggers)
|
|
589
|
+
self.len(3, core.view.triggers.triggers)
|
|
590
|
+
|
|
468
591
|
async def test_syn_cmd_runts(self):
|
|
469
592
|
|
|
470
593
|
async with self.getTestDmon() as dmon:
|
|
@@ -554,6 +677,49 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
554
677
|
self.eq(nodes[0].get('output'), ('inet:fqdn',))
|
|
555
678
|
self.eq(nodes[0].get('nodedata'), (('foo', 'inet:ipv4'), ('bar', 'inet:fqdn')))
|
|
556
679
|
|
|
680
|
+
async with self.getTestCore() as core:
|
|
681
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
682
|
+
|
|
683
|
+
numcmds = len(core.stormcmds)
|
|
684
|
+
|
|
685
|
+
stormpkg = {
|
|
686
|
+
'name': 'stormpkg',
|
|
687
|
+
'version': '1.2.3',
|
|
688
|
+
'synapse_version': '>=2.8.0,<3.0.0',
|
|
689
|
+
'commands': (
|
|
690
|
+
{
|
|
691
|
+
'name': 'pkgcmd.old',
|
|
692
|
+
'storm': '$lib.print(hi)',
|
|
693
|
+
},
|
|
694
|
+
),
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
q = '''
|
|
698
|
+
init {
|
|
699
|
+
$cmds = ()
|
|
700
|
+
$count = (0)
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
syn:cmd
|
|
704
|
+
|
|
705
|
+
$cmds.append(({'name': $node.repr(), 'doc': :doc }))
|
|
706
|
+
|
|
707
|
+
$count = ($count + 1)
|
|
708
|
+
|
|
709
|
+
if ($count = (2)) {
|
|
710
|
+
$lib.pkg.add($pkgdef)
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
spin |
|
|
714
|
+
|
|
715
|
+
fini { return($cmds) }
|
|
716
|
+
'''
|
|
717
|
+
|
|
718
|
+
opts = {'vars': {'pkgdef': stormpkg}}
|
|
719
|
+
cmds = await core.callStorm(q, opts=opts)
|
|
720
|
+
self.len(numcmds, cmds)
|
|
721
|
+
self.len(numcmds + 1, core.stormcmds)
|
|
722
|
+
|
|
557
723
|
async def test_syn_cron_runts(self):
|
|
558
724
|
|
|
559
725
|
async with self.getTestCore() as core:
|
|
@@ -582,3 +748,35 @@ class SynModelTest(s_t_utils.SynTest):
|
|
|
582
748
|
self.eq(nodes[0].ndef, ('syn:cron', iden))
|
|
583
749
|
self.eq(nodes[0].get('doc'), 'hehe')
|
|
584
750
|
self.eq(nodes[0].get('name'), 'haha')
|
|
751
|
+
|
|
752
|
+
async with self.getTestCore() as core:
|
|
753
|
+
# Check we can iterate runt nodes while changing the underlying dictionary
|
|
754
|
+
|
|
755
|
+
q = '''
|
|
756
|
+
init {
|
|
757
|
+
$appts = ()
|
|
758
|
+
$count = (0)
|
|
759
|
+
|
|
760
|
+
cron.add --hour 1 --day 1 {#foo} |
|
|
761
|
+
cron.add --hour 2 --day 1 {#foo} |
|
|
762
|
+
cron.add --hour 3 --day 1 {#foo}
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
syn:cron
|
|
766
|
+
|
|
767
|
+
$appts.append(({'name': $node.repr(), 'doc': :doc }))
|
|
768
|
+
|
|
769
|
+
$count = ($count + 1)
|
|
770
|
+
|
|
771
|
+
if ($count = (2)) {
|
|
772
|
+
cron.add --hour 4 --day 1 {#foo}
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
spin |
|
|
776
|
+
|
|
777
|
+
fini { return($appts) }
|
|
778
|
+
'''
|
|
779
|
+
|
|
780
|
+
appts = await core.callStorm(q)
|
|
781
|
+
self.len(3, appts)
|
|
782
|
+
self.len(4, core.agenda.appts)
|
|
@@ -56,18 +56,6 @@ class UnivServerTest(s_t_utils.SynTest):
|
|
|
56
56
|
async with await s_telepath.openurl(f'cell://{dirn}') as proxy:
|
|
57
57
|
self.eq('cell', await proxy.getCellType())
|
|
58
58
|
|
|
59
|
-
argv = [
|
|
60
|
-
'synapse.tests.test_lib_cell.EchoAuth',
|
|
61
|
-
'--telepath', 'tcp://127.0.0.1:0/',
|
|
62
|
-
'--https', '0',
|
|
63
|
-
'--name', 'univtest',
|
|
64
|
-
dirn,
|
|
65
|
-
]
|
|
66
|
-
# Or start the Cortex off a a EchoAuth (don't do this in practice...)
|
|
67
|
-
async with await s_s_univ.main(argv) as cell:
|
|
68
|
-
async with await s_telepath.openurl(f'cell://{dirn}') as proxy:
|
|
69
|
-
self.eq('echoauth', await proxy.getCellType())
|
|
70
|
-
|
|
71
59
|
argv = ['synapse.lib.newp.Newp']
|
|
72
60
|
with self.raises(s_exc.NoSuchCtor):
|
|
73
61
|
async with await s_s_univ.main(argv) as core:
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
|
|
3
|
+
import synapse.exc as s_exc
|
|
4
|
+
import synapse.common as s_common
|
|
5
|
+
|
|
6
|
+
import synapse.lib.time as s_time
|
|
7
|
+
import synapse.lib.output as s_output
|
|
8
|
+
|
|
9
|
+
import synapse.tests.utils as s_test
|
|
10
|
+
import synapse.tools.apikey as s_t_apikey
|
|
11
|
+
|
|
12
|
+
async def getApiKeyByName(core, name):
|
|
13
|
+
keys = {k.get('name'): k async for k in core.getApiKeys()}
|
|
14
|
+
return keys.get(name)
|
|
15
|
+
|
|
16
|
+
class ApiKeyTest(s_test.SynTest):
|
|
17
|
+
|
|
18
|
+
async def test_tools_apikey(self):
|
|
19
|
+
async with self.getTestCore() as core:
|
|
20
|
+
|
|
21
|
+
await core.auth.addUser('blackout')
|
|
22
|
+
|
|
23
|
+
rooturl = core.getLocalUrl()
|
|
24
|
+
blckurl = core.getLocalUrl(user='blackout')
|
|
25
|
+
|
|
26
|
+
# Add API keys
|
|
27
|
+
argv = (
|
|
28
|
+
'--svcurl', rooturl,
|
|
29
|
+
'add',
|
|
30
|
+
'rootkey00',
|
|
31
|
+
'-d', '120',
|
|
32
|
+
)
|
|
33
|
+
outp = s_output.OutPutStr()
|
|
34
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
35
|
+
|
|
36
|
+
self.isin('Successfully added API key with name=rootkey00.', str(outp))
|
|
37
|
+
rootkey00 = await getApiKeyByName(core, 'rootkey00')
|
|
38
|
+
|
|
39
|
+
self.isin(f'Iden: {rootkey00.get("iden")}', str(outp))
|
|
40
|
+
self.isin(' API Key: ', str(outp))
|
|
41
|
+
self.isin(' Name: rootkey00', str(outp))
|
|
42
|
+
self.isin(f' Created: {s_time.repr(rootkey00.get("created"))}', str(outp))
|
|
43
|
+
self.isin(f' Updated: {s_time.repr(rootkey00.get("updated"))}', str(outp))
|
|
44
|
+
self.isin(f' Expires: {s_time.repr(rootkey00.get("expires"))}', str(outp))
|
|
45
|
+
self.eq(rootkey00.get('expires'), rootkey00.get('created') + 120000)
|
|
46
|
+
|
|
47
|
+
argv = (
|
|
48
|
+
'--svcurl', rooturl,
|
|
49
|
+
'add',
|
|
50
|
+
'-u', 'blackout',
|
|
51
|
+
'blckkey00',
|
|
52
|
+
)
|
|
53
|
+
outp = s_output.OutPutStr()
|
|
54
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
55
|
+
|
|
56
|
+
self.isin('Successfully added API key with name=blckkey00.', str(outp))
|
|
57
|
+
blckkey00 = await getApiKeyByName(core, 'blckkey00')
|
|
58
|
+
|
|
59
|
+
self.isin(f'Iden: {blckkey00.get("iden")}', str(outp))
|
|
60
|
+
self.isin(' API Key: ', str(outp))
|
|
61
|
+
self.isin(' Name: blckkey00', str(outp))
|
|
62
|
+
self.isin(f' Created: {s_time.repr(blckkey00.get("created"))}', str(outp))
|
|
63
|
+
self.isin(f' Updated: {s_time.repr(blckkey00.get("updated"))}', str(outp))
|
|
64
|
+
self.notin(' Expires: ', str(outp))
|
|
65
|
+
|
|
66
|
+
argv = (
|
|
67
|
+
'--svcurl', blckurl,
|
|
68
|
+
'add',
|
|
69
|
+
'blckkey01',
|
|
70
|
+
)
|
|
71
|
+
outp = s_output.OutPutStr()
|
|
72
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
73
|
+
|
|
74
|
+
self.isin('Successfully added API key with name=blckkey01.', str(outp))
|
|
75
|
+
blckkey01 = await getApiKeyByName(core, 'blckkey01')
|
|
76
|
+
|
|
77
|
+
self.isin(f'Iden: {blckkey01.get("iden")}', str(outp))
|
|
78
|
+
self.isin(' API Key: ', str(outp))
|
|
79
|
+
self.isin(' Name: blckkey01', str(outp))
|
|
80
|
+
self.isin(f' Created: {s_time.repr(blckkey01.get("created"))}', str(outp))
|
|
81
|
+
self.isin(f' Updated: {s_time.repr(blckkey01.get("updated"))}', str(outp))
|
|
82
|
+
self.notin(' Expires: ', str(outp))
|
|
83
|
+
|
|
84
|
+
# List API keys
|
|
85
|
+
argv = (
|
|
86
|
+
'--svcurl', rooturl,
|
|
87
|
+
'list',
|
|
88
|
+
)
|
|
89
|
+
outp = s_output.OutPutStr()
|
|
90
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
91
|
+
|
|
92
|
+
self.isin(f'Iden: {rootkey00.get("iden")}', str(outp))
|
|
93
|
+
self.notin(' API Key: ', str(outp))
|
|
94
|
+
self.isin(' Name: rootkey00', str(outp))
|
|
95
|
+
self.isin(f' Created: {s_time.repr(rootkey00.get("created"))}', str(outp))
|
|
96
|
+
self.isin(f' Updated: {s_time.repr(rootkey00.get("updated"))}', str(outp))
|
|
97
|
+
self.isin(f' Expires: {s_time.repr(rootkey00.get("expires"))}', str(outp))
|
|
98
|
+
self.eq(rootkey00.get('expires'), rootkey00.get('created') + 120000)
|
|
99
|
+
|
|
100
|
+
argv = (
|
|
101
|
+
'--svcurl', rooturl,
|
|
102
|
+
'list',
|
|
103
|
+
'-u', 'blackout',
|
|
104
|
+
)
|
|
105
|
+
outp = s_output.OutPutStr()
|
|
106
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
107
|
+
|
|
108
|
+
self.isin(f'Iden: {blckkey00.get("iden")}', str(outp))
|
|
109
|
+
self.notin(' API Key: ', str(outp))
|
|
110
|
+
self.isin(' Name: blckkey00', str(outp))
|
|
111
|
+
self.isin(f' Created: {s_time.repr(blckkey00.get("created"))}', str(outp))
|
|
112
|
+
self.isin(f' Updated: {s_time.repr(blckkey00.get("updated"))}', str(outp))
|
|
113
|
+
self.notin(' Expires: ', str(outp))
|
|
114
|
+
|
|
115
|
+
self.isin(f'Iden: {blckkey01.get("iden")}', str(outp))
|
|
116
|
+
self.notin(' API Key: ', str(outp))
|
|
117
|
+
self.isin(' Name: blckkey01', str(outp))
|
|
118
|
+
self.isin(f' Created: {s_time.repr(blckkey01.get("created"))}', str(outp))
|
|
119
|
+
self.isin(f' Updated: {s_time.repr(blckkey01.get("updated"))}', str(outp))
|
|
120
|
+
self.notin(' Expires: ', str(outp))
|
|
121
|
+
|
|
122
|
+
argv = (
|
|
123
|
+
'--svcurl', blckurl,
|
|
124
|
+
'list',
|
|
125
|
+
)
|
|
126
|
+
outp = s_output.OutPutStr()
|
|
127
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
128
|
+
|
|
129
|
+
self.isin(f'Iden: {blckkey00.get("iden")}', str(outp))
|
|
130
|
+
self.notin(' API Key: ', str(outp))
|
|
131
|
+
self.isin(' Name: blckkey00', str(outp))
|
|
132
|
+
self.isin(f' Created: {s_time.repr(blckkey00.get("created"))}', str(outp))
|
|
133
|
+
self.isin(f' Updated: {s_time.repr(blckkey00.get("updated"))}', str(outp))
|
|
134
|
+
self.notin(' Expires: ', str(outp))
|
|
135
|
+
|
|
136
|
+
self.isin(f'Iden: {blckkey01.get("iden")}', str(outp))
|
|
137
|
+
self.notin(' API Key: ', str(outp))
|
|
138
|
+
self.isin(' Name: blckkey01', str(outp))
|
|
139
|
+
self.isin(f' Created: {s_time.repr(blckkey01.get("created"))}', str(outp))
|
|
140
|
+
self.isin(f' Updated: {s_time.repr(blckkey01.get("updated"))}', str(outp))
|
|
141
|
+
self.notin(' Expires: ', str(outp))
|
|
142
|
+
|
|
143
|
+
# Delete API keys
|
|
144
|
+
rootiden00 = rootkey00.get('iden')
|
|
145
|
+
argv = (
|
|
146
|
+
'--svcurl', rooturl,
|
|
147
|
+
'del',
|
|
148
|
+
rootiden00,
|
|
149
|
+
)
|
|
150
|
+
outp = s_output.OutPutStr()
|
|
151
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
152
|
+
self.isin(f'Successfully deleted API key with iden={rootiden00}.', str(outp))
|
|
153
|
+
|
|
154
|
+
blckiden00 = blckkey00.get('iden')
|
|
155
|
+
argv = (
|
|
156
|
+
'--svcurl', rooturl,
|
|
157
|
+
'del',
|
|
158
|
+
blckiden00,
|
|
159
|
+
)
|
|
160
|
+
outp = s_output.OutPutStr()
|
|
161
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
162
|
+
self.isin(f'Successfully deleted API key with iden={blckiden00}.', str(outp))
|
|
163
|
+
|
|
164
|
+
blckiden01 = blckkey01.get('iden')
|
|
165
|
+
argv = (
|
|
166
|
+
'--svcurl', blckurl,
|
|
167
|
+
'del',
|
|
168
|
+
blckiden01,
|
|
169
|
+
)
|
|
170
|
+
outp = s_output.OutPutStr()
|
|
171
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
172
|
+
self.isin(f'Successfully deleted API key with iden={blckiden01}.', str(outp))
|
|
173
|
+
|
|
174
|
+
# List API keys again
|
|
175
|
+
argv = (
|
|
176
|
+
'--svcurl', rooturl,
|
|
177
|
+
'list',
|
|
178
|
+
)
|
|
179
|
+
outp = s_output.OutPutStr()
|
|
180
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
181
|
+
self.isin('No API keys found.', str(outp))
|
|
182
|
+
|
|
183
|
+
argv = (
|
|
184
|
+
'--svcurl', rooturl,
|
|
185
|
+
'list',
|
|
186
|
+
'-u', 'blackout',
|
|
187
|
+
)
|
|
188
|
+
outp = s_output.OutPutStr()
|
|
189
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
190
|
+
self.isin('No API keys found.', str(outp))
|
|
191
|
+
|
|
192
|
+
argv = (
|
|
193
|
+
'--svcurl', blckurl,
|
|
194
|
+
'list',
|
|
195
|
+
)
|
|
196
|
+
outp = s_output.OutPutStr()
|
|
197
|
+
self.eq(0, await s_t_apikey.main(argv, outp=outp))
|
|
198
|
+
self.isin('No API keys found.', str(outp))
|
|
199
|
+
|
|
200
|
+
# Check errors
|
|
201
|
+
argv = (
|
|
202
|
+
'--svcurl', rooturl,
|
|
203
|
+
'list',
|
|
204
|
+
'-u', 'newp',
|
|
205
|
+
)
|
|
206
|
+
outp = s_output.OutPutStr()
|
|
207
|
+
self.eq(1, await s_t_apikey.main(argv, outp=outp))
|
|
208
|
+
self.isin('ERROR: NoSuchUser: No user named newp.', str(outp))
|
|
209
|
+
|
|
210
|
+
argv = (
|
|
211
|
+
'--svcurl', blckurl,
|
|
212
|
+
'list',
|
|
213
|
+
'-u', 'root',
|
|
214
|
+
)
|
|
215
|
+
outp = s_output.OutPutStr()
|
|
216
|
+
self.eq(1, await s_t_apikey.main(argv, outp=outp))
|
|
217
|
+
self.isin('ERROR: AuthDeny: getUserInfo denied for non-admin and non-self', str(outp))
|
|
218
|
+
|
|
219
|
+
newpiden = s_common.guid()
|
|
220
|
+
argv = (
|
|
221
|
+
'--svcurl', rooturl,
|
|
222
|
+
'del',
|
|
223
|
+
newpiden,
|
|
224
|
+
)
|
|
225
|
+
outp = s_output.OutPutStr()
|
|
226
|
+
self.eq(1, await s_t_apikey.main(argv, outp=outp))
|
|
227
|
+
self.isin(f"ERROR: NoSuchIden: User API key with iden='{newpiden}' does not exist.", str(outp))
|
synapse/tests/test_utils.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import time
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
4
5
|
import unittest
|
|
5
6
|
|
|
@@ -109,13 +110,13 @@ class TestUtils(s_t_utils.SynTest):
|
|
|
109
110
|
def test_syntest_logstream_event(self):
|
|
110
111
|
|
|
111
112
|
@s_common.firethread
|
|
112
|
-
def logathing():
|
|
113
|
+
def logathing(mesg):
|
|
113
114
|
time.sleep(0.01)
|
|
114
|
-
logger.error(
|
|
115
|
+
logger.error(mesg)
|
|
115
116
|
|
|
116
117
|
logger.error('notthere')
|
|
117
118
|
with self.getLoggerStream('synapse.tests.test_utils', 'Test Message') as stream:
|
|
118
|
-
thr = logathing()
|
|
119
|
+
thr = logathing('StreamEvent Test Message')
|
|
119
120
|
self.true(stream.wait(10))
|
|
120
121
|
thr.join()
|
|
121
122
|
|
|
@@ -124,16 +125,34 @@ class TestUtils(s_t_utils.SynTest):
|
|
|
124
125
|
self.isin('StreamEvent Test Message', mesgs)
|
|
125
126
|
self.notin('notthere', mesgs)
|
|
126
127
|
|
|
128
|
+
with self.getLoggerStream('synapse.tests.test_utils', 'Test Message') as stream:
|
|
129
|
+
thr = logathing(json.dumps({'mesg': 'Test Message'}))
|
|
130
|
+
self.true(stream.wait(10))
|
|
131
|
+
thr.join()
|
|
132
|
+
|
|
133
|
+
msgs = stream.jsonlines()
|
|
134
|
+
self.len(1, msgs)
|
|
135
|
+
self.eq(msgs[0], {'mesg': 'Test Message'})
|
|
136
|
+
|
|
127
137
|
def test_syntest_envars(self):
|
|
128
138
|
os.environ['foo'] = '1'
|
|
129
139
|
os.environ['bar'] = '2'
|
|
130
140
|
|
|
131
|
-
with self.setTstEnvars(foo=1, bar='joke', baz=1234) as cm:
|
|
141
|
+
with self.setTstEnvars(foo=1, bar='joke', baz=1234, FOO_THING=1, BAR_THING=0) as cm:
|
|
132
142
|
self.none(cm)
|
|
133
143
|
self.eq(os.environ.get('foo'), '1')
|
|
134
144
|
self.eq(os.environ.get('bar'), 'joke')
|
|
135
145
|
self.eq(os.environ.get('baz'), '1234')
|
|
136
146
|
|
|
147
|
+
self.thisEnvMust('FOO_THING', 'baz')
|
|
148
|
+
self.thisEnvMustNot('BAR_THING', 'NEWP_THING')
|
|
149
|
+
with self.raises(unittest.SkipTest):
|
|
150
|
+
self.thisEnvMust('MEWP_THING')
|
|
151
|
+
with self.raises(unittest.SkipTest):
|
|
152
|
+
self.thisEnvMust('BAR_THING')
|
|
153
|
+
with self.raises(unittest.SkipTest):
|
|
154
|
+
self.thisEnvMustNot('FOO_THING')
|
|
155
|
+
|
|
137
156
|
self.eq(os.environ.get('foo'), '1')
|
|
138
157
|
self.eq(os.environ.get('bar'), '2')
|
|
139
158
|
self.none(os.environ.get('baz'))
|
synapse/tests/utils.py
CHANGED
|
@@ -21,9 +21,11 @@ import io
|
|
|
21
21
|
import os
|
|
22
22
|
import sys
|
|
23
23
|
import copy
|
|
24
|
+
import json
|
|
24
25
|
import math
|
|
25
26
|
import types
|
|
26
27
|
import shutil
|
|
28
|
+
import typing
|
|
27
29
|
import asyncio
|
|
28
30
|
import hashlib
|
|
29
31
|
import inspect
|
|
@@ -97,6 +99,10 @@ def norm(z):
|
|
|
97
99
|
def deguidify(x):
|
|
98
100
|
return regex.sub('[0-9a-f]{32}', '*' * 32, x)
|
|
99
101
|
|
|
102
|
+
def jsonlines(text: str):
|
|
103
|
+
lines = [k for k in text.split('\n') if k]
|
|
104
|
+
return [json.loads(line) for line in lines]
|
|
105
|
+
|
|
100
106
|
async def waitForBehold(core, events):
|
|
101
107
|
async for mesg in core.behold():
|
|
102
108
|
for event in list(events):
|
|
@@ -789,6 +795,10 @@ class StreamEvent(io.StringIO, threading.Event):
|
|
|
789
795
|
if self.mesg and self.mesg in s:
|
|
790
796
|
self.set()
|
|
791
797
|
|
|
798
|
+
def jsonlines(self) -> typing.List[dict]:
|
|
799
|
+
'''Get the messages as jsonlines. May throw Json errors if the captured stream is not jsonlines.'''
|
|
800
|
+
return jsonlines(self.getvalue())
|
|
801
|
+
|
|
792
802
|
class AsyncStreamEvent(io.StringIO, asyncio.Event):
|
|
793
803
|
'''
|
|
794
804
|
A combination of a io.StringIO object and an asyncio.Event object.
|
|
@@ -821,6 +831,10 @@ class AsyncStreamEvent(io.StringIO, asyncio.Event):
|
|
|
821
831
|
return await asyncio.Event.wait(self)
|
|
822
832
|
return await s_coro.event_wait(self, timeout=timeout)
|
|
823
833
|
|
|
834
|
+
def jsonlines(self) -> typing.List[dict]:
|
|
835
|
+
'''Get the messages as jsonlines. May throw Json errors if the captured stream is not jsonlines.'''
|
|
836
|
+
return jsonlines(self.getvalue())
|
|
837
|
+
|
|
824
838
|
class HttpReflector(s_httpapi.Handler):
|
|
825
839
|
'''Test handler which reflects get/post data back to the caller'''
|
|
826
840
|
|
|
@@ -1126,6 +1140,28 @@ class SynTest(unittest.TestCase):
|
|
|
1126
1140
|
'''
|
|
1127
1141
|
return TstOutPut()
|
|
1128
1142
|
|
|
1143
|
+
def thisEnvMust(self, *envvars):
|
|
1144
|
+
'''
|
|
1145
|
+
Requires a host must have environment variables set to truthy values.
|
|
1146
|
+
|
|
1147
|
+
Args:
|
|
1148
|
+
*envars: Environment variables to require being present.
|
|
1149
|
+
'''
|
|
1150
|
+
for envar in envvars:
|
|
1151
|
+
if not s_common.envbool(envar):
|
|
1152
|
+
self.skip(f'Envar {envar} is not set to a truthy value.')
|
|
1153
|
+
|
|
1154
|
+
def thisEnvMustNot(self, *envvars):
|
|
1155
|
+
'''
|
|
1156
|
+
Requires a host must not have environment variables set to truthy values.
|
|
1157
|
+
|
|
1158
|
+
Args:
|
|
1159
|
+
*envars: Environment variables to require being absent or set to falsey values.
|
|
1160
|
+
'''
|
|
1161
|
+
for envar in envvars:
|
|
1162
|
+
if s_common.envbool(envar):
|
|
1163
|
+
self.skip(f'Envar {envar} is set to a truthy value.')
|
|
1164
|
+
|
|
1129
1165
|
def thisHostMust(self, **props): # pragma: no cover
|
|
1130
1166
|
'''
|
|
1131
1167
|
Requires a host having a specific property.
|
|
@@ -1719,7 +1755,7 @@ class SynTest(unittest.TestCase):
|
|
|
1719
1755
|
slogger.setLevel(level)
|
|
1720
1756
|
|
|
1721
1757
|
@contextlib.contextmanager
|
|
1722
|
-
def getAsyncLoggerStream(self, logname, mesg=''):
|
|
1758
|
+
def getAsyncLoggerStream(self, logname, mesg='') -> contextlib.AbstractContextManager[StreamEvent, None, None]:
|
|
1723
1759
|
'''
|
|
1724
1760
|
Async version of getLoggerStream.
|
|
1725
1761
|
|
|
@@ -1764,7 +1800,7 @@ class SynTest(unittest.TestCase):
|
|
|
1764
1800
|
slogger.setLevel(level)
|
|
1765
1801
|
|
|
1766
1802
|
@contextlib.contextmanager
|
|
1767
|
-
def getStructuredAsyncLoggerStream(self, logname, mesg=''):
|
|
1803
|
+
def getStructuredAsyncLoggerStream(self, logname, mesg='') -> contextlib.AbstractContextManager[AsyncStreamEvent, None, None]:
|
|
1768
1804
|
'''
|
|
1769
1805
|
Async version of getLoggerStream which uses structured logging.
|
|
1770
1806
|
|
|
@@ -1787,9 +1823,7 @@ class SynTest(unittest.TestCase):
|
|
|
1787
1823
|
# Wait for the mesg to be written to the stream
|
|
1788
1824
|
await stream.wait(timeout=10)
|
|
1789
1825
|
|
|
1790
|
-
|
|
1791
|
-
raw_mesgs = [m for m in data.split('\n') if m]
|
|
1792
|
-
msgs = [json.loads(m) for m in raw_mesgs]
|
|
1826
|
+
msgs = stream.jsonlines()
|
|
1793
1827
|
# Do something with messages
|
|
1794
1828
|
|
|
1795
1829
|
Returns:
|