synapse 2.209.0__py311-none-any.whl → 2.211.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/lib/base.py +2 -3
- synapse/lib/cell.py +14 -4
- synapse/lib/coro.py +5 -0
- synapse/lib/json.py +48 -22
- synapse/lib/nexus.py +6 -0
- synapse/lib/node.py +1 -1
- synapse/lib/schemas.py +10 -1
- synapse/lib/share.py +0 -3
- synapse/lib/snap.py +3 -0
- synapse/lib/storm.py +10 -2
- synapse/lib/stormlib/auth.py +6 -0
- synapse/lib/stormlib/notifications.py +12 -2
- synapse/lib/stormtypes.py +2 -2
- synapse/lib/version.py +2 -2
- synapse/models/entity.py +26 -0
- synapse/models/inet.py +55 -0
- synapse/models/orgs.py +0 -1
- synapse/models/person.py +9 -2
- synapse/tests/test_cortex.py +3 -3
- synapse/tests/test_lib_aha.py +1 -1
- synapse/tests/test_lib_base.py +5 -0
- synapse/tests/test_lib_cell.py +28 -8
- synapse/tests/test_lib_coro.py +23 -0
- synapse/tests/test_lib_json.py +41 -16
- synapse/tests/test_lib_storm.py +20 -0
- synapse/tests/test_lib_stormtypes.py +16 -18
- synapse/tests/test_lib_view.py +14 -0
- synapse/tests/test_model_entity.py +21 -0
- synapse/tests/test_model_gov_intl.py +2 -2
- synapse/tests/test_model_inet.py +30 -0
- synapse/tests/test_model_media.py +1 -0
- synapse/tests/test_model_orgs.py +18 -2
- synapse/tests/test_model_person.py +12 -0
- synapse/tests/test_telepath.py +52 -41
- synapse/tests/test_tools_aha.py +7 -8
- synapse/tests/test_tools_genpkg.py +9 -0
- synapse/tests/utils.py +1 -1
- synapse/tools/aha/clone.py +7 -1
- synapse/tools/aha/easycert.py +37 -42
- synapse/tools/aha/enroll.py +7 -1
- synapse/tools/aha/list.py +60 -65
- synapse/tools/aha/mirror.py +7 -1
- synapse/tools/aha/provision/service.py +7 -1
- synapse/tools/aha/provision/user.py +7 -1
- synapse/tools/apikey.py +8 -1
- synapse/tools/autodoc.py +8 -2
- synapse/tools/axon2axon.py +7 -1
- synapse/tools/cellauth.py +6 -5
- synapse/tools/cmdr.py +2 -1
- synapse/tools/csvtool.py +7 -2
- synapse/tools/feed.py +8 -2
- synapse/tools/genpkg.py +16 -3
- synapse/tools/healthcheck.py +7 -1
- synapse/tools/livebackup.py +7 -3
- synapse/tools/modrole.py +7 -1
- synapse/tools/moduser.py +7 -2
- synapse/tools/promote.py +7 -3
- synapse/tools/pullfile.py +6 -1
- synapse/tools/pushfile.py +7 -1
- synapse/tools/reload.py +7 -4
- synapse/tools/rstorm.py +8 -2
- synapse/tools/snapshot.py +7 -1
- synapse/tools/storm.py +7 -1
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/METADATA +2 -2
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/RECORD +68 -67
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/WHEEL +1 -1
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.209.0.dist-info → synapse-2.211.0.dist-info}/top_level.txt +0 -0
synapse/tests/test_lib_aha.py
CHANGED
|
@@ -781,7 +781,7 @@ class AhaTest(s_test.SynTest):
|
|
|
781
781
|
self.false(axon3.isactive)
|
|
782
782
|
self.eq('aha://root@axon...', axon03.conf.get('mirror'))
|
|
783
783
|
|
|
784
|
-
retn, outp = await self.execToolMain(s_a_list.
|
|
784
|
+
retn, outp = await self.execToolMain(s_a_list.main, [aha.getLocalUrl()])
|
|
785
785
|
self.eq(retn, 0)
|
|
786
786
|
outp.expect('Service network leader')
|
|
787
787
|
outp.expect('00.axon synapse True')
|
synapse/tests/test_lib_base.py
CHANGED
|
@@ -86,6 +86,11 @@ class BaseTest(s_t_utils.SynTest):
|
|
|
86
86
|
await Hehe.anit(-1)
|
|
87
87
|
self.eq(cm.exception.get('mesg'), 'boom')
|
|
88
88
|
|
|
89
|
+
if __debug__:
|
|
90
|
+
with self.raises(AssertionError) as cm:
|
|
91
|
+
Hehe()
|
|
92
|
+
self.eq(str(cm.exception), 'Objects from Base must be constructed solely via "anit"')
|
|
93
|
+
|
|
89
94
|
async def test_coro_fini(self):
|
|
90
95
|
|
|
91
96
|
event = asyncio.Event()
|
synapse/tests/test_lib_cell.py
CHANGED
|
@@ -2238,7 +2238,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
2238
2238
|
self.false(core00.isactive)
|
|
2239
2239
|
|
|
2240
2240
|
modinfo = s_common.yamlload(core00.dirn, 'cell.mods.yaml')
|
|
2241
|
-
self.
|
|
2241
|
+
self.eq('aha://root@core...', modinfo.get('mirror', ''))
|
|
2242
2242
|
modinfo = s_common.yamlload(core01.dirn, 'cell.mods.yaml')
|
|
2243
2243
|
self.none(modinfo.get('mirror'))
|
|
2244
2244
|
|
|
@@ -2321,7 +2321,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
2321
2321
|
self.false(core00.isactive)
|
|
2322
2322
|
|
|
2323
2323
|
modinfo = s_common.yamlload(core00.dirn, 'cell.mods.yaml')
|
|
2324
|
-
self.
|
|
2324
|
+
self.eq('aha://root@core...', modinfo.get('mirror', ''))
|
|
2325
2325
|
modinfo = s_common.yamlload(core01.dirn, 'cell.mods.yaml')
|
|
2326
2326
|
self.none(modinfo.get('mirror'))
|
|
2327
2327
|
|
|
@@ -2333,7 +2333,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
2333
2333
|
modinfo = s_common.yamlload(core00.dirn, 'cell.mods.yaml')
|
|
2334
2334
|
self.none(modinfo.get('mirror'))
|
|
2335
2335
|
modinfo = s_common.yamlload(core01.dirn, 'cell.mods.yaml')
|
|
2336
|
-
self.
|
|
2336
|
+
self.eq('aha://root@core...', modinfo.get('mirror', ''))
|
|
2337
2337
|
|
|
2338
2338
|
# Backup the mirror (core01) which points to the core00
|
|
2339
2339
|
async with await axon00.upload() as upfd:
|
|
@@ -3285,6 +3285,7 @@ class CellTest(s_t_utils.SynTest):
|
|
|
3285
3285
|
dirn00 = s_common.genpath(dirn, '00.cell')
|
|
3286
3286
|
dirn01 = s_common.genpath(dirn, '01.cell')
|
|
3287
3287
|
dirn02 = s_common.genpath(dirn, '02.cell')
|
|
3288
|
+
dirn0002 = s_common.genpath(dirn, '00.02.cell')
|
|
3288
3289
|
|
|
3289
3290
|
cell00 = await base.enter_context(self.addSvcToAha(aha, '00.cell', s_cell.Cell, dirn=dirn00))
|
|
3290
3291
|
cell01 = await base.enter_context(self.addSvcToAha(aha, '01.cell', s_cell.Cell, dirn=dirn01,
|
|
@@ -3301,24 +3302,43 @@ class CellTest(s_t_utils.SynTest):
|
|
|
3301
3302
|
await cell01.handoff('some://url')
|
|
3302
3303
|
self.isin('01.cell is not the current leader', cm.exception.get('mesg'))
|
|
3303
3304
|
|
|
3304
|
-
#
|
|
3305
|
-
# control over the topology update is available during the promotion process.
|
|
3306
|
-
# Promote 02.cell -> Promote 01.cell -> Promote 00.cell -> BadState exception
|
|
3305
|
+
# Promote 02.cell -> Promote 01.cell -> Promote 00.cell, without breaking the configured topology
|
|
3307
3306
|
await cell02.promote(graceful=True)
|
|
3308
3307
|
self.false(cell00.isactive)
|
|
3308
|
+
self.eq(cell00.conf.get('mirror'), 'aha://root@cell...')
|
|
3309
3309
|
self.false(cell01.isactive)
|
|
3310
|
+
self.eq(cell01.conf.get('mirror'), 'aha://root@cell...')
|
|
3310
3311
|
self.true(cell02.isactive)
|
|
3312
|
+
self.none(cell02.conf.get('mirror'))
|
|
3311
3313
|
await cell02.sync()
|
|
3312
3314
|
|
|
3313
3315
|
await cell01.promote(graceful=True)
|
|
3314
3316
|
self.false(cell00.isactive)
|
|
3317
|
+
self.eq(cell00.conf.get('mirror'), 'aha://root@cell...')
|
|
3315
3318
|
self.true(cell01.isactive)
|
|
3319
|
+
self.none(cell01.conf.get('mirror'))
|
|
3316
3320
|
self.false(cell02.isactive)
|
|
3321
|
+
self.eq(cell02.conf.get('mirror'), 'aha://root@cell...')
|
|
3317
3322
|
await cell02.sync()
|
|
3318
3323
|
|
|
3324
|
+
await cell00.promote(graceful=True)
|
|
3325
|
+
self.true(cell00.isactive)
|
|
3326
|
+
self.none(cell00.conf.get('mirror'))
|
|
3327
|
+
self.false(cell01.isactive)
|
|
3328
|
+
self.eq(cell01.conf.get('mirror'), 'aha://root@cell...')
|
|
3329
|
+
self.false(cell02.isactive)
|
|
3330
|
+
self.eq(cell02.conf.get('mirror'), 'aha://root@cell...')
|
|
3331
|
+
await cell02.sync()
|
|
3332
|
+
|
|
3333
|
+
# A follower of a follower cannot be promoted up since its leader is not the active cell.
|
|
3334
|
+
cell0002 = await base.enter_context(self.addSvcToAha(aha, '00.02.cell', s_cell.Cell, dirn=dirn0002,
|
|
3335
|
+
provinfo={'mirror': '02.cell'}))
|
|
3336
|
+
self.false(cell0002.isactive)
|
|
3337
|
+
self.eq(cell0002.conf.get('mirror'), 'aha://root@02.cell...')
|
|
3319
3338
|
with self.raises(s_exc.BadState) as cm:
|
|
3320
|
-
await
|
|
3321
|
-
|
|
3339
|
+
await cell0002.promote(graceful=True)
|
|
3340
|
+
mesg = 'ahaname=02.cell is not the current leader and cannot handoff leadership to aha://00.02.cell.synapse.'
|
|
3341
|
+
self.isin(mesg, cm.exception.get('mesg'))
|
|
3322
3342
|
|
|
3323
3343
|
async def test_cell_get_aha_proxy(self):
|
|
3324
3344
|
|
synapse/tests/test_lib_coro.py
CHANGED
|
@@ -212,3 +212,26 @@ class CoroTest(s_t_utils.SynTest):
|
|
|
212
212
|
|
|
213
213
|
with self.raises(Exception):
|
|
214
214
|
await s_coro._parserforked(newp)
|
|
215
|
+
|
|
216
|
+
async def test_lib_coro_create_task(self):
|
|
217
|
+
|
|
218
|
+
async def sleep(n):
|
|
219
|
+
await asyncio.sleep(n)
|
|
220
|
+
if n == 0:
|
|
221
|
+
return 1 / 0
|
|
222
|
+
return n
|
|
223
|
+
|
|
224
|
+
s_coro.create_task(sleep(0.1))
|
|
225
|
+
s_coro.create_task(sleep(0.15))
|
|
226
|
+
s_coro.create_task(sleep(0.2))
|
|
227
|
+
self.len(3, s_coro.bgtasks)
|
|
228
|
+
results = await s_coro.await_bg_tasks()
|
|
229
|
+
self.eq(set(results), {0.1, 0.15, 0.2})
|
|
230
|
+
self.len(0, s_coro.bgtasks)
|
|
231
|
+
results = await s_coro.await_bg_tasks()
|
|
232
|
+
self.eq(results, [])
|
|
233
|
+
|
|
234
|
+
s_coro.create_task(sleep(0))
|
|
235
|
+
results = await s_coro.await_bg_tasks()
|
|
236
|
+
self.len(1, results)
|
|
237
|
+
self.isinstance(results[0], ZeroDivisionError)
|
synapse/tests/test_lib_json.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import io
|
|
2
2
|
import json
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import yyjson
|
|
5
5
|
|
|
6
6
|
import synapse.exc as s_exc
|
|
7
7
|
import synapse.common as s_common
|
|
@@ -44,9 +44,9 @@ class JsonTest(s_test.SynTest):
|
|
|
44
44
|
inval = '{"a": "😀\ud83d\ude47"}'
|
|
45
45
|
outval = {'a': '😀\ud83d\ude47'}
|
|
46
46
|
|
|
47
|
-
#
|
|
48
|
-
with self.raises(
|
|
49
|
-
|
|
47
|
+
# yyjson.loads fails because of the surrogate pairs
|
|
48
|
+
with self.raises(ValueError):
|
|
49
|
+
yyjson.loads(inval)
|
|
50
50
|
|
|
51
51
|
# stdlib json.loads passes because of voodoo magic
|
|
52
52
|
self.eq(outval, json.loads(inval))
|
|
@@ -63,9 +63,9 @@ class JsonTest(s_test.SynTest):
|
|
|
63
63
|
inval = {'a': '😀\ud83d\ude47'}
|
|
64
64
|
outval = b'{"a": "\\ud83d\\ude00\\ud83d\\ude47"}'
|
|
65
65
|
|
|
66
|
-
#
|
|
67
|
-
with self.raises(
|
|
68
|
-
|
|
66
|
+
# yyjson.dumps fails because of the surrogate pairs
|
|
67
|
+
with self.raises(UnicodeEncodeError):
|
|
68
|
+
yyjson.dumps(inval)
|
|
69
69
|
|
|
70
70
|
# stdlib json.dumps passes because of voodoo magic
|
|
71
71
|
self.eq(outval.decode(), json.dumps(inval))
|
|
@@ -85,15 +85,15 @@ class JsonTest(s_test.SynTest):
|
|
|
85
85
|
|
|
86
86
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
87
87
|
s_json.dumps({}.items())
|
|
88
|
-
self.eq(exc.exception.get('mesg'), '
|
|
88
|
+
self.eq(exc.exception.get('mesg'), "TypeError: Object of type 'dict_items' is not JSON serializable")
|
|
89
89
|
|
|
90
90
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
91
91
|
s_json.dumps({1: 'foo'})
|
|
92
|
-
self.eq(exc.exception.get('mesg'),
|
|
92
|
+
self.eq(exc.exception.get('mesg'), "TypeError: Dictionary keys must be strings")
|
|
93
93
|
|
|
94
94
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
95
95
|
s_json.dumps({'\ud83d\ude47': {}.items()})
|
|
96
|
-
self.eq(exc.exception.get('mesg'),
|
|
96
|
+
self.eq(exc.exception.get('mesg'), "TypeError: Dictionary keys must be strings")
|
|
97
97
|
|
|
98
98
|
self.eq(b'"dict_items([])"', s_json.dumps({}.items(), default=str))
|
|
99
99
|
|
|
@@ -111,6 +111,20 @@ class JsonTest(s_test.SynTest):
|
|
|
111
111
|
s_json.dump({'c': 'd', 'a': 'b'}, buf)
|
|
112
112
|
self.eq(b'{"c":"d","a":"b"}', buf.getvalue())
|
|
113
113
|
|
|
114
|
+
async def test_lib_json_large_integers(self):
|
|
115
|
+
valu = [
|
|
116
|
+
1, 2,
|
|
117
|
+
-1, -2,
|
|
118
|
+
1.0, 2.0,
|
|
119
|
+
-1.0, -2.0,
|
|
120
|
+
2**63, -2**63, -2**63 - 1,
|
|
121
|
+
2**64, -2**64, 2**64 + 1,
|
|
122
|
+
2**128, 2**128 + 1,
|
|
123
|
+
-2**128, -2**128 - 1,
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
self.eq(valu, s_json.loads(s_json.dumps(valu)))
|
|
127
|
+
|
|
114
128
|
async def test_jsload(self):
|
|
115
129
|
with self.getTestDir() as dirn:
|
|
116
130
|
with s_common.genfile(dirn, 'jsload.json') as fp:
|
|
@@ -147,41 +161,52 @@ class JsonTest(s_test.SynTest):
|
|
|
147
161
|
|
|
148
162
|
buf = io.BytesIO()
|
|
149
163
|
|
|
164
|
+
msg = "Object of type '_io.BytesIO' is not JSON serializable"
|
|
150
165
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
151
166
|
s_json.reqjsonsafe(buf)
|
|
152
|
-
self.isin(
|
|
167
|
+
self.isin(msg, exc.exception.get('mesg'))
|
|
153
168
|
|
|
154
169
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
155
170
|
s_json.reqjsonsafe({'foo': buf})
|
|
156
|
-
self.isin(
|
|
171
|
+
self.isin(msg, exc.exception.get('mesg'))
|
|
157
172
|
|
|
158
173
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
159
174
|
s_json.reqjsonsafe(['foo', buf])
|
|
160
|
-
self.isin(
|
|
175
|
+
self.isin(msg, exc.exception.get('mesg'))
|
|
161
176
|
|
|
162
177
|
items = (
|
|
163
178
|
(None, None),
|
|
164
179
|
(1234, None),
|
|
165
180
|
('1234', None),
|
|
181
|
+
('1234"', None),
|
|
166
182
|
({'asdf': 'haha'}, None),
|
|
167
183
|
({'a': (1,), 'b': [{'': 4}, 56, None, {'t': True, 'f': False}, 'oh my']}, None),
|
|
168
184
|
(b'1234', s_exc.MustBeJsonSafe),
|
|
185
|
+
(b'1234"', s_exc.MustBeJsonSafe),
|
|
186
|
+
({'a': float('nan')}, s_exc.MustBeJsonSafe),
|
|
169
187
|
({'a': 'a', 2: 2}, s_exc.MustBeJsonSafe),
|
|
170
188
|
({'a', 'b', 'c'}, s_exc.MustBeJsonSafe),
|
|
171
189
|
(s_common.novalu, s_exc.MustBeJsonSafe),
|
|
172
190
|
)
|
|
173
191
|
for (item, eret) in items:
|
|
174
192
|
if eret is None:
|
|
175
|
-
self.none(s_json.reqjsonsafe(item))
|
|
193
|
+
self.none(s_json.reqjsonsafe(item), msg=item)
|
|
176
194
|
else:
|
|
177
195
|
with self.raises(eret):
|
|
178
196
|
s_json.reqjsonsafe(item)
|
|
179
197
|
|
|
180
|
-
text
|
|
198
|
+
for text in ['😀', 'asdf', 'asdf"', '"asdf']:
|
|
199
|
+
s_json.reqjsonsafe(text)
|
|
200
|
+
|
|
201
|
+
text = ['😀\ud83d\ude47']
|
|
181
202
|
s_json.reqjsonsafe(text)
|
|
182
203
|
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
183
204
|
s_json.reqjsonsafe(text, strict=True)
|
|
184
|
-
self.eq(exc.exception.get('mesg'), '
|
|
205
|
+
self.eq(exc.exception.get('mesg'), "'utf-8' codec can't encode characters in position 1-2: surrogates not allowed")
|
|
206
|
+
|
|
207
|
+
with self.raises(s_exc.MustBeJsonSafe) as exc:
|
|
208
|
+
s_json.reqjsonsafe(b'1234', strict=True)
|
|
209
|
+
self.eq(exc.exception.get('mesg'), 'Object of type bytes is not JSON serializable')
|
|
185
210
|
|
|
186
211
|
async def test_lib_json_data_at_rest(self):
|
|
187
212
|
async with self.getRegrCore('json-data') as core:
|
synapse/tests/test_lib_storm.py
CHANGED
|
@@ -2384,6 +2384,26 @@ class StormTest(s_t_utils.SynTest):
|
|
|
2384
2384
|
self.eq('barvuln', embeds['vuln']['name'])
|
|
2385
2385
|
self.eq('foohw', embeds['node']['name'])
|
|
2386
2386
|
|
|
2387
|
+
# embed through `econ:pay:instrument` type that extends from `ndef`
|
|
2388
|
+
await core.nodes('''
|
|
2389
|
+
[ econ:acct:payment=* :from:instrument={ [ econ:pay:card=(testcard,) :name=infime ] } ]
|
|
2390
|
+
''')
|
|
2391
|
+
|
|
2392
|
+
opts = {
|
|
2393
|
+
'embeds': {
|
|
2394
|
+
'econ:acct:payment': {
|
|
2395
|
+
'from:instrument': ['name'],
|
|
2396
|
+
}
|
|
2397
|
+
}
|
|
2398
|
+
}
|
|
2399
|
+
msgs = await core.stormlist('econ:acct:payment', opts=opts)
|
|
2400
|
+
node = [m[1] for m in msgs if m[0] == 'node'][0]
|
|
2401
|
+
self.eq('econ:acct:payment', node[0][0])
|
|
2402
|
+
|
|
2403
|
+
embeds = node[1]['embeds']
|
|
2404
|
+
self.eq('86caf7a47348d56b2f6bec3e767a9fc7eaaaf5a80d7bbaa235fab763c7dcc560', embeds['from:instrument']['*'])
|
|
2405
|
+
self.eq('infime', embeds['from:instrument']['name'])
|
|
2406
|
+
|
|
2387
2407
|
async def test_storm_wget(self):
|
|
2388
2408
|
|
|
2389
2409
|
async def _getRespFromSha(core, mesgs):
|
|
@@ -1291,35 +1291,33 @@ class StormTypesTest(s_test.SynTest):
|
|
|
1291
1291
|
self.len(1, nodes)
|
|
1292
1292
|
self.eq('visi@vertex.link', nodes[0].ndef[1])
|
|
1293
1293
|
|
|
1294
|
-
|
|
1295
|
-
self.eq(1, nodes[0].ndef[1])
|
|
1294
|
+
self.true(await core.callStorm('$s = woot return($s.startswith(w))'))
|
|
1296
1295
|
|
|
1297
|
-
|
|
1298
|
-
self.eq(0, nodes[0].ndef[1])
|
|
1296
|
+
self.false(await core.callStorm('$s = woot return($s.endswith(visi))'))
|
|
1299
1297
|
|
|
1300
|
-
|
|
1301
|
-
self.eq(' woot',
|
|
1298
|
+
valu = await core.callStorm('$s = woot return($s.rjust(10))')
|
|
1299
|
+
self.eq(' woot', valu)
|
|
1302
1300
|
|
|
1303
|
-
|
|
1304
|
-
self.eq('xxxxxxwoot',
|
|
1301
|
+
valu = await core.callStorm('$s = woot return($s.rjust(10, x))')
|
|
1302
|
+
self.eq('xxxxxxwoot', valu)
|
|
1305
1303
|
|
|
1306
|
-
|
|
1307
|
-
self.eq('woot ',
|
|
1304
|
+
valu = await core.callStorm('$s = woot return($s.ljust(10))')
|
|
1305
|
+
self.eq('woot ', valu)
|
|
1308
1306
|
|
|
1309
|
-
|
|
1310
|
-
self.eq('wootxxxxxx',
|
|
1307
|
+
valu = await core.callStorm('$s = woot return($s.ljust(10, x))')
|
|
1308
|
+
self.eq('wootxxxxxx', valu)
|
|
1311
1309
|
|
|
1312
1310
|
sobj = s_stormtypes.Str('beepbeep')
|
|
1313
1311
|
self.len(8, sobj)
|
|
1314
1312
|
|
|
1315
|
-
|
|
1316
|
-
self.eq('foo.bar.baz',
|
|
1313
|
+
valu = await core.callStorm('$s = (foo, bar, baz) return((".").join($s))')
|
|
1314
|
+
self.eq('foo.bar.baz', valu)
|
|
1317
1315
|
|
|
1318
|
-
|
|
1319
|
-
self.eq('foo.bar.baz',
|
|
1316
|
+
valu = await core.callStorm('$s = foo-bar-baz return($s.replace("-", "."))')
|
|
1317
|
+
self.eq('foo.bar.baz', valu)
|
|
1320
1318
|
|
|
1321
|
-
|
|
1322
|
-
self.eq('foo.bar-baz',
|
|
1319
|
+
valu = await core.callStorm('$s = foo-bar-baz return($s.replace("-", ".", 1))')
|
|
1320
|
+
self.eq('foo.bar-baz', valu)
|
|
1323
1321
|
|
|
1324
1322
|
q = '$foo=" foo " return ( $foo.strip() )'
|
|
1325
1323
|
self.eq('foo', await core.callStorm(q))
|
synapse/tests/test_lib_view.py
CHANGED
|
@@ -332,6 +332,20 @@ class ViewTest(s_t_utils.SynTest):
|
|
|
332
332
|
self.len(100, nodeedit[0][2])
|
|
333
333
|
self.len(2, nodeedit[1][2])
|
|
334
334
|
|
|
335
|
+
await core.nodes('[ test:str=lowertag +#a.b=2020]')
|
|
336
|
+
|
|
337
|
+
vdef2 = await core.view.fork()
|
|
338
|
+
opts = {'view': vdef2['iden']}
|
|
339
|
+
await core.nodes('test:str=lowertag [ +#a.b.c ]', opts=opts)
|
|
340
|
+
|
|
341
|
+
retn = await core.callStorm('test:str=lowertag return($node.getStorNodes())', opts=opts)
|
|
342
|
+
|
|
343
|
+
# Only leaf tag is added in our top layer
|
|
344
|
+
self.isin('a.b.c', retn[0].get('tags'))
|
|
345
|
+
self.notin('a.b', retn[0].get('tags'))
|
|
346
|
+
|
|
347
|
+
self.isin('a.b', retn[1].get('tags'))
|
|
348
|
+
|
|
335
349
|
async def test_view_merge_ival(self):
|
|
336
350
|
|
|
337
351
|
async with self.getTestCore() as core:
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import synapse.tests.utils as s_test
|
|
2
|
+
|
|
3
|
+
class EntityModelTest(s_test.SynTest):
|
|
4
|
+
|
|
5
|
+
async def test_entity_relationship(self):
|
|
6
|
+
|
|
7
|
+
async with self.getTestCore() as core:
|
|
8
|
+
|
|
9
|
+
nodes = await core.nodes('''[
|
|
10
|
+
entity:relationship=*
|
|
11
|
+
:type=tasks
|
|
12
|
+
:period=(2022, ?)
|
|
13
|
+
:source={[ ou:org=({"name": "China Ministry of State Security (MSS)"}) ]}
|
|
14
|
+
:target={[ risk:threat=({"org:name": "APT34", "reporter:name": "vertex"}) ]}
|
|
15
|
+
]''')
|
|
16
|
+
|
|
17
|
+
self.len(1, nodes)
|
|
18
|
+
self.eq(nodes[0].get('type'), 'tasks.')
|
|
19
|
+
self.eq(nodes[0].get('period'), (1640995200000, 9223372036854775807))
|
|
20
|
+
self.eq(nodes[0].get('source'), ('ou:org', '3332a704ed21dc3274d5731acc54a0ee'))
|
|
21
|
+
self.eq(nodes[0].get('target'), ('risk:threat', 'e15738ebae52273300b51c08eaad3a36'))
|
synapse/tests/test_model_inet.py
CHANGED
|
@@ -2971,7 +2971,9 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
2971
2971
|
q = '''
|
|
2972
2972
|
[ inet:service:platform=(slack,)
|
|
2973
2973
|
:url="https://slack.com"
|
|
2974
|
+
:urls=(https://slacker.com,)
|
|
2974
2975
|
:name=Slack
|
|
2976
|
+
:names=("slack chat",)
|
|
2975
2977
|
:provider={ ou:org:name=$provname }
|
|
2976
2978
|
:provider:name=$provname
|
|
2977
2979
|
]
|
|
@@ -2980,11 +2982,19 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
2980
2982
|
self.len(1, nodes)
|
|
2981
2983
|
self.eq(nodes[0].ndef, ('inet:service:platform', s_common.guid(('slack',))))
|
|
2982
2984
|
self.eq(nodes[0].get('url'), 'https://slack.com')
|
|
2985
|
+
self.eq(nodes[0].get('urls'), ('https://slacker.com',))
|
|
2983
2986
|
self.eq(nodes[0].get('name'), 'slack')
|
|
2987
|
+
self.eq(nodes[0].get('names'), ('slack chat',))
|
|
2984
2988
|
self.eq(nodes[0].get('provider'), provider.ndef[1])
|
|
2985
2989
|
self.eq(nodes[0].get('provider:name'), provname.lower())
|
|
2986
2990
|
platform = nodes[0]
|
|
2987
2991
|
|
|
2992
|
+
nodes = await core.nodes('[ inet:service:platform=({"name": "slack chat"}) ]')
|
|
2993
|
+
self.eq(nodes[0].ndef, platform.ndef)
|
|
2994
|
+
|
|
2995
|
+
nodes = await core.nodes('[ inet:service:platform=({"url": "https://slacker.com"}) ]')
|
|
2996
|
+
self.eq(nodes[0].ndef, platform.ndef)
|
|
2997
|
+
|
|
2988
2998
|
q = '''
|
|
2989
2999
|
[ inet:service:instance=(vertex, slack)
|
|
2990
3000
|
:id='T2XK1223Y'
|
|
@@ -3164,6 +3174,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3164
3174
|
:creator=$visiiden
|
|
3165
3175
|
:platform=$platiden
|
|
3166
3176
|
:instance=$instiden
|
|
3177
|
+
:topic=' My Topic '
|
|
3167
3178
|
]
|
|
3168
3179
|
'''
|
|
3169
3180
|
opts = {'vars': {
|
|
@@ -3175,6 +3186,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3175
3186
|
self.len(1, nodes)
|
|
3176
3187
|
self.eq(nodes[0].ndef, ('inet:service:channel', s_common.guid(('general', 'channel', 'vertex', 'slack'))))
|
|
3177
3188
|
self.eq(nodes[0].get('name'), 'general')
|
|
3189
|
+
self.eq(nodes[0].get('topic'), 'my topic')
|
|
3178
3190
|
self.eq(nodes[0].get('period'), (1420070400000, 9223372036854775807))
|
|
3179
3191
|
self.eq(nodes[0].get('creator'), visiacct.ndef[1])
|
|
3180
3192
|
self.eq(nodes[0].get('platform'), platform.ndef[1])
|
|
@@ -3243,12 +3255,18 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3243
3255
|
:group=$devsiden
|
|
3244
3256
|
:public=$lib.false
|
|
3245
3257
|
:repost=*
|
|
3258
|
+
:mentions=(
|
|
3259
|
+
(inet:service:group, $devsiden),
|
|
3260
|
+
(inet:service:account, $blckiden),
|
|
3261
|
+
(inet:service:account, $blckiden),
|
|
3262
|
+
)
|
|
3246
3263
|
)
|
|
3247
3264
|
|
|
3248
3265
|
(inet:service:message=(blackout, visi, 1715856900000, vertex, slack)
|
|
3249
3266
|
:type=chat.direct
|
|
3250
3267
|
:to=$visiiden
|
|
3251
3268
|
:public=$lib.false
|
|
3269
|
+
:mentions?=((inet:service:message:attachment, $atchiden),)
|
|
3252
3270
|
)
|
|
3253
3271
|
|
|
3254
3272
|
(inet:service:message=(blackout, general, 1715856900000, vertex, slack)
|
|
@@ -3296,10 +3314,15 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3296
3314
|
self.eq(nodes[0].get('group'), devsgrp.ndef[1])
|
|
3297
3315
|
self.false(nodes[0].get('public'))
|
|
3298
3316
|
self.eq(nodes[0].get('type'), 'chat.group.')
|
|
3317
|
+
self.eq(
|
|
3318
|
+
nodes[0].get('mentions'),
|
|
3319
|
+
(('inet:service:account', blckacct.ndef[1]), ('inet:service:group', devsgrp.ndef[1]))
|
|
3320
|
+
)
|
|
3299
3321
|
|
|
3300
3322
|
self.eq(nodes[1].get('to'), visiacct.ndef[1])
|
|
3301
3323
|
self.false(nodes[1].get('public'))
|
|
3302
3324
|
self.eq(nodes[1].get('type'), 'chat.direct.')
|
|
3325
|
+
self.none(nodes[1].get('mentions'))
|
|
3303
3326
|
|
|
3304
3327
|
self.eq(nodes[2].get('channel'), gnrlchan.ndef[1])
|
|
3305
3328
|
self.true(nodes[2].get('public'))
|
|
@@ -3370,12 +3393,15 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3370
3393
|
|
|
3371
3394
|
q = '''
|
|
3372
3395
|
[ inet:service:access=(api, blackout, 1715856900000, vertex, slack)
|
|
3396
|
+
:action=foo.bar
|
|
3373
3397
|
:account=$blckiden
|
|
3374
3398
|
:instance=$instiden
|
|
3375
3399
|
:platform=$platiden
|
|
3376
3400
|
:resource=$rsrciden
|
|
3377
3401
|
:success=$lib.true
|
|
3378
3402
|
:time=(1715856900000)
|
|
3403
|
+
:app={[ inet:service:app=({"name": "slack web"}) ]}
|
|
3404
|
+
:client:app={[ inet:service:app=({"name": "slack web"}) :desc="The slack web application"]}
|
|
3379
3405
|
]
|
|
3380
3406
|
'''
|
|
3381
3407
|
opts = {'vars': {
|
|
@@ -3387,16 +3413,19 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3387
3413
|
}}
|
|
3388
3414
|
nodes = await core.nodes(q, opts=opts)
|
|
3389
3415
|
self.len(1, nodes)
|
|
3416
|
+
self.eq(nodes[0].get('action'), 'foo.bar.')
|
|
3390
3417
|
self.eq(nodes[0].get('account'), blckacct.ndef[1])
|
|
3391
3418
|
self.eq(nodes[0].get('instance'), platinst.ndef[1])
|
|
3392
3419
|
self.eq(nodes[0].get('platform'), platform.ndef[1])
|
|
3393
3420
|
self.eq(nodes[0].get('resource'), resource.ndef[1])
|
|
3394
3421
|
self.true(nodes[0].get('success'))
|
|
3395
3422
|
self.eq(nodes[0].get('time'), 1715856900000)
|
|
3423
|
+
self.eq(nodes[0].get('app'), nodes[0].get('client:app'))
|
|
3396
3424
|
|
|
3397
3425
|
q = '''
|
|
3398
3426
|
[ inet:service:message=(visi, says, relax)
|
|
3399
3427
|
:title="Hehe Haha"
|
|
3428
|
+
:hashtags="#hehe,#haha,#hehe"
|
|
3400
3429
|
:thread={[
|
|
3401
3430
|
inet:service:thread=*
|
|
3402
3431
|
:title="Woot Woot"
|
|
@@ -3410,6 +3439,7 @@ class InetModelTest(s_t_utils.SynTest):
|
|
|
3410
3439
|
'''
|
|
3411
3440
|
nodes = await core.nodes(q)
|
|
3412
3441
|
self.len(1, nodes)
|
|
3442
|
+
self.eq(['#haha', '#hehe'], nodes[0].get('hashtags'))
|
|
3413
3443
|
self.len(1, await core.nodes('inet:service:message=(visi, says, hello) -> inet:service:thread:message'))
|
|
3414
3444
|
self.len(1, await core.nodes('''
|
|
3415
3445
|
inet:service:message:title="hehe haha"
|
synapse/tests/test_model_orgs.py
CHANGED
|
@@ -455,8 +455,24 @@ class OuModelTest(s_t_utils.SynTest):
|
|
|
455
455
|
'place': place0,
|
|
456
456
|
'url': 'http://arrowcon.org/2018/dinner',
|
|
457
457
|
}
|
|
458
|
-
q = '''
|
|
459
|
-
|
|
458
|
+
q = '''
|
|
459
|
+
[ ou:conference:event=$valu
|
|
460
|
+
:name=$p.name
|
|
461
|
+
:desc=$p.desc
|
|
462
|
+
:start=$p.start
|
|
463
|
+
:end=$p.end
|
|
464
|
+
:conference=$p.conference
|
|
465
|
+
:contact=$p.contact
|
|
466
|
+
:place=$p.place
|
|
467
|
+
:url=$p.url
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
// :conference should not be RO
|
|
471
|
+
[ -:conference ]
|
|
472
|
+
|
|
473
|
+
// Put the value back
|
|
474
|
+
[ :conference=$p.conference ]
|
|
475
|
+
'''
|
|
460
476
|
nodes = await core.nodes(q, opts={'vars': {'valu': c0, 'p': props}})
|
|
461
477
|
self.len(1, nodes)
|
|
462
478
|
node = nodes[0]
|
|
@@ -151,6 +151,10 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
151
151
|
'users': ('visi', 'invisigoth'),
|
|
152
152
|
'crypto:address': 'btc/1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2',
|
|
153
153
|
'langs': (lang00 := s_common.guid(),),
|
|
154
|
+
'banner': file0,
|
|
155
|
+
'passwd': 'hunter2',
|
|
156
|
+
'website': 'https://blogs.vertex.link/brutus',
|
|
157
|
+
'websites': ('https://foo.com', 'https://bar.com', 'https://foo.com'),
|
|
154
158
|
}
|
|
155
159
|
opts = {'vars': {'valu': con0, 'p': props}}
|
|
156
160
|
q = '''[(ps:contact=$valu
|
|
@@ -172,6 +176,10 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
172
176
|
:death:place=$p."death:place" :death:place:loc=$p."death:place:loc"
|
|
173
177
|
:death:place:name=$p."death:place:name"
|
|
174
178
|
:service:accounts=(*, *) :langs=$p.langs
|
|
179
|
+
:banner=$p.banner
|
|
180
|
+
:passwd=$p.passwd
|
|
181
|
+
:website=$p.website
|
|
182
|
+
:websites=$p.websites
|
|
175
183
|
)]'''
|
|
176
184
|
nodes = await core.nodes(q, opts=opts)
|
|
177
185
|
self.len(1, nodes)
|
|
@@ -215,6 +223,10 @@ class PsModelTest(s_t_utils.SynTest):
|
|
|
215
223
|
self.eq(node.get('death:place:loc'), 'us.va.reston')
|
|
216
224
|
self.eq(node.get('birth:place:name'), 'reston, va, usa, earth, sol, milkyway')
|
|
217
225
|
self.eq(node.get('death:place:name'), 'reston, va, usa, earth, sol, milkyway')
|
|
226
|
+
self.eq(node.get('banner'), file0)
|
|
227
|
+
self.eq(node.get('passwd'), 'hunter2')
|
|
228
|
+
self.eq(node.get('website'), 'https://blogs.vertex.link/brutus')
|
|
229
|
+
self.eq(node.get('websites'), ('https://bar.com', 'https://foo.com'))
|
|
218
230
|
self.len(1, await core.nodes('ps:contact :birth:place -> geo:place'))
|
|
219
231
|
self.len(1, await core.nodes('ps:contact :death:place -> geo:place'))
|
|
220
232
|
self.len(2, await core.nodes('ps:contact :service:accounts -> inet:service:account'))
|