synapse 2.218.1__py311-none-any.whl → 2.220.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/cortex.py +113 -14
- synapse/daemon.py +2 -1
- synapse/data/__init__.py +4 -0
- synapse/data/lark/__init__.py +0 -0
- synapse/data/lark/imap.lark +8 -0
- synapse/exc.py +2 -0
- synapse/lib/ast.py +86 -84
- synapse/lib/json.py +6 -5
- synapse/lib/layer.py +27 -0
- synapse/lib/link.py +49 -50
- synapse/lib/parser.py +3 -5
- synapse/lib/schemas.py +25 -0
- synapse/lib/storm.py +1 -0
- synapse/lib/stormlib/imap.py +476 -35
- synapse/lib/stormtypes.py +177 -2
- synapse/lib/version.py +2 -2
- synapse/models/inet.py +3 -0
- synapse/tests/files/stormpkg/badinits.yaml +12 -0
- synapse/tests/files/stormpkg/testpkg.yaml +12 -0
- synapse/tests/test_lib_grammar.py +2 -4
- synapse/tests/test_lib_json.py +29 -0
- synapse/tests/test_lib_layer.py +119 -0
- synapse/tests/test_lib_storm.py +184 -1
- synapse/tests/test_lib_stormlib_imap.py +1307 -230
- synapse/tests/test_lib_stormtypes.py +157 -0
- synapse/tests/test_model_inet.py +3 -0
- synapse/tests/test_telepath.py +31 -0
- synapse/tests/test_tools_genpkg.py +4 -0
- synapse/tests/utils.py +1 -1
- synapse/tools/genpkg.py +9 -0
- synapse/utils/stormcov/plugin.py +2 -5
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/METADATA +2 -3
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/RECORD +37 -34
- /synapse/{lib → data/lark}/storm.lark +0 -0
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/WHEEL +0 -0
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/licenses/LICENSE +0 -0
- {synapse-2.218.1.dist-info → synapse-2.220.0.dist-info}/top_level.txt +0 -0
synapse/lib/stormtypes.py
CHANGED
|
@@ -2,7 +2,6 @@ import bz2
|
|
|
2
2
|
import copy
|
|
3
3
|
import gzip
|
|
4
4
|
import time
|
|
5
|
-
|
|
6
5
|
import regex
|
|
7
6
|
import types
|
|
8
7
|
import base64
|
|
@@ -10,6 +9,7 @@ import pprint
|
|
|
10
9
|
import struct
|
|
11
10
|
import asyncio
|
|
12
11
|
import decimal
|
|
12
|
+
import hashlib
|
|
13
13
|
import inspect
|
|
14
14
|
import logging
|
|
15
15
|
import binascii
|
|
@@ -730,6 +730,18 @@ class LibPkg(Lib):
|
|
|
730
730
|
{'name': 'pkgdef', 'type': 'dict', 'desc': 'A Storm Package definition.', },
|
|
731
731
|
),
|
|
732
732
|
'returns': {'type': 'dict', 'desc': 'A dictionary listing dependencies and if they are met.', }}},
|
|
733
|
+
{'name': 'vars',
|
|
734
|
+
'desc': "Get a dictionary representing the package's persistent variables.",
|
|
735
|
+
'type': {'type': 'function', '_funcname': '_libPkgVars',
|
|
736
|
+
'args': (
|
|
737
|
+
{'name': 'name', 'type': 'str',
|
|
738
|
+
'desc': 'A Storm Package name to get vars for.', },
|
|
739
|
+
),
|
|
740
|
+
'returns': {'type': 'pkg:vars', 'desc': 'A dictionary representing the package variables.', }}},
|
|
741
|
+
)
|
|
742
|
+
_storm_lib_perms = (
|
|
743
|
+
{'perm': ('power-ups', '<name>', 'admin'), 'gate': 'cortex',
|
|
744
|
+
'desc': 'Controls the ability to interact with the vars for a Storm Package by name.'},
|
|
733
745
|
)
|
|
734
746
|
_storm_lib_path = ('pkg',)
|
|
735
747
|
|
|
@@ -741,6 +753,7 @@ class LibPkg(Lib):
|
|
|
741
753
|
'del': self._libPkgDel,
|
|
742
754
|
'list': self._libPkgList,
|
|
743
755
|
'deps': self._libPkgDeps,
|
|
756
|
+
'vars': self._libPkgVars,
|
|
744
757
|
}
|
|
745
758
|
|
|
746
759
|
async def _libPkgAdd(self, pkgdef, verify=False):
|
|
@@ -780,6 +793,11 @@ class LibPkg(Lib):
|
|
|
780
793
|
pkgdef = await toprim(pkgdef)
|
|
781
794
|
return await self.runt.snap.core.verifyStormPkgDeps(pkgdef)
|
|
782
795
|
|
|
796
|
+
async def _libPkgVars(self, name):
|
|
797
|
+
name = await tostr(name)
|
|
798
|
+
confirm(('power-ups', name, 'admin'))
|
|
799
|
+
return PkgVars(self.runt, name)
|
|
800
|
+
|
|
783
801
|
@registry.registerLib
|
|
784
802
|
class LibDmon(Lib):
|
|
785
803
|
'''
|
|
@@ -2745,9 +2763,13 @@ class LibAxon(Lib):
|
|
|
2745
2763
|
|
|
2746
2764
|
self.runt.confirm(('axon', 'upload'))
|
|
2747
2765
|
|
|
2766
|
+
sha256 = hashlib.sha256(byts).digest()
|
|
2767
|
+
|
|
2748
2768
|
await self.runt.snap.core.getAxon()
|
|
2749
|
-
|
|
2769
|
+
if await self.runt.snap.core.axon.has(sha256):
|
|
2770
|
+
return (len(byts), s_common.ehex(sha256))
|
|
2750
2771
|
|
|
2772
|
+
size, sha256 = await self.runt.snap.core.axon.put(byts)
|
|
2751
2773
|
return (size, s_common.ehex(sha256))
|
|
2752
2774
|
|
|
2753
2775
|
@stormfunc(readonly=True)
|
|
@@ -4945,6 +4967,24 @@ class Bytes(Prim):
|
|
|
4945
4967
|
{'name': 'offset', 'type': 'int', 'desc': 'An offset to begin unpacking from.', 'default': 0},
|
|
4946
4968
|
),
|
|
4947
4969
|
'returns': {'type': 'list', 'desc': 'The unpacked primitive values.', }}},
|
|
4970
|
+
{'name': 'xor', 'desc': '''
|
|
4971
|
+
Perform an "exclusive or" bitwise operation on the bytes and another set of bytes.
|
|
4972
|
+
|
|
4973
|
+
Notes:
|
|
4974
|
+
The key bytes provided as an argument will be repeated as needed until all bytes have been
|
|
4975
|
+
xor'd.
|
|
4976
|
+
|
|
4977
|
+
If a string is provided as the key argument, it will be utf8 encoded before being xor'd.
|
|
4978
|
+
|
|
4979
|
+
Examples:
|
|
4980
|
+
Perform an xor operation on the bytes in $encoded using the bytes in $key::
|
|
4981
|
+
|
|
4982
|
+
$decoded = $encoded.xor($key)''',
|
|
4983
|
+
'type': {'type': 'function', '_funcname': '_methXor',
|
|
4984
|
+
'args': (
|
|
4985
|
+
{'name': 'key', 'type': ['str', 'bytes'], 'desc': 'The key bytes to perform the xor operation with.'},
|
|
4986
|
+
),
|
|
4987
|
+
'returns': {'type': 'bytes', 'desc': "The xor'd bytes."}}},
|
|
4948
4988
|
)
|
|
4949
4989
|
_storm_typename = 'bytes'
|
|
4950
4990
|
_ismutable = False
|
|
@@ -4955,6 +4995,7 @@ class Bytes(Prim):
|
|
|
4955
4995
|
|
|
4956
4996
|
def getObjLocals(self):
|
|
4957
4997
|
return {
|
|
4998
|
+
'xor': self._methXor,
|
|
4958
4999
|
'decode': self._methDecode,
|
|
4959
5000
|
'bunzip': self._methBunzip,
|
|
4960
5001
|
'gunzip': self._methGunzip,
|
|
@@ -5043,6 +5084,26 @@ class Bytes(Prim):
|
|
|
5043
5084
|
except UnicodeDecodeError as e:
|
|
5044
5085
|
raise s_exc.StormRuntimeError(mesg=f'{e}: {s_common.trimText(repr(valu))}') from None
|
|
5045
5086
|
|
|
5087
|
+
@stormfunc(readonly=True)
|
|
5088
|
+
async def _methXor(self, key):
|
|
5089
|
+
key = await toprim(key)
|
|
5090
|
+
if isinstance(key, str):
|
|
5091
|
+
key = key.encode()
|
|
5092
|
+
|
|
5093
|
+
if not isinstance(key, bytes):
|
|
5094
|
+
raise s_exc.BadArg(mesg='$bytes.xor() key argument must be bytes or a str.')
|
|
5095
|
+
|
|
5096
|
+
if len(key) == 0:
|
|
5097
|
+
raise s_exc.BadArg(mesg='$bytes.xor() key length must be greater than 0.')
|
|
5098
|
+
|
|
5099
|
+
arry = bytearray(self.valu)
|
|
5100
|
+
keylen = len(key)
|
|
5101
|
+
|
|
5102
|
+
for i in range(len(arry)):
|
|
5103
|
+
arry[i] ^= key[i % keylen]
|
|
5104
|
+
|
|
5105
|
+
return bytes(arry)
|
|
5106
|
+
|
|
5046
5107
|
@registry.registerType
|
|
5047
5108
|
class Dict(Prim):
|
|
5048
5109
|
'''
|
|
@@ -6015,6 +6076,45 @@ class LibVars(Lib):
|
|
|
6015
6076
|
async def _libVarsType(self, valu):
|
|
6016
6077
|
return await totype(valu)
|
|
6017
6078
|
|
|
6079
|
+
@registry.registerType
|
|
6080
|
+
class PkgVars(Prim):
|
|
6081
|
+
'''
|
|
6082
|
+
The Storm deref/setitem/iter convention on top of pkg vars information.
|
|
6083
|
+
'''
|
|
6084
|
+
_storm_typename = 'pkg:vars'
|
|
6085
|
+
_ismutable = True
|
|
6086
|
+
|
|
6087
|
+
def __init__(self, runt, valu, path=None):
|
|
6088
|
+
Prim.__init__(self, valu, path=path)
|
|
6089
|
+
self.runt = runt
|
|
6090
|
+
|
|
6091
|
+
def _reqPkgAdmin(self):
|
|
6092
|
+
confirm(('power-ups', self.valu, 'admin'))
|
|
6093
|
+
|
|
6094
|
+
@stormfunc(readonly=True)
|
|
6095
|
+
async def deref(self, name):
|
|
6096
|
+
self._reqPkgAdmin()
|
|
6097
|
+
name = await tostr(name)
|
|
6098
|
+
return await self.runt.snap.core.getStormPkgVar(self.valu, name)
|
|
6099
|
+
|
|
6100
|
+
async def setitem(self, name, valu):
|
|
6101
|
+
self._reqPkgAdmin()
|
|
6102
|
+
name = await tostr(name)
|
|
6103
|
+
|
|
6104
|
+
if valu is undef:
|
|
6105
|
+
await self.runt.snap.core.popStormPkgVar(self.valu, name)
|
|
6106
|
+
return
|
|
6107
|
+
|
|
6108
|
+
valu = await toprim(valu)
|
|
6109
|
+
await self.runt.snap.core.setStormPkgVar(self.valu, name, valu)
|
|
6110
|
+
|
|
6111
|
+
@stormfunc(readonly=True)
|
|
6112
|
+
async def iter(self):
|
|
6113
|
+
self._reqPkgAdmin()
|
|
6114
|
+
async for name, valu in self.runt.snap.core.iterStormPkgVars(self.valu):
|
|
6115
|
+
yield name, valu
|
|
6116
|
+
await asyncio.sleep(0)
|
|
6117
|
+
|
|
6018
6118
|
@registry.registerType
|
|
6019
6119
|
class Query(Prim):
|
|
6020
6120
|
'''
|
|
@@ -7069,6 +7169,37 @@ class Layer(Prim):
|
|
|
7069
7169
|
'desc': 'The name of the form to get storage nodes for.'},
|
|
7070
7170
|
),
|
|
7071
7171
|
'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Tuple of buid, sode values.', }}},
|
|
7172
|
+
{'name': 'getStorNodesByProp', 'desc': '''
|
|
7173
|
+
Get buid, sode tuples representing the data stored in the layer for a given property.
|
|
7174
|
+
Notes:
|
|
7175
|
+
The storage nodes represent **only** the data stored in the layer
|
|
7176
|
+
and may not represent whole nodes.
|
|
7177
|
+
''',
|
|
7178
|
+
'type': {'type': 'function', '_funcname': 'getStorNodesByProp',
|
|
7179
|
+
'args': (
|
|
7180
|
+
{'name': 'propname', 'type': 'str', 'desc': 'The full property name to lift by.'},
|
|
7181
|
+
{'name': 'propvalu', 'type': 'obj', 'desc': 'The value for the property.', 'default': None},
|
|
7182
|
+
{'name': 'propcmpr', 'type': 'str', 'desc': 'The comparison operation to use on the value.',
|
|
7183
|
+
'default': '='},
|
|
7184
|
+
),
|
|
7185
|
+
'returns': {'name': 'Yields', 'type': 'list', 'desc': 'Tuple of buid, sode values.', }}},
|
|
7186
|
+
{'name': 'setStorNodeProp',
|
|
7187
|
+
'desc': 'Set a property on a node in this layer.',
|
|
7188
|
+
'type': {'type': 'function', '_funcname': 'setStorNodeProp',
|
|
7189
|
+
'args': (
|
|
7190
|
+
{'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
|
|
7191
|
+
{'name': 'prop', 'type': 'str', 'desc': 'The property name to set.'},
|
|
7192
|
+
{'name': 'valu', 'type': 'any', 'desc': 'The value to set.'},
|
|
7193
|
+
),
|
|
7194
|
+
'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
|
|
7195
|
+
{'name': 'delStorNodeProp',
|
|
7196
|
+
'desc': 'Delete a property from a node in this layer.',
|
|
7197
|
+
'type': {'type': 'function', '_funcname': 'delStorNodeProp',
|
|
7198
|
+
'args': (
|
|
7199
|
+
{'name': 'nodeid', 'type': 'str', 'desc': 'The hex string of the node iden.'},
|
|
7200
|
+
{'name': 'prop', 'type': 'str', 'desc': 'The property name to delete.'},
|
|
7201
|
+
),
|
|
7202
|
+
'returns': {'type': 'boolean', 'desc': 'Returns true if edits were made.'}}},
|
|
7072
7203
|
{'name': 'getMirrorStatus', 'desc': '''
|
|
7073
7204
|
Return a dictionary of the mirror synchronization status for the layer.
|
|
7074
7205
|
''',
|
|
@@ -7287,10 +7418,13 @@ class Layer(Prim):
|
|
|
7287
7418
|
'getStorNode': self.getStorNode,
|
|
7288
7419
|
'getStorNodes': self.getStorNodes,
|
|
7289
7420
|
'getStorNodesByForm': self.getStorNodesByForm,
|
|
7421
|
+
'getStorNodesByProp': self.getStorNodesByProp,
|
|
7290
7422
|
'getEdgesByN1': self.getEdgesByN1,
|
|
7291
7423
|
'getEdgesByN2': self.getEdgesByN2,
|
|
7292
7424
|
'getNodeData': self.getNodeData,
|
|
7293
7425
|
'getMirrorStatus': self.getMirrorStatus,
|
|
7426
|
+
'setStorNodeProp': self.setStorNodeProp,
|
|
7427
|
+
'delStorNodeProp': self.delStorNodeProp,
|
|
7294
7428
|
}
|
|
7295
7429
|
|
|
7296
7430
|
@stormfunc(readonly=True)
|
|
@@ -7364,6 +7498,25 @@ class Layer(Prim):
|
|
|
7364
7498
|
layr = self.runt.snap.core.getLayer(iden)
|
|
7365
7499
|
return await layr.getMirrorStatus()
|
|
7366
7500
|
|
|
7501
|
+
async def setStorNodeProp(self, nodeid, prop, valu):
|
|
7502
|
+
iden = self.valu.get('iden')
|
|
7503
|
+
layr = self.runt.snap.core.getLayer(iden)
|
|
7504
|
+
buid = s_common.uhex(await tostr(nodeid))
|
|
7505
|
+
prop = await tostr(prop)
|
|
7506
|
+
valu = await tostor(valu)
|
|
7507
|
+
self.runt.reqAdmin(mesg='setStorNodeProp() requires admin privileges.')
|
|
7508
|
+
meta = {'time': s_common.now(), 'user': self.runt.user.iden}
|
|
7509
|
+
return await layr.setStorNodeProp(buid, prop, valu, meta=meta)
|
|
7510
|
+
|
|
7511
|
+
async def delStorNodeProp(self, nodeid, prop):
|
|
7512
|
+
iden = self.valu.get('iden')
|
|
7513
|
+
layr = self.runt.snap.core.getLayer(iden)
|
|
7514
|
+
buid = s_common.uhex(await tostr(nodeid))
|
|
7515
|
+
prop = await tostr(prop)
|
|
7516
|
+
self.runt.reqAdmin(mesg='delStorNodeProp() requires admin privileges.')
|
|
7517
|
+
meta = {'time': s_common.now(), 'user': self.runt.user.iden}
|
|
7518
|
+
return await layr.delStorNodeProp(buid, prop, meta=meta)
|
|
7519
|
+
|
|
7367
7520
|
async def _addPull(self, url, offs=0, queue_size=s_const.layer_pdef_qsize, chunk_size=s_const.layer_pdef_csize):
|
|
7368
7521
|
url = await tostr(url)
|
|
7369
7522
|
offs = await toint(offs)
|
|
@@ -7646,6 +7799,28 @@ class Layer(Prim):
|
|
|
7646
7799
|
async for item in layr.getStorNodesByForm(form):
|
|
7647
7800
|
yield item
|
|
7648
7801
|
|
|
7802
|
+
@stormfunc(readonly=True)
|
|
7803
|
+
async def getStorNodesByProp(self, propname, propvalu=None, propcmpr='='):
|
|
7804
|
+
propname = await tostr(propname)
|
|
7805
|
+
propvalu = await tostor(propvalu)
|
|
7806
|
+
propcmpr = await tostr(propcmpr)
|
|
7807
|
+
|
|
7808
|
+
layriden = self.valu.get('iden')
|
|
7809
|
+
await self.runt.reqUserCanReadLayer(layriden)
|
|
7810
|
+
layr = self.runt.snap.core.getLayer(layriden)
|
|
7811
|
+
|
|
7812
|
+
prop = self.runt.snap.core.model.reqProp(propname)
|
|
7813
|
+
|
|
7814
|
+
if propvalu is not None:
|
|
7815
|
+
norm, info = prop.type.norm(propvalu)
|
|
7816
|
+
cmprvals = prop.type.getStorCmprs(propcmpr, norm)
|
|
7817
|
+
async for _, buid, sode in layr.liftByPropValu(prop.form.name, prop.name, cmprvals):
|
|
7818
|
+
yield (s_common.ehex(buid), sode)
|
|
7819
|
+
return
|
|
7820
|
+
|
|
7821
|
+
async for _, buid, sode in layr.liftByProp(prop.form.name, prop.name):
|
|
7822
|
+
yield (s_common.ehex(buid), sode)
|
|
7823
|
+
|
|
7649
7824
|
@stormfunc(readonly=True)
|
|
7650
7825
|
async def getEdges(self):
|
|
7651
7826
|
layriden = self.valu.get('iden')
|
synapse/lib/version.py
CHANGED
|
@@ -223,6 +223,6 @@ def reqVersion(valu, reqver,
|
|
|
223
223
|
##############################################################################
|
|
224
224
|
# The following are touched during the release process by bumpversion.
|
|
225
225
|
# Do not modify these directly.
|
|
226
|
-
version = (2,
|
|
226
|
+
version = (2, 220, 0)
|
|
227
227
|
verstring = '.'.join([str(x) for x in version])
|
|
228
|
-
commit = '
|
|
228
|
+
commit = '913156d6c195af916a32860341f285954cb4e882'
|
synapse/models/inet.py
CHANGED
|
@@ -3796,6 +3796,9 @@ class InetModule(s_module.CoreModule):
|
|
|
3796
3796
|
('user', ('inet:user', {}), {
|
|
3797
3797
|
'doc': 'The current user name of the account.'}),
|
|
3798
3798
|
|
|
3799
|
+
('parent', ('inet:service:account', {}), {
|
|
3800
|
+
'doc': 'A parent account which owns this account.'}),
|
|
3801
|
+
|
|
3799
3802
|
('email', ('inet:email', {}), {
|
|
3800
3803
|
'doc': 'The current email address associated with the account.'}),
|
|
3801
3804
|
|
|
@@ -45,6 +45,18 @@ onload: |
|
|
|
45
45
|
$lib.time.sleep($lib.globals.get(onload_sleep, 0))
|
|
46
46
|
$lib.globals.set(testpkg, testpkg-done)
|
|
47
47
|
|
|
48
|
+
inits:
|
|
49
|
+
key: testpkg:version
|
|
50
|
+
versions:
|
|
51
|
+
- name: first
|
|
52
|
+
version: 0
|
|
53
|
+
inaugural: true
|
|
54
|
+
query: "$lib.globals.set(testpkg-first, (true))"
|
|
55
|
+
- name: second
|
|
56
|
+
desc: Another init
|
|
57
|
+
version: 2
|
|
58
|
+
query: "$lib.globals.set(testpkg-second, (true))"
|
|
59
|
+
|
|
48
60
|
external_modules:
|
|
49
61
|
- name: testext
|
|
50
62
|
package: synapse.tests.files
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import lark # type: ignore
|
|
2
2
|
|
|
3
3
|
import synapse.exc as s_exc
|
|
4
|
+
import synapse.data as s_data
|
|
4
5
|
|
|
5
6
|
import synapse.lib.parser as s_parser
|
|
6
|
-
import synapse.lib.datfile as s_datfile
|
|
7
7
|
import synapse.lib.grammar as s_grammar
|
|
8
8
|
|
|
9
9
|
import synapse.tests.utils as s_t_utils
|
|
@@ -1414,9 +1414,7 @@ class GrammarTest(s_t_utils.SynTest):
|
|
|
1414
1414
|
'''
|
|
1415
1415
|
Validates that we have no grammar ambiguities
|
|
1416
1416
|
'''
|
|
1417
|
-
|
|
1418
|
-
grammar = larkf.read().decode()
|
|
1419
|
-
|
|
1417
|
+
grammar = s_data.getLark('storm')
|
|
1420
1418
|
parser = lark.Lark(grammar, start='query', debug=True, regex=True, parser='lalr',
|
|
1421
1419
|
keep_all_tokens=True, maybe_placeholders=False,
|
|
1422
1420
|
propagate_positions=True)
|
synapse/tests/test_lib_json.py
CHANGED
|
@@ -125,6 +125,35 @@ class JsonTest(s_test.SynTest):
|
|
|
125
125
|
|
|
126
126
|
self.eq(valu, s_json.loads(s_json.dumps(valu)))
|
|
127
127
|
|
|
128
|
+
async def test_lib_json_control_strings(self):
|
|
129
|
+
valus = [
|
|
130
|
+
'line1"line2',
|
|
131
|
+
'line1/line2',
|
|
132
|
+
'line1\\line2',
|
|
133
|
+
'line1\bline2',
|
|
134
|
+
'line1\fline2',
|
|
135
|
+
'line1\nline2',
|
|
136
|
+
'line1\rline2',
|
|
137
|
+
'line1\tline2',
|
|
138
|
+
'line1\u0009line2',
|
|
139
|
+
'line1\u1000line2',
|
|
140
|
+
'line1\u2000line2',
|
|
141
|
+
'line1\u3000line2',
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
with self.getLoggerStream('synapse.lib.json') as stream:
|
|
145
|
+
async with self.getTestCore() as core:
|
|
146
|
+
for valu in valus:
|
|
147
|
+
q = '$lib.print($valu) $lib.print($lib.json.save($valu))'
|
|
148
|
+
msgs = await core.stormlist(q, opts={'vars': {'valu': valu}})
|
|
149
|
+
self.stormHasNoWarnErr(msgs)
|
|
150
|
+
|
|
151
|
+
self.eq(s_json.loads(s_json.dumps(valu)), valu)
|
|
152
|
+
|
|
153
|
+
stream.seek(0)
|
|
154
|
+
data = stream.read()
|
|
155
|
+
self.notin('fallback JSON', data)
|
|
156
|
+
|
|
128
157
|
async def test_jsload(self):
|
|
129
158
|
with self.getTestDir() as dirn:
|
|
130
159
|
with s_common.genfile(dirn, 'jsload.json') as fp:
|
synapse/tests/test_lib_layer.py
CHANGED
|
@@ -2283,3 +2283,122 @@ class LayerTest(s_t_utils.SynTest):
|
|
|
2283
2283
|
|
|
2284
2284
|
sodes = await s_t_utils.alist(layr00.getStorNodesByForm('inet:ipv4'))
|
|
2285
2285
|
self.len(0, sodes)
|
|
2286
|
+
|
|
2287
|
+
async def test_layer_migrate_props_fork(self):
|
|
2288
|
+
|
|
2289
|
+
async with self.getTestCore() as core:
|
|
2290
|
+
|
|
2291
|
+
iden = (await core.addUser('lowuser')).get('iden')
|
|
2292
|
+
lowuser = {'user': iden}
|
|
2293
|
+
|
|
2294
|
+
fork00 = await core.view.fork()
|
|
2295
|
+
layr00 = core.getLayer(fork00['layers'][0]['iden'])
|
|
2296
|
+
|
|
2297
|
+
await core.nodes('''
|
|
2298
|
+
for $prop in (_custom:risk:level, _custom:risk:severity) {
|
|
2299
|
+
$lib.model.ext.addFormProp(
|
|
2300
|
+
test:guid,
|
|
2301
|
+
$prop,
|
|
2302
|
+
(["int", {"enums": [[10, "low"], [20, "medium"], [30, "high"]]}]),
|
|
2303
|
+
({"doc": "hey now"}),
|
|
2304
|
+
)
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
''')
|
|
2308
|
+
self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
|
|
2309
|
+
self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:severity'))
|
|
2310
|
+
|
|
2311
|
+
await core.nodes('[ test:guid=* :name=test1 :_custom:risk:level=low ]', opts={'view': fork00['iden']})
|
|
2312
|
+
|
|
2313
|
+
await core.getView(fork00['iden']).delete()
|
|
2314
|
+
|
|
2315
|
+
with self.raises(s_exc.CantDelProp) as cm:
|
|
2316
|
+
await core.callStorm('''
|
|
2317
|
+
$fullprop = "test:guid:_custom:risk:level"
|
|
2318
|
+
for $view in $lib.view.list(deporder=$lib.true) {
|
|
2319
|
+
view.exec $view.iden {
|
|
2320
|
+
yield $lib.layer.get().liftByProp($fullprop)
|
|
2321
|
+
$repr = $node.repr("_custom:risk:level")
|
|
2322
|
+
[ :severity=$repr -:_custom:risk:level ]
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
$lib.model.ext.delFormProp("test:guid", "_custom:risk:level")
|
|
2326
|
+
''')
|
|
2327
|
+
self.isin('Nodes still exist with prop: test:guid:_custom:risk:level', str(cm.exception))
|
|
2328
|
+
self.len(1, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
|
|
2329
|
+
|
|
2330
|
+
with self.raises(s_exc.NoSuchProp) as cm:
|
|
2331
|
+
await core.callStorm('''
|
|
2332
|
+
$layer = $lib.layer.get()
|
|
2333
|
+
$layer.getStorNodesByProp("foo:bar:_custom:risk:level")
|
|
2334
|
+
''')
|
|
2335
|
+
self.isin('No property named', str(cm.exception))
|
|
2336
|
+
|
|
2337
|
+
with self.raises(s_exc.NoSuchProp):
|
|
2338
|
+
await core.callStorm('''
|
|
2339
|
+
$fullprop = "test:guid:_custom:risk:level"
|
|
2340
|
+
for $layer in $lib.layer.list() {
|
|
2341
|
+
for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
|
|
2342
|
+
$oldv = $sode.props."_custom:risk:level"
|
|
2343
|
+
$layer.setStorNodeProp($buid, "foo:bar:severity", $oldv.0)
|
|
2344
|
+
}
|
|
2345
|
+
}
|
|
2346
|
+
''')
|
|
2347
|
+
|
|
2348
|
+
with self.raises(s_exc.BadTypeValu):
|
|
2349
|
+
await core.callStorm('''
|
|
2350
|
+
$fullprop = "test:guid:_custom:risk:level"
|
|
2351
|
+
for $layer in $lib.layer.list() {
|
|
2352
|
+
for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
|
|
2353
|
+
$layer.setStorNodeProp($buid, $fullprop, "newp")
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
''')
|
|
2357
|
+
|
|
2358
|
+
with self.raises(s_exc.NoSuchProp):
|
|
2359
|
+
await core.callStorm('''
|
|
2360
|
+
$fullprop = "test:guid:_custom:risk:level"
|
|
2361
|
+
for $layer in $lib.layer.list() {
|
|
2362
|
+
for ($buid, $sode) in $layer.getStorNodesByProp($fullprop) {
|
|
2363
|
+
$layer.delStorNodeProp($buid, "foo:bar:severity")
|
|
2364
|
+
}
|
|
2365
|
+
}
|
|
2366
|
+
''')
|
|
2367
|
+
|
|
2368
|
+
with self.raises(s_exc.AuthDeny) as cm:
|
|
2369
|
+
await core.callStorm('''
|
|
2370
|
+
$buid = "8c454b27df9c0ba109c123265b50869759bccac5bbec83b41992b4e91207f4a4"
|
|
2371
|
+
$layer = $lib.layer.get()
|
|
2372
|
+
$layer.setStorNodeProp($buid, "foo:bar:severity", "newp")
|
|
2373
|
+
''', opts=lowuser)
|
|
2374
|
+
self.isin('requires admin privileges', str(cm.exception))
|
|
2375
|
+
|
|
2376
|
+
with self.raises(s_exc.AuthDeny) as cm:
|
|
2377
|
+
await core.callStorm('''
|
|
2378
|
+
$buid = "8c454b27df9c0ba109c123265b50869759bccac5bbec83b41992b4e91207f4a4"
|
|
2379
|
+
$layer = $lib.layer.get()
|
|
2380
|
+
$layer.delStorNodeProp($buid, "foo:bar:severity")
|
|
2381
|
+
''', opts=lowuser)
|
|
2382
|
+
self.isin('requires admin privileges', str(cm.exception))
|
|
2383
|
+
|
|
2384
|
+
await core.callStorm('''
|
|
2385
|
+
$fullprop = "test:guid:_custom:risk:level"
|
|
2386
|
+
for $layer in $lib.layer.list() {
|
|
2387
|
+
if $layer.getPropCount($fullprop, maxsize=1) {
|
|
2388
|
+
for ($buid, $sode) in $layer.getStorNodesByProp($fullprop, (10), "=") {
|
|
2389
|
+
$oldv = $sode.props."_custom:risk:level"
|
|
2390
|
+
$layer.setStorNodeProp($buid, "test:guid:_custom:risk:severity", $oldv.0)
|
|
2391
|
+
$layer.delStorNodeProp($buid, $fullprop)
|
|
2392
|
+
}
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
$lib.model.ext.delFormProp("test:guid", "_custom:risk:level")
|
|
2396
|
+
''')
|
|
2397
|
+
self.len(0, await core.nodes('syn:prop=test:guid:_custom:risk:level'))
|
|
2398
|
+
self.len(0, await core.nodes('test:guid:_custom:risk:severity'))
|
|
2399
|
+
|
|
2400
|
+
view00 = (await core.addView(vdef={'layers': [layr00.iden]}))['iden']
|
|
2401
|
+
nodes = await core.nodes('test:guid', opts={'view': view00})
|
|
2402
|
+
self.len(1, nodes)
|
|
2403
|
+
self.none(nodes[0].props.get('_custom:risk:level'))
|
|
2404
|
+
self.eq(nodes[0].props.get('_custom:risk:severity'), 10)
|